1 // SPDX-License-Identifier: MIT 2 /* 3 * Copyright © 2022 Intel Corporation 4 */ 5 6 #include "xe_huc.h" 7 8 #include <drm/drm_managed.h> 9 10 #include "abi/gsc_pxp_commands_abi.h" 11 #include "regs/xe_gsc_regs.h" 12 #include "regs/xe_guc_regs.h" 13 #include "xe_assert.h" 14 #include "xe_bo.h" 15 #include "xe_device.h" 16 #include "xe_force_wake.h" 17 #include "xe_gsc_submit.h" 18 #include "xe_gt.h" 19 #include "xe_guc.h" 20 #include "xe_map.h" 21 #include "xe_mmio.h" 22 #include "xe_uc_fw.h" 23 24 static struct xe_gt * 25 huc_to_gt(struct xe_huc *huc) 26 { 27 return container_of(huc, struct xe_gt, uc.huc); 28 } 29 30 static struct xe_device * 31 huc_to_xe(struct xe_huc *huc) 32 { 33 return gt_to_xe(huc_to_gt(huc)); 34 } 35 36 static struct xe_guc * 37 huc_to_guc(struct xe_huc *huc) 38 { 39 return &container_of(huc, struct xe_uc, huc)->guc; 40 } 41 42 static void free_gsc_pkt(struct drm_device *drm, void *arg) 43 { 44 struct xe_huc *huc = arg; 45 46 xe_bo_unpin_map_no_vm(huc->gsc_pkt); 47 huc->gsc_pkt = NULL; 48 } 49 50 #define PXP43_HUC_AUTH_INOUT_SIZE SZ_4K 51 static int huc_alloc_gsc_pkt(struct xe_huc *huc) 52 { 53 struct xe_gt *gt = huc_to_gt(huc); 54 struct xe_device *xe = gt_to_xe(gt); 55 struct xe_bo *bo; 56 int err; 57 58 /* we use a single object for both input and output */ 59 bo = xe_bo_create_pin_map(xe, gt_to_tile(gt), NULL, 60 PXP43_HUC_AUTH_INOUT_SIZE * 2, 61 ttm_bo_type_kernel, 62 XE_BO_CREATE_SYSTEM_BIT | 63 XE_BO_CREATE_GGTT_BIT); 64 if (IS_ERR(bo)) 65 return PTR_ERR(bo); 66 67 huc->gsc_pkt = bo; 68 69 err = drmm_add_action_or_reset(&xe->drm, free_gsc_pkt, huc); 70 if (err) { 71 free_gsc_pkt(&xe->drm, huc); 72 return err; 73 } 74 75 return 0; 76 } 77 78 int xe_huc_init(struct xe_huc *huc) 79 { 80 struct xe_gt *gt = huc_to_gt(huc); 81 struct xe_tile *tile = gt_to_tile(gt); 82 struct xe_device *xe = gt_to_xe(gt); 83 int ret; 84 85 huc->fw.type = XE_UC_FW_TYPE_HUC; 86 87 /* On platforms with a media GT the HuC is only available there */ 88 if (tile->media_gt && (gt != tile->media_gt)) { 89 xe_uc_fw_change_status(&huc->fw, XE_UC_FIRMWARE_NOT_SUPPORTED); 90 return 0; 91 } 92 93 ret = xe_uc_fw_init(&huc->fw); 94 if (ret) 95 goto out; 96 97 if (!xe_uc_fw_is_enabled(&huc->fw)) 98 return 0; 99 100 if (huc->fw.has_gsc_headers) { 101 ret = huc_alloc_gsc_pkt(huc); 102 if (ret) 103 goto out; 104 } 105 106 xe_uc_fw_change_status(&huc->fw, XE_UC_FIRMWARE_LOADABLE); 107 108 return 0; 109 110 out: 111 drm_err(&xe->drm, "HuC init failed with %d", ret); 112 return ret; 113 } 114 115 int xe_huc_init_post_hwconfig(struct xe_huc *huc) 116 { 117 struct xe_tile *tile = gt_to_tile(huc_to_gt(huc)); 118 struct xe_device *xe = huc_to_xe(huc); 119 int ret; 120 121 if (!IS_DGFX(huc_to_xe(huc))) 122 return 0; 123 124 if (!xe_uc_fw_is_loadable(&huc->fw)) 125 return 0; 126 127 ret = xe_managed_bo_reinit_in_vram(xe, tile, &huc->fw.bo); 128 if (ret) 129 return ret; 130 131 return 0; 132 } 133 134 int xe_huc_upload(struct xe_huc *huc) 135 { 136 if (!xe_uc_fw_is_loadable(&huc->fw)) 137 return 0; 138 return xe_uc_fw_upload(&huc->fw, 0, HUC_UKERNEL); 139 } 140 141 #define huc_auth_msg_wr(xe_, map_, offset_, field_, val_) \ 142 xe_map_wr_field(xe_, map_, offset_, struct pxp43_new_huc_auth_in, field_, val_) 143 #define huc_auth_msg_rd(xe_, map_, offset_, field_) \ 144 xe_map_rd_field(xe_, map_, offset_, struct pxp43_huc_auth_out, field_) 145 146 static u32 huc_emit_pxp_auth_msg(struct xe_device *xe, struct iosys_map *map, 147 u32 wr_offset, u32 huc_offset, u32 huc_size) 148 { 149 xe_map_memset(xe, map, wr_offset, 0, sizeof(struct pxp43_new_huc_auth_in)); 150 151 huc_auth_msg_wr(xe, map, wr_offset, header.api_version, PXP_APIVER(4, 3)); 152 huc_auth_msg_wr(xe, map, wr_offset, header.command_id, PXP43_CMDID_NEW_HUC_AUTH); 153 huc_auth_msg_wr(xe, map, wr_offset, header.status, 0); 154 huc_auth_msg_wr(xe, map, wr_offset, header.buffer_len, 155 sizeof(struct pxp43_new_huc_auth_in) - sizeof(struct pxp_cmd_header)); 156 huc_auth_msg_wr(xe, map, wr_offset, huc_base_address, huc_offset); 157 huc_auth_msg_wr(xe, map, wr_offset, huc_size, huc_size); 158 159 return wr_offset + sizeof(struct pxp43_new_huc_auth_in); 160 } 161 162 static int huc_auth_via_gsccs(struct xe_huc *huc) 163 { 164 struct xe_gt *gt = huc_to_gt(huc); 165 struct xe_device *xe = gt_to_xe(gt); 166 struct xe_bo *pkt = huc->gsc_pkt; 167 u32 wr_offset; 168 u32 rd_offset; 169 u64 ggtt_offset; 170 u32 out_status; 171 int retry = 5; 172 int err = 0; 173 174 if (!pkt) 175 return -ENODEV; 176 177 ggtt_offset = xe_bo_ggtt_addr(pkt); 178 179 wr_offset = xe_gsc_emit_header(xe, &pkt->vmap, 0, HECI_MEADDRESS_PXP, 0, 180 sizeof(struct pxp43_new_huc_auth_in)); 181 wr_offset = huc_emit_pxp_auth_msg(xe, &pkt->vmap, wr_offset, 182 xe_bo_ggtt_addr(huc->fw.bo), 183 huc->fw.bo->size); 184 do { 185 err = xe_gsc_pkt_submit_kernel(>->uc.gsc, ggtt_offset, wr_offset, 186 ggtt_offset + PXP43_HUC_AUTH_INOUT_SIZE, 187 PXP43_HUC_AUTH_INOUT_SIZE); 188 if (err) 189 break; 190 191 if (xe_gsc_check_and_update_pending(xe, &pkt->vmap, 0, &pkt->vmap, 192 PXP43_HUC_AUTH_INOUT_SIZE)) { 193 err = -EBUSY; 194 msleep(50); 195 } 196 } while (--retry && err == -EBUSY); 197 198 if (err) { 199 drm_err(&xe->drm, "failed to submit GSC request to auth: %d\n", err); 200 return err; 201 } 202 203 err = xe_gsc_read_out_header(xe, &pkt->vmap, PXP43_HUC_AUTH_INOUT_SIZE, 204 sizeof(struct pxp43_huc_auth_out), &rd_offset); 205 if (err) { 206 drm_err(&xe->drm, "HuC: invalid GSC reply for auth (err=%d)\n", err); 207 return err; 208 } 209 210 /* 211 * The GSC will return PXP_STATUS_OP_NOT_PERMITTED if the HuC is already 212 * authenticated. If the same error is ever returned with HuC not loaded 213 * we'll still catch it when we check the authentication bit later. 214 */ 215 out_status = huc_auth_msg_rd(xe, &pkt->vmap, rd_offset, header.status); 216 if (out_status != PXP_STATUS_SUCCESS && out_status != PXP_STATUS_OP_NOT_PERMITTED) { 217 drm_err(&xe->drm, "auth failed with GSC error = 0x%x\n", out_status); 218 return -EIO; 219 } 220 221 return 0; 222 } 223 224 static const struct { 225 const char *name; 226 struct xe_reg reg; 227 u32 val; 228 } huc_auth_modes[XE_HUC_AUTH_TYPES_COUNT] = { 229 [XE_HUC_AUTH_VIA_GUC] = { "GuC", 230 HUC_KERNEL_LOAD_INFO, 231 HUC_LOAD_SUCCESSFUL }, 232 [XE_HUC_AUTH_VIA_GSC] = { "GSC", 233 HECI_FWSTS5(MTL_GSC_HECI1_BASE), 234 HECI1_FWSTS5_HUC_AUTH_DONE }, 235 }; 236 237 bool xe_huc_is_authenticated(struct xe_huc *huc, enum xe_huc_auth_types type) 238 { 239 struct xe_gt *gt = huc_to_gt(huc); 240 241 return xe_mmio_read32(gt, huc_auth_modes[type].reg) & huc_auth_modes[type].val; 242 } 243 244 int xe_huc_auth(struct xe_huc *huc, enum xe_huc_auth_types type) 245 { 246 struct xe_device *xe = huc_to_xe(huc); 247 struct xe_gt *gt = huc_to_gt(huc); 248 struct xe_guc *guc = huc_to_guc(huc); 249 int ret; 250 251 if (!xe_uc_fw_is_loadable(&huc->fw)) 252 return 0; 253 254 /* On newer platforms the HuC survives reset, so no need to re-auth */ 255 if (xe_huc_is_authenticated(huc, type)) { 256 xe_uc_fw_change_status(&huc->fw, XE_UC_FIRMWARE_RUNNING); 257 return 0; 258 } 259 260 if (!xe_uc_fw_is_loaded(&huc->fw)) 261 return -ENOEXEC; 262 263 switch (type) { 264 case XE_HUC_AUTH_VIA_GUC: 265 ret = xe_guc_auth_huc(guc, xe_bo_ggtt_addr(huc->fw.bo) + 266 xe_uc_fw_rsa_offset(&huc->fw)); 267 break; 268 case XE_HUC_AUTH_VIA_GSC: 269 ret = huc_auth_via_gsccs(huc); 270 break; 271 default: 272 XE_WARN_ON(type); 273 return -EINVAL; 274 } 275 if (ret) { 276 drm_err(&xe->drm, "Failed to trigger HuC auth via %s: %d\n", 277 huc_auth_modes[type].name, ret); 278 goto fail; 279 } 280 281 ret = xe_mmio_wait32(gt, huc_auth_modes[type].reg, huc_auth_modes[type].val, 282 huc_auth_modes[type].val, 100000, NULL, false); 283 if (ret) { 284 drm_err(&xe->drm, "HuC: Firmware not verified %d\n", ret); 285 goto fail; 286 } 287 288 xe_uc_fw_change_status(&huc->fw, XE_UC_FIRMWARE_RUNNING); 289 drm_dbg(&xe->drm, "HuC authenticated via %s\n", huc_auth_modes[type].name); 290 291 return 0; 292 293 fail: 294 drm_err(&xe->drm, "HuC: Auth via %s failed: %d\n", 295 huc_auth_modes[type].name, ret); 296 xe_uc_fw_change_status(&huc->fw, XE_UC_FIRMWARE_LOAD_FAIL); 297 298 return ret; 299 } 300 301 void xe_huc_sanitize(struct xe_huc *huc) 302 { 303 if (!xe_uc_fw_is_loadable(&huc->fw)) 304 return; 305 xe_uc_fw_change_status(&huc->fw, XE_UC_FIRMWARE_LOADABLE); 306 } 307 308 void xe_huc_print_info(struct xe_huc *huc, struct drm_printer *p) 309 { 310 struct xe_gt *gt = huc_to_gt(huc); 311 int err; 312 313 xe_uc_fw_print(&huc->fw, p); 314 315 if (!xe_uc_fw_is_enabled(&huc->fw)) 316 return; 317 318 err = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT); 319 if (err) 320 return; 321 322 drm_printf(p, "\nHuC status: 0x%08x\n", 323 xe_mmio_read32(gt, HUC_KERNEL_LOAD_INFO)); 324 325 xe_force_wake_put(gt_to_fw(gt), XE_FW_GT); 326 } 327