1 // SPDX-License-Identifier: MIT 2 /* 3 * Copyright © 2022 Intel Corporation 4 */ 5 6 #include "xe_huc.h" 7 8 #include "regs/xe_guc_regs.h" 9 #include "xe_assert.h" 10 #include "xe_bo.h" 11 #include "xe_device.h" 12 #include "xe_force_wake.h" 13 #include "xe_gt.h" 14 #include "xe_guc.h" 15 #include "xe_mmio.h" 16 #include "xe_uc_fw.h" 17 18 static struct xe_gt * 19 huc_to_gt(struct xe_huc *huc) 20 { 21 return container_of(huc, struct xe_gt, uc.huc); 22 } 23 24 static struct xe_device * 25 huc_to_xe(struct xe_huc *huc) 26 { 27 return gt_to_xe(huc_to_gt(huc)); 28 } 29 30 static struct xe_guc * 31 huc_to_guc(struct xe_huc *huc) 32 { 33 return &container_of(huc, struct xe_uc, huc)->guc; 34 } 35 36 int xe_huc_init(struct xe_huc *huc) 37 { 38 struct xe_gt *gt = huc_to_gt(huc); 39 struct xe_tile *tile = gt_to_tile(gt); 40 struct xe_device *xe = gt_to_xe(gt); 41 int ret; 42 43 huc->fw.type = XE_UC_FW_TYPE_HUC; 44 45 /* On platforms with a media GT the HuC is only available there */ 46 if (tile->media_gt && (gt != tile->media_gt)) { 47 xe_uc_fw_change_status(&huc->fw, XE_UC_FIRMWARE_NOT_SUPPORTED); 48 return 0; 49 } 50 51 ret = xe_uc_fw_init(&huc->fw); 52 if (ret) 53 goto out; 54 55 if (!xe_uc_fw_is_enabled(&huc->fw)) 56 return 0; 57 58 xe_uc_fw_change_status(&huc->fw, XE_UC_FIRMWARE_LOADABLE); 59 60 return 0; 61 62 out: 63 drm_err(&xe->drm, "HuC init failed with %d", ret); 64 return ret; 65 } 66 67 int xe_huc_upload(struct xe_huc *huc) 68 { 69 if (!xe_uc_fw_is_loadable(&huc->fw)) 70 return 0; 71 return xe_uc_fw_upload(&huc->fw, 0, HUC_UKERNEL); 72 } 73 74 int xe_huc_auth(struct xe_huc *huc) 75 { 76 struct xe_device *xe = huc_to_xe(huc); 77 struct xe_gt *gt = huc_to_gt(huc); 78 struct xe_guc *guc = huc_to_guc(huc); 79 int ret; 80 81 if (!xe_uc_fw_is_loadable(&huc->fw)) 82 return 0; 83 84 xe_assert(xe, !xe_uc_fw_is_running(&huc->fw)); 85 86 /* On newer platforms the HuC survives reset, so no need to re-auth */ 87 if (xe_mmio_read32(gt, HUC_KERNEL_LOAD_INFO) & HUC_LOAD_SUCCESSFUL) { 88 xe_uc_fw_change_status(&huc->fw, XE_UC_FIRMWARE_RUNNING); 89 return 0; 90 } 91 92 if (!xe_uc_fw_is_loaded(&huc->fw)) 93 return -ENOEXEC; 94 95 ret = xe_guc_auth_huc(guc, xe_bo_ggtt_addr(huc->fw.bo) + 96 xe_uc_fw_rsa_offset(&huc->fw)); 97 if (ret) { 98 drm_err(&xe->drm, "HuC: GuC did not ack Auth request %d\n", 99 ret); 100 goto fail; 101 } 102 103 ret = xe_mmio_wait32(gt, HUC_KERNEL_LOAD_INFO, HUC_LOAD_SUCCESSFUL, 104 HUC_LOAD_SUCCESSFUL, 100000, NULL, false); 105 if (ret) { 106 drm_err(&xe->drm, "HuC: Firmware not verified %d\n", ret); 107 goto fail; 108 } 109 110 xe_uc_fw_change_status(&huc->fw, XE_UC_FIRMWARE_RUNNING); 111 drm_dbg(&xe->drm, "HuC authenticated\n"); 112 113 return 0; 114 115 fail: 116 drm_err(&xe->drm, "HuC authentication failed %d\n", ret); 117 xe_uc_fw_change_status(&huc->fw, XE_UC_FIRMWARE_LOAD_FAIL); 118 119 return ret; 120 } 121 122 void xe_huc_sanitize(struct xe_huc *huc) 123 { 124 if (!xe_uc_fw_is_loadable(&huc->fw)) 125 return; 126 xe_uc_fw_change_status(&huc->fw, XE_UC_FIRMWARE_LOADABLE); 127 } 128 129 void xe_huc_print_info(struct xe_huc *huc, struct drm_printer *p) 130 { 131 struct xe_gt *gt = huc_to_gt(huc); 132 int err; 133 134 xe_uc_fw_print(&huc->fw, p); 135 136 if (!xe_uc_fw_is_enabled(&huc->fw)) 137 return; 138 139 err = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT); 140 if (err) 141 return; 142 143 drm_printf(p, "\nHuC status: 0x%08x\n", 144 xe_mmio_read32(gt, HUC_KERNEL_LOAD_INFO)); 145 146 xe_force_wake_put(gt_to_fw(gt), XE_FW_GT); 147 } 148