summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/xe/xe_huc.c
blob: e0377083d1f2d9da4f8b038c68218deca11795f5 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
// SPDX-License-Identifier: MIT
/*
 * Copyright © 2022 Intel Corporation
 */

#include "xe_huc.h"

#include "regs/xe_guc_regs.h"
#include "xe_bo.h"
#include "xe_device.h"
#include "xe_force_wake.h"
#include "xe_gt.h"
#include "xe_guc.h"
#include "xe_mmio.h"
#include "xe_uc_fw.h"

static struct xe_gt *
huc_to_gt(struct xe_huc *huc)
{
	return container_of(huc, struct xe_gt, uc.huc);
}

static struct xe_device *
huc_to_xe(struct xe_huc *huc)
{
	return gt_to_xe(huc_to_gt(huc));
}

static struct xe_guc *
huc_to_guc(struct xe_huc *huc)
{
	return &container_of(huc, struct xe_uc, huc)->guc;
}

int xe_huc_init(struct xe_huc *huc)
{
	struct xe_device *xe = huc_to_xe(huc);
	int ret;

	huc->fw.type = XE_UC_FW_TYPE_HUC;
	ret = xe_uc_fw_init(&huc->fw);
	if (ret)
		goto out;

	xe_uc_fw_change_status(&huc->fw, XE_UC_FIRMWARE_LOADABLE);

	return 0;

out:
	if (xe_uc_fw_is_disabled(&huc->fw)) {
		drm_info(&xe->drm, "HuC disabled\n");
		return 0;
	}
	drm_err(&xe->drm, "HuC init failed with %d", ret);
	return ret;
}

int xe_huc_upload(struct xe_huc *huc)
{
	if (xe_uc_fw_is_disabled(&huc->fw))
		return 0;
	return xe_uc_fw_upload(&huc->fw, 0, HUC_UKERNEL);
}

int xe_huc_auth(struct xe_huc *huc)
{
	struct xe_device *xe = huc_to_xe(huc);
	struct xe_gt *gt = huc_to_gt(huc);
	struct xe_guc *guc = huc_to_guc(huc);
	int ret;
	if (xe_uc_fw_is_disabled(&huc->fw))
		return 0;

	XE_BUG_ON(xe_uc_fw_is_running(&huc->fw));

	if (!xe_uc_fw_is_loaded(&huc->fw))
		return -ENOEXEC;

	ret = xe_guc_auth_huc(guc, xe_bo_ggtt_addr(huc->fw.bo) +
			      xe_uc_fw_rsa_offset(&huc->fw));
	if (ret) {
		drm_err(&xe->drm, "HuC: GuC did not ack Auth request %d\n",
			ret);
		goto fail;
	}

	ret = xe_mmio_wait32(gt, HUC_KERNEL_LOAD_INFO,
			     HUC_LOAD_SUCCESSFUL,
			     HUC_LOAD_SUCCESSFUL, 100000, NULL, false);
	if (ret) {
		drm_err(&xe->drm, "HuC: Firmware not verified %d\n", ret);
		goto fail;
	}

	xe_uc_fw_change_status(&huc->fw, XE_UC_FIRMWARE_RUNNING);
	drm_dbg(&xe->drm, "HuC authenticated\n");

	return 0;

fail:
	drm_err(&xe->drm, "HuC authentication failed %d\n", ret);
	xe_uc_fw_change_status(&huc->fw, XE_UC_FIRMWARE_LOAD_FAIL);

	return ret;
}

void xe_huc_sanitize(struct xe_huc *huc)
{
	if (xe_uc_fw_is_disabled(&huc->fw))
		return;
	xe_uc_fw_change_status(&huc->fw, XE_UC_FIRMWARE_LOADABLE);
}

void xe_huc_print_info(struct xe_huc *huc, struct drm_printer *p)
{
	struct xe_gt *gt = huc_to_gt(huc);
	int err;

	xe_uc_fw_print(&huc->fw, p);

	if (xe_uc_fw_is_disabled(&huc->fw))
		return;

	err = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT);
	if (err)
		return;

	drm_printf(p, "\nHuC status: 0x%08x\n",
		   xe_mmio_read32(gt, HUC_KERNEL_LOAD_INFO));

	xe_force_wake_put(gt_to_fw(gt), XE_FW_GT);
}