]> Git Repo - J-linux.git/blob - drivers/gpu/drm/xe/xe_huc.c
Merge tag 'kbuild-v6.9' of git://git.kernel.org/pub/scm/linux/kernel/git/masahiroy...
[J-linux.git] / drivers / gpu / drm / xe / xe_huc.c
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(&gt->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 }
This page took 0.046326 seconds and 4 git commands to generate.