1 /*
2  * Copyright (c) 2017, 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 #include "priv.h"
23 
24 #include <core/memory.h>
25 #include <subdev/acr.h>
26 #include <subdev/timer.h>
27 
28 #include <nvfw/flcn.h>
29 #include <nvfw/sec2.h>
30 
31 int
gp102_sec2_nofw(struct nvkm_sec2 * sec2,int ver,const struct nvkm_sec2_fwif * fwif)32 gp102_sec2_nofw(struct nvkm_sec2 *sec2, int ver,
33 		const struct nvkm_sec2_fwif *fwif)
34 {
35 	nvkm_warn(&sec2->engine.subdev, "firmware unavailable\n");
36 	return 0;
37 }
38 
39 static int
gp102_sec2_acr_bootstrap_falcon_callback(void * priv,struct nvfw_falcon_msg * hdr)40 gp102_sec2_acr_bootstrap_falcon_callback(void *priv, struct nvfw_falcon_msg *hdr)
41 {
42 	struct nv_sec2_acr_bootstrap_falcon_msg *msg =
43 		container_of(hdr, typeof(*msg), msg.hdr);
44 	struct nvkm_subdev *subdev = priv;
45 	const char *name = nvkm_acr_lsf_id(msg->falcon_id);
46 
47 	if (msg->error_code) {
48 		nvkm_error(subdev, "ACR_BOOTSTRAP_FALCON failed for "
49 				   "falcon %d [%s]: %08x\n",
50 			   msg->falcon_id, name, msg->error_code);
51 		return -EINVAL;
52 	}
53 
54 	nvkm_debug(subdev, "%s booted\n", name);
55 	return 0;
56 }
57 
58 static int
gp102_sec2_acr_bootstrap_falcon(struct nvkm_falcon * falcon,enum nvkm_acr_lsf_id id)59 gp102_sec2_acr_bootstrap_falcon(struct nvkm_falcon *falcon,
60 			        enum nvkm_acr_lsf_id id)
61 {
62 	struct nvkm_sec2 *sec2 = container_of(falcon, typeof(*sec2), falcon);
63 	struct nv_sec2_acr_bootstrap_falcon_cmd cmd = {
64 		.cmd.hdr.unit_id = sec2->func->unit_acr,
65 		.cmd.hdr.size = sizeof(cmd),
66 		.cmd.cmd_type = NV_SEC2_ACR_CMD_BOOTSTRAP_FALCON,
67 		.flags = NV_SEC2_ACR_BOOTSTRAP_FALCON_FLAGS_RESET_YES,
68 		.falcon_id = id,
69 	};
70 
71 	return nvkm_falcon_cmdq_send(sec2->cmdq, &cmd.cmd.hdr,
72 				     gp102_sec2_acr_bootstrap_falcon_callback,
73 				     &sec2->engine.subdev,
74 				     msecs_to_jiffies(1000));
75 }
76 
77 static void
gp102_sec2_acr_bld_patch(struct nvkm_acr * acr,u32 bld,s64 adjust)78 gp102_sec2_acr_bld_patch(struct nvkm_acr *acr, u32 bld, s64 adjust)
79 {
80 	struct loader_config_v1 hdr;
81 	nvkm_robj(acr->wpr, bld, &hdr, sizeof(hdr));
82 	hdr.code_dma_base = hdr.code_dma_base + adjust;
83 	hdr.data_dma_base = hdr.data_dma_base + adjust;
84 	hdr.overlay_dma_base = hdr.overlay_dma_base + adjust;
85 	nvkm_wobj(acr->wpr, bld, &hdr, sizeof(hdr));
86 	loader_config_v1_dump(&acr->subdev, &hdr);
87 }
88 
89 static void
gp102_sec2_acr_bld_write(struct nvkm_acr * acr,u32 bld,struct nvkm_acr_lsfw * lsfw)90 gp102_sec2_acr_bld_write(struct nvkm_acr *acr, u32 bld,
91 			 struct nvkm_acr_lsfw *lsfw)
92 {
93 	const struct loader_config_v1 hdr = {
94 		.dma_idx = FALCON_SEC2_DMAIDX_UCODE,
95 		.code_dma_base = lsfw->offset.img + lsfw->app_start_offset,
96 		.code_size_total = lsfw->app_size,
97 		.code_size_to_load = lsfw->app_resident_code_size,
98 		.code_entry_point = lsfw->app_imem_entry,
99 		.data_dma_base = lsfw->offset.img + lsfw->app_start_offset +
100 				 lsfw->app_resident_data_offset,
101 		.data_size = lsfw->app_resident_data_size,
102 		.overlay_dma_base = lsfw->offset.img + lsfw->app_start_offset,
103 		.argc = 1,
104 		.argv = lsfw->falcon->func->emem_addr,
105 	};
106 
107 	nvkm_wobj(acr->wpr, bld, &hdr, sizeof(hdr));
108 }
109 
110 static const struct nvkm_acr_lsf_func
111 gp102_sec2_acr_0 = {
112 	.bld_size = sizeof(struct loader_config_v1),
113 	.bld_write = gp102_sec2_acr_bld_write,
114 	.bld_patch = gp102_sec2_acr_bld_patch,
115 	.bootstrap_falcons = BIT_ULL(NVKM_ACR_LSF_FECS) |
116 			     BIT_ULL(NVKM_ACR_LSF_GPCCS) |
117 			     BIT_ULL(NVKM_ACR_LSF_SEC2),
118 	.bootstrap_falcon = gp102_sec2_acr_bootstrap_falcon,
119 };
120 
121 int
gp102_sec2_initmsg(struct nvkm_sec2 * sec2)122 gp102_sec2_initmsg(struct nvkm_sec2 *sec2)
123 {
124 	struct nv_sec2_init_msg msg;
125 	int ret, i;
126 
127 	ret = nvkm_falcon_msgq_recv_initmsg(sec2->msgq, &msg, sizeof(msg));
128 	if (ret)
129 		return ret;
130 
131 	if (msg.hdr.unit_id != NV_SEC2_UNIT_INIT ||
132 	    msg.msg_type != NV_SEC2_INIT_MSG_INIT)
133 		return -EINVAL;
134 
135 	for (i = 0; i < ARRAY_SIZE(msg.queue_info); i++) {
136 		if (msg.queue_info[i].id == NV_SEC2_INIT_MSG_QUEUE_ID_MSGQ) {
137 			nvkm_falcon_msgq_init(sec2->msgq,
138 					      msg.queue_info[i].index,
139 					      msg.queue_info[i].offset,
140 					      msg.queue_info[i].size);
141 		} else {
142 			nvkm_falcon_cmdq_init(sec2->cmdq,
143 					      msg.queue_info[i].index,
144 					      msg.queue_info[i].offset,
145 					      msg.queue_info[i].size);
146 		}
147 	}
148 
149 	return 0;
150 }
151 
152 irqreturn_t
gp102_sec2_intr(struct nvkm_inth * inth)153 gp102_sec2_intr(struct nvkm_inth *inth)
154 {
155 	struct nvkm_sec2 *sec2 = container_of(inth, typeof(*sec2), engine.subdev.inth);
156 	struct nvkm_subdev *subdev = &sec2->engine.subdev;
157 	struct nvkm_falcon *falcon = &sec2->falcon;
158 	u32 disp = nvkm_falcon_rd32(falcon, 0x01c);
159 	u32 intr = nvkm_falcon_rd32(falcon, 0x008) & disp & ~(disp >> 16);
160 
161 	if (intr & 0x00000040) {
162 		if (unlikely(atomic_read(&sec2->initmsg) == 0)) {
163 			int ret = sec2->func->initmsg(sec2);
164 
165 			if (ret)
166 				nvkm_error(subdev, "error parsing init message: %d\n", ret);
167 
168 			atomic_set(&sec2->initmsg, ret ?: 1);
169 		}
170 
171 		if (atomic_read(&sec2->initmsg) > 0) {
172 			if (!nvkm_falcon_msgq_empty(sec2->msgq))
173 				nvkm_falcon_msgq_recv(sec2->msgq);
174 		}
175 
176 		nvkm_falcon_wr32(falcon, 0x004, 0x00000040);
177 		intr &= ~0x00000040;
178 	}
179 
180 	if (intr & 0x00000010) {
181 		if (atomic_read(&sec2->running)) {
182 			FLCN_ERR(falcon, "halted");
183 			gm200_flcn_tracepc(falcon);
184 		}
185 
186 		nvkm_falcon_wr32(falcon, 0x004, 0x00000010);
187 		intr &= ~0x00000010;
188 	}
189 
190 	if (intr) {
191 		nvkm_error(subdev, "unhandled intr %08x\n", intr);
192 		nvkm_falcon_wr32(falcon, 0x004, intr);
193 	}
194 
195 	return IRQ_HANDLED;
196 }
197 
198 static const struct nvkm_falcon_func
199 gp102_sec2_flcn = {
200 	.disable = gm200_flcn_disable,
201 	.enable = gm200_flcn_enable,
202 	.reset_pmc = true,
203 	.reset_eng = gp102_flcn_reset_eng,
204 	.reset_wait_mem_scrubbing = gm200_flcn_reset_wait_mem_scrubbing,
205 	.debug = 0x408,
206 	.bind_inst = gm200_flcn_bind_inst,
207 	.bind_stat = gm200_flcn_bind_stat,
208 	.bind_intr = true,
209 	.imem_pio = &gm200_flcn_imem_pio,
210 	.dmem_pio = &gm200_flcn_dmem_pio,
211 	.emem_addr = 0x01000000,
212 	.emem_pio = &gp102_flcn_emem_pio,
213 	.start = nvkm_falcon_v1_start,
214 	.cmdq = { 0xa00, 0xa04, 8 },
215 	.msgq = { 0xa30, 0xa34, 8 },
216 };
217 
218 const struct nvkm_sec2_func
219 gp102_sec2 = {
220 	.flcn = &gp102_sec2_flcn,
221 	.unit_unload = NV_SEC2_UNIT_UNLOAD,
222 	.unit_acr = NV_SEC2_UNIT_ACR,
223 	.intr = gp102_sec2_intr,
224 	.initmsg = gp102_sec2_initmsg,
225 };
226 
227 MODULE_FIRMWARE("nvidia/gp102/sec2/desc.bin");
228 MODULE_FIRMWARE("nvidia/gp102/sec2/image.bin");
229 MODULE_FIRMWARE("nvidia/gp102/sec2/sig.bin");
230 MODULE_FIRMWARE("nvidia/gp104/sec2/desc.bin");
231 MODULE_FIRMWARE("nvidia/gp104/sec2/image.bin");
232 MODULE_FIRMWARE("nvidia/gp104/sec2/sig.bin");
233 MODULE_FIRMWARE("nvidia/gp106/sec2/desc.bin");
234 MODULE_FIRMWARE("nvidia/gp106/sec2/image.bin");
235 MODULE_FIRMWARE("nvidia/gp106/sec2/sig.bin");
236 MODULE_FIRMWARE("nvidia/gp107/sec2/desc.bin");
237 MODULE_FIRMWARE("nvidia/gp107/sec2/image.bin");
238 MODULE_FIRMWARE("nvidia/gp107/sec2/sig.bin");
239 
240 void
gp102_sec2_acr_bld_patch_1(struct nvkm_acr * acr,u32 bld,s64 adjust)241 gp102_sec2_acr_bld_patch_1(struct nvkm_acr *acr, u32 bld, s64 adjust)
242 {
243 	struct flcn_bl_dmem_desc_v2 hdr;
244 	nvkm_robj(acr->wpr, bld, &hdr, sizeof(hdr));
245 	hdr.code_dma_base = hdr.code_dma_base + adjust;
246 	hdr.data_dma_base = hdr.data_dma_base + adjust;
247 	nvkm_wobj(acr->wpr, bld, &hdr, sizeof(hdr));
248 	flcn_bl_dmem_desc_v2_dump(&acr->subdev, &hdr);
249 }
250 
251 void
gp102_sec2_acr_bld_write_1(struct nvkm_acr * acr,u32 bld,struct nvkm_acr_lsfw * lsfw)252 gp102_sec2_acr_bld_write_1(struct nvkm_acr *acr, u32 bld,
253 			   struct nvkm_acr_lsfw *lsfw)
254 {
255 	const struct flcn_bl_dmem_desc_v2 hdr = {
256 		.ctx_dma = FALCON_SEC2_DMAIDX_UCODE,
257 		.code_dma_base = lsfw->offset.img + lsfw->app_start_offset,
258 		.non_sec_code_off = lsfw->app_resident_code_offset,
259 		.non_sec_code_size = lsfw->app_resident_code_size,
260 		.code_entry_point = lsfw->app_imem_entry,
261 		.data_dma_base = lsfw->offset.img + lsfw->app_start_offset +
262 				 lsfw->app_resident_data_offset,
263 		.data_size = lsfw->app_resident_data_size,
264 		.argc = 1,
265 		.argv = lsfw->falcon->func->emem_addr,
266 	};
267 
268 	nvkm_wobj(acr->wpr, bld, &hdr, sizeof(hdr));
269 }
270 
271 const struct nvkm_acr_lsf_func
272 gp102_sec2_acr_1 = {
273 	.bld_size = sizeof(struct flcn_bl_dmem_desc_v2),
274 	.bld_write = gp102_sec2_acr_bld_write_1,
275 	.bld_patch = gp102_sec2_acr_bld_patch_1,
276 	.bootstrap_falcons = BIT_ULL(NVKM_ACR_LSF_FECS) |
277 			     BIT_ULL(NVKM_ACR_LSF_GPCCS) |
278 			     BIT_ULL(NVKM_ACR_LSF_SEC2),
279 	.bootstrap_falcon = gp102_sec2_acr_bootstrap_falcon,
280 };
281 
282 int
gp102_sec2_load(struct nvkm_sec2 * sec2,int ver,const struct nvkm_sec2_fwif * fwif)283 gp102_sec2_load(struct nvkm_sec2 *sec2, int ver,
284 		const struct nvkm_sec2_fwif *fwif)
285 {
286 	return nvkm_acr_lsfw_load_sig_image_desc_v1(&sec2->engine.subdev,
287 						    &sec2->falcon,
288 						    NVKM_ACR_LSF_SEC2, "sec2/",
289 						    ver, fwif->acr);
290 }
291 
292 MODULE_FIRMWARE("nvidia/gp102/sec2/desc-1.bin");
293 MODULE_FIRMWARE("nvidia/gp102/sec2/image-1.bin");
294 MODULE_FIRMWARE("nvidia/gp102/sec2/sig-1.bin");
295 MODULE_FIRMWARE("nvidia/gp104/sec2/desc-1.bin");
296 MODULE_FIRMWARE("nvidia/gp104/sec2/image-1.bin");
297 MODULE_FIRMWARE("nvidia/gp104/sec2/sig-1.bin");
298 MODULE_FIRMWARE("nvidia/gp106/sec2/desc-1.bin");
299 MODULE_FIRMWARE("nvidia/gp106/sec2/image-1.bin");
300 MODULE_FIRMWARE("nvidia/gp106/sec2/sig-1.bin");
301 MODULE_FIRMWARE("nvidia/gp107/sec2/desc-1.bin");
302 MODULE_FIRMWARE("nvidia/gp107/sec2/image-1.bin");
303 MODULE_FIRMWARE("nvidia/gp107/sec2/sig-1.bin");
304 
305 static const struct nvkm_sec2_fwif
306 gp102_sec2_fwif[] = {
307 	{  1, gp102_sec2_load, &gp102_sec2, &gp102_sec2_acr_1 },
308 	{  0, gp102_sec2_load, &gp102_sec2, &gp102_sec2_acr_0 },
309 	{ -1, gp102_sec2_nofw, &gp102_sec2 },
310 	{}
311 };
312 
313 int
gp102_sec2_new(struct nvkm_device * device,enum nvkm_subdev_type type,int inst,struct nvkm_sec2 ** psec2)314 gp102_sec2_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
315 	       struct nvkm_sec2 **psec2)
316 {
317 	return nvkm_sec2_new_(gp102_sec2_fwif, device, type, inst, 0, psec2);
318 }
319