aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/drivers/accel/habanalabs/common/security.h
blob: 476f70687c09977d32759cfda2d1bc973b217e22 (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
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
/* SPDX-License-Identifier: GPL-2.0
 *
 * Copyright 2016-2022 HabanaLabs, Ltd.
 * All Rights Reserved.
 *
 */

#ifndef SECURITY_H_
#define SECURITY_H_

#include <linux/io-64-nonatomic-lo-hi.h>

struct hl_device;

/* special blocks */
#define HL_GLBL_ERR_ADDRESS_MASK	GENMASK(11, 0)
/* GLBL_ERR_ADDR register offset from the start of the block */
#define HL_GLBL_ERR_ADDR_OFFSET		0xF44
/* GLBL_ERR_CAUSE register offset from the start of the block */
#define HL_GLBL_ERR_CAUSE_OFFSET	0xF48

/*
 * struct hl_special_block_info - stores address details of a particular type of
 * IP block which has a SPECIAL part.
 *
 * @block_type: block type as described in every ASIC's block_types enum.
 * @base_addr: base address of the first block of particular type,
 *             e.g., address of NIC0_UMR0_0 of 'NIC_UMR' block.
 * @major: number of major blocks of particular type.
 * @minor: number of minor blocks of particular type.
 * @sub_minor: number of sub minor blocks of particular type.
 * @major_offset: address gap between 2 consecutive major blocks of particular type,
 *                e.g., offset between NIC0_UMR0_0 and NIC1_UMR0_0 is 0x80000.
 * @minor_offset: address gap between 2 consecutive minor blocks of particular type,
 *                e.g., offset between NIC0_UMR0_0 and NIC0_UMR1_0 is 0x20000.
 * @sub_minor_offset: address gap between 2 consecutive sub_minor blocks of particular
 *                    type, e.g., offset between NIC0_UMR0_0 and NIC0_UMR0_1 is 0x1000.
 *
 * e.g., in Gaudi2, NIC_UMR blocks can be interpreted as:
 * NIC<major>_UMR<minor>_<sub_minor> where major=12, minor=2, sub_minor=15.
 * In other words, for each of 12 major numbers (i.e 0 to 11) there are
 * 2 blocks with different minor numbers (i.e. 0 to 1). Again, for each minor
 * number there are 15 blocks with different sub_minor numbers (i.e. 0 to 14).
 * So different blocks are NIC0_UMR0_0, NIC0_UMR0_1, ..., NIC0_UMR1_0, ....,
 * NIC11_UMR1_14.
 *
 * Struct's formatted data is located in the SOL-based auto-generated protbits headers.
 */
struct hl_special_block_info {
	int block_type;
	u32 base_addr;
	u32 major;
	u32 minor;
	u32 sub_minor;
	u32 major_offset;
	u32 minor_offset;
	u32 sub_minor_offset;
};

/*
 * struct hl_automated_pb_cfg - represents configurations of a particular type
 * of IP block which has protection bits.
 *
 * @addr: address details as described in hl_automation_pb_addr struct.
 * @prot_map: each bit corresponds to one among 32 protection configuration regs
 *            (e.g., SPECIAL_GLBL_PRIV). '1' means 0xffffffff and '0' means 0x0
 *            to be written into the corresponding protection configuration reg.
 *            This bit is meaningful if same bit in data_map is 0, otherwise ignored.
 * @data_map: each bit corresponds to one among 32 protection configuration regs
 *            (e.g., SPECIAL_GLBL_PRIV). '1' means corresponding protection
 *            configuration reg is to be written with a value in array pointed
 *            by 'data', otherwise the value is decided by 'prot_map'.
 * @data: pointer to data array which stores the config value(s) to be written
 *            to corresponding protection configuration reg(s).
 * @data_size: size of the data array.
 *
 * Each bit of 'data_map' and 'prot_map' fields corresponds to one among 32
 * protection configuration registers e.g., SPECIAL GLBL PRIV regs (starting at
 * offset 0xE80). '1' in 'data_map' means protection configuration to be done
 * using configuration in data array. '0' in 'data_map" means protection
 * configuration to be done as per the value of corresponding bit in 'prot_map'.
 * '1' in 'prot_map' means the register to be programmed with 0xFFFFFFFF
 * (all non-protected). '0' in 'prot_map' means the register to be programmed
 * with 0x0 (all protected).
 *
 * e.g., prot_map = 0x00000001, data_map = 0xC0000000 , data = {0xff, 0x12}
 * SPECIAL_GLBL_PRIV[0] = 0xFFFFFFFF
 * SPECIAL_GLBL_PRIV[1..29] = 0x0
 * SPECIAL_GLBL_PRIV[30] = 0xFF
 * SPECIAL_GLBL_PRIV[31] = 0x12
 */
struct hl_automated_pb_cfg {
	struct hl_special_block_info addr;
	u32 prot_map;
	u32 data_map;
	const u32 *data;
	u8 data_size;
};

/* struct hl_special_blocks_cfg - holds special blocks cfg data.
 *
 * @priv_automated_pb_cfg: points to the main privileged PB array.
 * @sec_automated_pb_cfg: points to the main secured PB array.
 * @skip_blocks_cfg: holds arrays of block types & block ranges to be excluded.
 * @priv_cfg_size: size of the main privileged PB array.
 * @sec_cfg_size: size of the main secured PB array.
 * @prot_lvl_priv: indication if it's a privileged/secured PB configurations.
 */
struct hl_special_blocks_cfg {
	struct hl_automated_pb_cfg *priv_automated_pb_cfg;
	struct hl_automated_pb_cfg *sec_automated_pb_cfg;
	struct hl_skip_blocks_cfg *skip_blocks_cfg;
	u32 priv_cfg_size;
	u32 sec_cfg_size;
	u8 prot_lvl_priv;
};

/* Automated security */

/* struct hl_skip_blocks_cfg - holds arrays of block types & block ranges to be
 * excluded from special blocks configurations.
 *
 * @block_types: an array of block types NOT to be configured.
 * @block_types_len: len of an array of block types not to be configured.
 * @block_ranges: an array of block ranges not to be configured.
 * @block_ranges_len: len of an array of block ranges not to be configured.
 * @skip_block_hook: hook that will be called before initializing special blocks.
 */
struct hl_skip_blocks_cfg {
	int *block_types;
	size_t block_types_len;
	struct range *block_ranges;
	size_t block_ranges_len;
	bool (*skip_block_hook)(struct hl_device *hdev,
				struct hl_special_blocks_cfg *special_blocks_cfg,
				u32 blk_idx, u32 major, u32 minor, u32 sub_minor);
};

/**
 * struct iterate_special_ctx - HW module special block iterator
 * @fn: function to apply to each HW module special block instance
 * @data: optional internal data to the function iterator
 */
struct iterate_special_ctx {
	/*
	 * callback for the HW module special block iterator
	 * @hdev: pointer to the habanalabs device structure
	 * @block_id: block (ASIC specific definition can be dcore/hdcore)
	 * @major: major block index within block_id
	 * @minor: minor block index within the major block
	 * @sub_minor: sub_minor block index within the minor block
	 * @data: function specific data
	 */
	int (*fn)(struct hl_device *hdev, u32 block_id, u32 major, u32 minor,
						u32 sub_minor, void *data);
	void *data;
};

int hl_iterate_special_blocks(struct hl_device *hdev, struct iterate_special_ctx *ctx);
void hl_check_for_glbl_errors(struct hl_device *hdev);

#endif /* SECURITY_H_ */