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 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 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 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 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 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 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 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 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 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 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 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