aboutsummaryrefslogtreecommitdiff
path: root/src/target/armv8.h
blob: f5aa211097d5dc5e96f5ff42bd03aa2246c79c52 (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
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
/* SPDX-License-Identifier: GPL-2.0-or-later */

/***************************************************************************
 *   Copyright (C) 2015 by David Ung                                       *
 ***************************************************************************/

#ifndef OPENOCD_TARGET_ARMV8_H
#define OPENOCD_TARGET_ARMV8_H

#include "arm_adi_v5.h"
#include "arm.h"
#include "armv4_5_mmu.h"
#include "armv4_5_cache.h"
#include "armv8_dpm.h"
#include "arm_cti.h"

enum {
	ARMV8_R0 = 0,
	ARMV8_R1,
	ARMV8_R2,
	ARMV8_R3,
	ARMV8_R4,
	ARMV8_R5,
	ARMV8_R6,
	ARMV8_R7,
	ARMV8_R8,
	ARMV8_R9,
	ARMV8_R10,
	ARMV8_R11,
	ARMV8_R12,
	ARMV8_R13,
	ARMV8_R14,
	ARMV8_R15,
	ARMV8_R16,
	ARMV8_R17,
	ARMV8_R18,
	ARMV8_R19,
	ARMV8_R20,
	ARMV8_R21,
	ARMV8_R22,
	ARMV8_R23,
	ARMV8_R24,
	ARMV8_R25,
	ARMV8_R26,
	ARMV8_R27,
	ARMV8_R28,
	ARMV8_R29,
	ARMV8_R30,

	ARMV8_SP = 31,
	ARMV8_PC = 32,
	ARMV8_XPSR = 33,

	ARMV8_V0 = 34,
	ARMV8_V1,
	ARMV8_V2,
	ARMV8_V3,
	ARMV8_V4,
	ARMV8_V5,
	ARMV8_V6,
	ARMV8_V7,
	ARMV8_V8,
	ARMV8_V9,
	ARMV8_V10,
	ARMV8_V11,
	ARMV8_V12,
	ARMV8_V13,
	ARMV8_V14,
	ARMV8_V15,
	ARMV8_V16,
	ARMV8_V17,
	ARMV8_V18,
	ARMV8_V19,
	ARMV8_V20,
	ARMV8_V21,
	ARMV8_V22,
	ARMV8_V23,
	ARMV8_V24,
	ARMV8_V25,
	ARMV8_V26,
	ARMV8_V27,
	ARMV8_V28,
	ARMV8_V29,
	ARMV8_V30,
	ARMV8_V31,
	ARMV8_FPSR,
	ARMV8_FPCR,

	ARMV8_ELR_EL1 = 68,
	ARMV8_ESR_EL1 = 69,
	ARMV8_SPSR_EL1 = 70,

	ARMV8_ELR_EL2 = 71,
	ARMV8_ESR_EL2 = 72,
	ARMV8_SPSR_EL2 = 73,

	ARMV8_ELR_EL3 = 74,
	ARMV8_ESR_EL3 = 75,
	ARMV8_SPSR_EL3 = 76,

	/* Pseudo registers defined by GDB to remove the pauth signature. */
	ARMV8_PAUTH_DMASK = 77,
	ARMV8_PAUTH_CMASK = 78,

	ARMV8_LAST_REG,
};

enum run_control_op {
	ARMV8_RUNCONTROL_UNKNOWN = 0,
	ARMV8_RUNCONTROL_RESUME = 1,
	ARMV8_RUNCONTROL_HALT = 2,
	ARMV8_RUNCONTROL_STEP = 3,
};

#define ARMV8_COMMON_MAGIC 0x0A450AAAU

/* VA to PA translation operations opc2 values*/
#define V2PCWPR  0
#define V2PCWPW  1
#define V2PCWUR  2
#define V2PCWUW  3
#define V2POWPR  4
#define V2POWPW  5
#define V2POWUR  6
#define V2POWUW  7
/*   L210/L220 cache controller support */
struct armv8_l2x_cache {
	uint32_t base;
	uint32_t way;
};

struct armv8_cachesize {
	uint32_t level_num;
	/*  cache dimensioning */
	uint32_t linelen;
	uint32_t associativity;
	uint32_t nsets;
	uint32_t cachesize;
	/* info for set way operation on cache */
	uint32_t index;
	uint32_t index_shift;
	uint32_t way;
	uint32_t way_shift;
};

/* information about one architecture cache at any level */
struct armv8_arch_cache {
	int ctype;				/* cache type, CLIDR encoding */
	struct armv8_cachesize d_u_size;	/* data cache */
	struct armv8_cachesize i_size;		/* instruction cache */
};

struct armv8_cache_common {
	int info;
	int loc;
	uint32_t iminline;
	uint32_t dminline;
	struct armv8_arch_cache arch[6];	/* cache info, L1 - L7 */
	int i_cache_enabled;
	int d_u_cache_enabled;

	/* l2 external unified cache if some */
	void *l2_cache;
	int (*flush_all_data_cache)(struct target *target);
	int (*display_cache_info)(struct command_invocation *cmd,
			struct armv8_cache_common *armv8_cache);
};

struct armv8_mmu_common {
	/* following field mmu working way */
	int32_t ttbr1_used; /*  -1 not initialized, 0 no ttbr1 1 ttbr1 used and  */
	uint64_t ttbr0_mask;/*  masked to be used  */

	uint32_t ttbcr;     /* cache for ttbcr register */
	uint32_t ttbr_mask[2];
	uint32_t ttbr_range[2];

	int (*read_physical_memory)(struct target *target, target_addr_t address,
			uint32_t size, uint32_t count, uint8_t *buffer);
	struct armv8_cache_common armv8_cache;
	uint32_t mmu_enabled;
};

struct armv8_common {
	unsigned int common_magic;

	struct arm arm;
	struct reg_cache *core_cache;

	/* Core Debug Unit */
	struct arm_dpm dpm;
	target_addr_t debug_base;
	struct adiv5_ap *debug_ap;

	const uint32_t *opcodes;

	/* mdir */
	uint8_t multi_processor_system;
	uint8_t cluster_id;
	uint8_t cpu_id;

	/* armv8 aarch64 need below information for page translation */
	uint8_t va_size;
	uint8_t pa_size;
	uint32_t page_size;
	uint64_t ttbr_base;
	bool is_armv8r;

	struct armv8_mmu_common armv8_mmu;

	struct arm_cti *cti;

	/* True if OpenOCD provides pointer auth related info to GDB */
	bool enable_pauth;

	/* last run-control command issued to this target (resume, halt, step) */
	enum run_control_op last_run_control_op;

	/* Direct processor core register read and writes */
	int (*read_reg_u64)(struct armv8_common *armv8, int num, uint64_t *value);
	int (*write_reg_u64)(struct armv8_common *armv8, int num, uint64_t value);

	/* SIMD/FPU registers read/write interface */
	int (*read_reg_u128)(struct armv8_common *armv8, int num,
			uint64_t *lvalue, uint64_t *hvalue);
	int (*write_reg_u128)(struct armv8_common *armv8, int num,
			uint64_t lvalue, uint64_t hvalue);

	int (*examine_debug_reason)(struct target *target);
	int (*post_debug_entry)(struct target *target);

	void (*pre_restore_context)(struct target *target);
};

static inline struct armv8_common *
target_to_armv8(struct target *target)
{
	return container_of(target->arch_info, struct armv8_common, arm);
}

static inline bool is_armv8(struct armv8_common *armv8)
{
	return armv8->common_magic == ARMV8_COMMON_MAGIC;
}

/* register offsets from armv8.debug_base */
#define CPUV8_DBG_MAINID0		0xD00
#define CPUV8_DBG_CPUFEATURE0	0xD20
#define CPUV8_DBG_DBGFEATURE0	0xD28
#define CPUV8_DBG_MEMFEATURE0	0xD38

#define CPUV8_DBG_LOCKACCESS 0xFB0
#define CPUV8_DBG_LOCKSTATUS 0xFB4

#define CPUV8_DBG_EDESR		0x20
#define CPUV8_DBG_EDECR		0x24
#define CPUV8_DBG_EDWAR0	0x30
#define CPUV8_DBG_EDWAR1	0x34
#define CPUV8_DBG_DSCR		0x088
#define CPUV8_DBG_DRCR		0x090
#define CPUV8_DBG_ECCR		0x098
#define CPUV8_DBG_PRCR		0x310
#define CPUV8_DBG_PRSR		0x314

#define CPUV8_DBG_DTRRX		0x080
#define CPUV8_DBG_ITR		0x084
#define CPUV8_DBG_SCR		0x088
#define CPUV8_DBG_DTRTX		0x08c

#define CPUV8_DBG_BVR_BASE	0x400
#define CPUV8_DBG_BCR_BASE	0x408
#define CPUV8_DBG_WVR_BASE	0x800
#define CPUV8_DBG_WCR_BASE	0x808
#define CPUV8_DBG_VCR		0x01C

#define CPUV8_DBG_OSLAR		0x300

#define CPUV8_DBG_AUTHSTATUS	0xFB8

#define PAGE_SIZE_4KB				0x1000
#define PAGE_SIZE_4KB_LEVEL0_BITS	39
#define PAGE_SIZE_4KB_LEVEL1_BITS	30
#define PAGE_SIZE_4KB_LEVEL2_BITS	21
#define PAGE_SIZE_4KB_LEVEL3_BITS	12

#define PAGE_SIZE_4KB_LEVEL0_MASK	((0x1FFULL) << PAGE_SIZE_4KB_LEVEL0_BITS)
#define PAGE_SIZE_4KB_LEVEL1_MASK	((0x1FFULL) << PAGE_SIZE_4KB_LEVEL1_BITS)
#define PAGE_SIZE_4KB_LEVEL2_MASK	((0x1FFULL) << PAGE_SIZE_4KB_LEVEL2_BITS)
#define PAGE_SIZE_4KB_LEVEL3_MASK	((0x1FFULL) << PAGE_SIZE_4KB_LEVEL3_BITS)

#define PAGE_SIZE_4KB_TRBBASE_MASK	0xFFFFFFFFF000

int armv8_arch_state(struct target *target);
int armv8_read_mpidr(struct armv8_common *armv8);
int armv8_identify_cache(struct armv8_common *armv8);
int armv8_init_arch_info(struct target *target, struct armv8_common *armv8);
int armv8_mmu_translate_va_pa(struct target *target, target_addr_t va,
		target_addr_t *val, int meminfo);
int armv8_mmu_translate_va(struct target *target,  target_addr_t va, target_addr_t *val);

int armv8_handle_cache_info_command(struct command_invocation *cmd,
		struct armv8_cache_common *armv8_cache);

void armv8_set_cpsr(struct arm *arm, uint32_t cpsr);

static inline unsigned int armv8_curel_from_core_mode(enum arm_mode core_mode)
{
	switch (core_mode) {
	/* Aarch32 modes */
	case ARM_MODE_USR:
		return 0;
	case ARM_MODE_SVC:
	case ARM_MODE_ABT: /* FIXME: EL3? */
	case ARM_MODE_IRQ: /* FIXME: EL3? */
	case ARM_MODE_FIQ: /* FIXME: EL3? */
	case ARM_MODE_UND: /* FIXME: EL3? */
	case ARM_MODE_SYS: /* FIXME: EL3? */
		return 1;
	/* case ARM_MODE_HYP:
	 *     return 2;
	 */
	case ARM_MODE_MON:
		return 3;
	/* all Aarch64 modes */
	default:
		return (core_mode >> 2) & 3;
	}
}

const char *armv8_mode_name(unsigned psr_mode);
void armv8_select_reg_access(struct armv8_common *armv8, bool is_aarch64);
int armv8_set_dbgreg_bits(struct armv8_common *armv8, unsigned int reg, unsigned long mask, unsigned long value);

extern void armv8_free_reg_cache(struct target *target);

extern const struct command_registration armv8_command_handlers[];

#endif /* OPENOCD_TARGET_ARMV8_H */