902d29016b004d4ab0402017212728e1091ae0f5
[fw/openocd] / src / target / armv8.c
1 /***************************************************************************
2  *   Copyright (C) 2015 by David Ung                                       *
3  *                                                                         *
4  *   This program is free software; you can redistribute it and/or modify  *
5  *   it under the terms of the GNU General Public License as published by  *
6  *   the Free Software Foundation; either version 2 of the License, or     *
7  *   (at your option) any later version.                                   *
8  *                                                                         *
9  *   This program is distributed in the hope that it will be useful,       *
10  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
11  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
12  *   GNU General Public License for more details.                          *
13  *                                                                         *
14  *   You should have received a copy of the GNU General Public License     *
15  *   along with this program; if not, write to the                         *
16  *   Free Software Foundation, Inc.,                                       *
17  ***************************************************************************/
18
19 #ifdef HAVE_CONFIG_H
20 #include "config.h"
21 #endif
22
23 #include <helper/replacements.h>
24
25 #include "armv8.h"
26 #include "arm_disassembler.h"
27
28 #include "register.h"
29 #include <helper/binarybuffer.h>
30 #include <helper/command.h>
31
32 #include <stdlib.h>
33 #include <string.h>
34 #include <unistd.h>
35
36 #include "arm_opcodes.h"
37 #include "target.h"
38 #include "target_type.h"
39
40 static int armv8_read_core_reg(struct target *target, struct reg *r,
41         int num, enum arm_mode mode)
42 {
43         uint64_t reg_value;
44         int retval;
45         struct arm_reg *armv8_core_reg;
46         struct armv8_common *armv8 = target_to_armv8(target);
47
48         assert(num < (int)armv8->arm.core_cache->num_regs);
49
50         armv8_core_reg = armv8->arm.core_cache->reg_list[num].arch_info;
51         retval = armv8->load_core_reg_u64(target,
52                         armv8_core_reg->num, &reg_value);
53
54         buf_set_u64(armv8->arm.core_cache->reg_list[num].value, 0, 64, reg_value);
55         armv8->arm.core_cache->reg_list[num].valid = 1;
56         armv8->arm.core_cache->reg_list[num].dirty = 0;
57
58         return retval;
59 }
60
61 #if 0
62 static int armv8_write_core_reg(struct target *target, struct reg *r,
63         int num, enum arm_mode mode, target_addr_t value)
64 {
65         int retval;
66         struct arm_reg *armv8_core_reg;
67         struct armv8_common *armv8 = target_to_armv8(target);
68
69         assert(num < (int)armv8->arm.core_cache->num_regs);
70
71         armv8_core_reg = armv8->arm.core_cache->reg_list[num].arch_info;
72         retval = armv8->store_core_reg_u64(target,
73                                             armv8_core_reg->num,
74                                             value);
75         if (retval != ERROR_OK) {
76                 LOG_ERROR("JTAG failure");
77                 armv8->arm.core_cache->reg_list[num].dirty = armv8->arm.core_cache->reg_list[num].valid;
78                 return ERROR_JTAG_DEVICE_ERROR;
79         }
80
81         LOG_DEBUG("write core reg %i value 0x%" PRIx64 "", num, value);
82         armv8->arm.core_cache->reg_list[num].valid = 1;
83         armv8->arm.core_cache->reg_list[num].dirty = 0;
84
85         return ERROR_OK;
86 }
87 #endif
88
89 static void armv8_show_fault_registers(struct target *target)
90 {
91         /* TODO */
92 }
93
94 static int armv8_read_ttbcr(struct target *target)
95 {
96         struct armv8_common *armv8 = target_to_armv8(target);
97         struct arm_dpm *dpm = armv8->arm.dpm;
98         uint32_t ttbcr;
99         int retval = dpm->prepare(dpm);
100         if (retval != ERROR_OK)
101                 goto done;
102         /*  MRC p15,0,<Rt>,c2,c0,2 ; Read CP15 Translation Table Base Control Register*/
103         retval = dpm->instr_read_data_r0(dpm,
104                         ARMV4_5_MRC(15, 0, 0, 2, 0, 2),
105                         &ttbcr);
106         if (retval != ERROR_OK)
107                 goto done;
108         armv8->armv8_mmu.ttbr1_used = ((ttbcr & 0x7) != 0) ? 1 : 0;
109         armv8->armv8_mmu.ttbr0_mask  = 7 << (32 - ((ttbcr & 0x7)));
110 #if 0
111         LOG_INFO("ttb1 %s ,ttb0_mask %x",
112                 armv8->armv8_mmu.ttbr1_used ? "used" : "not used",
113                 armv8->armv8_mmu.ttbr0_mask);
114 #endif
115         if (armv8->armv8_mmu.ttbr1_used == 1) {
116                 LOG_INFO("SVC access above %" PRIx32,
117                          (uint32_t)(0xffffffff & armv8->armv8_mmu.ttbr0_mask));
118                 armv8->armv8_mmu.os_border = 0xffffffff & armv8->armv8_mmu.ttbr0_mask;
119         } else {
120                 /*  fix me , default is hard coded LINUX border  */
121                 armv8->armv8_mmu.os_border = 0xc0000000;
122         }
123 done:
124         dpm->finish(dpm);
125         return retval;
126 }
127
128
129 /*  method adapted to cortex A : reused arm v4 v5 method*/
130 int armv8_mmu_translate_va(struct target *target,  uint32_t va, uint32_t *val)
131 {
132         uint32_t first_lvl_descriptor = 0x0;
133         uint32_t second_lvl_descriptor = 0x0;
134         int retval;
135         struct armv8_common *armv8 = target_to_armv8(target);
136         struct arm_dpm *dpm = armv8->arm.dpm;
137         uint32_t ttb = 0;       /*  default ttb0 */
138         if (armv8->armv8_mmu.ttbr1_used == -1)
139                 armv8_read_ttbcr(target);
140         if ((armv8->armv8_mmu.ttbr1_used) &&
141                 (va > (0xffffffff & armv8->armv8_mmu.ttbr0_mask))) {
142                 /*  select ttb 1 */
143                 ttb = 1;
144         }
145         retval = dpm->prepare(dpm);
146         if (retval != ERROR_OK)
147                 goto done;
148
149         /*  MRC p15,0,<Rt>,c2,c0,ttb */
150         retval = dpm->instr_read_data_r0(dpm,
151                         ARMV4_5_MRC(15, 0, 0, 2, 0, ttb),
152                         &ttb);
153         if (retval != ERROR_OK)
154                 return retval;
155         retval = armv8->armv8_mmu.read_physical_memory(target,
156                         (ttb & 0xffffc000) | ((va & 0xfff00000) >> 18),
157                         4, 1, (uint8_t *)&first_lvl_descriptor);
158         if (retval != ERROR_OK)
159                 return retval;
160         first_lvl_descriptor = target_buffer_get_u32(target, (uint8_t *)
161                         &first_lvl_descriptor);
162         /*  reuse armv4_5 piece of code, specific armv8 changes may come later */
163         LOG_DEBUG("1st lvl desc: %8.8" PRIx32 "", first_lvl_descriptor);
164
165         if ((first_lvl_descriptor & 0x3) == 0) {
166                 LOG_ERROR("Address translation failure");
167                 return ERROR_TARGET_TRANSLATION_FAULT;
168         }
169
170
171         if ((first_lvl_descriptor & 0x3) == 2) {
172                 /* section descriptor */
173                 *val = (first_lvl_descriptor & 0xfff00000) | (va & 0x000fffff);
174                 return ERROR_OK;
175         }
176
177         if ((first_lvl_descriptor & 0x3) == 1) {
178                 /* coarse page table */
179                 retval = armv8->armv8_mmu.read_physical_memory(target,
180                                 (first_lvl_descriptor & 0xfffffc00) | ((va & 0x000ff000) >> 10),
181                                 4, 1, (uint8_t *)&second_lvl_descriptor);
182                 if (retval != ERROR_OK)
183                         return retval;
184         } else if ((first_lvl_descriptor & 0x3) == 3)   {
185                 /* fine page table */
186                 retval = armv8->armv8_mmu.read_physical_memory(target,
187                                 (first_lvl_descriptor & 0xfffff000) | ((va & 0x000ffc00) >> 8),
188                                 4, 1, (uint8_t *)&second_lvl_descriptor);
189                 if (retval != ERROR_OK)
190                         return retval;
191         }
192
193         second_lvl_descriptor = target_buffer_get_u32(target, (uint8_t *)
194                         &second_lvl_descriptor);
195
196         LOG_DEBUG("2nd lvl desc: %8.8" PRIx32 "", second_lvl_descriptor);
197
198         if ((second_lvl_descriptor & 0x3) == 0) {
199                 LOG_ERROR("Address translation failure");
200                 return ERROR_TARGET_TRANSLATION_FAULT;
201         }
202
203         if ((second_lvl_descriptor & 0x3) == 1) {
204                 /* large page descriptor */
205                 *val = (second_lvl_descriptor & 0xffff0000) | (va & 0x0000ffff);
206                 return ERROR_OK;
207         }
208
209         if ((second_lvl_descriptor & 0x3) == 2) {
210                 /* small page descriptor */
211                 *val = (second_lvl_descriptor & 0xfffff000) | (va & 0x00000fff);
212                 return ERROR_OK;
213         }
214
215         if ((second_lvl_descriptor & 0x3) == 3) {
216                 *val = (second_lvl_descriptor & 0xfffffc00) | (va & 0x000003ff);
217                 return ERROR_OK;
218         }
219
220         /* should not happen */
221         LOG_ERROR("Address translation failure");
222         return ERROR_TARGET_TRANSLATION_FAULT;
223
224 done:
225         return retval;
226 }
227
228 /*  V8 method VA TO PA  */
229 int armv8_mmu_translate_va_pa(struct target *target, target_addr_t va,
230         target_addr_t *val, int meminfo)
231 {
232         return ERROR_OK;
233 }
234
235 static int armv8_handle_inner_cache_info_command(struct command_context *cmd_ctx,
236         struct armv8_cache_common *armv8_cache)
237 {
238         if (armv8_cache->ctype == -1) {
239                 command_print(cmd_ctx, "cache not yet identified");
240                 return ERROR_OK;
241         }
242
243         command_print(cmd_ctx,
244                 "D-Cache: linelen %" PRIi32 ", associativity %" PRIi32 ", nsets %" PRIi32 ", cachesize %" PRId32 " KBytes",
245                 armv8_cache->d_u_size.linelen,
246                 armv8_cache->d_u_size.associativity,
247                 armv8_cache->d_u_size.nsets,
248                 armv8_cache->d_u_size.cachesize);
249
250         command_print(cmd_ctx,
251                 "I-Cache: linelen %" PRIi32 ", associativity %" PRIi32 ", nsets %" PRIi32 ", cachesize %" PRId32 " KBytes",
252                 armv8_cache->i_size.linelen,
253                 armv8_cache->i_size.associativity,
254                 armv8_cache->i_size.nsets,
255                 armv8_cache->i_size.cachesize);
256
257         return ERROR_OK;
258 }
259
260 static int _armv8_flush_all_data(struct target *target)
261 {
262         struct armv8_common *armv8 = target_to_armv8(target);
263         struct arm_dpm *dpm = armv8->arm.dpm;
264         struct armv8_cachesize *d_u_size =
265                 &(armv8->armv8_mmu.armv8_cache.d_u_size);
266         int32_t c_way, c_index = d_u_size->index;
267         int retval;
268         /*  check that cache data is on at target halt */
269         if (!armv8->armv8_mmu.armv8_cache.d_u_cache_enabled) {
270                 LOG_INFO("flushed not performed :cache not on at target halt");
271                 return ERROR_OK;
272         }
273         retval = dpm->prepare(dpm);
274         if (retval != ERROR_OK)
275                 goto done;
276         do {
277                 c_way = d_u_size->way;
278                 do {
279                         uint32_t value = (c_index << d_u_size->index_shift)
280                                 | (c_way << d_u_size->way_shift);
281                         /*  DCCISW */
282                         /* LOG_INFO ("%d %d %x",c_way,c_index,value); */
283                         retval = dpm->instr_write_data_r0(dpm,
284                                         ARMV4_5_MCR(15, 0, 0, 7, 14, 2),
285                                         value);
286                         if (retval != ERROR_OK)
287                                 goto done;
288                         c_way -= 1;
289                 } while (c_way >= 0);
290                 c_index -= 1;
291         } while (c_index >= 0);
292         return retval;
293 done:
294         LOG_ERROR("flushed failed");
295         dpm->finish(dpm);
296         return retval;
297 }
298
299 static int  armv8_flush_all_data(struct target *target)
300 {
301         int retval = ERROR_FAIL;
302         /*  check that armv8_cache is correctly identify */
303         struct armv8_common *armv8 = target_to_armv8(target);
304         if (armv8->armv8_mmu.armv8_cache.ctype == -1) {
305                 LOG_ERROR("trying to flush un-identified cache");
306                 return retval;
307         }
308
309         if (target->smp) {
310                 /*  look if all the other target have been flushed in order to flush level
311                  *  2 */
312                 struct target_list *head;
313                 struct target *curr;
314                 head = target->head;
315                 while (head != (struct target_list *)NULL) {
316                         curr = head->target;
317                         if (curr->state == TARGET_HALTED) {
318                                 LOG_INFO("Wait flushing data l1 on core %" PRId32, curr->coreid);
319                                 retval = _armv8_flush_all_data(curr);
320                         }
321                         head = head->next;
322                 }
323         } else
324                 retval = _armv8_flush_all_data(target);
325         return retval;
326 }
327
328 int armv8_handle_cache_info_command(struct command_context *cmd_ctx,
329         struct armv8_cache_common *armv8_cache)
330 {
331         if (armv8_cache->ctype == -1) {
332                 command_print(cmd_ctx, "cache not yet identified");
333                 return ERROR_OK;
334         }
335
336         if (armv8_cache->display_cache_info)
337                 armv8_cache->display_cache_info(cmd_ctx, armv8_cache);
338         return ERROR_OK;
339 }
340
341 /*  retrieve core id cluster id  */
342 static int armv8_read_mpidr(struct target *target)
343 {
344         int retval = ERROR_FAIL;
345         struct armv8_common *armv8 = target_to_armv8(target);
346         struct arm_dpm *dpm = armv8->arm.dpm;
347         uint32_t mpidr;
348         retval = dpm->prepare(dpm);
349         if (retval != ERROR_OK)
350                 goto done;
351         /* MRC p15,0,<Rd>,c0,c0,5; read Multiprocessor ID register*/
352
353         retval = dpm->instr_read_data_r0(dpm,
354                         ARMV4_5_MRC(15, 0, 0, 0, 0, 5),
355                         &mpidr);
356         if (retval != ERROR_OK)
357                 goto done;
358         if (mpidr & 1<<31) {
359                 armv8->multi_processor_system = (mpidr >> 30) & 1;
360                 armv8->cluster_id = (mpidr >> 8) & 0xf;
361                 armv8->cpu_id = mpidr & 0x3;
362                 LOG_INFO("%s cluster %x core %x %s", target_name(target),
363                         armv8->cluster_id,
364                         armv8->cpu_id,
365                         armv8->multi_processor_system == 0 ? "multi core" : "mono core");
366
367         } else
368                 LOG_ERROR("mpdir not in multiprocessor format");
369
370 done:
371         dpm->finish(dpm);
372         return retval;
373
374
375 }
376
377 int armv8_identify_cache(struct target *target)
378 {
379         /*  read cache descriptor */
380         int retval = ERROR_FAIL;
381         struct armv8_common *armv8 = target_to_armv8(target);
382         struct arm_dpm *dpm = armv8->arm.dpm;
383         uint32_t cache_selected, clidr;
384         uint32_t cache_i_reg, cache_d_reg;
385         struct armv8_cache_common *cache = &(armv8->armv8_mmu.armv8_cache);
386         if (!armv8->is_armv7r)
387                 armv8_read_ttbcr(target);
388         retval = dpm->prepare(dpm);
389
390         if (retval != ERROR_OK)
391                 goto done;
392         /*  retrieve CLIDR
393          *  mrc p15, 1, r0, c0, c0, 1           @ read clidr */
394         retval = dpm->instr_read_data_r0(dpm,
395                         ARMV4_5_MRC(15, 1, 0, 0, 0, 1),
396                         &clidr);
397         if (retval != ERROR_OK)
398                 goto done;
399         clidr = (clidr & 0x7000000) >> 23;
400         LOG_INFO("number of cache level %" PRIx32, (uint32_t)(clidr / 2));
401         if ((clidr / 2) > 1) {
402                 /* FIXME not supported present in cortex A8 and later */
403                 /*  in cortex A7, A15 */
404                 LOG_ERROR("cache l2 present :not supported");
405         }
406         /*  retrieve selected cache
407          *  MRC p15, 2,<Rd>, c0, c0, 0; Read CSSELR */
408         retval = dpm->instr_read_data_r0(dpm,
409                         ARMV4_5_MRC(15, 2, 0, 0, 0, 0),
410                         &cache_selected);
411         if (retval != ERROR_OK)
412                 goto done;
413
414         retval = armv8->arm.mrc(target, 15,
415                         2, 0,   /* op1, op2 */
416                         0, 0,   /* CRn, CRm */
417                         &cache_selected);
418         if (retval != ERROR_OK)
419                 goto done;
420         /* select instruction cache
421          *  MCR p15, 2,<Rd>, c0, c0, 0; Write CSSELR
422          *  [0]  : 1 instruction cache selection , 0 data cache selection */
423         retval = dpm->instr_write_data_r0(dpm,
424                         ARMV4_5_MRC(15, 2, 0, 0, 0, 0),
425                         1);
426         if (retval != ERROR_OK)
427                 goto done;
428
429         /* read CCSIDR
430          * MRC P15,1,<RT>,C0, C0,0 ;on cortex A9 read CCSIDR
431          * [2:0] line size  001 eight word per line
432          * [27:13] NumSet 0x7f 16KB, 0xff 32Kbytes, 0x1ff 64Kbytes */
433         retval = dpm->instr_read_data_r0(dpm,
434                         ARMV4_5_MRC(15, 1, 0, 0, 0, 0),
435                         &cache_i_reg);
436         if (retval != ERROR_OK)
437                 goto done;
438
439         /*  select data cache*/
440         retval = dpm->instr_write_data_r0(dpm,
441                         ARMV4_5_MRC(15, 2, 0, 0, 0, 0),
442                         0);
443         if (retval != ERROR_OK)
444                 goto done;
445
446         retval = dpm->instr_read_data_r0(dpm,
447                         ARMV4_5_MRC(15, 1, 0, 0, 0, 0),
448                         &cache_d_reg);
449         if (retval != ERROR_OK)
450                 goto done;
451
452         /*  restore selected cache  */
453         dpm->instr_write_data_r0(dpm,
454                 ARMV4_5_MRC(15, 2, 0, 0, 0, 0),
455                 cache_selected);
456
457         if (retval != ERROR_OK)
458                 goto done;
459         dpm->finish(dpm);
460
461         /* put fake type */
462         cache->d_u_size.linelen = 16 << (cache_d_reg & 0x7);
463         cache->d_u_size.cachesize = (((cache_d_reg >> 13) & 0x7fff)+1)/8;
464         cache->d_u_size.nsets = (cache_d_reg >> 13) & 0x7fff;
465         cache->d_u_size.associativity = ((cache_d_reg >> 3) & 0x3ff) + 1;
466         /*  compute info for set way operation on cache */
467         cache->d_u_size.index_shift = (cache_d_reg & 0x7) + 4;
468         cache->d_u_size.index = (cache_d_reg >> 13) & 0x7fff;
469         cache->d_u_size.way = ((cache_d_reg >> 3) & 0x3ff);
470         cache->d_u_size.way_shift = cache->d_u_size.way + 1;
471         {
472                 int i = 0;
473                 while (((cache->d_u_size.way_shift >> i) & 1) != 1)
474                         i++;
475                 cache->d_u_size.way_shift = 32-i;
476         }
477 #if 0
478         LOG_INFO("data cache index %d << %d, way %d << %d",
479                         cache->d_u_size.index, cache->d_u_size.index_shift,
480                         cache->d_u_size.way,
481                         cache->d_u_size.way_shift);
482
483         LOG_INFO("data cache %d bytes %d KBytes asso %d ways",
484                         cache->d_u_size.linelen,
485                         cache->d_u_size.cachesize,
486                         cache->d_u_size.associativity);
487 #endif
488         cache->i_size.linelen = 16 << (cache_i_reg & 0x7);
489         cache->i_size.associativity = ((cache_i_reg >> 3) & 0x3ff) + 1;
490         cache->i_size.nsets = (cache_i_reg >> 13) & 0x7fff;
491         cache->i_size.cachesize = (((cache_i_reg >> 13) & 0x7fff)+1)/8;
492         /*  compute info for set way operation on cache */
493         cache->i_size.index_shift = (cache_i_reg & 0x7) + 4;
494         cache->i_size.index = (cache_i_reg >> 13) & 0x7fff;
495         cache->i_size.way = ((cache_i_reg >> 3) & 0x3ff);
496         cache->i_size.way_shift = cache->i_size.way + 1;
497         {
498                 int i = 0;
499                 while (((cache->i_size.way_shift >> i) & 1) != 1)
500                         i++;
501                 cache->i_size.way_shift = 32-i;
502         }
503 #if 0
504         LOG_INFO("instruction cache index %d << %d, way %d << %d",
505                         cache->i_size.index, cache->i_size.index_shift,
506                         cache->i_size.way, cache->i_size.way_shift);
507
508         LOG_INFO("instruction cache %d bytes %d KBytes asso %d ways",
509                         cache->i_size.linelen,
510                         cache->i_size.cachesize,
511                         cache->i_size.associativity);
512 #endif
513         /*  if no l2 cache initialize l1 data cache flush function function */
514         if (armv8->armv8_mmu.armv8_cache.flush_all_data_cache == NULL) {
515                 armv8->armv8_mmu.armv8_cache.display_cache_info =
516                         armv8_handle_inner_cache_info_command;
517                 armv8->armv8_mmu.armv8_cache.flush_all_data_cache =
518                         armv8_flush_all_data;
519         }
520         armv8->armv8_mmu.armv8_cache.ctype = 0;
521
522 done:
523         dpm->finish(dpm);
524         armv8_read_mpidr(target);
525         return retval;
526
527 }
528
529 int armv8_init_arch_info(struct target *target, struct armv8_common *armv8)
530 {
531         struct arm *arm = &armv8->arm;
532         arm->arch_info = armv8;
533         target->arch_info = &armv8->arm;
534         /*  target is useful in all function arm v4 5 compatible */
535         armv8->arm.target = target;
536         armv8->arm.common_magic = ARM_COMMON_MAGIC;
537         armv8->common_magic = ARMV8_COMMON_MAGIC;
538
539         arm->read_core_reg = armv8_read_core_reg;
540 #if 0
541         arm->write_core_reg = armv8_write_core_reg;
542 #endif
543
544         armv8->armv8_mmu.armv8_cache.l2_cache = NULL;
545         armv8->armv8_mmu.armv8_cache.ctype = -1;
546         armv8->armv8_mmu.armv8_cache.flush_all_data_cache = NULL;
547         armv8->armv8_mmu.armv8_cache.display_cache_info = NULL;
548         return ERROR_OK;
549 }
550
551 int armv8_arch_state(struct target *target)
552 {
553         static const char * const state[] = {
554                 "disabled", "enabled"
555         };
556
557         struct armv8_common *armv8 = target_to_armv8(target);
558         struct arm *arm = &armv8->arm;
559
560         if (armv8->common_magic != ARMV8_COMMON_MAGIC) {
561                 LOG_ERROR("BUG: called for a non-Armv8 target");
562                 return ERROR_COMMAND_SYNTAX_ERROR;
563         }
564
565         arm_arch_state(target);
566
567         if (armv8->is_armv7r) {
568                 LOG_USER("D-Cache: %s, I-Cache: %s",
569                         state[armv8->armv8_mmu.armv8_cache.d_u_cache_enabled],
570                         state[armv8->armv8_mmu.armv8_cache.i_cache_enabled]);
571         } else {
572                 LOG_USER("MMU: %s, D-Cache: %s, I-Cache: %s",
573                         state[armv8->armv8_mmu.mmu_enabled],
574                         state[armv8->armv8_mmu.armv8_cache.d_u_cache_enabled],
575                         state[armv8->armv8_mmu.armv8_cache.i_cache_enabled]);
576         }
577
578         if (arm->core_mode == ARM_MODE_ABT)
579                 armv8_show_fault_registers(target);
580         if (target->debug_reason == DBG_REASON_WATCHPOINT)
581                 LOG_USER("Watchpoint triggered at PC %#08x",
582                         (unsigned) armv8->dpm.wp_pc);
583
584         return ERROR_OK;
585 }
586
587 static const struct {
588         unsigned id;
589         const char *name;
590         unsigned bits;
591         enum reg_type type;
592         const char *group;
593         const char *feature;
594 } armv8_regs[] = {
595         { ARMV8_R0,  "x0",  64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
596         { ARMV8_R1,  "x1",  64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
597         { ARMV8_R2,  "x2",  64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
598         { ARMV8_R3,  "x3",  64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
599         { ARMV8_R4,  "x4",  64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
600         { ARMV8_R5,  "x5",  64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
601         { ARMV8_R6,  "x6",  64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
602         { ARMV8_R7,  "x7",  64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
603         { ARMV8_R8,  "x8",  64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
604         { ARMV8_R9,  "x9",  64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
605         { ARMV8_R10, "x10", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
606         { ARMV8_R11, "x11", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
607         { ARMV8_R12, "x12", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
608         { ARMV8_R13, "x13", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
609         { ARMV8_R14, "x14", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
610         { ARMV8_R15, "x15", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
611         { ARMV8_R16, "x16", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
612         { ARMV8_R17, "x17", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
613         { ARMV8_R18, "x18", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
614         { ARMV8_R19, "x19", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
615         { ARMV8_R20, "x20", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
616         { ARMV8_R21, "x21", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
617         { ARMV8_R22, "x22", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
618         { ARMV8_R23, "x23", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
619         { ARMV8_R24, "x24", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
620         { ARMV8_R25, "x25", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
621         { ARMV8_R26, "x26", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
622         { ARMV8_R27, "x27", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
623         { ARMV8_R28, "x28", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
624         { ARMV8_R29, "x29", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
625         { ARMV8_R30, "x30", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
626
627         { ARMV8_R31, "sp", 64, REG_TYPE_DATA_PTR, "general", "org.gnu.gdb.aarch64.core" },
628         { ARMV8_PC,  "pc", 64, REG_TYPE_CODE_PTR, "general", "org.gnu.gdb.aarch64.core" },
629
630         { ARMV8_xPSR, "CPSR", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
631 };
632
633 #define ARMV8_NUM_REGS ARRAY_SIZE(armv8_regs)
634
635
636 static int armv8_get_core_reg(struct reg *reg)
637 {
638         int retval;
639         struct arm_reg *armv8_reg = reg->arch_info;
640         struct target *target = armv8_reg->target;
641         struct arm *arm = target_to_arm(target);
642
643         if (target->state != TARGET_HALTED)
644                 return ERROR_TARGET_NOT_HALTED;
645
646         retval = arm->read_core_reg(target, reg, armv8_reg->num, arm->core_mode);
647
648         return retval;
649 }
650
651 static int armv8_set_core_reg(struct reg *reg, uint8_t *buf)
652 {
653         struct arm_reg *armv8_reg = reg->arch_info;
654         struct target *target = armv8_reg->target;
655         uint64_t value = buf_get_u64(buf, 0, 64);
656
657         if (target->state != TARGET_HALTED)
658                 return ERROR_TARGET_NOT_HALTED;
659
660         buf_set_u64(reg->value, 0, 64, value);
661         reg->dirty = 1;
662         reg->valid = 1;
663
664         return ERROR_OK;
665 }
666
667 static const struct reg_arch_type armv8_reg_type = {
668         .get = armv8_get_core_reg,
669         .set = armv8_set_core_reg,
670 };
671
672 /** Builds cache of architecturally defined registers.  */
673 struct reg_cache *armv8_build_reg_cache(struct target *target)
674 {
675         struct armv8_common *armv8 = target_to_armv8(target);
676         struct arm *arm = &armv8->arm;
677         int num_regs = ARMV8_NUM_REGS;
678         struct reg_cache **cache_p = register_get_last_cache_p(&target->reg_cache);
679         struct reg_cache *cache = malloc(sizeof(struct reg_cache));
680         struct reg *reg_list = calloc(num_regs, sizeof(struct reg));
681         struct arm_reg *arch_info = calloc(num_regs, sizeof(struct arm_reg));
682         struct reg_feature *feature;
683         int i;
684
685         /* Build the process context cache */
686         cache->name = "arm v8 registers";
687         cache->next = NULL;
688         cache->reg_list = reg_list;
689         cache->num_regs = num_regs;
690         (*cache_p) = cache;
691
692         for (i = 0; i < num_regs; i++) {
693                 arch_info[i].num = armv8_regs[i].id;
694                 arch_info[i].target = target;
695                 arch_info[i].arm = arm;
696
697                 reg_list[i].name = armv8_regs[i].name;
698                 reg_list[i].size = armv8_regs[i].bits;
699                 reg_list[i].value = calloc(1, 4);
700                 reg_list[i].dirty = 0;
701                 reg_list[i].valid = 0;
702                 reg_list[i].type = &armv8_reg_type;
703                 reg_list[i].arch_info = &arch_info[i];
704
705                 reg_list[i].group = armv8_regs[i].group;
706                 reg_list[i].number = i;
707                 reg_list[i].exist = true;
708                 reg_list[i].caller_save = true; /* gdb defaults to true */
709
710                 feature = calloc(1, sizeof(struct reg_feature));
711                 if (feature) {
712                         feature->name = armv8_regs[i].feature;
713                         reg_list[i].feature = feature;
714                 } else
715                         LOG_ERROR("unable to allocate feature list");
716
717                 reg_list[i].reg_data_type = calloc(1, sizeof(struct reg_data_type));
718                 if (reg_list[i].reg_data_type)
719                         reg_list[i].reg_data_type->type = armv8_regs[i].type;
720                 else
721                         LOG_ERROR("unable to allocate reg type list");
722         }
723
724         arm->cpsr = reg_list + ARMV8_xPSR;
725         arm->pc = reg_list + ARMV8_PC;
726         arm->core_cache = cache;
727
728         return cache;
729 }
730
731 struct reg *armv8_reg_current(struct arm *arm, unsigned regnum)
732 {
733         struct reg *r;
734
735         if (regnum > 33)
736                 return NULL;
737
738         r = arm->core_cache->reg_list + regnum;
739         return r;
740 }
741
742 const struct command_registration armv8_command_handlers[] = {
743         {
744                 .chain = dap_command_handlers,
745         },
746         COMMAND_REGISTRATION_DONE
747 };
748
749
750 int armv8_get_gdb_reg_list(struct target *target,
751         struct reg **reg_list[], int *reg_list_size,
752         enum target_register_class reg_class)
753 {
754         struct arm *arm = target_to_arm(target);
755         int i;
756
757         switch (reg_class) {
758         case REG_CLASS_GENERAL:
759         case REG_CLASS_ALL:
760                 *reg_list_size = 34;
761                 *reg_list = malloc(sizeof(struct reg *) * (*reg_list_size));
762
763                 for (i = 0; i < *reg_list_size; i++)
764                                 (*reg_list)[i] = armv8_reg_current(arm, i);
765
766                 return ERROR_OK;
767                 break;
768
769         default:
770                 LOG_ERROR("not a valid register class type in query.");
771                 return ERROR_FAIL;
772                 break;
773         }
774 }