summaryrefslogtreecommitdiff
path: root/drivers/edgetpu/gcip-kernel-driver/include/gcip/gcip-image-config.h
blob: df09d39c7f1a3dc49c2a7e288f89dc9f31b74d84 (plain)
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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Framework for parsing the firmware image configuration.
 *
 * Copyright (C) 2022 Google LLC
 */

#ifndef __GCIP_IMAGE_CONFIG_H__
#define __GCIP_IMAGE_CONFIG_H__

#include <asm/page.h>
#include <linux/bits.h>
#include <linux/types.h>

#define GCIP_FW_NUM_VERSIONS 4
#define GCIP_IMG_CFG_MAX_IOMMU_MAPPINGS 22
#define GCIP_IMG_CFG_MAX_NS_IOMMU_MAPPINGS 5

#define GCIP_FW_PRIV_LEVEL_GSA 0
#define GCIP_FW_PRIV_LEVEL_TZ 1
#define GCIP_FW_PRIV_LEVEL_NS 2

/*
 * The image configuration attached to the signed firmware.
 */
struct gcip_image_config {
	__u32 carveout_base;
	__u32 firmware_base;
	__u32 firmware_size;
	__u32 firmware_versions[GCIP_FW_NUM_VERSIONS];
	__u32 config_version;
	__u32 privilege_level;
	__u32 remapped_region_start;
	__u32 remapped_region_size;
	__u32 num_iommu_mappings;
	struct {
		/* Device virtual address */
		__u32 virt_address;
		/*
		 * Encodes a 12-bit aligned address and the corresponding size
		 * into a 32-bit value.
		 * Detailed encoding method is defined in gcip-image-config.c.
		 */
		__u32 image_config_value;
	} iommu_mappings[GCIP_IMG_CFG_MAX_IOMMU_MAPPINGS];
	__u32 remapped_data_start;
	__u32 remapped_data_size;
	__u32 num_ns_iommu_mappings;
	__u32 ns_iommu_mappings[GCIP_IMG_CFG_MAX_NS_IOMMU_MAPPINGS];
} __packed;

#define GCIP_IMAGE_CONFIG_FLAGS_SECURE (1u << 0)

struct gcip_image_config_ops {
	/*
	 * Adds an IOMMU mapping from @daddr to @paddr with size @size.
	 *
	 * It is ensured that there is no overflow on @paddr + @size before calling this function.
	 *
	 * @flags is a bit-field with the following attributes:
	 *   [0:0] - Security. 1 for secure and 0 for non-secure.
	 *   [31:1] - Reserved.
	 *
	 * Returns 0 on success. Otherwise a negative errno.
	 * Mandatory.
	 */
	int (*map)(void *data, dma_addr_t daddr, phys_addr_t paddr, size_t size,
		   unsigned int flags);
	/*
	 * Removes the IOMMU mapping previously added by @map.
	 *
	 * Mandatory.
	 */
	void (*unmap)(void *data, dma_addr_t daddr, size_t size, unsigned int flags);
};

struct gcip_image_config_parser {
	struct device *dev;
	void *data; /* User-specify data, will be passed to ops. */
	const struct gcip_image_config_ops *ops;
	/* The last image config being successfully parsed. */
	struct gcip_image_config last_config;
};

#define GCIP_IMG_CFG_ADDR_SHIFT 12
#define GCIP_IMG_CFG_MB_SHIFT 20
#define GCIP_IMG_CFG_SIZE_MODE_BIT BIT(GCIP_IMG_CFG_ADDR_SHIFT - 1)
#define GCIP_IMG_CFG_SECURE_SIZE_MASK (GCIP_IMG_CFG_SIZE_MODE_BIT - 1u)
#define GCIP_IMG_CFG_NS_SIZE_MASK (GCIP_IMG_CFG_SIZE_MODE_BIT - 1u)
#define GCIP_IMG_CFG_ADDR_MASK ~(BIT(GCIP_IMG_CFG_ADDR_SHIFT) - 1u)

/* For decoding the size of ns_iommu_mappings. */
static inline u32 gcip_ns_config_to_size(u32 cfg)
{
	if (cfg & GCIP_IMG_CFG_SIZE_MODE_BIT)
		return (cfg & GCIP_IMG_CFG_NS_SIZE_MASK) << PAGE_SHIFT;

	return (cfg & GCIP_IMG_CFG_NS_SIZE_MASK) << GCIP_IMG_CFG_MB_SHIFT;
}

/* For decoding the size of iommu_mappings. */
static inline u32 gcip_config_to_size(u32 cfg)
{
	if (cfg & GCIP_IMG_CFG_SIZE_MODE_BIT)
		return (cfg & GCIP_IMG_CFG_SECURE_SIZE_MASK) << PAGE_SHIFT;

	return BIT(cfg & GCIP_IMG_CFG_SECURE_SIZE_MASK) << PAGE_SHIFT;
}

/*
 * Initializes the image configuration parser.
 *
 * @dev is only used for logging.
 * @data will be passed to operations.
 *
 * Returns 0 on success. Returns -EINVAL when any mandatory operations is NULL.
 */
int gcip_image_config_parser_init(struct gcip_image_config_parser *parser,
				  const struct gcip_image_config_ops *ops, struct device *dev,
				  void *data);

/*
 * Parses the image configuration and adds specified IOMMU mappings by calling pre-registered
 * operations.
 *
 * Number of mappings to be added might be different according to the value of
 * @config->privilege_level:
 * - GCIP_FW_PRIV_LEVEL_NS:
 *   Both @iommu_mappings and @ns_iommu_mappings will be added. Because GCIP_FW_PRIV_LEVEL_NS means
 *   the firmware will run in non-secure mode and all transactions will go through the non-secure
 *   IOMMU.
 * - Otherwise:
 *   Only @ns_iommu_mappings are considered. TZ/GSA will be the one who programs secure IOMMU for
 *   those secure IOMMU mappings.
 *
 * Before parsing the newly passed @config, the mappings of the last record (stored by @parser
 * internally) will be reverted. If there is any mapping in the new config fails to be mapped, the
 * reverted last config will be reverted again. i.e. This function will keep the mapping state the
 * same as before calling it on any error happens. But if the IOMMU state is somehow corrupted and
 * hence fails to roll back the reverted last image config, only an error is logged. See the pseudo
 * code below:
 *
 * gcip_image_config_parse(config):
 *   unmap(last_image_config)
 *   if ret = map(config) fails:
 *     LOG("Failed to map image config, rolling back to the last image config.")
 *     if map(last_image_config) fails:
 *       LOG("Failed to roll back the last image config.")
 *     return ret
 *  else:
 *    last_image_config = config
 *  return SUCCESS
 *
 * A special case being considered is if the content of @config is identical to the last
 * successfully parsed image config, this function will return 0 immediately without removing /
 * adding any mapping.
 *
 * Returns 0 on success. Otherwise an errno, which usually would be the one returned by
 * gcip_image_config_ops.map. On error no new mapping specified in @config is added.
 */
int gcip_image_config_parse(struct gcip_image_config_parser *parser,
			    struct gcip_image_config *config);

/*
 * Clears the mappings specified in the last image config.
 *
 * It's valid to call this function without any image config has been successfully parsed, or when
 * the last image config is already cleared. In which case this function works as no-op.
 */
void gcip_image_config_clear(struct gcip_image_config_parser *parser);

/*
 * Returns whether the privilege level specified by @config is non-secure.
 */
static inline bool gcip_image_config_is_ns(struct gcip_image_config *config)
{
	return config->privilege_level == GCIP_FW_PRIV_LEVEL_NS;
}

#endif /* __GCIP_IMAGE_CONFIG_H__ */