1
2
3
4
5
6
7
8
9#include "qemu/osdep.h"
10#include "qemu/log.h"
11#include "trace.h"
12#include "cpu.h"
13#include "internals.h"
14#include "exec/helper-proto.h"
15#include "qemu/main-loop.h"
16#include "qemu/timer.h"
17#include "qemu/bitops.h"
18#include "qemu/crc32c.h"
19#include "qemu/qemu-print.h"
20#include "exec/exec-all.h"
21#include <zlib.h>
22#include "hw/irq.h"
23#include "sysemu/cpu-timers.h"
24#include "sysemu/kvm.h"
25#include "sysemu/tcg.h"
26#include "qapi/error.h"
27#include "qemu/guest-random.h"
28#ifdef CONFIG_TCG
29#include "semihosting/common-semi.h"
30#endif
31#include "cpregs.h"
32
33#define ARM_CPU_FREQ 1000000000
34
35static void switch_mode(CPUARMState *env, int mode);
36
37static uint64_t raw_read(CPUARMState *env, const ARMCPRegInfo *ri)
38{
39 assert(ri->fieldoffset);
40 if (cpreg_field_is_64bit(ri)) {
41 return CPREG_FIELD64(env, ri);
42 } else {
43 return CPREG_FIELD32(env, ri);
44 }
45}
46
47void raw_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
48{
49 assert(ri->fieldoffset);
50 if (cpreg_field_is_64bit(ri)) {
51 CPREG_FIELD64(env, ri) = value;
52 } else {
53 CPREG_FIELD32(env, ri) = value;
54 }
55}
56
57static void *raw_ptr(CPUARMState *env, const ARMCPRegInfo *ri)
58{
59 return (char *)env + ri->fieldoffset;
60}
61
62uint64_t read_raw_cp_reg(CPUARMState *env, const ARMCPRegInfo *ri)
63{
64
65 if (ri->type & ARM_CP_CONST) {
66 return ri->resetvalue;
67 } else if (ri->raw_readfn) {
68 return ri->raw_readfn(env, ri);
69 } else if (ri->readfn) {
70 return ri->readfn(env, ri);
71 } else {
72 return raw_read(env, ri);
73 }
74}
75
76static void write_raw_cp_reg(CPUARMState *env, const ARMCPRegInfo *ri,
77 uint64_t v)
78{
79
80
81
82
83
84
85 if (ri->type & ARM_CP_CONST) {
86 return;
87 } else if (ri->raw_writefn) {
88 ri->raw_writefn(env, ri, v);
89 } else if (ri->writefn) {
90 ri->writefn(env, ri, v);
91 } else {
92 raw_write(env, ri, v);
93 }
94}
95
96static bool raw_accessors_invalid(const ARMCPRegInfo *ri)
97{
98
99
100
101
102
103
104
105
106
107
108
109
110 if ((ri->type & ARM_CP_CONST) ||
111 ri->fieldoffset ||
112 ((ri->raw_writefn || ri->writefn) && (ri->raw_readfn || ri->readfn))) {
113 return false;
114 }
115 return true;
116}
117
118bool write_cpustate_to_list(ARMCPU *cpu, bool kvm_sync)
119{
120
121 int i;
122 bool ok = true;
123
124 for (i = 0; i < cpu->cpreg_array_len; i++) {
125 uint32_t regidx = kvm_to_cpreg_id(cpu->cpreg_indexes[i]);
126 const ARMCPRegInfo *ri;
127 uint64_t newval;
128
129 ri = get_arm_cp_reginfo(cpu->cp_regs, regidx);
130 if (!ri) {
131 ok = false;
132 continue;
133 }
134 if (ri->type & ARM_CP_NO_RAW) {
135 continue;
136 }
137
138 newval = read_raw_cp_reg(&cpu->env, ri);
139 if (kvm_sync) {
140
141
142
143
144
145
146 uint64_t oldval = cpu->cpreg_values[i];
147
148 if (oldval == newval) {
149 continue;
150 }
151
152 write_raw_cp_reg(&cpu->env, ri, oldval);
153 if (read_raw_cp_reg(&cpu->env, ri) != oldval) {
154 continue;
155 }
156
157 write_raw_cp_reg(&cpu->env, ri, newval);
158 }
159 cpu->cpreg_values[i] = newval;
160 }
161 return ok;
162}
163
164bool write_list_to_cpustate(ARMCPU *cpu)
165{
166 int i;
167 bool ok = true;
168
169 for (i = 0; i < cpu->cpreg_array_len; i++) {
170 uint32_t regidx = kvm_to_cpreg_id(cpu->cpreg_indexes[i]);
171 uint64_t v = cpu->cpreg_values[i];
172 const ARMCPRegInfo *ri;
173
174 ri = get_arm_cp_reginfo(cpu->cp_regs, regidx);
175 if (!ri) {
176 ok = false;
177 continue;
178 }
179 if (ri->type & ARM_CP_NO_RAW) {
180 continue;
181 }
182
183
184
185
186
187 write_raw_cp_reg(&cpu->env, ri, v);
188 if (read_raw_cp_reg(&cpu->env, ri) != v) {
189 ok = false;
190 }
191 }
192 return ok;
193}
194
195static void add_cpreg_to_list(gpointer key, gpointer opaque)
196{
197 ARMCPU *cpu = opaque;
198 uint32_t regidx = (uintptr_t)key;
199 const ARMCPRegInfo *ri = get_arm_cp_reginfo(cpu->cp_regs, regidx);
200
201 if (!(ri->type & (ARM_CP_NO_RAW | ARM_CP_ALIAS))) {
202 cpu->cpreg_indexes[cpu->cpreg_array_len] = cpreg_to_kvm_id(regidx);
203
204 cpu->cpreg_array_len++;
205 }
206}
207
208static void count_cpreg(gpointer key, gpointer opaque)
209{
210 ARMCPU *cpu = opaque;
211 const ARMCPRegInfo *ri;
212
213 ri = g_hash_table_lookup(cpu->cp_regs, key);
214
215 if (!(ri->type & (ARM_CP_NO_RAW | ARM_CP_ALIAS))) {
216 cpu->cpreg_array_len++;
217 }
218}
219
220static gint cpreg_key_compare(gconstpointer a, gconstpointer b)
221{
222 uint64_t aidx = cpreg_to_kvm_id((uintptr_t)a);
223 uint64_t bidx = cpreg_to_kvm_id((uintptr_t)b);
224
225 if (aidx > bidx) {
226 return 1;
227 }
228 if (aidx < bidx) {
229 return -1;
230 }
231 return 0;
232}
233
234void init_cpreg_list(ARMCPU *cpu)
235{
236
237
238
239
240 GList *keys;
241 int arraylen;
242
243 keys = g_hash_table_get_keys(cpu->cp_regs);
244 keys = g_list_sort(keys, cpreg_key_compare);
245
246 cpu->cpreg_array_len = 0;
247
248 g_list_foreach(keys, count_cpreg, cpu);
249
250 arraylen = cpu->cpreg_array_len;
251 cpu->cpreg_indexes = g_new(uint64_t, arraylen);
252 cpu->cpreg_values = g_new(uint64_t, arraylen);
253 cpu->cpreg_vmstate_indexes = g_new(uint64_t, arraylen);
254 cpu->cpreg_vmstate_values = g_new(uint64_t, arraylen);
255 cpu->cpreg_vmstate_array_len = cpu->cpreg_array_len;
256 cpu->cpreg_array_len = 0;
257
258 g_list_foreach(keys, add_cpreg_to_list, cpu);
259
260 assert(cpu->cpreg_array_len == arraylen);
261
262 g_list_free(keys);
263}
264
265
266
267
268static CPAccessResult access_el3_aa32ns(CPUARMState *env,
269 const ARMCPRegInfo *ri,
270 bool isread)
271{
272 if (!is_a64(env) && arm_current_el(env) == 3 &&
273 arm_is_secure_below_el3(env)) {
274 return CP_ACCESS_TRAP_UNCATEGORIZED;
275 }
276 return CP_ACCESS_OK;
277}
278
279
280
281
282
283
284
285static CPAccessResult access_trap_aa32s_el1(CPUARMState *env,
286 const ARMCPRegInfo *ri,
287 bool isread)
288{
289 if (arm_current_el(env) == 3) {
290 return CP_ACCESS_OK;
291 }
292 if (arm_is_secure_below_el3(env)) {
293 if (env->cp15.scr_el3 & SCR_EEL2) {
294 return CP_ACCESS_TRAP_EL2;
295 }
296 return CP_ACCESS_TRAP_EL3;
297 }
298
299 return CP_ACCESS_TRAP_UNCATEGORIZED;
300}
301
302
303
304
305
306static CPAccessResult access_tpm(CPUARMState *env, const ARMCPRegInfo *ri,
307 bool isread)
308{
309 int el = arm_current_el(env);
310 uint64_t mdcr_el2 = arm_mdcr_el2_eff(env);
311
312 if (el < 2 && (mdcr_el2 & MDCR_TPM)) {
313 return CP_ACCESS_TRAP_EL2;
314 }
315 if (el < 3 && (env->cp15.mdcr_el3 & MDCR_TPM)) {
316 return CP_ACCESS_TRAP_EL3;
317 }
318 return CP_ACCESS_OK;
319}
320
321
322static CPAccessResult access_tvm_trvm(CPUARMState *env, const ARMCPRegInfo *ri,
323 bool isread)
324{
325 if (arm_current_el(env) == 1) {
326 uint64_t trap = isread ? HCR_TRVM : HCR_TVM;
327 if (arm_hcr_el2_eff(env) & trap) {
328 return CP_ACCESS_TRAP_EL2;
329 }
330 }
331 return CP_ACCESS_OK;
332}
333
334
335static CPAccessResult access_tsw(CPUARMState *env, const ARMCPRegInfo *ri,
336 bool isread)
337{
338 if (arm_current_el(env) == 1 && (arm_hcr_el2_eff(env) & HCR_TSW)) {
339 return CP_ACCESS_TRAP_EL2;
340 }
341 return CP_ACCESS_OK;
342}
343
344
345static CPAccessResult access_tacr(CPUARMState *env, const ARMCPRegInfo *ri,
346 bool isread)
347{
348 if (arm_current_el(env) == 1 && (arm_hcr_el2_eff(env) & HCR_TACR)) {
349 return CP_ACCESS_TRAP_EL2;
350 }
351 return CP_ACCESS_OK;
352}
353
354
355static CPAccessResult access_ttlb(CPUARMState *env, const ARMCPRegInfo *ri,
356 bool isread)
357{
358 if (arm_current_el(env) == 1 && (arm_hcr_el2_eff(env) & HCR_TTLB)) {
359 return CP_ACCESS_TRAP_EL2;
360 }
361 return CP_ACCESS_OK;
362}
363
364
365static CPAccessResult access_ttlbis(CPUARMState *env, const ARMCPRegInfo *ri,
366 bool isread)
367{
368 if (arm_current_el(env) == 1 &&
369 (arm_hcr_el2_eff(env) & (HCR_TTLB | HCR_TTLBIS))) {
370 return CP_ACCESS_TRAP_EL2;
371 }
372 return CP_ACCESS_OK;
373}
374
375#ifdef TARGET_AARCH64
376
377static CPAccessResult access_ttlbos(CPUARMState *env, const ARMCPRegInfo *ri,
378 bool isread)
379{
380 if (arm_current_el(env) == 1 &&
381 (arm_hcr_el2_eff(env) & (HCR_TTLB | HCR_TTLBOS))) {
382 return CP_ACCESS_TRAP_EL2;
383 }
384 return CP_ACCESS_OK;
385}
386#endif
387
388static void dacr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
389{
390 ARMCPU *cpu = env_archcpu(env);
391
392 raw_write(env, ri, value);
393 tlb_flush(CPU(cpu));
394}
395
396static void fcse_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
397{
398 ARMCPU *cpu = env_archcpu(env);
399
400 if (raw_read(env, ri) != value) {
401
402
403
404
405 tlb_flush(CPU(cpu));
406 raw_write(env, ri, value);
407 }
408}
409
410static void contextidr_write(CPUARMState *env, const ARMCPRegInfo *ri,
411 uint64_t value)
412{
413 ARMCPU *cpu = env_archcpu(env);
414
415 if (raw_read(env, ri) != value && !arm_feature(env, ARM_FEATURE_PMSA)
416 && !extended_addresses_enabled(env)) {
417
418
419
420
421
422 tlb_flush(CPU(cpu));
423 }
424 raw_write(env, ri, value);
425}
426
427static int alle1_tlbmask(CPUARMState *env)
428{
429
430
431
432
433
434 return (ARMMMUIdxBit_E10_1 |
435 ARMMMUIdxBit_E10_1_PAN |
436 ARMMMUIdxBit_E10_0 |
437 ARMMMUIdxBit_Stage2 |
438 ARMMMUIdxBit_Stage2_S);
439}
440
441
442
443static void tlbiall_is_write(CPUARMState *env, const ARMCPRegInfo *ri,
444 uint64_t value)
445{
446 CPUState *cs = env_cpu(env);
447
448 tlb_flush_all_cpus_synced(cs);
449}
450
451static void tlbiasid_is_write(CPUARMState *env, const ARMCPRegInfo *ri,
452 uint64_t value)
453{
454 CPUState *cs = env_cpu(env);
455
456 tlb_flush_all_cpus_synced(cs);
457}
458
459static void tlbimva_is_write(CPUARMState *env, const ARMCPRegInfo *ri,
460 uint64_t value)
461{
462 CPUState *cs = env_cpu(env);
463
464 tlb_flush_page_all_cpus_synced(cs, value & TARGET_PAGE_MASK);
465}
466
467static void tlbimvaa_is_write(CPUARMState *env, const ARMCPRegInfo *ri,
468 uint64_t value)
469{
470 CPUState *cs = env_cpu(env);
471
472 tlb_flush_page_all_cpus_synced(cs, value & TARGET_PAGE_MASK);
473}
474
475
476
477
478
479
480static bool tlb_force_broadcast(CPUARMState *env)
481{
482 return arm_current_el(env) == 1 && (arm_hcr_el2_eff(env) & HCR_FB);
483}
484
485static void tlbiall_write(CPUARMState *env, const ARMCPRegInfo *ri,
486 uint64_t value)
487{
488
489 CPUState *cs = env_cpu(env);
490
491 if (tlb_force_broadcast(env)) {
492 tlb_flush_all_cpus_synced(cs);
493 } else {
494 tlb_flush(cs);
495 }
496}
497
498static void tlbimva_write(CPUARMState *env, const ARMCPRegInfo *ri,
499 uint64_t value)
500{
501
502 CPUState *cs = env_cpu(env);
503
504 value &= TARGET_PAGE_MASK;
505 if (tlb_force_broadcast(env)) {
506 tlb_flush_page_all_cpus_synced(cs, value);
507 } else {
508 tlb_flush_page(cs, value);
509 }
510}
511
512static void tlbiasid_write(CPUARMState *env, const ARMCPRegInfo *ri,
513 uint64_t value)
514{
515
516 CPUState *cs = env_cpu(env);
517
518 if (tlb_force_broadcast(env)) {
519 tlb_flush_all_cpus_synced(cs);
520 } else {
521 tlb_flush(cs);
522 }
523}
524
525static void tlbimvaa_write(CPUARMState *env, const ARMCPRegInfo *ri,
526 uint64_t value)
527{
528
529 CPUState *cs = env_cpu(env);
530
531 value &= TARGET_PAGE_MASK;
532 if (tlb_force_broadcast(env)) {
533 tlb_flush_page_all_cpus_synced(cs, value);
534 } else {
535 tlb_flush_page(cs, value);
536 }
537}
538
539static void tlbiall_nsnh_write(CPUARMState *env, const ARMCPRegInfo *ri,
540 uint64_t value)
541{
542 CPUState *cs = env_cpu(env);
543
544 tlb_flush_by_mmuidx(cs, alle1_tlbmask(env));
545}
546
547static void tlbiall_nsnh_is_write(CPUARMState *env, const ARMCPRegInfo *ri,
548 uint64_t value)
549{
550 CPUState *cs = env_cpu(env);
551
552 tlb_flush_by_mmuidx_all_cpus_synced(cs, alle1_tlbmask(env));
553}
554
555
556static void tlbiall_hyp_write(CPUARMState *env, const ARMCPRegInfo *ri,
557 uint64_t value)
558{
559 CPUState *cs = env_cpu(env);
560
561 tlb_flush_by_mmuidx(cs, ARMMMUIdxBit_E2);
562}
563
564static void tlbiall_hyp_is_write(CPUARMState *env, const ARMCPRegInfo *ri,
565 uint64_t value)
566{
567 CPUState *cs = env_cpu(env);
568
569 tlb_flush_by_mmuidx_all_cpus_synced(cs, ARMMMUIdxBit_E2);
570}
571
572static void tlbimva_hyp_write(CPUARMState *env, const ARMCPRegInfo *ri,
573 uint64_t value)
574{
575 CPUState *cs = env_cpu(env);
576 uint64_t pageaddr = value & ~MAKE_64BIT_MASK(0, 12);
577
578 tlb_flush_page_by_mmuidx(cs, pageaddr, ARMMMUIdxBit_E2);
579}
580
581static void tlbimva_hyp_is_write(CPUARMState *env, const ARMCPRegInfo *ri,
582 uint64_t value)
583{
584 CPUState *cs = env_cpu(env);
585 uint64_t pageaddr = value & ~MAKE_64BIT_MASK(0, 12);
586
587 tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr,
588 ARMMMUIdxBit_E2);
589}
590
591static void tlbiipas2_hyp_write(CPUARMState *env, const ARMCPRegInfo *ri,
592 uint64_t value)
593{
594 CPUState *cs = env_cpu(env);
595 uint64_t pageaddr = (value & MAKE_64BIT_MASK(0, 28)) << 12;
596
597 tlb_flush_page_by_mmuidx(cs, pageaddr, ARMMMUIdxBit_Stage2);
598}
599
600static void tlbiipas2is_hyp_write(CPUARMState *env, const ARMCPRegInfo *ri,
601 uint64_t value)
602{
603 CPUState *cs = env_cpu(env);
604 uint64_t pageaddr = (value & MAKE_64BIT_MASK(0, 28)) << 12;
605
606 tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr, ARMMMUIdxBit_Stage2);
607}
608
609static const ARMCPRegInfo cp_reginfo[] = {
610
611
612
613
614
615
616 { .name = "FCSEIDR",
617 .cp = 15, .opc1 = 0, .crn = 13, .crm = 0, .opc2 = 0,
618 .access = PL1_RW, .secure = ARM_CP_SECSTATE_NS,
619 .fieldoffset = offsetof(CPUARMState, cp15.fcseidr_ns),
620 .resetvalue = 0, .writefn = fcse_write, .raw_writefn = raw_write, },
621 { .name = "FCSEIDR_S",
622 .cp = 15, .opc1 = 0, .crn = 13, .crm = 0, .opc2 = 0,
623 .access = PL1_RW, .secure = ARM_CP_SECSTATE_S,
624 .fieldoffset = offsetof(CPUARMState, cp15.fcseidr_s),
625 .resetvalue = 0, .writefn = fcse_write, .raw_writefn = raw_write, },
626
627
628
629
630
631
632
633 { .name = "CONTEXTIDR_EL1", .state = ARM_CP_STATE_BOTH,
634 .opc0 = 3, .opc1 = 0, .crn = 13, .crm = 0, .opc2 = 1,
635 .access = PL1_RW, .accessfn = access_tvm_trvm,
636 .fgt = FGT_CONTEXTIDR_EL1,
637 .secure = ARM_CP_SECSTATE_NS,
638 .fieldoffset = offsetof(CPUARMState, cp15.contextidr_el[1]),
639 .resetvalue = 0, .writefn = contextidr_write, .raw_writefn = raw_write, },
640 { .name = "CONTEXTIDR_S", .state = ARM_CP_STATE_AA32,
641 .cp = 15, .opc1 = 0, .crn = 13, .crm = 0, .opc2 = 1,
642 .access = PL1_RW, .accessfn = access_tvm_trvm,
643 .secure = ARM_CP_SECSTATE_S,
644 .fieldoffset = offsetof(CPUARMState, cp15.contextidr_s),
645 .resetvalue = 0, .writefn = contextidr_write, .raw_writefn = raw_write, },
646};
647
648static const ARMCPRegInfo not_v8_cp_reginfo[] = {
649
650
651
652
653
654 { .name = "DACR",
655 .cp = 15, .opc1 = CP_ANY, .crn = 3, .crm = CP_ANY, .opc2 = CP_ANY,
656 .access = PL1_RW, .accessfn = access_tvm_trvm, .resetvalue = 0,
657 .writefn = dacr_write, .raw_writefn = raw_write,
658 .bank_fieldoffsets = { offsetoflow32(CPUARMState, cp15.dacr_s),
659 offsetoflow32(CPUARMState, cp15.dacr_ns) } },
660
661
662
663
664 { .name = "TLB_LOCKDOWN", .cp = 15, .crn = 10, .crm = 0,
665 .opc1 = CP_ANY, .opc2 = CP_ANY, .access = PL1_RW, .type = ARM_CP_NOP },
666 { .name = "TLB_LOCKDOWN", .cp = 15, .crn = 10, .crm = 1,
667 .opc1 = CP_ANY, .opc2 = CP_ANY, .access = PL1_RW, .type = ARM_CP_NOP },
668 { .name = "TLB_LOCKDOWN", .cp = 15, .crn = 10, .crm = 4,
669 .opc1 = CP_ANY, .opc2 = CP_ANY, .access = PL1_RW, .type = ARM_CP_NOP },
670 { .name = "TLB_LOCKDOWN", .cp = 15, .crn = 10, .crm = 8,
671 .opc1 = CP_ANY, .opc2 = CP_ANY, .access = PL1_RW, .type = ARM_CP_NOP },
672
673 { .name = "CACHEMAINT", .cp = 15, .crn = 7, .crm = CP_ANY,
674 .opc1 = 0, .opc2 = CP_ANY, .access = PL1_W,
675 .type = ARM_CP_NOP | ARM_CP_OVERRIDE },
676};
677
678static const ARMCPRegInfo not_v6_cp_reginfo[] = {
679
680
681
682
683 { .name = "WFI_v5", .cp = 15, .crn = 7, .crm = 8, .opc1 = 0, .opc2 = 2,
684 .access = PL1_W, .type = ARM_CP_WFI },
685};
686
687static const ARMCPRegInfo not_v7_cp_reginfo[] = {
688
689
690
691
692 { .name = "WFI_v6", .cp = 15, .crn = 7, .crm = 0, .opc1 = 0, .opc2 = 4,
693 .access = PL1_W, .type = ARM_CP_WFI },
694
695
696
697
698
699 { .name = "DLOCKDOWN", .cp = 15, .crn = 9, .crm = 0, .opc1 = 0, .opc2 = 0,
700 .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.c9_data),
701 .resetvalue = 0 },
702 { .name = "ILOCKDOWN", .cp = 15, .crn = 9, .crm = 0, .opc1 = 0, .opc2 = 1,
703 .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.c9_insn),
704 .resetvalue = 0 },
705
706 { .name = "DUMMY", .cp = 15, .crn = 0, .crm = 0, .opc1 = 1, .opc2 = CP_ANY,
707 .access = PL1_R, .type = ARM_CP_CONST | ARM_CP_NO_RAW,
708 .resetvalue = 0 },
709
710
711
712
713
714
715 { .name = "DBGDIDR", .cp = 14, .crn = 0, .crm = 0, .opc1 = 0, .opc2 = 0,
716 .access = PL0_R, .type = ARM_CP_CONST, .resetvalue = 0 },
717
718
719
720
721 { .name = "TLBIALL", .cp = 15, .crn = 8, .crm = CP_ANY,
722 .opc1 = CP_ANY, .opc2 = 0, .access = PL1_W, .writefn = tlbiall_write,
723 .type = ARM_CP_NO_RAW },
724 { .name = "TLBIMVA", .cp = 15, .crn = 8, .crm = CP_ANY,
725 .opc1 = CP_ANY, .opc2 = 1, .access = PL1_W, .writefn = tlbimva_write,
726 .type = ARM_CP_NO_RAW },
727 { .name = "TLBIASID", .cp = 15, .crn = 8, .crm = CP_ANY,
728 .opc1 = CP_ANY, .opc2 = 2, .access = PL1_W, .writefn = tlbiasid_write,
729 .type = ARM_CP_NO_RAW },
730 { .name = "TLBIMVAA", .cp = 15, .crn = 8, .crm = CP_ANY,
731 .opc1 = CP_ANY, .opc2 = 3, .access = PL1_W, .writefn = tlbimvaa_write,
732 .type = ARM_CP_NO_RAW },
733 { .name = "PRRR", .cp = 15, .crn = 10, .crm = 2,
734 .opc1 = 0, .opc2 = 0, .access = PL1_RW, .type = ARM_CP_NOP },
735 { .name = "NMRR", .cp = 15, .crn = 10, .crm = 2,
736 .opc1 = 0, .opc2 = 1, .access = PL1_RW, .type = ARM_CP_NOP },
737};
738
739static void cpacr_write(CPUARMState *env, const ARMCPRegInfo *ri,
740 uint64_t value)
741{
742 uint32_t mask = 0;
743
744
745 if (!arm_feature(env, ARM_FEATURE_V8)) {
746
747
748
749
750
751 if (cpu_isar_feature(aa32_vfp_simd, env_archcpu(env))) {
752
753 mask |= R_CPACR_ASEDIS_MASK |
754 R_CPACR_D32DIS_MASK |
755 R_CPACR_CP11_MASK |
756 R_CPACR_CP10_MASK;
757
758 if (!arm_feature(env, ARM_FEATURE_NEON)) {
759
760 value |= R_CPACR_ASEDIS_MASK;
761 }
762
763
764
765
766
767 if (!cpu_isar_feature(aa32_simd_r32, env_archcpu(env))) {
768
769 value |= R_CPACR_D32DIS_MASK;
770 }
771 }
772 value &= mask;
773 }
774
775
776
777
778
779 if (arm_feature(env, ARM_FEATURE_EL3) && !arm_el_is_aa64(env, 3) &&
780 !arm_is_secure(env) && !extract32(env->cp15.nsacr, 10, 1)) {
781 mask = R_CPACR_CP11_MASK | R_CPACR_CP10_MASK;
782 value = (value & ~mask) | (env->cp15.cpacr_el1 & mask);
783 }
784
785 env->cp15.cpacr_el1 = value;
786}
787
788static uint64_t cpacr_read(CPUARMState *env, const ARMCPRegInfo *ri)
789{
790
791
792
793
794 uint64_t value = env->cp15.cpacr_el1;
795
796 if (arm_feature(env, ARM_FEATURE_EL3) && !arm_el_is_aa64(env, 3) &&
797 !arm_is_secure(env) && !extract32(env->cp15.nsacr, 10, 1)) {
798 value = ~(R_CPACR_CP11_MASK | R_CPACR_CP10_MASK);
799 }
800 return value;
801}
802
803
804static void cpacr_reset(CPUARMState *env, const ARMCPRegInfo *ri)
805{
806
807
808
809
810 cpacr_write(env, ri, 0);
811}
812
813static CPAccessResult cpacr_access(CPUARMState *env, const ARMCPRegInfo *ri,
814 bool isread)
815{
816 if (arm_feature(env, ARM_FEATURE_V8)) {
817
818 if (arm_current_el(env) == 1 && arm_is_el2_enabled(env) &&
819 FIELD_EX64(env->cp15.cptr_el[2], CPTR_EL2, TCPAC)) {
820 return CP_ACCESS_TRAP_EL2;
821
822 } else if (arm_current_el(env) < 3 &&
823 FIELD_EX64(env->cp15.cptr_el[3], CPTR_EL3, TCPAC)) {
824 return CP_ACCESS_TRAP_EL3;
825 }
826 }
827
828 return CP_ACCESS_OK;
829}
830
831static CPAccessResult cptr_access(CPUARMState *env, const ARMCPRegInfo *ri,
832 bool isread)
833{
834
835 if (arm_current_el(env) == 2 &&
836 FIELD_EX64(env->cp15.cptr_el[3], CPTR_EL3, TCPAC)) {
837 return CP_ACCESS_TRAP_EL3;
838 }
839
840 return CP_ACCESS_OK;
841}
842
843static const ARMCPRegInfo v6_cp_reginfo[] = {
844
845 { .name = "MVA_prefetch",
846 .cp = 15, .crn = 7, .crm = 13, .opc1 = 0, .opc2 = 1,
847 .access = PL1_W, .type = ARM_CP_NOP },
848
849
850
851
852
853 { .name = "ISB", .cp = 15, .crn = 7, .crm = 5, .opc1 = 0, .opc2 = 4,
854 .access = PL0_W, .type = ARM_CP_NO_RAW, .writefn = arm_cp_write_ignore },
855 { .name = "DSB", .cp = 15, .crn = 7, .crm = 10, .opc1 = 0, .opc2 = 4,
856 .access = PL0_W, .type = ARM_CP_NOP },
857 { .name = "DMB", .cp = 15, .crn = 7, .crm = 10, .opc1 = 0, .opc2 = 5,
858 .access = PL0_W, .type = ARM_CP_NOP },
859 { .name = "IFAR", .cp = 15, .crn = 6, .crm = 0, .opc1 = 0, .opc2 = 2,
860 .access = PL1_RW, .accessfn = access_tvm_trvm,
861 .bank_fieldoffsets = { offsetof(CPUARMState, cp15.ifar_s),
862 offsetof(CPUARMState, cp15.ifar_ns) },
863 .resetvalue = 0, },
864
865
866
867
868 { .name = "WFAR", .cp = 15, .crn = 6, .crm = 0, .opc1 = 0, .opc2 = 1,
869 .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0, },
870 { .name = "CPACR", .state = ARM_CP_STATE_BOTH, .opc0 = 3,
871 .crn = 1, .crm = 0, .opc1 = 0, .opc2 = 2, .accessfn = cpacr_access,
872 .fgt = FGT_CPACR_EL1,
873 .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.cpacr_el1),
874 .resetfn = cpacr_reset, .writefn = cpacr_write, .readfn = cpacr_read },
875};
876
877typedef struct pm_event {
878 uint16_t number;
879
880 bool (*supported)(CPUARMState *);
881
882
883
884
885 uint64_t (*get_count)(CPUARMState *);
886
887
888
889
890
891
892 int64_t (*ns_per_count)(uint64_t);
893} pm_event;
894
895static bool event_always_supported(CPUARMState *env)
896{
897 return true;
898}
899
900static uint64_t swinc_get_count(CPUARMState *env)
901{
902
903
904
905
906 return 0;
907}
908
909static int64_t swinc_ns_per(uint64_t ignored)
910{
911 return -1;
912}
913
914
915
916
917
918static uint64_t cycles_get_count(CPUARMState *env)
919{
920#ifndef CONFIG_USER_ONLY
921 return muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL),
922 ARM_CPU_FREQ, NANOSECONDS_PER_SECOND);
923#else
924 return cpu_get_host_ticks();
925#endif
926}
927
928#ifndef CONFIG_USER_ONLY
929static int64_t cycles_ns_per(uint64_t cycles)
930{
931 return (ARM_CPU_FREQ / NANOSECONDS_PER_SECOND) * cycles;
932}
933
934static bool instructions_supported(CPUARMState *env)
935{
936 return icount_enabled() == 1;
937}
938
939static uint64_t instructions_get_count(CPUARMState *env)
940{
941 return (uint64_t)icount_get_raw();
942}
943
944static int64_t instructions_ns_per(uint64_t icount)
945{
946 return icount_to_ns((int64_t)icount);
947}
948#endif
949
950static bool pmuv3p1_events_supported(CPUARMState *env)
951{
952
953 return cpu_isar_feature(any_pmuv3p1, env_archcpu(env));
954}
955
956static bool pmuv3p4_events_supported(CPUARMState *env)
957{
958
959 return cpu_isar_feature(any_pmuv3p4, env_archcpu(env));
960}
961
962static uint64_t zero_event_get_count(CPUARMState *env)
963{
964
965 return 0;
966}
967
968static int64_t zero_event_ns_per(uint64_t cycles)
969{
970
971 return -1;
972}
973
974static const pm_event pm_events[] = {
975 { .number = 0x000,
976 .supported = event_always_supported,
977 .get_count = swinc_get_count,
978 .ns_per_count = swinc_ns_per,
979 },
980#ifndef CONFIG_USER_ONLY
981 { .number = 0x008,
982 .supported = instructions_supported,
983 .get_count = instructions_get_count,
984 .ns_per_count = instructions_ns_per,
985 },
986 { .number = 0x011,
987 .supported = event_always_supported,
988 .get_count = cycles_get_count,
989 .ns_per_count = cycles_ns_per,
990 },
991#endif
992 { .number = 0x023,
993 .supported = pmuv3p1_events_supported,
994 .get_count = zero_event_get_count,
995 .ns_per_count = zero_event_ns_per,
996 },
997 { .number = 0x024,
998 .supported = pmuv3p1_events_supported,
999 .get_count = zero_event_get_count,
1000 .ns_per_count = zero_event_ns_per,
1001 },
1002 { .number = 0x03c,
1003 .supported = pmuv3p4_events_supported,
1004 .get_count = zero_event_get_count,
1005 .ns_per_count = zero_event_ns_per,
1006 },
1007};
1008
1009
1010
1011
1012
1013
1014
1015#define MAX_EVENT_ID 0x3c
1016#define UNSUPPORTED_EVENT UINT16_MAX
1017static uint16_t supported_event_map[MAX_EVENT_ID + 1];
1018
1019
1020
1021
1022
1023
1024
1025void pmu_init(ARMCPU *cpu)
1026{
1027 unsigned int i;
1028
1029
1030
1031
1032
1033 for (i = 0; i < ARRAY_SIZE(supported_event_map); i++) {
1034 supported_event_map[i] = UNSUPPORTED_EVENT;
1035 }
1036 cpu->pmceid0 = 0;
1037 cpu->pmceid1 = 0;
1038
1039 for (i = 0; i < ARRAY_SIZE(pm_events); i++) {
1040 const pm_event *cnt = &pm_events[i];
1041 assert(cnt->number <= MAX_EVENT_ID);
1042
1043 assert(cnt->number <= 0x3f);
1044
1045 if (cnt->supported(&cpu->env)) {
1046 supported_event_map[cnt->number] = i;
1047 uint64_t event_mask = 1ULL << (cnt->number & 0x1f);
1048 if (cnt->number & 0x20) {
1049 cpu->pmceid1 |= event_mask;
1050 } else {
1051 cpu->pmceid0 |= event_mask;
1052 }
1053 }
1054 }
1055}
1056
1057
1058
1059
1060static bool event_supported(uint16_t number)
1061{
1062 if (number > MAX_EVENT_ID) {
1063 return false;
1064 }
1065 return supported_event_map[number] != UNSUPPORTED_EVENT;
1066}
1067
1068static CPAccessResult pmreg_access(CPUARMState *env, const ARMCPRegInfo *ri,
1069 bool isread)
1070{
1071
1072
1073
1074
1075
1076 int el = arm_current_el(env);
1077 uint64_t mdcr_el2 = arm_mdcr_el2_eff(env);
1078
1079 if (el == 0 && !(env->cp15.c9_pmuserenr & 1)) {
1080 return CP_ACCESS_TRAP;
1081 }
1082 if (el < 2 && (mdcr_el2 & MDCR_TPM)) {
1083 return CP_ACCESS_TRAP_EL2;
1084 }
1085 if (el < 3 && (env->cp15.mdcr_el3 & MDCR_TPM)) {
1086 return CP_ACCESS_TRAP_EL3;
1087 }
1088
1089 return CP_ACCESS_OK;
1090}
1091
1092static CPAccessResult pmreg_access_xevcntr(CPUARMState *env,
1093 const ARMCPRegInfo *ri,
1094 bool isread)
1095{
1096
1097 if (arm_feature(env, ARM_FEATURE_V8)
1098 && arm_current_el(env) == 0
1099 && (env->cp15.c9_pmuserenr & (1 << 3)) != 0
1100 && isread) {
1101 return CP_ACCESS_OK;
1102 }
1103
1104 return pmreg_access(env, ri, isread);
1105}
1106
1107static CPAccessResult pmreg_access_swinc(CPUARMState *env,
1108 const ARMCPRegInfo *ri,
1109 bool isread)
1110{
1111
1112 if (arm_feature(env, ARM_FEATURE_V8)
1113 && arm_current_el(env) == 0
1114 && (env->cp15.c9_pmuserenr & (1 << 1)) != 0
1115 && !isread) {
1116 return CP_ACCESS_OK;
1117 }
1118
1119 return pmreg_access(env, ri, isread);
1120}
1121
1122static CPAccessResult pmreg_access_selr(CPUARMState *env,
1123 const ARMCPRegInfo *ri,
1124 bool isread)
1125{
1126
1127 if (arm_feature(env, ARM_FEATURE_V8)
1128 && arm_current_el(env) == 0
1129 && (env->cp15.c9_pmuserenr & (1 << 3)) != 0) {
1130 return CP_ACCESS_OK;
1131 }
1132
1133 return pmreg_access(env, ri, isread);
1134}
1135
1136static CPAccessResult pmreg_access_ccntr(CPUARMState *env,
1137 const ARMCPRegInfo *ri,
1138 bool isread)
1139{
1140
1141 if (arm_feature(env, ARM_FEATURE_V8)
1142 && arm_current_el(env) == 0
1143 && (env->cp15.c9_pmuserenr & (1 << 2)) != 0
1144 && isread) {
1145 return CP_ACCESS_OK;
1146 }
1147
1148 return pmreg_access(env, ri, isread);
1149}
1150
1151
1152
1153
1154
1155
1156#define MDCR_EL2_PMU_ENABLE_BITS \
1157 (MDCR_HPME | MDCR_HPMD | MDCR_HPMN | MDCR_HCCD | MDCR_HLP)
1158#define MDCR_EL3_PMU_ENABLE_BITS (MDCR_SPME | MDCR_SCCD)
1159
1160
1161
1162
1163
1164static bool pmu_counter_enabled(CPUARMState *env, uint8_t counter)
1165{
1166 uint64_t filter;
1167 bool e, p, u, nsk, nsu, nsh, m;
1168 bool enabled, prohibited = false, filtered;
1169 bool secure = arm_is_secure(env);
1170 int el = arm_current_el(env);
1171 uint64_t mdcr_el2 = arm_mdcr_el2_eff(env);
1172 uint8_t hpmn = mdcr_el2 & MDCR_HPMN;
1173
1174 if (!arm_feature(env, ARM_FEATURE_PMU)) {
1175 return false;
1176 }
1177
1178 if (!arm_feature(env, ARM_FEATURE_EL2) ||
1179 (counter < hpmn || counter == 31)) {
1180 e = env->cp15.c9_pmcr & PMCRE;
1181 } else {
1182 e = mdcr_el2 & MDCR_HPME;
1183 }
1184 enabled = e && (env->cp15.c9_pmcnten & (1 << counter));
1185
1186
1187 if (el == 2 && (counter < hpmn || counter == 31)) {
1188 prohibited = mdcr_el2 & MDCR_HPMD;
1189 }
1190 if (secure) {
1191 prohibited = prohibited || !(env->cp15.mdcr_el3 & MDCR_SPME);
1192 }
1193
1194 if (counter == 31) {
1195
1196
1197
1198
1199
1200 prohibited = prohibited && env->cp15.c9_pmcr & PMCRDP;
1201 if (cpu_isar_feature(any_pmuv3p5, env_archcpu(env))) {
1202 if (secure) {
1203 prohibited = prohibited || (env->cp15.mdcr_el3 & MDCR_SCCD);
1204 }
1205 if (el == 2) {
1206 prohibited = prohibited || (mdcr_el2 & MDCR_HCCD);
1207 }
1208 }
1209 }
1210
1211 if (counter == 31) {
1212 filter = env->cp15.pmccfiltr_el0;
1213 } else {
1214 filter = env->cp15.c14_pmevtyper[counter];
1215 }
1216
1217 p = filter & PMXEVTYPER_P;
1218 u = filter & PMXEVTYPER_U;
1219 nsk = arm_feature(env, ARM_FEATURE_EL3) && (filter & PMXEVTYPER_NSK);
1220 nsu = arm_feature(env, ARM_FEATURE_EL3) && (filter & PMXEVTYPER_NSU);
1221 nsh = arm_feature(env, ARM_FEATURE_EL2) && (filter & PMXEVTYPER_NSH);
1222 m = arm_el_is_aa64(env, 1) &&
1223 arm_feature(env, ARM_FEATURE_EL3) && (filter & PMXEVTYPER_M);
1224
1225 if (el == 0) {
1226 filtered = secure ? u : u != nsu;
1227 } else if (el == 1) {
1228 filtered = secure ? p : p != nsk;
1229 } else if (el == 2) {
1230 filtered = !nsh;
1231 } else {
1232 filtered = m != p;
1233 }
1234
1235 if (counter != 31) {
1236
1237
1238
1239
1240 uint16_t event = filter & PMXEVTYPER_EVTCOUNT;
1241 if (!event_supported(event)) {
1242 return false;
1243 }
1244 }
1245
1246 return enabled && !prohibited && !filtered;
1247}
1248
1249static void pmu_update_irq(CPUARMState *env)
1250{
1251 ARMCPU *cpu = env_archcpu(env);
1252 qemu_set_irq(cpu->pmu_interrupt, (env->cp15.c9_pmcr & PMCRE) &&
1253 (env->cp15.c9_pminten & env->cp15.c9_pmovsr));
1254}
1255
1256static bool pmccntr_clockdiv_enabled(CPUARMState *env)
1257{
1258
1259
1260
1261
1262
1263
1264 return (env->cp15.c9_pmcr & (PMCRD | PMCRLC)) == PMCRD;
1265}
1266
1267static bool pmevcntr_is_64_bit(CPUARMState *env, int counter)
1268{
1269
1270
1271
1272 assert(counter < 31);
1273
1274 if (!cpu_isar_feature(any_pmuv3p5, env_archcpu(env))) {
1275 return false;
1276 }
1277
1278 if (arm_feature(env, ARM_FEATURE_EL2)) {
1279
1280
1281
1282
1283 bool hlp = env->cp15.mdcr_el2 & MDCR_HLP;
1284 int hpmn = env->cp15.mdcr_el2 & MDCR_HPMN;
1285
1286 if (hpmn != 0 && counter >= hpmn) {
1287 return hlp;
1288 }
1289 }
1290 return env->cp15.c9_pmcr & PMCRLP;
1291}
1292
1293
1294
1295
1296
1297
1298
1299static void pmccntr_op_start(CPUARMState *env)
1300{
1301 uint64_t cycles = cycles_get_count(env);
1302
1303 if (pmu_counter_enabled(env, 31)) {
1304 uint64_t eff_cycles = cycles;
1305 if (pmccntr_clockdiv_enabled(env)) {
1306 eff_cycles /= 64;
1307 }
1308
1309 uint64_t new_pmccntr = eff_cycles - env->cp15.c15_ccnt_delta;
1310
1311 uint64_t overflow_mask = env->cp15.c9_pmcr & PMCRLC ? \
1312 1ull << 63 : 1ull << 31;
1313 if (env->cp15.c15_ccnt & ~new_pmccntr & overflow_mask) {
1314 env->cp15.c9_pmovsr |= (1ULL << 31);
1315 pmu_update_irq(env);
1316 }
1317
1318 env->cp15.c15_ccnt = new_pmccntr;
1319 }
1320 env->cp15.c15_ccnt_delta = cycles;
1321}
1322
1323
1324
1325
1326
1327
1328static void pmccntr_op_finish(CPUARMState *env)
1329{
1330 if (pmu_counter_enabled(env, 31)) {
1331#ifndef CONFIG_USER_ONLY
1332
1333 uint64_t remaining_cycles = -env->cp15.c15_ccnt;
1334 if (!(env->cp15.c9_pmcr & PMCRLC)) {
1335 remaining_cycles = (uint32_t)remaining_cycles;
1336 }
1337 int64_t overflow_in = cycles_ns_per(remaining_cycles);
1338
1339 if (overflow_in > 0) {
1340 int64_t overflow_at;
1341
1342 if (!sadd64_overflow(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL),
1343 overflow_in, &overflow_at)) {
1344 ARMCPU *cpu = env_archcpu(env);
1345 timer_mod_anticipate_ns(cpu->pmu_timer, overflow_at);
1346 }
1347 }
1348#endif
1349
1350 uint64_t prev_cycles = env->cp15.c15_ccnt_delta;
1351 if (pmccntr_clockdiv_enabled(env)) {
1352 prev_cycles /= 64;
1353 }
1354 env->cp15.c15_ccnt_delta = prev_cycles - env->cp15.c15_ccnt;
1355 }
1356}
1357
1358static void pmevcntr_op_start(CPUARMState *env, uint8_t counter)
1359{
1360
1361 uint16_t event = env->cp15.c14_pmevtyper[counter] & PMXEVTYPER_EVTCOUNT;
1362 uint64_t count = 0;
1363 if (event_supported(event)) {
1364 uint16_t event_idx = supported_event_map[event];
1365 count = pm_events[event_idx].get_count(env);
1366 }
1367
1368 if (pmu_counter_enabled(env, counter)) {
1369 uint64_t new_pmevcntr = count - env->cp15.c14_pmevcntr_delta[counter];
1370 uint64_t overflow_mask = pmevcntr_is_64_bit(env, counter) ?
1371 1ULL << 63 : 1ULL << 31;
1372
1373 if (env->cp15.c14_pmevcntr[counter] & ~new_pmevcntr & overflow_mask) {
1374 env->cp15.c9_pmovsr |= (1 << counter);
1375 pmu_update_irq(env);
1376 }
1377 env->cp15.c14_pmevcntr[counter] = new_pmevcntr;
1378 }
1379 env->cp15.c14_pmevcntr_delta[counter] = count;
1380}
1381
1382static void pmevcntr_op_finish(CPUARMState *env, uint8_t counter)
1383{
1384 if (pmu_counter_enabled(env, counter)) {
1385#ifndef CONFIG_USER_ONLY
1386 uint16_t event = env->cp15.c14_pmevtyper[counter] & PMXEVTYPER_EVTCOUNT;
1387 uint16_t event_idx = supported_event_map[event];
1388 uint64_t delta = -(env->cp15.c14_pmevcntr[counter] + 1);
1389 int64_t overflow_in;
1390
1391 if (!pmevcntr_is_64_bit(env, counter)) {
1392 delta = (uint32_t)delta;
1393 }
1394 overflow_in = pm_events[event_idx].ns_per_count(delta);
1395
1396 if (overflow_in > 0) {
1397 int64_t overflow_at;
1398
1399 if (!sadd64_overflow(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL),
1400 overflow_in, &overflow_at)) {
1401 ARMCPU *cpu = env_archcpu(env);
1402 timer_mod_anticipate_ns(cpu->pmu_timer, overflow_at);
1403 }
1404 }
1405#endif
1406
1407 env->cp15.c14_pmevcntr_delta[counter] -=
1408 env->cp15.c14_pmevcntr[counter];
1409 }
1410}
1411
1412void pmu_op_start(CPUARMState *env)
1413{
1414 unsigned int i;
1415 pmccntr_op_start(env);
1416 for (i = 0; i < pmu_num_counters(env); i++) {
1417 pmevcntr_op_start(env, i);
1418 }
1419}
1420
1421void pmu_op_finish(CPUARMState *env)
1422{
1423 unsigned int i;
1424 pmccntr_op_finish(env);
1425 for (i = 0; i < pmu_num_counters(env); i++) {
1426 pmevcntr_op_finish(env, i);
1427 }
1428}
1429
1430void pmu_pre_el_change(ARMCPU *cpu, void *ignored)
1431{
1432 pmu_op_start(&cpu->env);
1433}
1434
1435void pmu_post_el_change(ARMCPU *cpu, void *ignored)
1436{
1437 pmu_op_finish(&cpu->env);
1438}
1439
1440void arm_pmu_timer_cb(void *opaque)
1441{
1442 ARMCPU *cpu = opaque;
1443
1444
1445
1446
1447
1448
1449
1450 pmu_op_start(&cpu->env);
1451 pmu_op_finish(&cpu->env);
1452}
1453
1454static void pmcr_write(CPUARMState *env, const ARMCPRegInfo *ri,
1455 uint64_t value)
1456{
1457 pmu_op_start(env);
1458
1459 if (value & PMCRC) {
1460
1461 env->cp15.c15_ccnt = 0;
1462 }
1463
1464 if (value & PMCRP) {
1465 unsigned int i;
1466 for (i = 0; i < pmu_num_counters(env); i++) {
1467 env->cp15.c14_pmevcntr[i] = 0;
1468 }
1469 }
1470
1471 env->cp15.c9_pmcr &= ~PMCR_WRITABLE_MASK;
1472 env->cp15.c9_pmcr |= (value & PMCR_WRITABLE_MASK);
1473
1474 pmu_op_finish(env);
1475}
1476
1477static void pmswinc_write(CPUARMState *env, const ARMCPRegInfo *ri,
1478 uint64_t value)
1479{
1480 unsigned int i;
1481 uint64_t overflow_mask, new_pmswinc;
1482
1483 for (i = 0; i < pmu_num_counters(env); i++) {
1484
1485 if ((value & (1 << i)) &&
1486
1487 pmu_counter_enabled(env, i) &&
1488
1489 (env->cp15.c14_pmevtyper[i] & PMXEVTYPER_EVTCOUNT) == 0x0) {
1490 pmevcntr_op_start(env, i);
1491
1492
1493
1494
1495
1496 new_pmswinc = env->cp15.c14_pmevcntr[i] + 1;
1497
1498 overflow_mask = pmevcntr_is_64_bit(env, i) ?
1499 1ULL << 63 : 1ULL << 31;
1500
1501 if (env->cp15.c14_pmevcntr[i] & ~new_pmswinc & overflow_mask) {
1502 env->cp15.c9_pmovsr |= (1 << i);
1503 pmu_update_irq(env);
1504 }
1505
1506 env->cp15.c14_pmevcntr[i] = new_pmswinc;
1507
1508 pmevcntr_op_finish(env, i);
1509 }
1510 }
1511}
1512
1513static uint64_t pmccntr_read(CPUARMState *env, const ARMCPRegInfo *ri)
1514{
1515 uint64_t ret;
1516 pmccntr_op_start(env);
1517 ret = env->cp15.c15_ccnt;
1518 pmccntr_op_finish(env);
1519 return ret;
1520}
1521
1522static void pmselr_write(CPUARMState *env, const ARMCPRegInfo *ri,
1523 uint64_t value)
1524{
1525
1526
1527
1528
1529
1530
1531 env->cp15.c9_pmselr = value & 0x1f;
1532}
1533
1534static void pmccntr_write(CPUARMState *env, const ARMCPRegInfo *ri,
1535 uint64_t value)
1536{
1537 pmccntr_op_start(env);
1538 env->cp15.c15_ccnt = value;
1539 pmccntr_op_finish(env);
1540}
1541
1542static void pmccntr_write32(CPUARMState *env, const ARMCPRegInfo *ri,
1543 uint64_t value)
1544{
1545 uint64_t cur_val = pmccntr_read(env, NULL);
1546
1547 pmccntr_write(env, ri, deposit64(cur_val, 0, 32, value));
1548}
1549
1550static void pmccfiltr_write(CPUARMState *env, const ARMCPRegInfo *ri,
1551 uint64_t value)
1552{
1553 pmccntr_op_start(env);
1554 env->cp15.pmccfiltr_el0 = value & PMCCFILTR_EL0;
1555 pmccntr_op_finish(env);
1556}
1557
1558static void pmccfiltr_write_a32(CPUARMState *env, const ARMCPRegInfo *ri,
1559 uint64_t value)
1560{
1561 pmccntr_op_start(env);
1562
1563 env->cp15.pmccfiltr_el0 = (env->cp15.pmccfiltr_el0 & PMCCFILTR_M) |
1564 (value & PMCCFILTR);
1565 pmccntr_op_finish(env);
1566}
1567
1568static uint64_t pmccfiltr_read_a32(CPUARMState *env, const ARMCPRegInfo *ri)
1569{
1570
1571 return env->cp15.pmccfiltr_el0 & PMCCFILTR;
1572}
1573
1574static void pmcntenset_write(CPUARMState *env, const ARMCPRegInfo *ri,
1575 uint64_t value)
1576{
1577 pmu_op_start(env);
1578 value &= pmu_counter_mask(env);
1579 env->cp15.c9_pmcnten |= value;
1580 pmu_op_finish(env);
1581}
1582
1583static void pmcntenclr_write(CPUARMState *env, const ARMCPRegInfo *ri,
1584 uint64_t value)
1585{
1586 pmu_op_start(env);
1587 value &= pmu_counter_mask(env);
1588 env->cp15.c9_pmcnten &= ~value;
1589 pmu_op_finish(env);
1590}
1591
1592static void pmovsr_write(CPUARMState *env, const ARMCPRegInfo *ri,
1593 uint64_t value)
1594{
1595 value &= pmu_counter_mask(env);
1596 env->cp15.c9_pmovsr &= ~value;
1597 pmu_update_irq(env);
1598}
1599
1600static void pmovsset_write(CPUARMState *env, const ARMCPRegInfo *ri,
1601 uint64_t value)
1602{
1603 value &= pmu_counter_mask(env);
1604 env->cp15.c9_pmovsr |= value;
1605 pmu_update_irq(env);
1606}
1607
1608static void pmevtyper_write(CPUARMState *env, const ARMCPRegInfo *ri,
1609 uint64_t value, const uint8_t counter)
1610{
1611 if (counter == 31) {
1612 pmccfiltr_write(env, ri, value);
1613 } else if (counter < pmu_num_counters(env)) {
1614 pmevcntr_op_start(env, counter);
1615
1616
1617
1618
1619
1620
1621
1622 uint16_t old_event = env->cp15.c14_pmevtyper[counter] &
1623 PMXEVTYPER_EVTCOUNT;
1624 uint16_t new_event = value & PMXEVTYPER_EVTCOUNT;
1625 if (old_event != new_event) {
1626 uint64_t count = 0;
1627 if (event_supported(new_event)) {
1628 uint16_t event_idx = supported_event_map[new_event];
1629 count = pm_events[event_idx].get_count(env);
1630 }
1631 env->cp15.c14_pmevcntr_delta[counter] = count;
1632 }
1633
1634 env->cp15.c14_pmevtyper[counter] = value & PMXEVTYPER_MASK;
1635 pmevcntr_op_finish(env, counter);
1636 }
1637
1638
1639
1640
1641
1642}
1643
1644static uint64_t pmevtyper_read(CPUARMState *env, const ARMCPRegInfo *ri,
1645 const uint8_t counter)
1646{
1647 if (counter == 31) {
1648 return env->cp15.pmccfiltr_el0;
1649 } else if (counter < pmu_num_counters(env)) {
1650 return env->cp15.c14_pmevtyper[counter];
1651 } else {
1652
1653
1654
1655
1656 return 0;
1657 }
1658}
1659
1660static void pmevtyper_writefn(CPUARMState *env, const ARMCPRegInfo *ri,
1661 uint64_t value)
1662{
1663 uint8_t counter = ((ri->crm & 3) << 3) | (ri->opc2 & 7);
1664 pmevtyper_write(env, ri, value, counter);
1665}
1666
1667static void pmevtyper_rawwrite(CPUARMState *env, const ARMCPRegInfo *ri,
1668 uint64_t value)
1669{
1670 uint8_t counter = ((ri->crm & 3) << 3) | (ri->opc2 & 7);
1671 env->cp15.c14_pmevtyper[counter] = value;
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682 uint16_t event = value & PMXEVTYPER_EVTCOUNT;
1683 if (event_supported(event)) {
1684 uint16_t event_idx = supported_event_map[event];
1685 env->cp15.c14_pmevcntr_delta[counter] =
1686 pm_events[event_idx].get_count(env);
1687 }
1688}
1689
1690static uint64_t pmevtyper_readfn(CPUARMState *env, const ARMCPRegInfo *ri)
1691{
1692 uint8_t counter = ((ri->crm & 3) << 3) | (ri->opc2 & 7);
1693 return pmevtyper_read(env, ri, counter);
1694}
1695
1696static void pmxevtyper_write(CPUARMState *env, const ARMCPRegInfo *ri,
1697 uint64_t value)
1698{
1699 pmevtyper_write(env, ri, value, env->cp15.c9_pmselr & 31);
1700}
1701
1702static uint64_t pmxevtyper_read(CPUARMState *env, const ARMCPRegInfo *ri)
1703{
1704 return pmevtyper_read(env, ri, env->cp15.c9_pmselr & 31);
1705}
1706
1707static void pmevcntr_write(CPUARMState *env, const ARMCPRegInfo *ri,
1708 uint64_t value, uint8_t counter)
1709{
1710 if (!cpu_isar_feature(any_pmuv3p5, env_archcpu(env))) {
1711
1712 value &= MAKE_64BIT_MASK(0, 32);
1713 }
1714 if (counter < pmu_num_counters(env)) {
1715 pmevcntr_op_start(env, counter);
1716 env->cp15.c14_pmevcntr[counter] = value;
1717 pmevcntr_op_finish(env, counter);
1718 }
1719
1720
1721
1722
1723}
1724
1725static uint64_t pmevcntr_read(CPUARMState *env, const ARMCPRegInfo *ri,
1726 uint8_t counter)
1727{
1728 if (counter < pmu_num_counters(env)) {
1729 uint64_t ret;
1730 pmevcntr_op_start(env, counter);
1731 ret = env->cp15.c14_pmevcntr[counter];
1732 pmevcntr_op_finish(env, counter);
1733 if (!cpu_isar_feature(any_pmuv3p5, env_archcpu(env))) {
1734
1735 ret &= MAKE_64BIT_MASK(0, 32);
1736 }
1737 return ret;
1738 } else {
1739
1740
1741
1742
1743 return 0;
1744 }
1745}
1746
1747static void pmevcntr_writefn(CPUARMState *env, const ARMCPRegInfo *ri,
1748 uint64_t value)
1749{
1750 uint8_t counter = ((ri->crm & 3) << 3) | (ri->opc2 & 7);
1751 pmevcntr_write(env, ri, value, counter);
1752}
1753
1754static uint64_t pmevcntr_readfn(CPUARMState *env, const ARMCPRegInfo *ri)
1755{
1756 uint8_t counter = ((ri->crm & 3) << 3) | (ri->opc2 & 7);
1757 return pmevcntr_read(env, ri, counter);
1758}
1759
1760static void pmevcntr_rawwrite(CPUARMState *env, const ARMCPRegInfo *ri,
1761 uint64_t value)
1762{
1763 uint8_t counter = ((ri->crm & 3) << 3) | (ri->opc2 & 7);
1764 assert(counter < pmu_num_counters(env));
1765 env->cp15.c14_pmevcntr[counter] = value;
1766 pmevcntr_write(env, ri, value, counter);
1767}
1768
1769static uint64_t pmevcntr_rawread(CPUARMState *env, const ARMCPRegInfo *ri)
1770{
1771 uint8_t counter = ((ri->crm & 3) << 3) | (ri->opc2 & 7);
1772 assert(counter < pmu_num_counters(env));
1773 return env->cp15.c14_pmevcntr[counter];
1774}
1775
1776static void pmxevcntr_write(CPUARMState *env, const ARMCPRegInfo *ri,
1777 uint64_t value)
1778{
1779 pmevcntr_write(env, ri, value, env->cp15.c9_pmselr & 31);
1780}
1781
1782static uint64_t pmxevcntr_read(CPUARMState *env, const ARMCPRegInfo *ri)
1783{
1784 return pmevcntr_read(env, ri, env->cp15.c9_pmselr & 31);
1785}
1786
1787static void pmuserenr_write(CPUARMState *env, const ARMCPRegInfo *ri,
1788 uint64_t value)
1789{
1790 if (arm_feature(env, ARM_FEATURE_V8)) {
1791 env->cp15.c9_pmuserenr = value & 0xf;
1792 } else {
1793 env->cp15.c9_pmuserenr = value & 1;
1794 }
1795}
1796
1797static void pmintenset_write(CPUARMState *env, const ARMCPRegInfo *ri,
1798 uint64_t value)
1799{
1800
1801 value &= pmu_counter_mask(env);
1802 env->cp15.c9_pminten |= value;
1803 pmu_update_irq(env);
1804}
1805
1806static void pmintenclr_write(CPUARMState *env, const ARMCPRegInfo *ri,
1807 uint64_t value)
1808{
1809 value &= pmu_counter_mask(env);
1810 env->cp15.c9_pminten &= ~value;
1811 pmu_update_irq(env);
1812}
1813
1814static void vbar_write(CPUARMState *env, const ARMCPRegInfo *ri,
1815 uint64_t value)
1816{
1817
1818
1819
1820
1821
1822
1823
1824 raw_write(env, ri, value & ~0x1FULL);
1825}
1826
1827static void scr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
1828{
1829
1830 uint64_t valid_mask = 0x3fff;
1831 ARMCPU *cpu = env_archcpu(env);
1832 uint64_t changed;
1833
1834
1835
1836
1837
1838
1839 if (arm_el_is_aa64(env, 3)) {
1840 value |= SCR_FW | SCR_AW;
1841 valid_mask &= ~SCR_NET;
1842
1843 if (!cpu_isar_feature(aa64_aa32_el1, cpu) &&
1844 !cpu_isar_feature(aa64_aa32_el2, cpu)) {
1845 value |= SCR_RW;
1846 }
1847 if (cpu_isar_feature(aa64_ras, cpu)) {
1848 valid_mask |= SCR_TERR;
1849 }
1850 if (cpu_isar_feature(aa64_lor, cpu)) {
1851 valid_mask |= SCR_TLOR;
1852 }
1853 if (cpu_isar_feature(aa64_pauth, cpu)) {
1854 valid_mask |= SCR_API | SCR_APK;
1855 }
1856 if (cpu_isar_feature(aa64_sel2, cpu)) {
1857 valid_mask |= SCR_EEL2;
1858 }
1859 if (cpu_isar_feature(aa64_mte, cpu)) {
1860 valid_mask |= SCR_ATA;
1861 }
1862 if (cpu_isar_feature(aa64_scxtnum, cpu)) {
1863 valid_mask |= SCR_ENSCXT;
1864 }
1865 if (cpu_isar_feature(aa64_doublefault, cpu)) {
1866 valid_mask |= SCR_EASE | SCR_NMEA;
1867 }
1868 if (cpu_isar_feature(aa64_sme, cpu)) {
1869 valid_mask |= SCR_ENTP2;
1870 }
1871 if (cpu_isar_feature(aa64_hcx, cpu)) {
1872 valid_mask |= SCR_HXEN;
1873 }
1874 if (cpu_isar_feature(aa64_fgt, cpu)) {
1875 valid_mask |= SCR_FGTEN;
1876 }
1877 } else {
1878 valid_mask &= ~(SCR_RW | SCR_ST);
1879 if (cpu_isar_feature(aa32_ras, cpu)) {
1880 valid_mask |= SCR_TERR;
1881 }
1882 }
1883
1884 if (!arm_feature(env, ARM_FEATURE_EL2)) {
1885 valid_mask &= ~SCR_HCE;
1886
1887
1888
1889
1890
1891
1892
1893
1894 if (arm_feature(env, ARM_FEATURE_V7) &&
1895 !arm_feature(env, ARM_FEATURE_V8)) {
1896 valid_mask &= ~SCR_SMD;
1897 }
1898 }
1899
1900
1901 value &= valid_mask;
1902 changed = env->cp15.scr_el3 ^ value;
1903 env->cp15.scr_el3 = value;
1904
1905
1906
1907
1908
1909 if (changed & SCR_NS) {
1910 tlb_flush_by_mmuidx(env_cpu(env), (ARMMMUIdxBit_E10_0 |
1911 ARMMMUIdxBit_E20_0 |
1912 ARMMMUIdxBit_E10_1 |
1913 ARMMMUIdxBit_E20_2 |
1914 ARMMMUIdxBit_E10_1_PAN |
1915 ARMMMUIdxBit_E20_2_PAN |
1916 ARMMMUIdxBit_E2));
1917 }
1918}
1919
1920static void scr_reset(CPUARMState *env, const ARMCPRegInfo *ri)
1921{
1922
1923
1924
1925
1926 scr_write(env, ri, 0);
1927}
1928
1929static CPAccessResult access_tid4(CPUARMState *env,
1930 const ARMCPRegInfo *ri,
1931 bool isread)
1932{
1933 if (arm_current_el(env) == 1 &&
1934 (arm_hcr_el2_eff(env) & (HCR_TID2 | HCR_TID4))) {
1935 return CP_ACCESS_TRAP_EL2;
1936 }
1937
1938 return CP_ACCESS_OK;
1939}
1940
1941static uint64_t ccsidr_read(CPUARMState *env, const ARMCPRegInfo *ri)
1942{
1943 ARMCPU *cpu = env_archcpu(env);
1944
1945
1946
1947
1948
1949 uint32_t index = A32_BANKED_REG_GET(env, csselr,
1950 ri->secure & ARM_CP_SECSTATE_S);
1951
1952 return cpu->ccsidr[index];
1953}
1954
1955static void csselr_write(CPUARMState *env, const ARMCPRegInfo *ri,
1956 uint64_t value)
1957{
1958 raw_write(env, ri, value & 0xf);
1959}
1960
1961static uint64_t isr_read(CPUARMState *env, const ARMCPRegInfo *ri)
1962{
1963 CPUState *cs = env_cpu(env);
1964 bool el1 = arm_current_el(env) == 1;
1965 uint64_t hcr_el2 = el1 ? arm_hcr_el2_eff(env) : 0;
1966 uint64_t ret = 0;
1967
1968 if (hcr_el2 & HCR_IMO) {
1969 if (cs->interrupt_request & CPU_INTERRUPT_VIRQ) {
1970 ret |= CPSR_I;
1971 }
1972 } else {
1973 if (cs->interrupt_request & CPU_INTERRUPT_HARD) {
1974 ret |= CPSR_I;
1975 }
1976 }
1977
1978 if (hcr_el2 & HCR_FMO) {
1979 if (cs->interrupt_request & CPU_INTERRUPT_VFIQ) {
1980 ret |= CPSR_F;
1981 }
1982 } else {
1983 if (cs->interrupt_request & CPU_INTERRUPT_FIQ) {
1984 ret |= CPSR_F;
1985 }
1986 }
1987
1988 if (hcr_el2 & HCR_AMO) {
1989 if (cs->interrupt_request & CPU_INTERRUPT_VSERR) {
1990 ret |= CPSR_A;
1991 }
1992 }
1993
1994 return ret;
1995}
1996
1997static CPAccessResult access_aa64_tid1(CPUARMState *env, const ARMCPRegInfo *ri,
1998 bool isread)
1999{
2000 if (arm_current_el(env) == 1 && (arm_hcr_el2_eff(env) & HCR_TID1)) {
2001 return CP_ACCESS_TRAP_EL2;
2002 }
2003
2004 return CP_ACCESS_OK;
2005}
2006
2007static CPAccessResult access_aa32_tid1(CPUARMState *env, const ARMCPRegInfo *ri,
2008 bool isread)
2009{
2010 if (arm_feature(env, ARM_FEATURE_V8)) {
2011 return access_aa64_tid1(env, ri, isread);
2012 }
2013
2014 return CP_ACCESS_OK;
2015}
2016
2017static const ARMCPRegInfo v7_cp_reginfo[] = {
2018
2019 { .name = "NOP", .cp = 15, .crn = 7, .crm = 0, .opc1 = 0, .opc2 = 4,
2020 .access = PL1_W, .type = ARM_CP_NOP },
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033 { .name = "PMCNTENSET", .cp = 15, .crn = 9, .crm = 12, .opc1 = 0, .opc2 = 1,
2034 .access = PL0_RW, .type = ARM_CP_ALIAS | ARM_CP_IO,
2035 .fieldoffset = offsetoflow32(CPUARMState, cp15.c9_pmcnten),
2036 .writefn = pmcntenset_write,
2037 .accessfn = pmreg_access,
2038 .fgt = FGT_PMCNTEN,
2039 .raw_writefn = raw_write },
2040 { .name = "PMCNTENSET_EL0", .state = ARM_CP_STATE_AA64, .type = ARM_CP_IO,
2041 .opc0 = 3, .opc1 = 3, .crn = 9, .crm = 12, .opc2 = 1,
2042 .access = PL0_RW, .accessfn = pmreg_access,
2043 .fgt = FGT_PMCNTEN,
2044 .fieldoffset = offsetof(CPUARMState, cp15.c9_pmcnten), .resetvalue = 0,
2045 .writefn = pmcntenset_write, .raw_writefn = raw_write },
2046 { .name = "PMCNTENCLR", .cp = 15, .crn = 9, .crm = 12, .opc1 = 0, .opc2 = 2,
2047 .access = PL0_RW,
2048 .fieldoffset = offsetoflow32(CPUARMState, cp15.c9_pmcnten),
2049 .accessfn = pmreg_access,
2050 .fgt = FGT_PMCNTEN,
2051 .writefn = pmcntenclr_write,
2052 .type = ARM_CP_ALIAS | ARM_CP_IO },
2053 { .name = "PMCNTENCLR_EL0", .state = ARM_CP_STATE_AA64,
2054 .opc0 = 3, .opc1 = 3, .crn = 9, .crm = 12, .opc2 = 2,
2055 .access = PL0_RW, .accessfn = pmreg_access,
2056 .fgt = FGT_PMCNTEN,
2057 .type = ARM_CP_ALIAS | ARM_CP_IO,
2058 .fieldoffset = offsetof(CPUARMState, cp15.c9_pmcnten),
2059 .writefn = pmcntenclr_write },
2060 { .name = "PMOVSR", .cp = 15, .crn = 9, .crm = 12, .opc1 = 0, .opc2 = 3,
2061 .access = PL0_RW, .type = ARM_CP_IO,
2062 .fieldoffset = offsetoflow32(CPUARMState, cp15.c9_pmovsr),
2063 .accessfn = pmreg_access,
2064 .fgt = FGT_PMOVS,
2065 .writefn = pmovsr_write,
2066 .raw_writefn = raw_write },
2067 { .name = "PMOVSCLR_EL0", .state = ARM_CP_STATE_AA64,
2068 .opc0 = 3, .opc1 = 3, .crn = 9, .crm = 12, .opc2 = 3,
2069 .access = PL0_RW, .accessfn = pmreg_access,
2070 .fgt = FGT_PMOVS,
2071 .type = ARM_CP_ALIAS | ARM_CP_IO,
2072 .fieldoffset = offsetof(CPUARMState, cp15.c9_pmovsr),
2073 .writefn = pmovsr_write,
2074 .raw_writefn = raw_write },
2075 { .name = "PMSWINC", .cp = 15, .crn = 9, .crm = 12, .opc1 = 0, .opc2 = 4,
2076 .access = PL0_W, .accessfn = pmreg_access_swinc,
2077 .fgt = FGT_PMSWINC_EL0,
2078 .type = ARM_CP_NO_RAW | ARM_CP_IO,
2079 .writefn = pmswinc_write },
2080 { .name = "PMSWINC_EL0", .state = ARM_CP_STATE_AA64,
2081 .opc0 = 3, .opc1 = 3, .crn = 9, .crm = 12, .opc2 = 4,
2082 .access = PL0_W, .accessfn = pmreg_access_swinc,
2083 .fgt = FGT_PMSWINC_EL0,
2084 .type = ARM_CP_NO_RAW | ARM_CP_IO,
2085 .writefn = pmswinc_write },
2086 { .name = "PMSELR", .cp = 15, .crn = 9, .crm = 12, .opc1 = 0, .opc2 = 5,
2087 .access = PL0_RW, .type = ARM_CP_ALIAS,
2088 .fgt = FGT_PMSELR_EL0,
2089 .fieldoffset = offsetoflow32(CPUARMState, cp15.c9_pmselr),
2090 .accessfn = pmreg_access_selr, .writefn = pmselr_write,
2091 .raw_writefn = raw_write},
2092 { .name = "PMSELR_EL0", .state = ARM_CP_STATE_AA64,
2093 .opc0 = 3, .opc1 = 3, .crn = 9, .crm = 12, .opc2 = 5,
2094 .access = PL0_RW, .accessfn = pmreg_access_selr,
2095 .fgt = FGT_PMSELR_EL0,
2096 .fieldoffset = offsetof(CPUARMState, cp15.c9_pmselr),
2097 .writefn = pmselr_write, .raw_writefn = raw_write, },
2098 { .name = "PMCCNTR", .cp = 15, .crn = 9, .crm = 13, .opc1 = 0, .opc2 = 0,
2099 .access = PL0_RW, .resetvalue = 0, .type = ARM_CP_ALIAS | ARM_CP_IO,
2100 .fgt = FGT_PMCCNTR_EL0,
2101 .readfn = pmccntr_read, .writefn = pmccntr_write32,
2102 .accessfn = pmreg_access_ccntr },
2103 { .name = "PMCCNTR_EL0", .state = ARM_CP_STATE_AA64,
2104 .opc0 = 3, .opc1 = 3, .crn = 9, .crm = 13, .opc2 = 0,
2105 .access = PL0_RW, .accessfn = pmreg_access_ccntr,
2106 .fgt = FGT_PMCCNTR_EL0,
2107 .type = ARM_CP_IO,
2108 .fieldoffset = offsetof(CPUARMState, cp15.c15_ccnt),
2109 .readfn = pmccntr_read, .writefn = pmccntr_write,
2110 .raw_readfn = raw_read, .raw_writefn = raw_write, },
2111 { .name = "PMCCFILTR", .cp = 15, .opc1 = 0, .crn = 14, .crm = 15, .opc2 = 7,
2112 .writefn = pmccfiltr_write_a32, .readfn = pmccfiltr_read_a32,
2113 .access = PL0_RW, .accessfn = pmreg_access,
2114 .fgt = FGT_PMCCFILTR_EL0,
2115 .type = ARM_CP_ALIAS | ARM_CP_IO,
2116 .resetvalue = 0, },
2117 { .name = "PMCCFILTR_EL0", .state = ARM_CP_STATE_AA64,
2118 .opc0 = 3, .opc1 = 3, .crn = 14, .crm = 15, .opc2 = 7,
2119 .writefn = pmccfiltr_write, .raw_writefn = raw_write,
2120 .access = PL0_RW, .accessfn = pmreg_access,
2121 .fgt = FGT_PMCCFILTR_EL0,
2122 .type = ARM_CP_IO,
2123 .fieldoffset = offsetof(CPUARMState, cp15.pmccfiltr_el0),
2124 .resetvalue = 0, },
2125 { .name = "PMXEVTYPER", .cp = 15, .crn = 9, .crm = 13, .opc1 = 0, .opc2 = 1,
2126 .access = PL0_RW, .type = ARM_CP_NO_RAW | ARM_CP_IO,
2127 .accessfn = pmreg_access,
2128 .fgt = FGT_PMEVTYPERN_EL0,
2129 .writefn = pmxevtyper_write, .readfn = pmxevtyper_read },
2130 { .name = "PMXEVTYPER_EL0", .state = ARM_CP_STATE_AA64,
2131 .opc0 = 3, .opc1 = 3, .crn = 9, .crm = 13, .opc2 = 1,
2132 .access = PL0_RW, .type = ARM_CP_NO_RAW | ARM_CP_IO,
2133 .accessfn = pmreg_access,
2134 .fgt = FGT_PMEVTYPERN_EL0,
2135 .writefn = pmxevtyper_write, .readfn = pmxevtyper_read },
2136 { .name = "PMXEVCNTR", .cp = 15, .crn = 9, .crm = 13, .opc1 = 0, .opc2 = 2,
2137 .access = PL0_RW, .type = ARM_CP_NO_RAW | ARM_CP_IO,
2138 .accessfn = pmreg_access_xevcntr,
2139 .fgt = FGT_PMEVCNTRN_EL0,
2140 .writefn = pmxevcntr_write, .readfn = pmxevcntr_read },
2141 { .name = "PMXEVCNTR_EL0", .state = ARM_CP_STATE_AA64,
2142 .opc0 = 3, .opc1 = 3, .crn = 9, .crm = 13, .opc2 = 2,
2143 .access = PL0_RW, .type = ARM_CP_NO_RAW | ARM_CP_IO,
2144 .accessfn = pmreg_access_xevcntr,
2145 .fgt = FGT_PMEVCNTRN_EL0,
2146 .writefn = pmxevcntr_write, .readfn = pmxevcntr_read },
2147 { .name = "PMUSERENR", .cp = 15, .crn = 9, .crm = 14, .opc1 = 0, .opc2 = 0,
2148 .access = PL0_R | PL1_RW, .accessfn = access_tpm,
2149 .fieldoffset = offsetoflow32(CPUARMState, cp15.c9_pmuserenr),
2150 .resetvalue = 0,
2151 .writefn = pmuserenr_write, .raw_writefn = raw_write },
2152 { .name = "PMUSERENR_EL0", .state = ARM_CP_STATE_AA64,
2153 .opc0 = 3, .opc1 = 3, .crn = 9, .crm = 14, .opc2 = 0,
2154 .access = PL0_R | PL1_RW, .accessfn = access_tpm, .type = ARM_CP_ALIAS,
2155 .fieldoffset = offsetof(CPUARMState, cp15.c9_pmuserenr),
2156 .resetvalue = 0,
2157 .writefn = pmuserenr_write, .raw_writefn = raw_write },
2158 { .name = "PMINTENSET", .cp = 15, .crn = 9, .crm = 14, .opc1 = 0, .opc2 = 1,
2159 .access = PL1_RW, .accessfn = access_tpm,
2160 .fgt = FGT_PMINTEN,
2161 .type = ARM_CP_ALIAS | ARM_CP_IO,
2162 .fieldoffset = offsetoflow32(CPUARMState, cp15.c9_pminten),
2163 .resetvalue = 0,
2164 .writefn = pmintenset_write, .raw_writefn = raw_write },
2165 { .name = "PMINTENSET_EL1", .state = ARM_CP_STATE_AA64,
2166 .opc0 = 3, .opc1 = 0, .crn = 9, .crm = 14, .opc2 = 1,
2167 .access = PL1_RW, .accessfn = access_tpm,
2168 .fgt = FGT_PMINTEN,
2169 .type = ARM_CP_IO,
2170 .fieldoffset = offsetof(CPUARMState, cp15.c9_pminten),
2171 .writefn = pmintenset_write, .raw_writefn = raw_write,
2172 .resetvalue = 0x0 },
2173 { .name = "PMINTENCLR", .cp = 15, .crn = 9, .crm = 14, .opc1 = 0, .opc2 = 2,
2174 .access = PL1_RW, .accessfn = access_tpm,
2175 .fgt = FGT_PMINTEN,
2176 .type = ARM_CP_ALIAS | ARM_CP_IO | ARM_CP_NO_RAW,
2177 .fieldoffset = offsetof(CPUARMState, cp15.c9_pminten),
2178 .writefn = pmintenclr_write, },
2179 { .name = "PMINTENCLR_EL1", .state = ARM_CP_STATE_AA64,
2180 .opc0 = 3, .opc1 = 0, .crn = 9, .crm = 14, .opc2 = 2,
2181 .access = PL1_RW, .accessfn = access_tpm,
2182 .fgt = FGT_PMINTEN,
2183 .type = ARM_CP_ALIAS | ARM_CP_IO | ARM_CP_NO_RAW,
2184 .fieldoffset = offsetof(CPUARMState, cp15.c9_pminten),
2185 .writefn = pmintenclr_write },
2186 { .name = "CCSIDR", .state = ARM_CP_STATE_BOTH,
2187 .opc0 = 3, .crn = 0, .crm = 0, .opc1 = 1, .opc2 = 0,
2188 .access = PL1_R,
2189 .accessfn = access_tid4,
2190 .fgt = FGT_CCSIDR_EL1,
2191 .readfn = ccsidr_read, .type = ARM_CP_NO_RAW },
2192 { .name = "CSSELR", .state = ARM_CP_STATE_BOTH,
2193 .opc0 = 3, .crn = 0, .crm = 0, .opc1 = 2, .opc2 = 0,
2194 .access = PL1_RW,
2195 .accessfn = access_tid4,
2196 .fgt = FGT_CSSELR_EL1,
2197 .writefn = csselr_write, .resetvalue = 0,
2198 .bank_fieldoffsets = { offsetof(CPUARMState, cp15.csselr_s),
2199 offsetof(CPUARMState, cp15.csselr_ns) } },
2200
2201
2202
2203
2204 { .name = "AIDR", .state = ARM_CP_STATE_BOTH,
2205 .opc0 = 3, .opc1 = 1, .crn = 0, .crm = 0, .opc2 = 7,
2206 .access = PL1_R, .type = ARM_CP_CONST,
2207 .accessfn = access_aa64_tid1,
2208 .fgt = FGT_AIDR_EL1,
2209 .resetvalue = 0 },
2210
2211
2212
2213
2214 { .name = "AFSR0_EL1", .state = ARM_CP_STATE_BOTH,
2215 .opc0 = 3, .opc1 = 0, .crn = 5, .crm = 1, .opc2 = 0,
2216 .access = PL1_RW, .accessfn = access_tvm_trvm,
2217 .fgt = FGT_AFSR0_EL1,
2218 .type = ARM_CP_CONST, .resetvalue = 0 },
2219 { .name = "AFSR1_EL1", .state = ARM_CP_STATE_BOTH,
2220 .opc0 = 3, .opc1 = 0, .crn = 5, .crm = 1, .opc2 = 1,
2221 .access = PL1_RW, .accessfn = access_tvm_trvm,
2222 .fgt = FGT_AFSR1_EL1,
2223 .type = ARM_CP_CONST, .resetvalue = 0 },
2224
2225
2226
2227
2228 { .name = "MAIR_EL1", .state = ARM_CP_STATE_AA64,
2229 .opc0 = 3, .opc1 = 0, .crn = 10, .crm = 2, .opc2 = 0,
2230 .access = PL1_RW, .accessfn = access_tvm_trvm,
2231 .fgt = FGT_MAIR_EL1,
2232 .fieldoffset = offsetof(CPUARMState, cp15.mair_el[1]),
2233 .resetvalue = 0 },
2234 { .name = "MAIR_EL3", .state = ARM_CP_STATE_AA64,
2235 .opc0 = 3, .opc1 = 6, .crn = 10, .crm = 2, .opc2 = 0,
2236 .access = PL3_RW, .fieldoffset = offsetof(CPUARMState, cp15.mair_el[3]),
2237 .resetvalue = 0 },
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247 { .name = "MAIR0", .state = ARM_CP_STATE_AA32,
2248 .cp = 15, .opc1 = 0, .crn = 10, .crm = 2, .opc2 = 0,
2249 .access = PL1_RW, .accessfn = access_tvm_trvm,
2250 .bank_fieldoffsets = { offsetof(CPUARMState, cp15.mair0_s),
2251 offsetof(CPUARMState, cp15.mair0_ns) },
2252 .resetfn = arm_cp_reset_ignore },
2253 { .name = "MAIR1", .state = ARM_CP_STATE_AA32,
2254 .cp = 15, .opc1 = 0, .crn = 10, .crm = 2, .opc2 = 1,
2255 .access = PL1_RW, .accessfn = access_tvm_trvm,
2256 .bank_fieldoffsets = { offsetof(CPUARMState, cp15.mair1_s),
2257 offsetof(CPUARMState, cp15.mair1_ns) },
2258 .resetfn = arm_cp_reset_ignore },
2259 { .name = "ISR_EL1", .state = ARM_CP_STATE_BOTH,
2260 .opc0 = 3, .opc1 = 0, .crn = 12, .crm = 1, .opc2 = 0,
2261 .fgt = FGT_ISR_EL1,
2262 .type = ARM_CP_NO_RAW, .access = PL1_R, .readfn = isr_read },
2263
2264 { .name = "ITLBIALL", .cp = 15, .opc1 = 0, .crn = 8, .crm = 5, .opc2 = 0,
2265 .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlb,
2266 .writefn = tlbiall_write },
2267 { .name = "ITLBIMVA", .cp = 15, .opc1 = 0, .crn = 8, .crm = 5, .opc2 = 1,
2268 .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlb,
2269 .writefn = tlbimva_write },
2270 { .name = "ITLBIASID", .cp = 15, .opc1 = 0, .crn = 8, .crm = 5, .opc2 = 2,
2271 .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlb,
2272 .writefn = tlbiasid_write },
2273
2274 { .name = "DTLBIALL", .cp = 15, .opc1 = 0, .crn = 8, .crm = 6, .opc2 = 0,
2275 .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlb,
2276 .writefn = tlbiall_write },
2277 { .name = "DTLBIMVA", .cp = 15, .opc1 = 0, .crn = 8, .crm = 6, .opc2 = 1,
2278 .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlb,
2279 .writefn = tlbimva_write },
2280 { .name = "DTLBIASID", .cp = 15, .opc1 = 0, .crn = 8, .crm = 6, .opc2 = 2,
2281 .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlb,
2282 .writefn = tlbiasid_write },
2283
2284 { .name = "TLBIALL", .cp = 15, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 0,
2285 .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlb,
2286 .writefn = tlbiall_write },
2287 { .name = "TLBIMVA", .cp = 15, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 1,
2288 .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlb,
2289 .writefn = tlbimva_write },
2290 { .name = "TLBIASID", .cp = 15, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 2,
2291 .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlb,
2292 .writefn = tlbiasid_write },
2293 { .name = "TLBIMVAA", .cp = 15, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 3,
2294 .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlb,
2295 .writefn = tlbimvaa_write },
2296};
2297
2298static const ARMCPRegInfo v7mp_cp_reginfo[] = {
2299
2300 { .name = "TLBIALLIS", .cp = 15, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 0,
2301 .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlbis,
2302 .writefn = tlbiall_is_write },
2303 { .name = "TLBIMVAIS", .cp = 15, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 1,
2304 .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlbis,
2305 .writefn = tlbimva_is_write },
2306 { .name = "TLBIASIDIS", .cp = 15, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 2,
2307 .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlbis,
2308 .writefn = tlbiasid_is_write },
2309 { .name = "TLBIMVAAIS", .cp = 15, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 3,
2310 .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlbis,
2311 .writefn = tlbimvaa_is_write },
2312};
2313
2314static const ARMCPRegInfo pmovsset_cp_reginfo[] = {
2315
2316 { .name = "PMOVSSET", .cp = 15, .opc1 = 0, .crn = 9, .crm = 14, .opc2 = 3,
2317 .access = PL0_RW, .accessfn = pmreg_access,
2318 .fgt = FGT_PMOVS,
2319 .type = ARM_CP_ALIAS | ARM_CP_IO,
2320 .fieldoffset = offsetoflow32(CPUARMState, cp15.c9_pmovsr),
2321 .writefn = pmovsset_write,
2322 .raw_writefn = raw_write },
2323 { .name = "PMOVSSET_EL0", .state = ARM_CP_STATE_AA64,
2324 .opc0 = 3, .opc1 = 3, .crn = 9, .crm = 14, .opc2 = 3,
2325 .access = PL0_RW, .accessfn = pmreg_access,
2326 .fgt = FGT_PMOVS,
2327 .type = ARM_CP_ALIAS | ARM_CP_IO,
2328 .fieldoffset = offsetof(CPUARMState, cp15.c9_pmovsr),
2329 .writefn = pmovsset_write,
2330 .raw_writefn = raw_write },
2331};
2332
2333static void teecr_write(CPUARMState *env, const ARMCPRegInfo *ri,
2334 uint64_t value)
2335{
2336 value &= 1;
2337 env->teecr = value;
2338}
2339
2340static CPAccessResult teecr_access(CPUARMState *env, const ARMCPRegInfo *ri,
2341 bool isread)
2342{
2343
2344
2345
2346
2347 if (arm_current_el(env) < 2 && !arm_is_secure_below_el3(env) &&
2348 (env->cp15.hstr_el2 & HSTR_TTEE)) {
2349 return CP_ACCESS_TRAP_EL2;
2350 }
2351 return CP_ACCESS_OK;
2352}
2353
2354static CPAccessResult teehbr_access(CPUARMState *env, const ARMCPRegInfo *ri,
2355 bool isread)
2356{
2357 if (arm_current_el(env) == 0 && (env->teecr & 1)) {
2358 return CP_ACCESS_TRAP;
2359 }
2360 return teecr_access(env, ri, isread);
2361}
2362
2363static const ARMCPRegInfo t2ee_cp_reginfo[] = {
2364 { .name = "TEECR", .cp = 14, .crn = 0, .crm = 0, .opc1 = 6, .opc2 = 0,
2365 .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, teecr),
2366 .resetvalue = 0,
2367 .writefn = teecr_write, .accessfn = teecr_access },
2368 { .name = "TEEHBR", .cp = 14, .crn = 1, .crm = 0, .opc1 = 6, .opc2 = 0,
2369 .access = PL0_RW, .fieldoffset = offsetof(CPUARMState, teehbr),
2370 .accessfn = teehbr_access, .resetvalue = 0 },
2371};
2372
2373static const ARMCPRegInfo v6k_cp_reginfo[] = {
2374 { .name = "TPIDR_EL0", .state = ARM_CP_STATE_AA64,
2375 .opc0 = 3, .opc1 = 3, .opc2 = 2, .crn = 13, .crm = 0,
2376 .access = PL0_RW,
2377 .fgt = FGT_TPIDR_EL0,
2378 .fieldoffset = offsetof(CPUARMState, cp15.tpidr_el[0]), .resetvalue = 0 },
2379 { .name = "TPIDRURW", .cp = 15, .crn = 13, .crm = 0, .opc1 = 0, .opc2 = 2,
2380 .access = PL0_RW,
2381 .fgt = FGT_TPIDR_EL0,
2382 .bank_fieldoffsets = { offsetoflow32(CPUARMState, cp15.tpidrurw_s),
2383 offsetoflow32(CPUARMState, cp15.tpidrurw_ns) },
2384 .resetfn = arm_cp_reset_ignore },
2385 { .name = "TPIDRRO_EL0", .state = ARM_CP_STATE_AA64,
2386 .opc0 = 3, .opc1 = 3, .opc2 = 3, .crn = 13, .crm = 0,
2387 .access = PL0_R | PL1_W,
2388 .fgt = FGT_TPIDRRO_EL0,
2389 .fieldoffset = offsetof(CPUARMState, cp15.tpidrro_el[0]),
2390 .resetvalue = 0},
2391 { .name = "TPIDRURO", .cp = 15, .crn = 13, .crm = 0, .opc1 = 0, .opc2 = 3,
2392 .access = PL0_R | PL1_W,
2393 .fgt = FGT_TPIDRRO_EL0,
2394 .bank_fieldoffsets = { offsetoflow32(CPUARMState, cp15.tpidruro_s),
2395 offsetoflow32(CPUARMState, cp15.tpidruro_ns) },
2396 .resetfn = arm_cp_reset_ignore },
2397 { .name = "TPIDR_EL1", .state = ARM_CP_STATE_AA64,
2398 .opc0 = 3, .opc1 = 0, .opc2 = 4, .crn = 13, .crm = 0,
2399 .access = PL1_RW,
2400 .fgt = FGT_TPIDR_EL1,
2401 .fieldoffset = offsetof(CPUARMState, cp15.tpidr_el[1]), .resetvalue = 0 },
2402 { .name = "TPIDRPRW", .opc1 = 0, .cp = 15, .crn = 13, .crm = 0, .opc2 = 4,
2403 .access = PL1_RW,
2404 .bank_fieldoffsets = { offsetoflow32(CPUARMState, cp15.tpidrprw_s),
2405 offsetoflow32(CPUARMState, cp15.tpidrprw_ns) },
2406 .resetvalue = 0 },
2407};
2408
2409#ifndef CONFIG_USER_ONLY
2410
2411static CPAccessResult gt_cntfrq_access(CPUARMState *env, const ARMCPRegInfo *ri,
2412 bool isread)
2413{
2414
2415
2416
2417
2418 int el = arm_current_el(env);
2419 uint64_t hcr;
2420 uint32_t cntkctl;
2421
2422 switch (el) {
2423 case 0:
2424 hcr = arm_hcr_el2_eff(env);
2425 if ((hcr & (HCR_E2H | HCR_TGE)) == (HCR_E2H | HCR_TGE)) {
2426 cntkctl = env->cp15.cnthctl_el2;
2427 } else {
2428 cntkctl = env->cp15.c14_cntkctl;
2429 }
2430 if (!extract32(cntkctl, 0, 2)) {
2431 return CP_ACCESS_TRAP;
2432 }
2433 break;
2434 case 1:
2435 if (!isread && ri->state == ARM_CP_STATE_AA32 &&
2436 arm_is_secure_below_el3(env)) {
2437
2438 return CP_ACCESS_TRAP_UNCATEGORIZED;
2439 }
2440 break;
2441 case 2:
2442 case 3:
2443 break;
2444 }
2445
2446 if (!isread && el < arm_highest_el(env)) {
2447 return CP_ACCESS_TRAP_UNCATEGORIZED;
2448 }
2449
2450 return CP_ACCESS_OK;
2451}
2452
2453static CPAccessResult gt_counter_access(CPUARMState *env, int timeridx,
2454 bool isread)
2455{
2456 unsigned int cur_el = arm_current_el(env);
2457 bool has_el2 = arm_is_el2_enabled(env);
2458 uint64_t hcr = arm_hcr_el2_eff(env);
2459
2460 switch (cur_el) {
2461 case 0:
2462
2463 if ((hcr & (HCR_E2H | HCR_TGE)) == (HCR_E2H | HCR_TGE)) {
2464 return (extract32(env->cp15.cnthctl_el2, timeridx, 1)
2465 ? CP_ACCESS_OK : CP_ACCESS_TRAP_EL2);
2466 }
2467
2468
2469 if (!extract32(env->cp15.c14_cntkctl, timeridx, 1)) {
2470 return CP_ACCESS_TRAP;
2471 }
2472
2473
2474 if (hcr & HCR_E2H) {
2475 if (timeridx == GTIMER_PHYS &&
2476 !extract32(env->cp15.cnthctl_el2, 10, 1)) {
2477 return CP_ACCESS_TRAP_EL2;
2478 }
2479 } else {
2480
2481 if (has_el2 && timeridx == GTIMER_PHYS &&
2482 !extract32(env->cp15.cnthctl_el2, 1, 1)) {
2483 return CP_ACCESS_TRAP_EL2;
2484 }
2485 }
2486 break;
2487
2488 case 1:
2489
2490 if (has_el2 && timeridx == GTIMER_PHYS &&
2491 (hcr & HCR_E2H
2492 ? !extract32(env->cp15.cnthctl_el2, 10, 1)
2493 : !extract32(env->cp15.cnthctl_el2, 0, 1))) {
2494 return CP_ACCESS_TRAP_EL2;
2495 }
2496 break;
2497 }
2498 return CP_ACCESS_OK;
2499}
2500
2501static CPAccessResult gt_timer_access(CPUARMState *env, int timeridx,
2502 bool isread)
2503{
2504 unsigned int cur_el = arm_current_el(env);
2505 bool has_el2 = arm_is_el2_enabled(env);
2506 uint64_t hcr = arm_hcr_el2_eff(env);
2507
2508 switch (cur_el) {
2509 case 0:
2510 if ((hcr & (HCR_E2H | HCR_TGE)) == (HCR_E2H | HCR_TGE)) {
2511
2512 return (extract32(env->cp15.cnthctl_el2, 9 - timeridx, 1)
2513 ? CP_ACCESS_OK : CP_ACCESS_TRAP_EL2);
2514 }
2515
2516
2517
2518
2519
2520 if (!extract32(env->cp15.c14_cntkctl, 9 - timeridx, 1)) {
2521 return CP_ACCESS_TRAP;
2522 }
2523
2524
2525 case 1:
2526 if (has_el2 && timeridx == GTIMER_PHYS) {
2527 if (hcr & HCR_E2H) {
2528
2529 if (!extract32(env->cp15.cnthctl_el2, 11, 1)) {
2530 return CP_ACCESS_TRAP_EL2;
2531 }
2532 } else {
2533
2534 if (!extract32(env->cp15.cnthctl_el2, 1, 1)) {
2535 return CP_ACCESS_TRAP_EL2;
2536 }
2537 }
2538 }
2539 break;
2540 }
2541 return CP_ACCESS_OK;
2542}
2543
2544static CPAccessResult gt_pct_access(CPUARMState *env,
2545 const ARMCPRegInfo *ri,
2546 bool isread)
2547{
2548 return gt_counter_access(env, GTIMER_PHYS, isread);
2549}
2550
2551static CPAccessResult gt_vct_access(CPUARMState *env,
2552 const ARMCPRegInfo *ri,
2553 bool isread)
2554{
2555 return gt_counter_access(env, GTIMER_VIRT, isread);
2556}
2557
2558static CPAccessResult gt_ptimer_access(CPUARMState *env, const ARMCPRegInfo *ri,
2559 bool isread)
2560{
2561 return gt_timer_access(env, GTIMER_PHYS, isread);
2562}
2563
2564static CPAccessResult gt_vtimer_access(CPUARMState *env, const ARMCPRegInfo *ri,
2565 bool isread)
2566{
2567 return gt_timer_access(env, GTIMER_VIRT, isread);
2568}
2569
2570static CPAccessResult gt_stimer_access(CPUARMState *env,
2571 const ARMCPRegInfo *ri,
2572 bool isread)
2573{
2574
2575
2576
2577
2578
2579 switch (arm_current_el(env)) {
2580 case 1:
2581 if (!arm_is_secure(env)) {
2582 return CP_ACCESS_TRAP;
2583 }
2584 if (!(env->cp15.scr_el3 & SCR_ST)) {
2585 return CP_ACCESS_TRAP_EL3;
2586 }
2587 return CP_ACCESS_OK;
2588 case 0:
2589 case 2:
2590 return CP_ACCESS_TRAP;
2591 case 3:
2592 return CP_ACCESS_OK;
2593 default:
2594 g_assert_not_reached();
2595 }
2596}
2597
2598static uint64_t gt_get_countervalue(CPUARMState *env)
2599{
2600 ARMCPU *cpu = env_archcpu(env);
2601
2602 return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) / gt_cntfrq_period_ns(cpu);
2603}
2604
2605static void gt_recalc_timer(ARMCPU *cpu, int timeridx)
2606{
2607 ARMGenericTimer *gt = &cpu->env.cp15.c14_timer[timeridx];
2608
2609 if (gt->ctl & 1) {
2610
2611
2612
2613
2614 uint64_t offset = timeridx == GTIMER_VIRT ?
2615 cpu->env.cp15.cntvoff_el2 : 0;
2616 uint64_t count = gt_get_countervalue(&cpu->env);
2617
2618 int istatus = count - offset >= gt->cval;
2619 uint64_t nexttick;
2620 int irqstate;
2621
2622 gt->ctl = deposit32(gt->ctl, 2, 1, istatus);
2623
2624 irqstate = (istatus && !(gt->ctl & 2));
2625 qemu_set_irq(cpu->gt_timer_outputs[timeridx], irqstate);
2626
2627 if (istatus) {
2628
2629 nexttick = UINT64_MAX;
2630 } else {
2631
2632 nexttick = gt->cval + offset;
2633 }
2634
2635
2636
2637
2638
2639
2640 if (nexttick > INT64_MAX / gt_cntfrq_period_ns(cpu)) {
2641 timer_mod_ns(cpu->gt_timer[timeridx], INT64_MAX);
2642 } else {
2643 timer_mod(cpu->gt_timer[timeridx], nexttick);
2644 }
2645 trace_arm_gt_recalc(timeridx, irqstate, nexttick);
2646 } else {
2647
2648 gt->ctl &= ~4;
2649 qemu_set_irq(cpu->gt_timer_outputs[timeridx], 0);
2650 timer_del(cpu->gt_timer[timeridx]);
2651 trace_arm_gt_recalc_disabled(timeridx);
2652 }
2653}
2654
2655static void gt_timer_reset(CPUARMState *env, const ARMCPRegInfo *ri,
2656 int timeridx)
2657{
2658 ARMCPU *cpu = env_archcpu(env);
2659
2660 timer_del(cpu->gt_timer[timeridx]);
2661}
2662
2663static uint64_t gt_cnt_read(CPUARMState *env, const ARMCPRegInfo *ri)
2664{
2665 return gt_get_countervalue(env);
2666}
2667
2668static uint64_t gt_virt_cnt_offset(CPUARMState *env)
2669{
2670 uint64_t hcr;
2671
2672 switch (arm_current_el(env)) {
2673 case 2:
2674 hcr = arm_hcr_el2_eff(env);
2675 if (hcr & HCR_E2H) {
2676 return 0;
2677 }
2678 break;
2679 case 0:
2680 hcr = arm_hcr_el2_eff(env);
2681 if ((hcr & (HCR_E2H | HCR_TGE)) == (HCR_E2H | HCR_TGE)) {
2682 return 0;
2683 }
2684 break;
2685 }
2686
2687 return env->cp15.cntvoff_el2;
2688}
2689
2690static uint64_t gt_virt_cnt_read(CPUARMState *env, const ARMCPRegInfo *ri)
2691{
2692 return gt_get_countervalue(env) - gt_virt_cnt_offset(env);
2693}
2694
2695static void gt_cval_write(CPUARMState *env, const ARMCPRegInfo *ri,
2696 int timeridx,
2697 uint64_t value)
2698{
2699 trace_arm_gt_cval_write(timeridx, value);
2700 env->cp15.c14_timer[timeridx].cval = value;
2701 gt_recalc_timer(env_archcpu(env), timeridx);
2702}
2703
2704static uint64_t gt_tval_read(CPUARMState *env, const ARMCPRegInfo *ri,
2705 int timeridx)
2706{
2707 uint64_t offset = 0;
2708
2709 switch (timeridx) {
2710 case GTIMER_VIRT:
2711 case GTIMER_HYPVIRT:
2712 offset = gt_virt_cnt_offset(env);
2713 break;
2714 }
2715
2716 return (uint32_t)(env->cp15.c14_timer[timeridx].cval -
2717 (gt_get_countervalue(env) - offset));
2718}
2719
2720static void gt_tval_write(CPUARMState *env, const ARMCPRegInfo *ri,
2721 int timeridx,
2722 uint64_t value)
2723{
2724 uint64_t offset = 0;
2725
2726 switch (timeridx) {
2727 case GTIMER_VIRT:
2728 case GTIMER_HYPVIRT:
2729 offset = gt_virt_cnt_offset(env);
2730 break;
2731 }
2732
2733 trace_arm_gt_tval_write(timeridx, value);
2734 env->cp15.c14_timer[timeridx].cval = gt_get_countervalue(env) - offset +
2735 sextract64(value, 0, 32);
2736 gt_recalc_timer(env_archcpu(env), timeridx);
2737}
2738
2739static void gt_ctl_write(CPUARMState *env, const ARMCPRegInfo *ri,
2740 int timeridx,
2741 uint64_t value)
2742{
2743 ARMCPU *cpu = env_archcpu(env);
2744 uint32_t oldval = env->cp15.c14_timer[timeridx].ctl;
2745
2746 trace_arm_gt_ctl_write(timeridx, value);
2747 env->cp15.c14_timer[timeridx].ctl = deposit64(oldval, 0, 2, value);
2748 if ((oldval ^ value) & 1) {
2749
2750 gt_recalc_timer(cpu, timeridx);
2751 } else if ((oldval ^ value) & 2) {
2752
2753
2754
2755
2756 int irqstate = (oldval & 4) && !(value & 2);
2757
2758 trace_arm_gt_imask_toggle(timeridx, irqstate);
2759 qemu_set_irq(cpu->gt_timer_outputs[timeridx], irqstate);
2760 }
2761}
2762
2763static void gt_phys_timer_reset(CPUARMState *env, const ARMCPRegInfo *ri)
2764{
2765 gt_timer_reset(env, ri, GTIMER_PHYS);
2766}
2767
2768static void gt_phys_cval_write(CPUARMState *env, const ARMCPRegInfo *ri,
2769 uint64_t value)
2770{
2771 gt_cval_write(env, ri, GTIMER_PHYS, value);
2772}
2773
2774static uint64_t gt_phys_tval_read(CPUARMState *env, const ARMCPRegInfo *ri)
2775{
2776 return gt_tval_read(env, ri, GTIMER_PHYS);
2777}
2778
2779static void gt_phys_tval_write(CPUARMState *env, const ARMCPRegInfo *ri,
2780 uint64_t value)
2781{
2782 gt_tval_write(env, ri, GTIMER_PHYS, value);
2783}
2784
2785static void gt_phys_ctl_write(CPUARMState *env, const ARMCPRegInfo *ri,
2786 uint64_t value)
2787{
2788 gt_ctl_write(env, ri, GTIMER_PHYS, value);
2789}
2790
2791static int gt_phys_redir_timeridx(CPUARMState *env)
2792{
2793 switch (arm_mmu_idx(env)) {
2794 case ARMMMUIdx_E20_0:
2795 case ARMMMUIdx_E20_2:
2796 case ARMMMUIdx_E20_2_PAN:
2797 return GTIMER_HYP;
2798 default:
2799 return GTIMER_PHYS;
2800 }
2801}
2802
2803static int gt_virt_redir_timeridx(CPUARMState *env)
2804{
2805 switch (arm_mmu_idx(env)) {
2806 case ARMMMUIdx_E20_0:
2807 case ARMMMUIdx_E20_2:
2808 case ARMMMUIdx_E20_2_PAN:
2809 return GTIMER_HYPVIRT;
2810 default:
2811 return GTIMER_VIRT;
2812 }
2813}
2814
2815static uint64_t gt_phys_redir_cval_read(CPUARMState *env,
2816 const ARMCPRegInfo *ri)
2817{
2818 int timeridx = gt_phys_redir_timeridx(env);
2819 return env->cp15.c14_timer[timeridx].cval;
2820}
2821
2822static void gt_phys_redir_cval_write(CPUARMState *env, const ARMCPRegInfo *ri,
2823 uint64_t value)
2824{
2825 int timeridx = gt_phys_redir_timeridx(env);
2826 gt_cval_write(env, ri, timeridx, value);
2827}
2828
2829static uint64_t gt_phys_redir_tval_read(CPUARMState *env,
2830 const ARMCPRegInfo *ri)
2831{
2832 int timeridx = gt_phys_redir_timeridx(env);
2833 return gt_tval_read(env, ri, timeridx);
2834}
2835
2836static void gt_phys_redir_tval_write(CPUARMState *env, const ARMCPRegInfo *ri,
2837 uint64_t value)
2838{
2839 int timeridx = gt_phys_redir_timeridx(env);
2840 gt_tval_write(env, ri, timeridx, value);
2841}
2842
2843static uint64_t gt_phys_redir_ctl_read(CPUARMState *env,
2844 const ARMCPRegInfo *ri)
2845{
2846 int timeridx = gt_phys_redir_timeridx(env);
2847 return env->cp15.c14_timer[timeridx].ctl;
2848}
2849
2850static void gt_phys_redir_ctl_write(CPUARMState *env, const ARMCPRegInfo *ri,
2851 uint64_t value)
2852{
2853 int timeridx = gt_phys_redir_timeridx(env);
2854 gt_ctl_write(env, ri, timeridx, value);
2855}
2856
2857static void gt_virt_timer_reset(CPUARMState *env, const ARMCPRegInfo *ri)
2858{
2859 gt_timer_reset(env, ri, GTIMER_VIRT);
2860}
2861
2862static void gt_virt_cval_write(CPUARMState *env, const ARMCPRegInfo *ri,
2863 uint64_t value)
2864{
2865 gt_cval_write(env, ri, GTIMER_VIRT, value);
2866}
2867
2868static uint64_t gt_virt_tval_read(CPUARMState *env, const ARMCPRegInfo *ri)
2869{
2870 return gt_tval_read(env, ri, GTIMER_VIRT);
2871}
2872
2873static void gt_virt_tval_write(CPUARMState *env, const ARMCPRegInfo *ri,
2874 uint64_t value)
2875{
2876 gt_tval_write(env, ri, GTIMER_VIRT, value);
2877}
2878
2879static void gt_virt_ctl_write(CPUARMState *env, const ARMCPRegInfo *ri,
2880 uint64_t value)
2881{
2882 gt_ctl_write(env, ri, GTIMER_VIRT, value);
2883}
2884
2885static void gt_cntvoff_write(CPUARMState *env, const ARMCPRegInfo *ri,
2886 uint64_t value)
2887{
2888 ARMCPU *cpu = env_archcpu(env);
2889
2890 trace_arm_gt_cntvoff_write(value);
2891 raw_write(env, ri, value);
2892 gt_recalc_timer(cpu, GTIMER_VIRT);
2893}
2894
2895static uint64_t gt_virt_redir_cval_read(CPUARMState *env,
2896 const ARMCPRegInfo *ri)
2897{
2898 int timeridx = gt_virt_redir_timeridx(env);
2899 return env->cp15.c14_timer[timeridx].cval;
2900}
2901
2902static void gt_virt_redir_cval_write(CPUARMState *env, const ARMCPRegInfo *ri,
2903 uint64_t value)
2904{
2905 int timeridx = gt_virt_redir_timeridx(env);
2906 gt_cval_write(env, ri, timeridx, value);
2907}
2908
2909static uint64_t gt_virt_redir_tval_read(CPUARMState *env,
2910 const ARMCPRegInfo *ri)
2911{
2912 int timeridx = gt_virt_redir_timeridx(env);
2913 return gt_tval_read(env, ri, timeridx);
2914}
2915
2916static void gt_virt_redir_tval_write(CPUARMState *env, const ARMCPRegInfo *ri,
2917 uint64_t value)
2918{
2919 int timeridx = gt_virt_redir_timeridx(env);
2920 gt_tval_write(env, ri, timeridx, value);
2921}
2922
2923static uint64_t gt_virt_redir_ctl_read(CPUARMState *env,
2924 const ARMCPRegInfo *ri)
2925{
2926 int timeridx = gt_virt_redir_timeridx(env);
2927 return env->cp15.c14_timer[timeridx].ctl;
2928}
2929
2930static void gt_virt_redir_ctl_write(CPUARMState *env, const ARMCPRegInfo *ri,
2931 uint64_t value)
2932{
2933 int timeridx = gt_virt_redir_timeridx(env);
2934 gt_ctl_write(env, ri, timeridx, value);
2935}
2936
2937static void gt_hyp_timer_reset(CPUARMState *env, const ARMCPRegInfo *ri)
2938{
2939 gt_timer_reset(env, ri, GTIMER_HYP);
2940}
2941
2942static void gt_hyp_cval_write(CPUARMState *env, const ARMCPRegInfo *ri,
2943 uint64_t value)
2944{
2945 gt_cval_write(env, ri, GTIMER_HYP, value);
2946}
2947
2948static uint64_t gt_hyp_tval_read(CPUARMState *env, const ARMCPRegInfo *ri)
2949{
2950 return gt_tval_read(env, ri, GTIMER_HYP);
2951}
2952
2953static void gt_hyp_tval_write(CPUARMState *env, const ARMCPRegInfo *ri,
2954 uint64_t value)
2955{
2956 gt_tval_write(env, ri, GTIMER_HYP, value);
2957}
2958
2959static void gt_hyp_ctl_write(CPUARMState *env, const ARMCPRegInfo *ri,
2960 uint64_t value)
2961{
2962 gt_ctl_write(env, ri, GTIMER_HYP, value);
2963}
2964
2965static void gt_sec_timer_reset(CPUARMState *env, const ARMCPRegInfo *ri)
2966{
2967 gt_timer_reset(env, ri, GTIMER_SEC);
2968}
2969
2970static void gt_sec_cval_write(CPUARMState *env, const ARMCPRegInfo *ri,
2971 uint64_t value)
2972{
2973 gt_cval_write(env, ri, GTIMER_SEC, value);
2974}
2975
2976static uint64_t gt_sec_tval_read(CPUARMState *env, const ARMCPRegInfo *ri)
2977{
2978 return gt_tval_read(env, ri, GTIMER_SEC);
2979}
2980
2981static void gt_sec_tval_write(CPUARMState *env, const ARMCPRegInfo *ri,
2982 uint64_t value)
2983{
2984 gt_tval_write(env, ri, GTIMER_SEC, value);
2985}
2986
2987static void gt_sec_ctl_write(CPUARMState *env, const ARMCPRegInfo *ri,
2988 uint64_t value)
2989{
2990 gt_ctl_write(env, ri, GTIMER_SEC, value);
2991}
2992
2993static void gt_hv_timer_reset(CPUARMState *env, const ARMCPRegInfo *ri)
2994{
2995 gt_timer_reset(env, ri, GTIMER_HYPVIRT);
2996}
2997
2998static void gt_hv_cval_write(CPUARMState *env, const ARMCPRegInfo *ri,
2999 uint64_t value)
3000{
3001 gt_cval_write(env, ri, GTIMER_HYPVIRT, value);
3002}
3003
3004static uint64_t gt_hv_tval_read(CPUARMState *env, const ARMCPRegInfo *ri)
3005{
3006 return gt_tval_read(env, ri, GTIMER_HYPVIRT);
3007}
3008
3009static void gt_hv_tval_write(CPUARMState *env, const ARMCPRegInfo *ri,
3010 uint64_t value)
3011{
3012 gt_tval_write(env, ri, GTIMER_HYPVIRT, value);
3013}
3014
3015static void gt_hv_ctl_write(CPUARMState *env, const ARMCPRegInfo *ri,
3016 uint64_t value)
3017{
3018 gt_ctl_write(env, ri, GTIMER_HYPVIRT, value);
3019}
3020
3021void arm_gt_ptimer_cb(void *opaque)
3022{
3023 ARMCPU *cpu = opaque;
3024
3025 gt_recalc_timer(cpu, GTIMER_PHYS);
3026}
3027
3028void arm_gt_vtimer_cb(void *opaque)
3029{
3030 ARMCPU *cpu = opaque;
3031
3032 gt_recalc_timer(cpu, GTIMER_VIRT);
3033}
3034
3035void arm_gt_htimer_cb(void *opaque)
3036{
3037 ARMCPU *cpu = opaque;
3038
3039 gt_recalc_timer(cpu, GTIMER_HYP);
3040}
3041
3042void arm_gt_stimer_cb(void *opaque)
3043{
3044 ARMCPU *cpu = opaque;
3045
3046 gt_recalc_timer(cpu, GTIMER_SEC);
3047}
3048
3049void arm_gt_hvtimer_cb(void *opaque)
3050{
3051 ARMCPU *cpu = opaque;
3052
3053 gt_recalc_timer(cpu, GTIMER_HYPVIRT);
3054}
3055
3056static void arm_gt_cntfrq_reset(CPUARMState *env, const ARMCPRegInfo *opaque)
3057{
3058 ARMCPU *cpu = env_archcpu(env);
3059
3060 cpu->env.cp15.c14_cntfrq = cpu->gt_cntfrq_hz;
3061}
3062
3063static const ARMCPRegInfo generic_timer_cp_reginfo[] = {
3064
3065
3066
3067
3068
3069 { .name = "CNTFRQ", .cp = 15, .crn = 14, .crm = 0, .opc1 = 0, .opc2 = 0,
3070 .type = ARM_CP_ALIAS,
3071 .access = PL1_RW | PL0_R, .accessfn = gt_cntfrq_access,
3072 .fieldoffset = offsetoflow32(CPUARMState, cp15.c14_cntfrq),
3073 },
3074 { .name = "CNTFRQ_EL0", .state = ARM_CP_STATE_AA64,
3075 .opc0 = 3, .opc1 = 3, .crn = 14, .crm = 0, .opc2 = 0,
3076 .access = PL1_RW | PL0_R, .accessfn = gt_cntfrq_access,
3077 .fieldoffset = offsetof(CPUARMState, cp15.c14_cntfrq),
3078 .resetfn = arm_gt_cntfrq_reset,
3079 },
3080
3081 { .name = "CNTKCTL", .state = ARM_CP_STATE_BOTH,
3082 .opc0 = 3, .opc1 = 0, .crn = 14, .crm = 1, .opc2 = 0,
3083 .access = PL1_RW,
3084 .fieldoffset = offsetof(CPUARMState, cp15.c14_cntkctl),
3085 .resetvalue = 0,
3086 },
3087
3088 { .name = "CNTP_CTL", .cp = 15, .crn = 14, .crm = 2, .opc1 = 0, .opc2 = 1,
3089 .secure = ARM_CP_SECSTATE_NS,
3090 .type = ARM_CP_IO | ARM_CP_ALIAS, .access = PL0_RW,
3091 .accessfn = gt_ptimer_access,
3092 .fieldoffset = offsetoflow32(CPUARMState,
3093 cp15.c14_timer[GTIMER_PHYS].ctl),
3094 .readfn = gt_phys_redir_ctl_read, .raw_readfn = raw_read,
3095 .writefn = gt_phys_redir_ctl_write, .raw_writefn = raw_write,
3096 },
3097 { .name = "CNTP_CTL_S",
3098 .cp = 15, .crn = 14, .crm = 2, .opc1 = 0, .opc2 = 1,
3099 .secure = ARM_CP_SECSTATE_S,
3100 .type = ARM_CP_IO | ARM_CP_ALIAS, .access = PL0_RW,
3101 .accessfn = gt_ptimer_access,
3102 .fieldoffset = offsetoflow32(CPUARMState,
3103 cp15.c14_timer[GTIMER_SEC].ctl),
3104 .writefn = gt_sec_ctl_write, .raw_writefn = raw_write,
3105 },
3106 { .name = "CNTP_CTL_EL0", .state = ARM_CP_STATE_AA64,
3107 .opc0 = 3, .opc1 = 3, .crn = 14, .crm = 2, .opc2 = 1,
3108 .type = ARM_CP_IO, .access = PL0_RW,
3109 .accessfn = gt_ptimer_access,
3110 .fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_PHYS].ctl),
3111 .resetvalue = 0,
3112 .readfn = gt_phys_redir_ctl_read, .raw_readfn = raw_read,
3113 .writefn = gt_phys_redir_ctl_write, .raw_writefn = raw_write,
3114 },
3115 { .name = "CNTV_CTL", .cp = 15, .crn = 14, .crm = 3, .opc1 = 0, .opc2 = 1,
3116 .type = ARM_CP_IO | ARM_CP_ALIAS, .access = PL0_RW,
3117 .accessfn = gt_vtimer_access,
3118 .fieldoffset = offsetoflow32(CPUARMState,
3119 cp15.c14_timer[GTIMER_VIRT].ctl),
3120 .readfn = gt_virt_redir_ctl_read, .raw_readfn = raw_read,
3121 .writefn = gt_virt_redir_ctl_write, .raw_writefn = raw_write,
3122 },
3123 { .name = "CNTV_CTL_EL0", .state = ARM_CP_STATE_AA64,
3124 .opc0 = 3, .opc1 = 3, .crn = 14, .crm = 3, .opc2 = 1,
3125 .type = ARM_CP_IO, .access = PL0_RW,
3126 .accessfn = gt_vtimer_access,
3127 .fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_VIRT].ctl),
3128 .resetvalue = 0,
3129 .readfn = gt_virt_redir_ctl_read, .raw_readfn = raw_read,
3130 .writefn = gt_virt_redir_ctl_write, .raw_writefn = raw_write,
3131 },
3132
3133 { .name = "CNTP_TVAL", .cp = 15, .crn = 14, .crm = 2, .opc1 = 0, .opc2 = 0,
3134 .secure = ARM_CP_SECSTATE_NS,
3135 .type = ARM_CP_NO_RAW | ARM_CP_IO, .access = PL0_RW,
3136 .accessfn = gt_ptimer_access,
3137 .readfn = gt_phys_redir_tval_read, .writefn = gt_phys_redir_tval_write,
3138 },
3139 { .name = "CNTP_TVAL_S",
3140 .cp = 15, .crn = 14, .crm = 2, .opc1 = 0, .opc2 = 0,
3141 .secure = ARM_CP_SECSTATE_S,
3142 .type = ARM_CP_NO_RAW | ARM_CP_IO, .access = PL0_RW,
3143 .accessfn = gt_ptimer_access,
3144 .readfn = gt_sec_tval_read, .writefn = gt_sec_tval_write,
3145 },
3146 { .name = "CNTP_TVAL_EL0", .state = ARM_CP_STATE_AA64,
3147 .opc0 = 3, .opc1 = 3, .crn = 14, .crm = 2, .opc2 = 0,
3148 .type = ARM_CP_NO_RAW | ARM_CP_IO, .access = PL0_RW,
3149 .accessfn = gt_ptimer_access, .resetfn = gt_phys_timer_reset,
3150 .readfn = gt_phys_redir_tval_read, .writefn = gt_phys_redir_tval_write,
3151 },
3152 { .name = "CNTV_TVAL", .cp = 15, .crn = 14, .crm = 3, .opc1 = 0, .opc2 = 0,
3153 .type = ARM_CP_NO_RAW | ARM_CP_IO, .access = PL0_RW,
3154 .accessfn = gt_vtimer_access,
3155 .readfn = gt_virt_redir_tval_read, .writefn = gt_virt_redir_tval_write,
3156 },
3157 { .name = "CNTV_TVAL_EL0", .state = ARM_CP_STATE_AA64,
3158 .opc0 = 3, .opc1 = 3, .crn = 14, .crm = 3, .opc2 = 0,
3159 .type = ARM_CP_NO_RAW | ARM_CP_IO, .access = PL0_RW,
3160 .accessfn = gt_vtimer_access, .resetfn = gt_virt_timer_reset,
3161 .readfn = gt_virt_redir_tval_read, .writefn = gt_virt_redir_tval_write,
3162 },
3163
3164 { .name = "CNTPCT", .cp = 15, .crm = 14, .opc1 = 0,
3165 .access = PL0_R, .type = ARM_CP_64BIT | ARM_CP_NO_RAW | ARM_CP_IO,
3166 .accessfn = gt_pct_access,
3167 .readfn = gt_cnt_read, .resetfn = arm_cp_reset_ignore,
3168 },
3169 { .name = "CNTPCT_EL0", .state = ARM_CP_STATE_AA64,
3170 .opc0 = 3, .opc1 = 3, .crn = 14, .crm = 0, .opc2 = 1,
3171 .access = PL0_R, .type = ARM_CP_NO_RAW | ARM_CP_IO,
3172 .accessfn = gt_pct_access, .readfn = gt_cnt_read,
3173 },
3174 { .name = "CNTVCT", .cp = 15, .crm = 14, .opc1 = 1,
3175 .access = PL0_R, .type = ARM_CP_64BIT | ARM_CP_NO_RAW | ARM_CP_IO,
3176 .accessfn = gt_vct_access,
3177 .readfn = gt_virt_cnt_read, .resetfn = arm_cp_reset_ignore,
3178 },
3179 { .name = "CNTVCT_EL0", .state = ARM_CP_STATE_AA64,
3180 .opc0 = 3, .opc1 = 3, .crn = 14, .crm = 0, .opc2 = 2,
3181 .access = PL0_R, .type = ARM_CP_NO_RAW | ARM_CP_IO,
3182 .accessfn = gt_vct_access, .readfn = gt_virt_cnt_read,
3183 },
3184
3185 { .name = "CNTP_CVAL", .cp = 15, .crm = 14, .opc1 = 2,
3186 .secure = ARM_CP_SECSTATE_NS,
3187 .access = PL0_RW,
3188 .type = ARM_CP_64BIT | ARM_CP_IO | ARM_CP_ALIAS,
3189 .fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_PHYS].cval),
3190 .accessfn = gt_ptimer_access,
3191 .readfn = gt_phys_redir_cval_read, .raw_readfn = raw_read,
3192 .writefn = gt_phys_redir_cval_write, .raw_writefn = raw_write,
3193 },
3194 { .name = "CNTP_CVAL_S", .cp = 15, .crm = 14, .opc1 = 2,
3195 .secure = ARM_CP_SECSTATE_S,
3196 .access = PL0_RW,
3197 .type = ARM_CP_64BIT | ARM_CP_IO | ARM_CP_ALIAS,
3198 .fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_SEC].cval),
3199 .accessfn = gt_ptimer_access,
3200 .writefn = gt_sec_cval_write, .raw_writefn = raw_write,
3201 },
3202 { .name = "CNTP_CVAL_EL0", .state = ARM_CP_STATE_AA64,
3203 .opc0 = 3, .opc1 = 3, .crn = 14, .crm = 2, .opc2 = 2,
3204 .access = PL0_RW,
3205 .type = ARM_CP_IO,
3206 .fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_PHYS].cval),
3207 .resetvalue = 0, .accessfn = gt_ptimer_access,
3208 .readfn = gt_phys_redir_cval_read, .raw_readfn = raw_read,
3209 .writefn = gt_phys_redir_cval_write, .raw_writefn = raw_write,
3210 },
3211 { .name = "CNTV_CVAL", .cp = 15, .crm = 14, .opc1 = 3,
3212 .access = PL0_RW,
3213 .type = ARM_CP_64BIT | ARM_CP_IO | ARM_CP_ALIAS,
3214 .fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_VIRT].cval),
3215 .accessfn = gt_vtimer_access,
3216 .readfn = gt_virt_redir_cval_read, .raw_readfn = raw_read,
3217 .writefn = gt_virt_redir_cval_write, .raw_writefn = raw_write,
3218 },
3219 { .name = "CNTV_CVAL_EL0", .state = ARM_CP_STATE_AA64,
3220 .opc0 = 3, .opc1 = 3, .crn = 14, .crm = 3, .opc2 = 2,
3221 .access = PL0_RW,
3222 .type = ARM_CP_IO,
3223 .fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_VIRT].cval),
3224 .resetvalue = 0, .accessfn = gt_vtimer_access,
3225 .readfn = gt_virt_redir_cval_read, .raw_readfn = raw_read,
3226 .writefn = gt_virt_redir_cval_write, .raw_writefn = raw_write,
3227 },
3228
3229
3230
3231
3232 { .name = "CNTPS_TVAL_EL1", .state = ARM_CP_STATE_AA64,
3233 .opc0 = 3, .opc1 = 7, .crn = 14, .crm = 2, .opc2 = 0,
3234 .type = ARM_CP_NO_RAW | ARM_CP_IO, .access = PL1_RW,
3235 .accessfn = gt_stimer_access,
3236 .readfn = gt_sec_tval_read,
3237 .writefn = gt_sec_tval_write,
3238 .resetfn = gt_sec_timer_reset,
3239 },
3240 { .name = "CNTPS_CTL_EL1", .state = ARM_CP_STATE_AA64,
3241 .opc0 = 3, .opc1 = 7, .crn = 14, .crm = 2, .opc2 = 1,
3242 .type = ARM_CP_IO, .access = PL1_RW,
3243 .accessfn = gt_stimer_access,
3244 .fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_SEC].ctl),
3245 .resetvalue = 0,
3246 .writefn = gt_sec_ctl_write, .raw_writefn = raw_write,
3247 },
3248 { .name = "CNTPS_CVAL_EL1", .state = ARM_CP_STATE_AA64,
3249 .opc0 = 3, .opc1 = 7, .crn = 14, .crm = 2, .opc2 = 2,
3250 .type = ARM_CP_IO, .access = PL1_RW,
3251 .accessfn = gt_stimer_access,
3252 .fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_SEC].cval),
3253 .writefn = gt_sec_cval_write, .raw_writefn = raw_write,
3254 },
3255};
3256
3257static CPAccessResult e2h_access(CPUARMState *env, const ARMCPRegInfo *ri,
3258 bool isread)
3259{
3260 if (!(arm_hcr_el2_eff(env) & HCR_E2H)) {
3261 return CP_ACCESS_TRAP;
3262 }
3263 return CP_ACCESS_OK;
3264}
3265
3266#else
3267
3268
3269
3270
3271
3272
3273static uint64_t gt_virt_cnt_read(CPUARMState *env, const ARMCPRegInfo *ri)
3274{
3275 ARMCPU *cpu = env_archcpu(env);
3276
3277
3278
3279
3280
3281
3282 return cpu_get_clock() / gt_cntfrq_period_ns(cpu);
3283}
3284
3285static const ARMCPRegInfo generic_timer_cp_reginfo[] = {
3286 { .name = "CNTFRQ_EL0", .state = ARM_CP_STATE_AA64,
3287 .opc0 = 3, .opc1 = 3, .crn = 14, .crm = 0, .opc2 = 0,
3288 .type = ARM_CP_CONST, .access = PL0_R ,
3289 .fieldoffset = offsetof(CPUARMState, cp15.c14_cntfrq),
3290 .resetvalue = NANOSECONDS_PER_SECOND / GTIMER_SCALE,
3291 },
3292 { .name = "CNTVCT_EL0", .state = ARM_CP_STATE_AA64,
3293 .opc0 = 3, .opc1 = 3, .crn = 14, .crm = 0, .opc2 = 2,
3294 .access = PL0_R, .type = ARM_CP_NO_RAW | ARM_CP_IO,
3295 .readfn = gt_virt_cnt_read,
3296 },
3297};
3298
3299#endif
3300
3301static void par_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
3302{
3303 if (arm_feature(env, ARM_FEATURE_LPAE)) {
3304 raw_write(env, ri, value);
3305 } else if (arm_feature(env, ARM_FEATURE_V7)) {
3306 raw_write(env, ri, value & 0xfffff6ff);
3307 } else {
3308 raw_write(env, ri, value & 0xfffff1ff);
3309 }
3310}
3311
3312#ifndef CONFIG_USER_ONLY
3313
3314
3315static CPAccessResult ats_access(CPUARMState *env, const ARMCPRegInfo *ri,
3316 bool isread)
3317{
3318 if (ri->opc2 & 4) {
3319
3320
3321
3322
3323
3324
3325 if (arm_current_el(env) == 1) {
3326 if (arm_is_secure_below_el3(env)) {
3327 if (env->cp15.scr_el3 & SCR_EEL2) {
3328 return CP_ACCESS_TRAP_EL2;
3329 }
3330 return CP_ACCESS_TRAP_EL3;
3331 }
3332 return CP_ACCESS_TRAP_UNCATEGORIZED;
3333 }
3334 }
3335 return CP_ACCESS_OK;
3336}
3337
3338#ifdef CONFIG_TCG
3339static uint64_t do_ats_write(CPUARMState *env, uint64_t value,
3340 MMUAccessType access_type, ARMMMUIdx mmu_idx,
3341 bool is_secure)
3342{
3343 bool ret;
3344 uint64_t par64;
3345 bool format64 = false;
3346 ARMMMUFaultInfo fi = {};
3347 GetPhysAddrResult res = {};
3348
3349 ret = get_phys_addr_with_secure(env, value, access_type, mmu_idx,
3350 is_secure, &res, &fi);
3351
3352
3353
3354
3355
3356 assert(!res.cacheattrs.is_s2_format);
3357
3358 if (ret) {
3359
3360
3361
3362
3363 int current_el = arm_current_el(env);
3364 int target_el;
3365 uint32_t syn, fsr, fsc;
3366 bool take_exc = false;
3367
3368 if (fi.s1ptw && current_el == 1
3369 && arm_mmu_idx_is_stage1_of_2(mmu_idx)) {
3370
3371
3372
3373
3374
3375
3376
3377
3378 if (fi.type == ARMFault_SyncExternalOnWalk &&
3379 (env->cp15.scr_el3 & SCR_EA)) {
3380 target_el = 3;
3381 } else {
3382 env->cp15.hpfar_el2 = extract64(fi.s2addr, 12, 47) << 4;
3383 if (arm_is_secure_below_el3(env) && fi.s1ns) {
3384 env->cp15.hpfar_el2 |= HPFAR_NS;
3385 }
3386 target_el = 2;
3387 }
3388 take_exc = true;
3389 } else if (fi.type == ARMFault_SyncExternalOnWalk) {
3390
3391
3392
3393
3394 if (fi.stage2) {
3395 if (current_el == 3) {
3396 target_el = 3;
3397 } else {
3398 target_el = 2;
3399 }
3400 } else {
3401 target_el = exception_target_el(env);
3402 }
3403 take_exc = true;
3404 }
3405
3406 if (take_exc) {
3407
3408 if (target_el == 2 || arm_el_is_aa64(env, target_el) ||
3409 arm_s1_regime_using_lpae_format(env, mmu_idx)) {
3410 fsr = arm_fi_to_lfsc(&fi);
3411 fsc = extract32(fsr, 0, 6);
3412 } else {
3413 fsr = arm_fi_to_sfsc(&fi);
3414 fsc = 0x3f;
3415 }
3416
3417
3418
3419
3420 syn = syn_data_abort_no_iss(current_el == target_el, 0,
3421 fi.ea, 1, fi.s1ptw, 1, fsc);
3422 env->exception.vaddress = value;
3423 env->exception.fsr = fsr;
3424 raise_exception(env, EXCP_DATA_ABORT, syn, target_el);
3425 }
3426 }
3427
3428 if (is_a64(env)) {
3429 format64 = true;
3430 } else if (arm_feature(env, ARM_FEATURE_LPAE)) {
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445 format64 = arm_s1_regime_using_lpae_format(env, mmu_idx);
3446
3447 if (arm_feature(env, ARM_FEATURE_EL2)) {
3448 if (mmu_idx == ARMMMUIdx_E10_0 ||
3449 mmu_idx == ARMMMUIdx_E10_1 ||
3450 mmu_idx == ARMMMUIdx_E10_1_PAN) {
3451 format64 |= env->cp15.hcr_el2 & (HCR_VM | HCR_DC);
3452 } else {
3453 format64 |= arm_current_el(env) == 2;
3454 }
3455 }
3456 }
3457
3458 if (format64) {
3459
3460 par64 = (1 << 11);
3461 if (!ret) {
3462 par64 |= res.f.phys_addr & ~0xfffULL;
3463 if (!res.f.attrs.secure) {
3464 par64 |= (1 << 9);
3465 }
3466 par64 |= (uint64_t)res.cacheattrs.attrs << 56;
3467 par64 |= res.cacheattrs.shareability << 7;
3468 } else {
3469 uint32_t fsr = arm_fi_to_lfsc(&fi);
3470
3471 par64 |= 1;
3472 par64 |= (fsr & 0x3f) << 1;
3473 if (fi.stage2) {
3474 par64 |= (1 << 9);
3475 }
3476 if (fi.s1ptw) {
3477 par64 |= (1 << 8);
3478 }
3479 }
3480 } else {
3481
3482
3483
3484
3485
3486 if (!ret) {
3487
3488 if (res.f.lg_page_size == 24
3489 && arm_feature(env, ARM_FEATURE_V7)) {
3490 par64 = (res.f.phys_addr & 0xff000000) | (1 << 1);
3491 } else {
3492 par64 = res.f.phys_addr & 0xfffff000;
3493 }
3494 if (!res.f.attrs.secure) {
3495 par64 |= (1 << 9);
3496 }
3497 } else {
3498 uint32_t fsr = arm_fi_to_sfsc(&fi);
3499
3500 par64 = ((fsr & (1 << 10)) >> 5) | ((fsr & (1 << 12)) >> 6) |
3501 ((fsr & 0xf) << 1) | 1;
3502 }
3503 }
3504 return par64;
3505}
3506#endif
3507
3508static void ats_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
3509{
3510#ifdef CONFIG_TCG
3511 MMUAccessType access_type = ri->opc2 & 1 ? MMU_DATA_STORE : MMU_DATA_LOAD;
3512 uint64_t par64;
3513 ARMMMUIdx mmu_idx;
3514 int el = arm_current_el(env);
3515 bool secure = arm_is_secure_below_el3(env);
3516
3517 switch (ri->opc2 & 6) {
3518 case 0:
3519
3520 switch (el) {
3521 case 3:
3522 mmu_idx = ARMMMUIdx_E3;
3523 secure = true;
3524 break;
3525 case 2:
3526 g_assert(!secure);
3527
3528 case 1:
3529 if (ri->crm == 9 && (env->uncached_cpsr & CPSR_PAN)) {
3530 mmu_idx = ARMMMUIdx_Stage1_E1_PAN;
3531 } else {
3532 mmu_idx = ARMMMUIdx_Stage1_E1;
3533 }
3534 break;
3535 default:
3536 g_assert_not_reached();
3537 }
3538 break;
3539 case 2:
3540
3541 switch (el) {
3542 case 3:
3543 mmu_idx = ARMMMUIdx_E10_0;
3544 secure = true;
3545 break;
3546 case 2:
3547 g_assert(!secure);
3548 mmu_idx = ARMMMUIdx_Stage1_E0;
3549 break;
3550 case 1:
3551 mmu_idx = ARMMMUIdx_Stage1_E0;
3552 break;
3553 default:
3554 g_assert_not_reached();
3555 }
3556 break;
3557 case 4:
3558
3559 mmu_idx = ARMMMUIdx_E10_1;
3560 secure = false;
3561 break;
3562 case 6:
3563
3564 mmu_idx = ARMMMUIdx_E10_0;
3565 secure = false;
3566 break;
3567 default:
3568 g_assert_not_reached();
3569 }
3570
3571 par64 = do_ats_write(env, value, access_type, mmu_idx, secure);
3572
3573 A32_BANKED_CURRENT_REG_SET(env, par, par64);
3574#else
3575
3576 g_assert_not_reached();
3577#endif
3578}
3579
3580static void ats1h_write(CPUARMState *env, const ARMCPRegInfo *ri,
3581 uint64_t value)
3582{
3583#ifdef CONFIG_TCG
3584 MMUAccessType access_type = ri->opc2 & 1 ? MMU_DATA_STORE : MMU_DATA_LOAD;
3585 uint64_t par64;
3586
3587
3588 par64 = do_ats_write(env, value, access_type, ARMMMUIdx_E2, false);
3589
3590 A32_BANKED_CURRENT_REG_SET(env, par, par64);
3591#else
3592
3593 g_assert_not_reached();
3594#endif
3595}
3596
3597static CPAccessResult at_s1e2_access(CPUARMState *env, const ARMCPRegInfo *ri,
3598 bool isread)
3599{
3600 if (arm_current_el(env) == 3 &&
3601 !(env->cp15.scr_el3 & (SCR_NS | SCR_EEL2))) {
3602 return CP_ACCESS_TRAP;
3603 }
3604 return CP_ACCESS_OK;
3605}
3606
3607static void ats_write64(CPUARMState *env, const ARMCPRegInfo *ri,
3608 uint64_t value)
3609{
3610#ifdef CONFIG_TCG
3611 MMUAccessType access_type = ri->opc2 & 1 ? MMU_DATA_STORE : MMU_DATA_LOAD;
3612 ARMMMUIdx mmu_idx;
3613 int secure = arm_is_secure_below_el3(env);
3614 uint64_t hcr_el2 = arm_hcr_el2_eff(env);
3615 bool regime_e20 = (hcr_el2 & (HCR_E2H | HCR_TGE)) == (HCR_E2H | HCR_TGE);
3616
3617 switch (ri->opc2 & 6) {
3618 case 0:
3619 switch (ri->opc1) {
3620 case 0:
3621 if (ri->crm == 9 && (env->pstate & PSTATE_PAN)) {
3622 mmu_idx = regime_e20 ?
3623 ARMMMUIdx_E20_2_PAN : ARMMMUIdx_Stage1_E1_PAN;
3624 } else {
3625 mmu_idx = regime_e20 ? ARMMMUIdx_E20_2 : ARMMMUIdx_Stage1_E1;
3626 }
3627 break;
3628 case 4:
3629 mmu_idx = hcr_el2 & HCR_E2H ? ARMMMUIdx_E20_2 : ARMMMUIdx_E2;
3630 break;
3631 case 6:
3632 mmu_idx = ARMMMUIdx_E3;
3633 secure = true;
3634 break;
3635 default:
3636 g_assert_not_reached();
3637 }
3638 break;
3639 case 2:
3640 mmu_idx = regime_e20 ? ARMMMUIdx_E20_0 : ARMMMUIdx_Stage1_E0;
3641 break;
3642 case 4:
3643 mmu_idx = regime_e20 ? ARMMMUIdx_E20_2 : ARMMMUIdx_E10_1;
3644 break;
3645 case 6:
3646 mmu_idx = regime_e20 ? ARMMMUIdx_E20_0 : ARMMMUIdx_E10_0;
3647 break;
3648 default:
3649 g_assert_not_reached();
3650 }
3651
3652 env->cp15.par_el[1] = do_ats_write(env, value, access_type,
3653 mmu_idx, secure);
3654#else
3655
3656 g_assert_not_reached();
3657#endif
3658}
3659#endif
3660
3661static const ARMCPRegInfo vapa_cp_reginfo[] = {
3662 { .name = "PAR", .cp = 15, .crn = 7, .crm = 4, .opc1 = 0, .opc2 = 0,
3663 .access = PL1_RW, .resetvalue = 0,
3664 .bank_fieldoffsets = { offsetoflow32(CPUARMState, cp15.par_s),
3665 offsetoflow32(CPUARMState, cp15.par_ns) },
3666 .writefn = par_write },
3667#ifndef CONFIG_USER_ONLY
3668
3669 { .name = "ATS", .cp = 15, .crn = 7, .crm = 8, .opc1 = 0, .opc2 = CP_ANY,
3670 .access = PL1_W, .accessfn = ats_access,
3671 .writefn = ats_write, .type = ARM_CP_NO_RAW | ARM_CP_RAISES_EXC },
3672#endif
3673};
3674
3675
3676static uint32_t simple_mpu_ap_bits(uint32_t val)
3677{
3678 uint32_t ret;
3679 uint32_t mask;
3680 int i;
3681 ret = 0;
3682 mask = 3;
3683 for (i = 0; i < 16; i += 2) {
3684 ret |= (val >> i) & mask;
3685 mask <<= 2;
3686 }
3687 return ret;
3688}
3689
3690
3691static uint32_t extended_mpu_ap_bits(uint32_t val)
3692{
3693 uint32_t ret;
3694 uint32_t mask;
3695 int i;
3696 ret = 0;
3697 mask = 3;
3698 for (i = 0; i < 16; i += 2) {
3699 ret |= (val & mask) << i;
3700 mask <<= 2;
3701 }
3702 return ret;
3703}
3704
3705static void pmsav5_data_ap_write(CPUARMState *env, const ARMCPRegInfo *ri,
3706 uint64_t value)
3707{
3708 env->cp15.pmsav5_data_ap = extended_mpu_ap_bits(value);
3709}
3710
3711static uint64_t pmsav5_data_ap_read(CPUARMState *env, const ARMCPRegInfo *ri)
3712{
3713 return simple_mpu_ap_bits(env->cp15.pmsav5_data_ap);
3714}
3715
3716static void pmsav5_insn_ap_write(CPUARMState *env, const ARMCPRegInfo *ri,
3717 uint64_t value)
3718{
3719 env->cp15.pmsav5_insn_ap = extended_mpu_ap_bits(value);
3720}
3721
3722static uint64_t pmsav5_insn_ap_read(CPUARMState *env, const ARMCPRegInfo *ri)
3723{
3724 return simple_mpu_ap_bits(env->cp15.pmsav5_insn_ap);
3725}
3726
3727static uint64_t pmsav7_read(CPUARMState *env, const ARMCPRegInfo *ri)
3728{
3729 uint32_t *u32p = *(uint32_t **)raw_ptr(env, ri);
3730
3731 if (!u32p) {
3732 return 0;
3733 }
3734
3735 u32p += env->pmsav7.rnr[M_REG_NS];
3736 return *u32p;
3737}
3738
3739static void pmsav7_write(CPUARMState *env, const ARMCPRegInfo *ri,
3740 uint64_t value)
3741{
3742 ARMCPU *cpu = env_archcpu(env);
3743 uint32_t *u32p = *(uint32_t **)raw_ptr(env, ri);
3744
3745 if (!u32p) {
3746 return;
3747 }
3748
3749 u32p += env->pmsav7.rnr[M_REG_NS];
3750 tlb_flush(CPU(cpu));
3751 *u32p = value;
3752}
3753
3754static void pmsav7_rgnr_write(CPUARMState *env, const ARMCPRegInfo *ri,
3755 uint64_t value)
3756{
3757 ARMCPU *cpu = env_archcpu(env);
3758 uint32_t nrgs = cpu->pmsav7_dregion;
3759
3760 if (value >= nrgs) {
3761 qemu_log_mask(LOG_GUEST_ERROR,
3762 "PMSAv7 RGNR write >= # supported regions, %" PRIu32
3763 " > %" PRIu32 "\n", (uint32_t)value, nrgs);
3764 return;
3765 }
3766
3767 raw_write(env, ri, value);
3768}
3769
3770static void prbar_write(CPUARMState *env, const ARMCPRegInfo *ri,
3771 uint64_t value)
3772{
3773 ARMCPU *cpu = env_archcpu(env);
3774
3775 tlb_flush(CPU(cpu));
3776 env->pmsav8.rbar[M_REG_NS][env->pmsav7.rnr[M_REG_NS]] = value;
3777}
3778
3779static uint64_t prbar_read(CPUARMState *env, const ARMCPRegInfo *ri)
3780{
3781 return env->pmsav8.rbar[M_REG_NS][env->pmsav7.rnr[M_REG_NS]];
3782}
3783
3784static void prlar_write(CPUARMState *env, const ARMCPRegInfo *ri,
3785 uint64_t value)
3786{
3787 ARMCPU *cpu = env_archcpu(env);
3788
3789 tlb_flush(CPU(cpu));
3790 env->pmsav8.rlar[M_REG_NS][env->pmsav7.rnr[M_REG_NS]] = value;
3791}
3792
3793static uint64_t prlar_read(CPUARMState *env, const ARMCPRegInfo *ri)
3794{
3795 return env->pmsav8.rlar[M_REG_NS][env->pmsav7.rnr[M_REG_NS]];
3796}
3797
3798static void prselr_write(CPUARMState *env, const ARMCPRegInfo *ri,
3799 uint64_t value)
3800{
3801 ARMCPU *cpu = env_archcpu(env);
3802
3803
3804
3805
3806
3807 if (value >= cpu->pmsav7_dregion) {
3808 return;
3809 }
3810
3811 env->pmsav7.rnr[M_REG_NS] = value;
3812}
3813
3814static void hprbar_write(CPUARMState *env, const ARMCPRegInfo *ri,
3815 uint64_t value)
3816{
3817 ARMCPU *cpu = env_archcpu(env);
3818
3819 tlb_flush(CPU(cpu));
3820 env->pmsav8.hprbar[env->pmsav8.hprselr] = value;
3821}
3822
3823static uint64_t hprbar_read(CPUARMState *env, const ARMCPRegInfo *ri)
3824{
3825 return env->pmsav8.hprbar[env->pmsav8.hprselr];
3826}
3827
3828static void hprlar_write(CPUARMState *env, const ARMCPRegInfo *ri,
3829 uint64_t value)
3830{
3831 ARMCPU *cpu = env_archcpu(env);
3832
3833 tlb_flush(CPU(cpu));
3834 env->pmsav8.hprlar[env->pmsav8.hprselr] = value;
3835}
3836
3837static uint64_t hprlar_read(CPUARMState *env, const ARMCPRegInfo *ri)
3838{
3839 return env->pmsav8.hprlar[env->pmsav8.hprselr];
3840}
3841
3842static void hprenr_write(CPUARMState *env, const ARMCPRegInfo *ri,
3843 uint64_t value)
3844{
3845 uint32_t n;
3846 uint32_t bit;
3847 ARMCPU *cpu = env_archcpu(env);
3848
3849
3850 int rmax = MIN(cpu->pmsav8r_hdregion, 32);
3851 value &= MAKE_64BIT_MASK(0, rmax);
3852
3853 tlb_flush(CPU(cpu));
3854
3855
3856 for (n = 0; n < rmax; ++n) {
3857 bit = extract32(value, n, 1);
3858 env->pmsav8.hprlar[n] = deposit32(
3859 env->pmsav8.hprlar[n], 0, 1, bit);
3860 }
3861}
3862
3863static uint64_t hprenr_read(CPUARMState *env, const ARMCPRegInfo *ri)
3864{
3865 uint32_t n;
3866 uint32_t result = 0x0;
3867 ARMCPU *cpu = env_archcpu(env);
3868
3869
3870 for (n = 0; n < MIN(cpu->pmsav8r_hdregion, 32); ++n) {
3871 if (env->pmsav8.hprlar[n] & 0x1) {
3872 result |= (0x1 << n);
3873 }
3874 }
3875 return result;
3876}
3877
3878static void hprselr_write(CPUARMState *env, const ARMCPRegInfo *ri,
3879 uint64_t value)
3880{
3881 ARMCPU *cpu = env_archcpu(env);
3882
3883
3884
3885
3886
3887 if (value >= cpu->pmsav8r_hdregion) {
3888 return;
3889 }
3890
3891 env->pmsav8.hprselr = value;
3892}
3893
3894static void pmsav8r_regn_write(CPUARMState *env, const ARMCPRegInfo *ri,
3895 uint64_t value)
3896{
3897 ARMCPU *cpu = env_archcpu(env);
3898 uint8_t index = (extract32(ri->opc0, 0, 1) << 4) |
3899 (extract32(ri->crm, 0, 3) << 1) | extract32(ri->opc2, 2, 1);
3900
3901 tlb_flush(CPU(cpu));
3902
3903 if (ri->opc1 & 4) {
3904 if (index >= cpu->pmsav8r_hdregion) {
3905 return;
3906 }
3907 if (ri->opc2 & 0x1) {
3908 env->pmsav8.hprlar[index] = value;
3909 } else {
3910 env->pmsav8.hprbar[index] = value;
3911 }
3912 } else {
3913 if (index >= cpu->pmsav7_dregion) {
3914 return;
3915 }
3916 if (ri->opc2 & 0x1) {
3917 env->pmsav8.rlar[M_REG_NS][index] = value;
3918 } else {
3919 env->pmsav8.rbar[M_REG_NS][index] = value;
3920 }
3921 }
3922}
3923
3924static uint64_t pmsav8r_regn_read(CPUARMState *env, const ARMCPRegInfo *ri)
3925{
3926 ARMCPU *cpu = env_archcpu(env);
3927 uint8_t index = (extract32(ri->opc0, 0, 1) << 4) |
3928 (extract32(ri->crm, 0, 3) << 1) | extract32(ri->opc2, 2, 1);
3929
3930 if (ri->opc1 & 4) {
3931 if (index >= cpu->pmsav8r_hdregion) {
3932 return 0x0;
3933 }
3934 if (ri->opc2 & 0x1) {
3935 return env->pmsav8.hprlar[index];
3936 } else {
3937 return env->pmsav8.hprbar[index];
3938 }
3939 } else {
3940 if (index >= cpu->pmsav7_dregion) {
3941 return 0x0;
3942 }
3943 if (ri->opc2 & 0x1) {
3944 return env->pmsav8.rlar[M_REG_NS][index];
3945 } else {
3946 return env->pmsav8.rbar[M_REG_NS][index];
3947 }
3948 }
3949}
3950
3951static const ARMCPRegInfo pmsav8r_cp_reginfo[] = {
3952 { .name = "PRBAR",
3953 .cp = 15, .opc1 = 0, .crn = 6, .crm = 3, .opc2 = 0,
3954 .access = PL1_RW, .type = ARM_CP_NO_RAW,
3955 .accessfn = access_tvm_trvm,
3956 .readfn = prbar_read, .writefn = prbar_write },
3957 { .name = "PRLAR",
3958 .cp = 15, .opc1 = 0, .crn = 6, .crm = 3, .opc2 = 1,
3959 .access = PL1_RW, .type = ARM_CP_NO_RAW,
3960 .accessfn = access_tvm_trvm,
3961 .readfn = prlar_read, .writefn = prlar_write },
3962 { .name = "PRSELR", .resetvalue = 0,
3963 .cp = 15, .opc1 = 0, .crn = 6, .crm = 2, .opc2 = 1,
3964 .access = PL1_RW, .accessfn = access_tvm_trvm,
3965 .writefn = prselr_write,
3966 .fieldoffset = offsetof(CPUARMState, pmsav7.rnr[M_REG_NS]) },
3967 { .name = "HPRBAR", .resetvalue = 0,
3968 .cp = 15, .opc1 = 4, .crn = 6, .crm = 3, .opc2 = 0,
3969 .access = PL2_RW, .type = ARM_CP_NO_RAW,
3970 .readfn = hprbar_read, .writefn = hprbar_write },
3971 { .name = "HPRLAR",
3972 .cp = 15, .opc1 = 4, .crn = 6, .crm = 3, .opc2 = 1,
3973 .access = PL2_RW, .type = ARM_CP_NO_RAW,
3974 .readfn = hprlar_read, .writefn = hprlar_write },
3975 { .name = "HPRSELR", .resetvalue = 0,
3976 .cp = 15, .opc1 = 4, .crn = 6, .crm = 2, .opc2 = 1,
3977 .access = PL2_RW,
3978 .writefn = hprselr_write,
3979 .fieldoffset = offsetof(CPUARMState, pmsav8.hprselr) },
3980 { .name = "HPRENR",
3981 .cp = 15, .opc1 = 4, .crn = 6, .crm = 1, .opc2 = 1,
3982 .access = PL2_RW, .type = ARM_CP_NO_RAW,
3983 .readfn = hprenr_read, .writefn = hprenr_write },
3984};
3985
3986static const ARMCPRegInfo pmsav7_cp_reginfo[] = {
3987
3988
3989
3990
3991
3992 { .name = "DRBAR", .cp = 15, .crn = 6, .opc1 = 0, .crm = 1, .opc2 = 0,
3993 .access = PL1_RW, .type = ARM_CP_NO_RAW,
3994 .fieldoffset = offsetof(CPUARMState, pmsav7.drbar),
3995 .readfn = pmsav7_read, .writefn = pmsav7_write,
3996 .resetfn = arm_cp_reset_ignore },
3997 { .name = "DRSR", .cp = 15, .crn = 6, .opc1 = 0, .crm = 1, .opc2 = 2,
3998 .access = PL1_RW, .type = ARM_CP_NO_RAW,
3999 .fieldoffset = offsetof(CPUARMState, pmsav7.drsr),
4000 .readfn = pmsav7_read, .writefn = pmsav7_write,
4001 .resetfn = arm_cp_reset_ignore },
4002 { .name = "DRACR", .cp = 15, .crn = 6, .opc1 = 0, .crm = 1, .opc2 = 4,
4003 .access = PL1_RW, .type = ARM_CP_NO_RAW,
4004 .fieldoffset = offsetof(CPUARMState, pmsav7.dracr),
4005 .readfn = pmsav7_read, .writefn = pmsav7_write,
4006 .resetfn = arm_cp_reset_ignore },
4007 { .name = "RGNR", .cp = 15, .crn = 6, .opc1 = 0, .crm = 2, .opc2 = 0,
4008 .access = PL1_RW,
4009 .fieldoffset = offsetof(CPUARMState, pmsav7.rnr[M_REG_NS]),
4010 .writefn = pmsav7_rgnr_write,
4011 .resetfn = arm_cp_reset_ignore },
4012};
4013
4014static const ARMCPRegInfo pmsav5_cp_reginfo[] = {
4015 { .name = "DATA_AP", .cp = 15, .crn = 5, .crm = 0, .opc1 = 0, .opc2 = 0,
4016 .access = PL1_RW, .type = ARM_CP_ALIAS,
4017 .fieldoffset = offsetof(CPUARMState, cp15.pmsav5_data_ap),
4018 .readfn = pmsav5_data_ap_read, .writefn = pmsav5_data_ap_write, },
4019 { .name = "INSN_AP", .cp = 15, .crn = 5, .crm = 0, .opc1 = 0, .opc2 = 1,
4020 .access = PL1_RW, .type = ARM_CP_ALIAS,
4021 .fieldoffset = offsetof(CPUARMState, cp15.pmsav5_insn_ap),
4022 .readfn = pmsav5_insn_ap_read, .writefn = pmsav5_insn_ap_write, },
4023 { .name = "DATA_EXT_AP", .cp = 15, .crn = 5, .crm = 0, .opc1 = 0, .opc2 = 2,
4024 .access = PL1_RW,
4025 .fieldoffset = offsetof(CPUARMState, cp15.pmsav5_data_ap),
4026 .resetvalue = 0, },
4027 { .name = "INSN_EXT_AP", .cp = 15, .crn = 5, .crm = 0, .opc1 = 0, .opc2 = 3,
4028 .access = PL1_RW,
4029 .fieldoffset = offsetof(CPUARMState, cp15.pmsav5_insn_ap),
4030 .resetvalue = 0, },
4031 { .name = "DCACHE_CFG", .cp = 15, .crn = 2, .crm = 0, .opc1 = 0, .opc2 = 0,
4032 .access = PL1_RW,
4033 .fieldoffset = offsetof(CPUARMState, cp15.c2_data), .resetvalue = 0, },
4034 { .name = "ICACHE_CFG", .cp = 15, .crn = 2, .crm = 0, .opc1 = 0, .opc2 = 1,
4035 .access = PL1_RW,
4036 .fieldoffset = offsetof(CPUARMState, cp15.c2_insn), .resetvalue = 0, },
4037
4038 { .name = "946_PRBS0", .cp = 15, .crn = 6, .crm = 0, .opc1 = 0,
4039 .opc2 = CP_ANY, .access = PL1_RW, .resetvalue = 0,
4040 .fieldoffset = offsetof(CPUARMState, cp15.c6_region[0]) },
4041 { .name = "946_PRBS1", .cp = 15, .crn = 6, .crm = 1, .opc1 = 0,
4042 .opc2 = CP_ANY, .access = PL1_RW, .resetvalue = 0,
4043 .fieldoffset = offsetof(CPUARMState, cp15.c6_region[1]) },
4044 { .name = "946_PRBS2", .cp = 15, .crn = 6, .crm = 2, .opc1 = 0,
4045 .opc2 = CP_ANY, .access = PL1_RW, .resetvalue = 0,
4046 .fieldoffset = offsetof(CPUARMState, cp15.c6_region[2]) },
4047 { .name = "946_PRBS3", .cp = 15, .crn = 6, .crm = 3, .opc1 = 0,
4048 .opc2 = CP_ANY, .access = PL1_RW, .resetvalue = 0,
4049 .fieldoffset = offsetof(CPUARMState, cp15.c6_region[3]) },
4050 { .name = "946_PRBS4", .cp = 15, .crn = 6, .crm = 4, .opc1 = 0,
4051 .opc2 = CP_ANY, .access = PL1_RW, .resetvalue = 0,
4052 .fieldoffset = offsetof(CPUARMState, cp15.c6_region[4]) },
4053 { .name = "946_PRBS5", .cp = 15, .crn = 6, .crm = 5, .opc1 = 0,
4054 .opc2 = CP_ANY, .access = PL1_RW, .resetvalue = 0,
4055 .fieldoffset = offsetof(CPUARMState, cp15.c6_region[5]) },
4056 { .name = "946_PRBS6", .cp = 15, .crn = 6, .crm = 6, .opc1 = 0,
4057 .opc2 = CP_ANY, .access = PL1_RW, .resetvalue = 0,
4058 .fieldoffset = offsetof(CPUARMState, cp15.c6_region[6]) },
4059 { .name = "946_PRBS7", .cp = 15, .crn = 6, .crm = 7, .opc1 = 0,
4060 .opc2 = CP_ANY, .access = PL1_RW, .resetvalue = 0,
4061 .fieldoffset = offsetof(CPUARMState, cp15.c6_region[7]) },
4062};
4063
4064static void vmsa_ttbcr_write(CPUARMState *env, const ARMCPRegInfo *ri,
4065 uint64_t value)
4066{
4067 ARMCPU *cpu = env_archcpu(env);
4068
4069 if (!arm_feature(env, ARM_FEATURE_V8)) {
4070 if (arm_feature(env, ARM_FEATURE_LPAE) && (value & TTBCR_EAE)) {
4071
4072
4073
4074
4075 value &= ~((7 << 19) | (3 << 14) | (0xf << 3));
4076 } else if (arm_feature(env, ARM_FEATURE_EL3)) {
4077
4078
4079
4080
4081
4082 value &= TTBCR_PD1 | TTBCR_PD0 | TTBCR_N;
4083 } else {
4084 value &= TTBCR_N;
4085 }
4086 }
4087
4088 if (arm_feature(env, ARM_FEATURE_LPAE)) {
4089
4090
4091
4092
4093 tlb_flush(CPU(cpu));
4094 }
4095 raw_write(env, ri, value);
4096}
4097
4098static void vmsa_tcr_el12_write(CPUARMState *env, const ARMCPRegInfo *ri,
4099 uint64_t value)
4100{
4101 ARMCPU *cpu = env_archcpu(env);
4102
4103
4104 tlb_flush(CPU(cpu));
4105 raw_write(env, ri, value);
4106}
4107
4108static void vmsa_ttbr_write(CPUARMState *env, const ARMCPRegInfo *ri,
4109 uint64_t value)
4110{
4111
4112 if (cpreg_field_is_64bit(ri) &&
4113 extract64(raw_read(env, ri) ^ value, 48, 16) != 0) {
4114 ARMCPU *cpu = env_archcpu(env);
4115 tlb_flush(CPU(cpu));
4116 }
4117 raw_write(env, ri, value);
4118}
4119
4120static void vmsa_tcr_ttbr_el2_write(CPUARMState *env, const ARMCPRegInfo *ri,
4121 uint64_t value)
4122{
4123
4124
4125
4126
4127
4128
4129 if (extract64(raw_read(env, ri) ^ value, 48, 16) &&
4130 (arm_hcr_el2_eff(env) & HCR_E2H)) {
4131 uint16_t mask = ARMMMUIdxBit_E20_2 |
4132 ARMMMUIdxBit_E20_2_PAN |
4133 ARMMMUIdxBit_E20_0;
4134 tlb_flush_by_mmuidx(env_cpu(env), mask);
4135 }
4136 raw_write(env, ri, value);
4137}
4138
4139static void vttbr_write(CPUARMState *env, const ARMCPRegInfo *ri,
4140 uint64_t value)
4141{
4142 ARMCPU *cpu = env_archcpu(env);
4143 CPUState *cs = CPU(cpu);
4144
4145
4146
4147
4148
4149 if (extract64(raw_read(env, ri) ^ value, 48, 16) != 0) {
4150 tlb_flush_by_mmuidx(cs, alle1_tlbmask(env));
4151 }
4152 raw_write(env, ri, value);
4153}
4154
4155static const ARMCPRegInfo vmsa_pmsa_cp_reginfo[] = {
4156 { .name = "DFSR", .cp = 15, .crn = 5, .crm = 0, .opc1 = 0, .opc2 = 0,
4157 .access = PL1_RW, .accessfn = access_tvm_trvm, .type = ARM_CP_ALIAS,
4158 .bank_fieldoffsets = { offsetoflow32(CPUARMState, cp15.dfsr_s),
4159 offsetoflow32(CPUARMState, cp15.dfsr_ns) }, },
4160 { .name = "IFSR", .cp = 15, .crn = 5, .crm = 0, .opc1 = 0, .opc2 = 1,
4161 .access = PL1_RW, .accessfn = access_tvm_trvm, .resetvalue = 0,
4162 .bank_fieldoffsets = { offsetoflow32(CPUARMState, cp15.ifsr_s),
4163 offsetoflow32(CPUARMState, cp15.ifsr_ns) } },
4164 { .name = "DFAR", .cp = 15, .opc1 = 0, .crn = 6, .crm = 0, .opc2 = 0,
4165 .access = PL1_RW, .accessfn = access_tvm_trvm, .resetvalue = 0,
4166 .bank_fieldoffsets = { offsetof(CPUARMState, cp15.dfar_s),
4167 offsetof(CPUARMState, cp15.dfar_ns) } },
4168 { .name = "FAR_EL1", .state = ARM_CP_STATE_AA64,
4169 .opc0 = 3, .crn = 6, .crm = 0, .opc1 = 0, .opc2 = 0,
4170 .access = PL1_RW, .accessfn = access_tvm_trvm,
4171 .fgt = FGT_FAR_EL1,
4172 .fieldoffset = offsetof(CPUARMState, cp15.far_el[1]),
4173 .resetvalue = 0, },
4174};
4175
4176static const ARMCPRegInfo vmsa_cp_reginfo[] = {
4177 { .name = "ESR_EL1", .state = ARM_CP_STATE_AA64,
4178 .opc0 = 3, .crn = 5, .crm = 2, .opc1 = 0, .opc2 = 0,
4179 .access = PL1_RW, .accessfn = access_tvm_trvm,
4180 .fgt = FGT_ESR_EL1,
4181 .fieldoffset = offsetof(CPUARMState, cp15.esr_el[1]), .resetvalue = 0, },
4182 { .name = "TTBR0_EL1", .state = ARM_CP_STATE_BOTH,
4183 .opc0 = 3, .opc1 = 0, .crn = 2, .crm = 0, .opc2 = 0,
4184 .access = PL1_RW, .accessfn = access_tvm_trvm,
4185 .fgt = FGT_TTBR0_EL1,
4186 .writefn = vmsa_ttbr_write, .resetvalue = 0,
4187 .bank_fieldoffsets = { offsetof(CPUARMState, cp15.ttbr0_s),
4188 offsetof(CPUARMState, cp15.ttbr0_ns) } },
4189 { .name = "TTBR1_EL1", .state = ARM_CP_STATE_BOTH,
4190 .opc0 = 3, .opc1 = 0, .crn = 2, .crm = 0, .opc2 = 1,
4191 .access = PL1_RW, .accessfn = access_tvm_trvm,
4192 .fgt = FGT_TTBR1_EL1,
4193 .writefn = vmsa_ttbr_write, .resetvalue = 0,
4194 .bank_fieldoffsets = { offsetof(CPUARMState, cp15.ttbr1_s),
4195 offsetof(CPUARMState, cp15.ttbr1_ns) } },
4196 { .name = "TCR_EL1", .state = ARM_CP_STATE_AA64,
4197 .opc0 = 3, .crn = 2, .crm = 0, .opc1 = 0, .opc2 = 2,
4198 .access = PL1_RW, .accessfn = access_tvm_trvm,
4199 .fgt = FGT_TCR_EL1,
4200 .writefn = vmsa_tcr_el12_write,
4201 .raw_writefn = raw_write,
4202 .resetvalue = 0,
4203 .fieldoffset = offsetof(CPUARMState, cp15.tcr_el[1]) },
4204 { .name = "TTBCR", .cp = 15, .crn = 2, .crm = 0, .opc1 = 0, .opc2 = 2,
4205 .access = PL1_RW, .accessfn = access_tvm_trvm,
4206 .type = ARM_CP_ALIAS, .writefn = vmsa_ttbcr_write,
4207 .raw_writefn = raw_write,
4208 .bank_fieldoffsets = { offsetoflow32(CPUARMState, cp15.tcr_el[3]),
4209 offsetoflow32(CPUARMState, cp15.tcr_el[1])} },
4210};
4211
4212
4213
4214
4215
4216static const ARMCPRegInfo ttbcr2_reginfo = {
4217 .name = "TTBCR2", .cp = 15, .opc1 = 0, .crn = 2, .crm = 0, .opc2 = 3,
4218 .access = PL1_RW, .accessfn = access_tvm_trvm,
4219 .type = ARM_CP_ALIAS,
4220 .bank_fieldoffsets = {
4221 offsetofhigh32(CPUARMState, cp15.tcr_el[3]),
4222 offsetofhigh32(CPUARMState, cp15.tcr_el[1]),
4223 },
4224};
4225
4226static void omap_ticonfig_write(CPUARMState *env, const ARMCPRegInfo *ri,
4227 uint64_t value)
4228{
4229 env->cp15.c15_ticonfig = value & 0xe7;
4230
4231 env->cp15.c0_cpuid = (value & (1 << 5)) ?
4232 ARM_CPUID_TI915T : ARM_CPUID_TI925T;
4233}
4234
4235static void omap_threadid_write(CPUARMState *env, const ARMCPRegInfo *ri,
4236 uint64_t value)
4237{
4238 env->cp15.c15_threadid = value & 0xffff;
4239}
4240
4241static void omap_wfi_write(CPUARMState *env, const ARMCPRegInfo *ri,
4242 uint64_t value)
4243{
4244
4245 cpu_interrupt(env_cpu(env), CPU_INTERRUPT_HALT);
4246}
4247
4248static void omap_cachemaint_write(CPUARMState *env, const ARMCPRegInfo *ri,
4249 uint64_t value)
4250{
4251
4252
4253
4254
4255 env->cp15.c15_i_max = 0x000;
4256 env->cp15.c15_i_min = 0xff0;
4257}
4258
4259static const ARMCPRegInfo omap_cp_reginfo[] = {
4260 { .name = "DFSR", .cp = 15, .crn = 5, .crm = CP_ANY,
4261 .opc1 = CP_ANY, .opc2 = CP_ANY, .access = PL1_RW, .type = ARM_CP_OVERRIDE,
4262 .fieldoffset = offsetoflow32(CPUARMState, cp15.esr_el[1]),
4263 .resetvalue = 0, },
4264 { .name = "", .cp = 15, .crn = 15, .crm = 0, .opc1 = 0, .opc2 = 0,
4265 .access = PL1_RW, .type = ARM_CP_NOP },
4266 { .name = "TICONFIG", .cp = 15, .crn = 15, .crm = 1, .opc1 = 0, .opc2 = 0,
4267 .access = PL1_RW,
4268 .fieldoffset = offsetof(CPUARMState, cp15.c15_ticonfig), .resetvalue = 0,
4269 .writefn = omap_ticonfig_write },
4270 { .name = "IMAX", .cp = 15, .crn = 15, .crm = 2, .opc1 = 0, .opc2 = 0,
4271 .access = PL1_RW,
4272 .fieldoffset = offsetof(CPUARMState, cp15.c15_i_max), .resetvalue = 0, },
4273 { .name = "IMIN", .cp = 15, .crn = 15, .crm = 3, .opc1 = 0, .opc2 = 0,
4274 .access = PL1_RW, .resetvalue = 0xff0,
4275 .fieldoffset = offsetof(CPUARMState, cp15.c15_i_min) },
4276 { .name = "THREADID", .cp = 15, .crn = 15, .crm = 4, .opc1 = 0, .opc2 = 0,
4277 .access = PL1_RW,
4278 .fieldoffset = offsetof(CPUARMState, cp15.c15_threadid), .resetvalue = 0,
4279 .writefn = omap_threadid_write },
4280 { .name = "TI925T_STATUS", .cp = 15, .crn = 15,
4281 .crm = 8, .opc1 = 0, .opc2 = 0, .access = PL1_RW,
4282 .type = ARM_CP_NO_RAW,
4283 .readfn = arm_cp_read_zero, .writefn = omap_wfi_write, },
4284
4285
4286
4287
4288
4289
4290 { .name = "OMAP_CACHEMAINT", .cp = 15, .crn = 7, .crm = CP_ANY,
4291 .opc1 = 0, .opc2 = CP_ANY, .access = PL1_W,
4292 .type = ARM_CP_OVERRIDE | ARM_CP_NO_RAW,
4293 .writefn = omap_cachemaint_write },
4294 { .name = "C9", .cp = 15, .crn = 9,
4295 .crm = CP_ANY, .opc1 = CP_ANY, .opc2 = CP_ANY, .access = PL1_RW,
4296 .type = ARM_CP_CONST | ARM_CP_OVERRIDE, .resetvalue = 0 },
4297};
4298
4299static void xscale_cpar_write(CPUARMState *env, const ARMCPRegInfo *ri,
4300 uint64_t value)
4301{
4302 env->cp15.c15_cpar = value & 0x3fff;
4303}
4304
4305static const ARMCPRegInfo xscale_cp_reginfo[] = {
4306 { .name = "XSCALE_CPAR",
4307 .cp = 15, .crn = 15, .crm = 1, .opc1 = 0, .opc2 = 0, .access = PL1_RW,
4308 .fieldoffset = offsetof(CPUARMState, cp15.c15_cpar), .resetvalue = 0,
4309 .writefn = xscale_cpar_write, },
4310 { .name = "XSCALE_AUXCR",
4311 .cp = 15, .crn = 1, .crm = 0, .opc1 = 0, .opc2 = 1, .access = PL1_RW,
4312 .fieldoffset = offsetof(CPUARMState, cp15.c1_xscaleauxcr),
4313 .resetvalue = 0, },
4314
4315
4316
4317
4318 { .name = "XSCALE_LOCK_ICACHE_LINE",
4319 .cp = 15, .opc1 = 0, .crn = 9, .crm = 1, .opc2 = 0,
4320 .access = PL1_W, .type = ARM_CP_NOP },
4321 { .name = "XSCALE_UNLOCK_ICACHE",
4322 .cp = 15, .opc1 = 0, .crn = 9, .crm = 1, .opc2 = 1,
4323 .access = PL1_W, .type = ARM_CP_NOP },
4324 { .name = "XSCALE_DCACHE_LOCK",
4325 .cp = 15, .opc1 = 0, .crn = 9, .crm = 2, .opc2 = 0,
4326 .access = PL1_RW, .type = ARM_CP_NOP },
4327 { .name = "XSCALE_UNLOCK_DCACHE",
4328 .cp = 15, .opc1 = 0, .crn = 9, .crm = 2, .opc2 = 1,
4329 .access = PL1_W, .type = ARM_CP_NOP },
4330};
4331
4332static const ARMCPRegInfo dummy_c15_cp_reginfo[] = {
4333
4334
4335
4336
4337
4338
4339 { .name = "C15_IMPDEF", .cp = 15, .crn = 15,
4340 .crm = CP_ANY, .opc1 = CP_ANY, .opc2 = CP_ANY,
4341 .access = PL1_RW,
4342 .type = ARM_CP_CONST | ARM_CP_NO_RAW | ARM_CP_OVERRIDE,
4343 .resetvalue = 0 },
4344};
4345
4346static const ARMCPRegInfo cache_dirty_status_cp_reginfo[] = {
4347
4348 { .name = "CDSR", .cp = 15, .crn = 7, .crm = 10, .opc1 = 0, .opc2 = 6,
4349 .access = PL1_R, .type = ARM_CP_CONST | ARM_CP_NO_RAW,
4350 .resetvalue = 0 },
4351};
4352
4353static const ARMCPRegInfo cache_block_ops_cp_reginfo[] = {
4354
4355 { .name = "BXSR", .cp = 15, .crn = 7, .crm = 12, .opc1 = 0, .opc2 = 4,
4356 .access = PL0_R, .type = ARM_CP_CONST | ARM_CP_NO_RAW,
4357 .resetvalue = 0 },
4358
4359 { .name = "IICR", .cp = 15, .crm = 5, .opc1 = 0,
4360 .access = PL1_W, .type = ARM_CP_NOP | ARM_CP_64BIT },
4361 { .name = "IDCR", .cp = 15, .crm = 6, .opc1 = 0,
4362 .access = PL1_W, .type = ARM_CP_NOP | ARM_CP_64BIT },
4363 { .name = "CDCR", .cp = 15, .crm = 12, .opc1 = 0,
4364 .access = PL0_W, .type = ARM_CP_NOP | ARM_CP_64BIT },
4365 { .name = "PIR", .cp = 15, .crm = 12, .opc1 = 1,
4366 .access = PL0_W, .type = ARM_CP_NOP | ARM_CP_64BIT },
4367 { .name = "PDR", .cp = 15, .crm = 12, .opc1 = 2,
4368 .access = PL0_W, .type = ARM_CP_NOP | ARM_CP_64BIT },
4369 { .name = "CIDCR", .cp = 15, .crm = 14, .opc1 = 0,
4370 .access = PL1_W, .type = ARM_CP_NOP | ARM_CP_64BIT },
4371};
4372
4373static const ARMCPRegInfo cache_test_clean_cp_reginfo[] = {
4374
4375
4376
4377
4378 { .name = "TC_DCACHE", .cp = 15, .crn = 7, .crm = 10, .opc1 = 0, .opc2 = 3,
4379 .access = PL0_R, .type = ARM_CP_CONST | ARM_CP_NO_RAW,
4380 .resetvalue = (1 << 30) },
4381 { .name = "TCI_DCACHE", .cp = 15, .crn = 7, .crm = 14, .opc1 = 0, .opc2 = 3,
4382 .access = PL0_R, .type = ARM_CP_CONST | ARM_CP_NO_RAW,
4383 .resetvalue = (1 << 30) },
4384};
4385
4386static const ARMCPRegInfo strongarm_cp_reginfo[] = {
4387
4388 { .name = "C9_READBUFFER", .cp = 15, .crn = 9,
4389 .crm = CP_ANY, .opc1 = CP_ANY, .opc2 = CP_ANY,
4390 .access = PL1_RW, .resetvalue = 0,
4391 .type = ARM_CP_CONST | ARM_CP_OVERRIDE | ARM_CP_NO_RAW },
4392};
4393
4394static uint64_t midr_read(CPUARMState *env, const ARMCPRegInfo *ri)
4395{
4396 unsigned int cur_el = arm_current_el(env);
4397
4398 if (arm_is_el2_enabled(env) && cur_el == 1) {
4399 return env->cp15.vpidr_el2;
4400 }
4401 return raw_read(env, ri);
4402}
4403
4404static uint64_t mpidr_read_val(CPUARMState *env)
4405{
4406 ARMCPU *cpu = env_archcpu(env);
4407 uint64_t mpidr = cpu->mp_affinity;
4408
4409 if (arm_feature(env, ARM_FEATURE_V7MP)) {
4410 mpidr |= (1U << 31);
4411
4412
4413
4414
4415
4416 if (cpu->mp_is_up) {
4417 mpidr |= (1u << 30);
4418 }
4419 }
4420 return mpidr;
4421}
4422
4423static uint64_t mpidr_read(CPUARMState *env, const ARMCPRegInfo *ri)
4424{
4425 unsigned int cur_el = arm_current_el(env);
4426
4427 if (arm_is_el2_enabled(env) && cur_el == 1) {
4428 return env->cp15.vmpidr_el2;
4429 }
4430 return mpidr_read_val(env);
4431}
4432
4433static const ARMCPRegInfo lpae_cp_reginfo[] = {
4434
4435 { .name = "AMAIR0", .state = ARM_CP_STATE_BOTH,
4436 .opc0 = 3, .crn = 10, .crm = 3, .opc1 = 0, .opc2 = 0,
4437 .access = PL1_RW, .accessfn = access_tvm_trvm,
4438 .fgt = FGT_AMAIR_EL1,
4439 .type = ARM_CP_CONST, .resetvalue = 0 },
4440
4441 { .name = "AMAIR1", .cp = 15, .crn = 10, .crm = 3, .opc1 = 0, .opc2 = 1,
4442 .access = PL1_RW, .accessfn = access_tvm_trvm,
4443 .type = ARM_CP_CONST, .resetvalue = 0 },
4444 { .name = "PAR", .cp = 15, .crm = 7, .opc1 = 0,
4445 .access = PL1_RW, .type = ARM_CP_64BIT, .resetvalue = 0,
4446 .bank_fieldoffsets = { offsetof(CPUARMState, cp15.par_s),
4447 offsetof(CPUARMState, cp15.par_ns)} },
4448 { .name = "TTBR0", .cp = 15, .crm = 2, .opc1 = 0,
4449 .access = PL1_RW, .accessfn = access_tvm_trvm,
4450 .type = ARM_CP_64BIT | ARM_CP_ALIAS,
4451 .bank_fieldoffsets = { offsetof(CPUARMState, cp15.ttbr0_s),
4452 offsetof(CPUARMState, cp15.ttbr0_ns) },
4453 .writefn = vmsa_ttbr_write, },
4454 { .name = "TTBR1", .cp = 15, .crm = 2, .opc1 = 1,
4455 .access = PL1_RW, .accessfn = access_tvm_trvm,
4456 .type = ARM_CP_64BIT | ARM_CP_ALIAS,
4457 .bank_fieldoffsets = { offsetof(CPUARMState, cp15.ttbr1_s),
4458 offsetof(CPUARMState, cp15.ttbr1_ns) },
4459 .writefn = vmsa_ttbr_write, },
4460};
4461
4462static uint64_t aa64_fpcr_read(CPUARMState *env, const ARMCPRegInfo *ri)
4463{
4464 return vfp_get_fpcr(env);
4465}
4466
4467static void aa64_fpcr_write(CPUARMState *env, const ARMCPRegInfo *ri,
4468 uint64_t value)
4469{
4470 vfp_set_fpcr(env, value);
4471}
4472
4473static uint64_t aa64_fpsr_read(CPUARMState *env, const ARMCPRegInfo *ri)
4474{
4475 return vfp_get_fpsr(env);
4476}
4477
4478static void aa64_fpsr_write(CPUARMState *env, const ARMCPRegInfo *ri,
4479 uint64_t value)
4480{
4481 vfp_set_fpsr(env, value);
4482}
4483
4484static CPAccessResult aa64_daif_access(CPUARMState *env, const ARMCPRegInfo *ri,
4485 bool isread)
4486{
4487 if (arm_current_el(env) == 0 && !(arm_sctlr(env, 0) & SCTLR_UMA)) {
4488 return CP_ACCESS_TRAP;
4489 }
4490 return CP_ACCESS_OK;
4491}
4492
4493static void aa64_daif_write(CPUARMState *env, const ARMCPRegInfo *ri,
4494 uint64_t value)
4495{
4496 env->daif = value & PSTATE_DAIF;
4497}
4498
4499static uint64_t aa64_pan_read(CPUARMState *env, const ARMCPRegInfo *ri)
4500{
4501 return env->pstate & PSTATE_PAN;
4502}
4503
4504static void aa64_pan_write(CPUARMState *env, const ARMCPRegInfo *ri,
4505 uint64_t value)
4506{
4507 env->pstate = (env->pstate & ~PSTATE_PAN) | (value & PSTATE_PAN);
4508}
4509
4510static const ARMCPRegInfo pan_reginfo = {
4511 .name = "PAN", .state = ARM_CP_STATE_AA64,
4512 .opc0 = 3, .opc1 = 0, .crn = 4, .crm = 2, .opc2 = 3,
4513 .type = ARM_CP_NO_RAW, .access = PL1_RW,
4514 .readfn = aa64_pan_read, .writefn = aa64_pan_write
4515};
4516
4517static uint64_t aa64_uao_read(CPUARMState *env, const ARMCPRegInfo *ri)
4518{
4519 return env->pstate & PSTATE_UAO;
4520}
4521
4522static void aa64_uao_write(CPUARMState *env, const ARMCPRegInfo *ri,
4523 uint64_t value)
4524{
4525 env->pstate = (env->pstate & ~PSTATE_UAO) | (value & PSTATE_UAO);
4526}
4527
4528static const ARMCPRegInfo uao_reginfo = {
4529 .name = "UAO", .state = ARM_CP_STATE_AA64,
4530 .opc0 = 3, .opc1 = 0, .crn = 4, .crm = 2, .opc2 = 4,
4531 .type = ARM_CP_NO_RAW, .access = PL1_RW,
4532 .readfn = aa64_uao_read, .writefn = aa64_uao_write
4533};
4534
4535static uint64_t aa64_dit_read(CPUARMState *env, const ARMCPRegInfo *ri)
4536{
4537 return env->pstate & PSTATE_DIT;
4538}
4539
4540static void aa64_dit_write(CPUARMState *env, const ARMCPRegInfo *ri,
4541 uint64_t value)
4542{
4543 env->pstate = (env->pstate & ~PSTATE_DIT) | (value & PSTATE_DIT);
4544}
4545
4546static const ARMCPRegInfo dit_reginfo = {
4547 .name = "DIT", .state = ARM_CP_STATE_AA64,
4548 .opc0 = 3, .opc1 = 3, .crn = 4, .crm = 2, .opc2 = 5,
4549 .type = ARM_CP_NO_RAW, .access = PL0_RW,
4550 .readfn = aa64_dit_read, .writefn = aa64_dit_write
4551};
4552
4553static uint64_t aa64_ssbs_read(CPUARMState *env, const ARMCPRegInfo *ri)
4554{
4555 return env->pstate & PSTATE_SSBS;
4556}
4557
4558static void aa64_ssbs_write(CPUARMState *env, const ARMCPRegInfo *ri,
4559 uint64_t value)
4560{
4561 env->pstate = (env->pstate & ~PSTATE_SSBS) | (value & PSTATE_SSBS);
4562}
4563
4564static const ARMCPRegInfo ssbs_reginfo = {
4565 .name = "SSBS", .state = ARM_CP_STATE_AA64,
4566 .opc0 = 3, .opc1 = 3, .crn = 4, .crm = 2, .opc2 = 6,
4567 .type = ARM_CP_NO_RAW, .access = PL0_RW,
4568 .readfn = aa64_ssbs_read, .writefn = aa64_ssbs_write
4569};
4570
4571static CPAccessResult aa64_cacheop_poc_access(CPUARMState *env,
4572 const ARMCPRegInfo *ri,
4573 bool isread)
4574{
4575
4576 switch (arm_current_el(env)) {
4577 case 0:
4578
4579 if (!(arm_sctlr(env, 0) & SCTLR_UCI)) {
4580 return CP_ACCESS_TRAP;
4581 }
4582
4583 case 1:
4584
4585 if (arm_hcr_el2_eff(env) & HCR_TPCP) {
4586 return CP_ACCESS_TRAP_EL2;
4587 }
4588 break;
4589 }
4590 return CP_ACCESS_OK;
4591}
4592
4593static CPAccessResult do_cacheop_pou_access(CPUARMState *env, uint64_t hcrflags)
4594{
4595
4596 switch (arm_current_el(env)) {
4597 case 0:
4598
4599 if (!(arm_sctlr(env, 0) & SCTLR_UCI)) {
4600 return CP_ACCESS_TRAP;
4601 }
4602
4603 case 1:
4604
4605 if (arm_hcr_el2_eff(env) & hcrflags) {
4606 return CP_ACCESS_TRAP_EL2;
4607 }
4608 break;
4609 }
4610 return CP_ACCESS_OK;
4611}
4612
4613static CPAccessResult access_ticab(CPUARMState *env, const ARMCPRegInfo *ri,
4614 bool isread)
4615{
4616 return do_cacheop_pou_access(env, HCR_TICAB | HCR_TPU);
4617}
4618
4619static CPAccessResult access_tocu(CPUARMState *env, const ARMCPRegInfo *ri,
4620 bool isread)
4621{
4622 return do_cacheop_pou_access(env, HCR_TOCU | HCR_TPU);
4623}
4624
4625
4626
4627
4628
4629
4630static int vae1_tlbmask(CPUARMState *env)
4631{
4632 uint64_t hcr = arm_hcr_el2_eff(env);
4633 uint16_t mask;
4634
4635 if ((hcr & (HCR_E2H | HCR_TGE)) == (HCR_E2H | HCR_TGE)) {
4636 mask = ARMMMUIdxBit_E20_2 |
4637 ARMMMUIdxBit_E20_2_PAN |
4638 ARMMMUIdxBit_E20_0;
4639 } else {
4640 mask = ARMMMUIdxBit_E10_1 |
4641 ARMMMUIdxBit_E10_1_PAN |
4642 ARMMMUIdxBit_E10_0;
4643 }
4644 return mask;
4645}
4646
4647
4648static int tlbbits_for_regime(CPUARMState *env, ARMMMUIdx mmu_idx,
4649 uint64_t addr)
4650{
4651 uint64_t tcr = regime_tcr(env, mmu_idx);
4652 int tbi = aa64_va_parameter_tbi(tcr, mmu_idx);
4653 int select = extract64(addr, 55, 1);
4654
4655 return (tbi >> select) & 1 ? 56 : 64;
4656}
4657
4658static int vae1_tlbbits(CPUARMState *env, uint64_t addr)
4659{
4660 uint64_t hcr = arm_hcr_el2_eff(env);
4661 ARMMMUIdx mmu_idx;
4662
4663
4664 if ((hcr & (HCR_E2H | HCR_TGE)) == (HCR_E2H | HCR_TGE)) {
4665 mmu_idx = ARMMMUIdx_E20_0;
4666 } else {
4667 mmu_idx = ARMMMUIdx_E10_0;
4668 }
4669
4670 return tlbbits_for_regime(env, mmu_idx, addr);
4671}
4672
4673static void tlbi_aa64_vmalle1is_write(CPUARMState *env, const ARMCPRegInfo *ri,
4674 uint64_t value)
4675{
4676 CPUState *cs = env_cpu(env);
4677 int mask = vae1_tlbmask(env);
4678
4679 tlb_flush_by_mmuidx_all_cpus_synced(cs, mask);
4680}
4681
4682static void tlbi_aa64_vmalle1_write(CPUARMState *env, const ARMCPRegInfo *ri,
4683 uint64_t value)
4684{
4685 CPUState *cs = env_cpu(env);
4686 int mask = vae1_tlbmask(env);
4687
4688 if (tlb_force_broadcast(env)) {
4689 tlb_flush_by_mmuidx_all_cpus_synced(cs, mask);
4690 } else {
4691 tlb_flush_by_mmuidx(cs, mask);
4692 }
4693}
4694
4695static int e2_tlbmask(CPUARMState *env)
4696{
4697 return (ARMMMUIdxBit_E20_0 |
4698 ARMMMUIdxBit_E20_2 |
4699 ARMMMUIdxBit_E20_2_PAN |
4700 ARMMMUIdxBit_E2);
4701}
4702
4703static void tlbi_aa64_alle1_write(CPUARMState *env, const ARMCPRegInfo *ri,
4704 uint64_t value)
4705{
4706 CPUState *cs = env_cpu(env);
4707 int mask = alle1_tlbmask(env);
4708
4709 tlb_flush_by_mmuidx(cs, mask);
4710}
4711
4712static void tlbi_aa64_alle2_write(CPUARMState *env, const ARMCPRegInfo *ri,
4713 uint64_t value)
4714{
4715 CPUState *cs = env_cpu(env);
4716 int mask = e2_tlbmask(env);
4717
4718 tlb_flush_by_mmuidx(cs, mask);
4719}
4720
4721static void tlbi_aa64_alle3_write(CPUARMState *env, const ARMCPRegInfo *ri,
4722 uint64_t value)
4723{
4724 ARMCPU *cpu = env_archcpu(env);
4725 CPUState *cs = CPU(cpu);
4726
4727 tlb_flush_by_mmuidx(cs, ARMMMUIdxBit_E3);
4728}
4729
4730static void tlbi_aa64_alle1is_write(CPUARMState *env, const ARMCPRegInfo *ri,
4731 uint64_t value)
4732{
4733 CPUState *cs = env_cpu(env);
4734 int mask = alle1_tlbmask(env);
4735
4736 tlb_flush_by_mmuidx_all_cpus_synced(cs, mask);
4737}
4738
4739static void tlbi_aa64_alle2is_write(CPUARMState *env, const ARMCPRegInfo *ri,
4740 uint64_t value)
4741{
4742 CPUState *cs = env_cpu(env);
4743 int mask = e2_tlbmask(env);
4744
4745 tlb_flush_by_mmuidx_all_cpus_synced(cs, mask);
4746}
4747
4748static void tlbi_aa64_alle3is_write(CPUARMState *env, const ARMCPRegInfo *ri,
4749 uint64_t value)
4750{
4751 CPUState *cs = env_cpu(env);
4752
4753 tlb_flush_by_mmuidx_all_cpus_synced(cs, ARMMMUIdxBit_E3);
4754}
4755
4756static void tlbi_aa64_vae2_write(CPUARMState *env, const ARMCPRegInfo *ri,
4757 uint64_t value)
4758{
4759
4760
4761
4762
4763
4764 CPUState *cs = env_cpu(env);
4765 int mask = e2_tlbmask(env);
4766 uint64_t pageaddr = sextract64(value << 12, 0, 56);
4767
4768 tlb_flush_page_by_mmuidx(cs, pageaddr, mask);
4769}
4770
4771static void tlbi_aa64_vae3_write(CPUARMState *env, const ARMCPRegInfo *ri,
4772 uint64_t value)
4773{
4774
4775
4776
4777
4778
4779 ARMCPU *cpu = env_archcpu(env);
4780 CPUState *cs = CPU(cpu);
4781 uint64_t pageaddr = sextract64(value << 12, 0, 56);
4782
4783 tlb_flush_page_by_mmuidx(cs, pageaddr, ARMMMUIdxBit_E3);
4784}
4785
4786static void tlbi_aa64_vae1is_write(CPUARMState *env, const ARMCPRegInfo *ri,
4787 uint64_t value)
4788{
4789 CPUState *cs = env_cpu(env);
4790 int mask = vae1_tlbmask(env);
4791 uint64_t pageaddr = sextract64(value << 12, 0, 56);
4792 int bits = vae1_tlbbits(env, pageaddr);
4793
4794 tlb_flush_page_bits_by_mmuidx_all_cpus_synced(cs, pageaddr, mask, bits);
4795}
4796
4797static void tlbi_aa64_vae1_write(CPUARMState *env, const ARMCPRegInfo *ri,
4798 uint64_t value)
4799{
4800
4801
4802
4803
4804
4805
4806 CPUState *cs = env_cpu(env);
4807 int mask = vae1_tlbmask(env);
4808 uint64_t pageaddr = sextract64(value << 12, 0, 56);
4809 int bits = vae1_tlbbits(env, pageaddr);
4810
4811 if (tlb_force_broadcast(env)) {
4812 tlb_flush_page_bits_by_mmuidx_all_cpus_synced(cs, pageaddr, mask, bits);
4813 } else {
4814 tlb_flush_page_bits_by_mmuidx(cs, pageaddr, mask, bits);
4815 }
4816}
4817
4818static void tlbi_aa64_vae2is_write(CPUARMState *env, const ARMCPRegInfo *ri,
4819 uint64_t value)
4820{
4821 CPUState *cs = env_cpu(env);
4822 uint64_t pageaddr = sextract64(value << 12, 0, 56);
4823 int bits = tlbbits_for_regime(env, ARMMMUIdx_E2, pageaddr);
4824
4825 tlb_flush_page_bits_by_mmuidx_all_cpus_synced(cs, pageaddr,
4826 ARMMMUIdxBit_E2, bits);
4827}
4828
4829static void tlbi_aa64_vae3is_write(CPUARMState *env, const ARMCPRegInfo *ri,
4830 uint64_t value)
4831{
4832 CPUState *cs = env_cpu(env);
4833 uint64_t pageaddr = sextract64(value << 12, 0, 56);
4834 int bits = tlbbits_for_regime(env, ARMMMUIdx_E3, pageaddr);
4835
4836 tlb_flush_page_bits_by_mmuidx_all_cpus_synced(cs, pageaddr,
4837 ARMMMUIdxBit_E3, bits);
4838}
4839
4840static int ipas2e1_tlbmask(CPUARMState *env, int64_t value)
4841{
4842
4843
4844
4845
4846 return (value >= 0
4847 && cpu_isar_feature(aa64_sel2, env_archcpu(env))
4848 && arm_is_secure_below_el3(env)
4849 ? ARMMMUIdxBit_Stage2_S
4850 : ARMMMUIdxBit_Stage2);
4851}
4852
4853static void tlbi_aa64_ipas2e1_write(CPUARMState *env, const ARMCPRegInfo *ri,
4854 uint64_t value)
4855{
4856 CPUState *cs = env_cpu(env);
4857 int mask = ipas2e1_tlbmask(env, value);
4858 uint64_t pageaddr = sextract64(value << 12, 0, 56);
4859
4860 if (tlb_force_broadcast(env)) {
4861 tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr, mask);
4862 } else {
4863 tlb_flush_page_by_mmuidx(cs, pageaddr, mask);
4864 }
4865}
4866
4867static void tlbi_aa64_ipas2e1is_write(CPUARMState *env, const ARMCPRegInfo *ri,
4868 uint64_t value)
4869{
4870 CPUState *cs = env_cpu(env);
4871 int mask = ipas2e1_tlbmask(env, value);
4872 uint64_t pageaddr = sextract64(value << 12, 0, 56);
4873
4874 tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr, mask);
4875}
4876
4877#ifdef TARGET_AARCH64
4878typedef struct {
4879 uint64_t base;
4880 uint64_t length;
4881} TLBIRange;
4882
4883static ARMGranuleSize tlbi_range_tg_to_gran_size(int tg)
4884{
4885
4886
4887
4888
4889 switch (tg) {
4890 case 1:
4891 return Gran4K;
4892 case 2:
4893 return Gran16K;
4894 case 3:
4895 return Gran64K;
4896 default:
4897 return GranInvalid;
4898 }
4899}
4900
4901static TLBIRange tlbi_aa64_get_range(CPUARMState *env, ARMMMUIdx mmuidx,
4902 uint64_t value)
4903{
4904 unsigned int page_size_granule, page_shift, num, scale, exponent;
4905
4906 uint64_t select = sextract64(value, 36, 1);
4907 ARMVAParameters param = aa64_va_parameters(env, select, mmuidx, true, false);
4908 TLBIRange ret = { };
4909 ARMGranuleSize gran;
4910
4911 page_size_granule = extract64(value, 46, 2);
4912 gran = tlbi_range_tg_to_gran_size(page_size_granule);
4913
4914
4915 if (gran != param.gran) {
4916 qemu_log_mask(LOG_GUEST_ERROR, "Invalid tlbi page size granule %d\n",
4917 page_size_granule);
4918 return ret;
4919 }
4920
4921 page_shift = arm_granule_bits(gran);
4922 num = extract64(value, 39, 5);
4923 scale = extract64(value, 44, 2);
4924 exponent = (5 * scale) + 1;
4925
4926 ret.length = (num + 1) << (exponent + page_shift);
4927
4928 if (param.select) {
4929 ret.base = sextract64(value, 0, 37);
4930 } else {
4931 ret.base = extract64(value, 0, 37);
4932 }
4933 if (param.ds) {
4934
4935
4936
4937
4938
4939 page_shift = 16;
4940 }
4941 ret.base <<= page_shift;
4942
4943 return ret;
4944}
4945
4946static void do_rvae_write(CPUARMState *env, uint64_t value,
4947 int idxmap, bool synced)
4948{
4949 ARMMMUIdx one_idx = ARM_MMU_IDX_A | ctz32(idxmap);
4950 TLBIRange range;
4951 int bits;
4952
4953 range = tlbi_aa64_get_range(env, one_idx, value);
4954 bits = tlbbits_for_regime(env, one_idx, range.base);
4955
4956 if (synced) {
4957 tlb_flush_range_by_mmuidx_all_cpus_synced(env_cpu(env),
4958 range.base,
4959 range.length,
4960 idxmap,
4961 bits);
4962 } else {
4963 tlb_flush_range_by_mmuidx(env_cpu(env), range.base,
4964 range.length, idxmap, bits);
4965 }
4966}
4967
4968static void tlbi_aa64_rvae1_write(CPUARMState *env,
4969 const ARMCPRegInfo *ri,
4970 uint64_t value)
4971{
4972
4973
4974
4975
4976
4977
4978
4979 do_rvae_write(env, value, vae1_tlbmask(env),
4980 tlb_force_broadcast(env));
4981}
4982
4983static void tlbi_aa64_rvae1is_write(CPUARMState *env,
4984 const ARMCPRegInfo *ri,
4985 uint64_t value)
4986{
4987
4988
4989
4990
4991
4992
4993
4994
4995 do_rvae_write(env, value, vae1_tlbmask(env), true);
4996}
4997
4998static int vae2_tlbmask(CPUARMState *env)
4999{
5000 return ARMMMUIdxBit_E2;
5001}
5002
5003static void tlbi_aa64_rvae2_write(CPUARMState *env,
5004 const ARMCPRegInfo *ri,
5005 uint64_t value)
5006{
5007
5008
5009
5010
5011
5012
5013
5014 do_rvae_write(env, value, vae2_tlbmask(env),
5015 tlb_force_broadcast(env));
5016
5017
5018}
5019
5020static void tlbi_aa64_rvae2is_write(CPUARMState *env,
5021 const ARMCPRegInfo *ri,
5022 uint64_t value)
5023{
5024
5025
5026
5027
5028
5029
5030
5031 do_rvae_write(env, value, vae2_tlbmask(env), true);
5032
5033}
5034
5035static void tlbi_aa64_rvae3_write(CPUARMState *env,
5036 const ARMCPRegInfo *ri,
5037 uint64_t value)
5038{
5039
5040
5041
5042
5043
5044
5045
5046 do_rvae_write(env, value, ARMMMUIdxBit_E3, tlb_force_broadcast(env));
5047}
5048
5049static void tlbi_aa64_rvae3is_write(CPUARMState *env,
5050 const ARMCPRegInfo *ri,
5051 uint64_t value)
5052{
5053
5054
5055
5056
5057
5058
5059
5060 do_rvae_write(env, value, ARMMMUIdxBit_E3, true);
5061}
5062
5063static void tlbi_aa64_ripas2e1_write(CPUARMState *env, const ARMCPRegInfo *ri,
5064 uint64_t value)
5065{
5066 do_rvae_write(env, value, ipas2e1_tlbmask(env, value),
5067 tlb_force_broadcast(env));
5068}
5069
5070static void tlbi_aa64_ripas2e1is_write(CPUARMState *env,
5071 const ARMCPRegInfo *ri,
5072 uint64_t value)
5073{
5074 do_rvae_write(env, value, ipas2e1_tlbmask(env, value), true);
5075}
5076#endif
5077
5078static CPAccessResult aa64_zva_access(CPUARMState *env, const ARMCPRegInfo *ri,
5079 bool isread)
5080{
5081 int cur_el = arm_current_el(env);
5082
5083 if (cur_el < 2) {
5084 uint64_t hcr = arm_hcr_el2_eff(env);
5085
5086 if (cur_el == 0) {
5087 if ((hcr & (HCR_E2H | HCR_TGE)) == (HCR_E2H | HCR_TGE)) {
5088 if (!(env->cp15.sctlr_el[2] & SCTLR_DZE)) {
5089 return CP_ACCESS_TRAP_EL2;
5090 }
5091 } else {
5092 if (!(env->cp15.sctlr_el[1] & SCTLR_DZE)) {
5093 return CP_ACCESS_TRAP;
5094 }
5095 if (hcr & HCR_TDZ) {
5096 return CP_ACCESS_TRAP_EL2;
5097 }
5098 }
5099 } else if (hcr & HCR_TDZ) {
5100 return CP_ACCESS_TRAP_EL2;
5101 }
5102 }
5103 return CP_ACCESS_OK;
5104}
5105
5106static uint64_t aa64_dczid_read(CPUARMState *env, const ARMCPRegInfo *ri)
5107{
5108 ARMCPU *cpu = env_archcpu(env);
5109 int dzp_bit = 1 << 4;
5110
5111
5112 if (aa64_zva_access(env, NULL, false) == CP_ACCESS_OK) {
5113 dzp_bit = 0;
5114 }
5115 return cpu->dcz_blocksize | dzp_bit;
5116}
5117
5118static CPAccessResult sp_el0_access(CPUARMState *env, const ARMCPRegInfo *ri,
5119 bool isread)
5120{
5121 if (!(env->pstate & PSTATE_SP)) {
5122
5123
5124
5125
5126 return CP_ACCESS_TRAP_UNCATEGORIZED;
5127 }
5128 return CP_ACCESS_OK;
5129}
5130
5131static uint64_t spsel_read(CPUARMState *env, const ARMCPRegInfo *ri)
5132{
5133 return env->pstate & PSTATE_SP;
5134}
5135
5136static void spsel_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t val)
5137{
5138 update_spsel(env, val);
5139}
5140
5141static void sctlr_write(CPUARMState *env, const ARMCPRegInfo *ri,
5142 uint64_t value)
5143{
5144 ARMCPU *cpu = env_archcpu(env);
5145
5146 if (arm_feature(env, ARM_FEATURE_PMSA) && !cpu->has_mpu) {
5147
5148 value &= ~SCTLR_M;
5149 }
5150
5151
5152
5153 if (ri->state == ARM_CP_STATE_AA64 && !cpu_isar_feature(aa64_mte, cpu)) {
5154 if (ri->opc1 == 6) {
5155 value &= ~(SCTLR_ITFSB | SCTLR_TCF | SCTLR_ATA);
5156 } else {
5157 value &= ~(SCTLR_ITFSB | SCTLR_TCF0 | SCTLR_TCF |
5158 SCTLR_ATA0 | SCTLR_ATA);
5159 }
5160 }
5161
5162 if (raw_read(env, ri) == value) {
5163
5164
5165
5166
5167 return;
5168 }
5169
5170 raw_write(env, ri, value);
5171
5172
5173 tlb_flush(CPU(cpu));
5174
5175 if (tcg_enabled() && ri->type & ARM_CP_SUPPRESS_TB_END) {
5176
5177
5178
5179
5180
5181
5182 arm_rebuild_hflags(env);
5183 }
5184}
5185
5186static void mdcr_el3_write(CPUARMState *env, const ARMCPRegInfo *ri,
5187 uint64_t value)
5188{
5189
5190
5191
5192
5193
5194 bool pmu_op = (env->cp15.mdcr_el3 ^ value) & MDCR_EL3_PMU_ENABLE_BITS;
5195
5196 if (pmu_op) {
5197 pmu_op_start(env);
5198 }
5199 env->cp15.mdcr_el3 = value;
5200 if (pmu_op) {
5201 pmu_op_finish(env);
5202 }
5203}
5204
5205static void sdcr_write(CPUARMState *env, const ARMCPRegInfo *ri,
5206 uint64_t value)
5207{
5208
5209 mdcr_el3_write(env, ri, value & SDCR_VALID_MASK);
5210}
5211
5212static void mdcr_el2_write(CPUARMState *env, const ARMCPRegInfo *ri,
5213 uint64_t value)
5214{
5215
5216
5217
5218
5219
5220 bool pmu_op = (env->cp15.mdcr_el2 ^ value) & MDCR_EL2_PMU_ENABLE_BITS;
5221
5222 if (pmu_op) {
5223 pmu_op_start(env);
5224 }
5225 env->cp15.mdcr_el2 = value;
5226 if (pmu_op) {
5227 pmu_op_finish(env);
5228 }
5229}
5230
5231static const ARMCPRegInfo v8_cp_reginfo[] = {
5232
5233
5234
5235
5236 { .name = "NZCV", .state = ARM_CP_STATE_AA64,
5237 .opc0 = 3, .opc1 = 3, .opc2 = 0, .crn = 4, .crm = 2,
5238 .access = PL0_RW, .type = ARM_CP_NZCV },
5239 { .name = "DAIF", .state = ARM_CP_STATE_AA64,
5240 .opc0 = 3, .opc1 = 3, .opc2 = 1, .crn = 4, .crm = 2,
5241 .type = ARM_CP_NO_RAW,
5242 .access = PL0_RW, .accessfn = aa64_daif_access,
5243 .fieldoffset = offsetof(CPUARMState, daif),
5244 .writefn = aa64_daif_write, .resetfn = arm_cp_reset_ignore },
5245 { .name = "FPCR", .state = ARM_CP_STATE_AA64,
5246 .opc0 = 3, .opc1 = 3, .opc2 = 0, .crn = 4, .crm = 4,
5247 .access = PL0_RW, .type = ARM_CP_FPU | ARM_CP_SUPPRESS_TB_END,
5248 .readfn = aa64_fpcr_read, .writefn = aa64_fpcr_write },
5249 { .name = "FPSR", .state = ARM_CP_STATE_AA64,
5250 .opc0 = 3, .opc1 = 3, .opc2 = 1, .crn = 4, .crm = 4,
5251 .access = PL0_RW, .type = ARM_CP_FPU | ARM_CP_SUPPRESS_TB_END,
5252 .readfn = aa64_fpsr_read, .writefn = aa64_fpsr_write },
5253 { .name = "DCZID_EL0", .state = ARM_CP_STATE_AA64,
5254 .opc0 = 3, .opc1 = 3, .opc2 = 7, .crn = 0, .crm = 0,
5255 .access = PL0_R, .type = ARM_CP_NO_RAW,
5256 .fgt = FGT_DCZID_EL0,
5257 .readfn = aa64_dczid_read },
5258 { .name = "DC_ZVA", .state = ARM_CP_STATE_AA64,
5259 .opc0 = 1, .opc1 = 3, .crn = 7, .crm = 4, .opc2 = 1,
5260 .access = PL0_W, .type = ARM_CP_DC_ZVA,
5261#ifndef CONFIG_USER_ONLY
5262
5263 .accessfn = aa64_zva_access,
5264 .fgt = FGT_DCZVA,
5265#endif
5266 },
5267 { .name = "CURRENTEL", .state = ARM_CP_STATE_AA64,
5268 .opc0 = 3, .opc1 = 0, .opc2 = 2, .crn = 4, .crm = 2,
5269 .access = PL1_R, .type = ARM_CP_CURRENTEL },
5270
5271 { .name = "IC_IALLUIS", .state = ARM_CP_STATE_AA64,
5272 .opc0 = 1, .opc1 = 0, .crn = 7, .crm = 1, .opc2 = 0,
5273 .access = PL1_W, .type = ARM_CP_NOP,
5274 .fgt = FGT_ICIALLUIS,
5275 .accessfn = access_ticab },
5276 { .name = "IC_IALLU", .state = ARM_CP_STATE_AA64,
5277 .opc0 = 1, .opc1 = 0, .crn = 7, .crm = 5, .opc2 = 0,
5278 .access = PL1_W, .type = ARM_CP_NOP,
5279 .fgt = FGT_ICIALLU,
5280 .accessfn = access_tocu },
5281 { .name = "IC_IVAU", .state = ARM_CP_STATE_AA64,
5282 .opc0 = 1, .opc1 = 3, .crn = 7, .crm = 5, .opc2 = 1,
5283 .access = PL0_W, .type = ARM_CP_NOP,
5284 .fgt = FGT_ICIVAU,
5285 .accessfn = access_tocu },
5286 { .name = "DC_IVAC", .state = ARM_CP_STATE_AA64,
5287 .opc0 = 1, .opc1 = 0, .crn = 7, .crm = 6, .opc2 = 1,
5288 .access = PL1_W, .accessfn = aa64_cacheop_poc_access,
5289 .fgt = FGT_DCIVAC,
5290 .type = ARM_CP_NOP },
5291 { .name = "DC_ISW", .state = ARM_CP_STATE_AA64,
5292 .opc0 = 1, .opc1 = 0, .crn = 7, .crm = 6, .opc2 = 2,
5293 .fgt = FGT_DCISW,
5294 .access = PL1_W, .accessfn = access_tsw, .type = ARM_CP_NOP },
5295 { .name = "DC_CVAC", .state = ARM_CP_STATE_AA64,
5296 .opc0 = 1, .opc1 = 3, .crn = 7, .crm = 10, .opc2 = 1,
5297 .access = PL0_W, .type = ARM_CP_NOP,
5298 .fgt = FGT_DCCVAC,
5299 .accessfn = aa64_cacheop_poc_access },
5300 { .name = "DC_CSW", .state = ARM_CP_STATE_AA64,
5301 .opc0 = 1, .opc1 = 0, .crn = 7, .crm = 10, .opc2 = 2,
5302 .fgt = FGT_DCCSW,
5303 .access = PL1_W, .accessfn = access_tsw, .type = ARM_CP_NOP },
5304 { .name = "DC_CVAU", .state = ARM_CP_STATE_AA64,
5305 .opc0 = 1, .opc1 = 3, .crn = 7, .crm = 11, .opc2 = 1,
5306 .access = PL0_W, .type = ARM_CP_NOP,
5307 .fgt = FGT_DCCVAU,
5308 .accessfn = access_tocu },
5309 { .name = "DC_CIVAC", .state = ARM_CP_STATE_AA64,
5310 .opc0 = 1, .opc1 = 3, .crn = 7, .crm = 14, .opc2 = 1,
5311 .access = PL0_W, .type = ARM_CP_NOP,
5312 .fgt = FGT_DCCIVAC,
5313 .accessfn = aa64_cacheop_poc_access },
5314 { .name = "DC_CISW", .state = ARM_CP_STATE_AA64,
5315 .opc0 = 1, .opc1 = 0, .crn = 7, .crm = 14, .opc2 = 2,
5316 .fgt = FGT_DCCISW,
5317 .access = PL1_W, .accessfn = access_tsw, .type = ARM_CP_NOP },
5318
5319 { .name = "TLBI_VMALLE1IS", .state = ARM_CP_STATE_AA64,
5320 .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 0,
5321 .access = PL1_W, .accessfn = access_ttlbis, .type = ARM_CP_NO_RAW,
5322 .fgt = FGT_TLBIVMALLE1IS,
5323 .writefn = tlbi_aa64_vmalle1is_write },
5324 { .name = "TLBI_VAE1IS", .state = ARM_CP_STATE_AA64,
5325 .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 1,
5326 .access = PL1_W, .accessfn = access_ttlbis, .type = ARM_CP_NO_RAW,
5327 .fgt = FGT_TLBIVAE1IS,
5328 .writefn = tlbi_aa64_vae1is_write },
5329 { .name = "TLBI_ASIDE1IS", .state = ARM_CP_STATE_AA64,
5330 .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 2,
5331 .access = PL1_W, .accessfn = access_ttlbis, .type = ARM_CP_NO_RAW,
5332 .fgt = FGT_TLBIASIDE1IS,
5333 .writefn = tlbi_aa64_vmalle1is_write },
5334 { .name = "TLBI_VAAE1IS", .state = ARM_CP_STATE_AA64,
5335 .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 3,
5336 .access = PL1_W, .accessfn = access_ttlbis, .type = ARM_CP_NO_RAW,
5337 .fgt = FGT_TLBIVAAE1IS,
5338 .writefn = tlbi_aa64_vae1is_write },
5339 { .name = "TLBI_VALE1IS", .state = ARM_CP_STATE_AA64,
5340 .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 5,
5341 .access = PL1_W, .accessfn = access_ttlbis, .type = ARM_CP_NO_RAW,
5342 .fgt = FGT_TLBIVALE1IS,
5343 .writefn = tlbi_aa64_vae1is_write },
5344 { .name = "TLBI_VAALE1IS", .state = ARM_CP_STATE_AA64,
5345 .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 7,
5346 .access = PL1_W, .accessfn = access_ttlbis, .type = ARM_CP_NO_RAW,
5347 .fgt = FGT_TLBIVAALE1IS,
5348 .writefn = tlbi_aa64_vae1is_write },
5349 { .name = "TLBI_VMALLE1", .state = ARM_CP_STATE_AA64,
5350 .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 0,
5351 .access = PL1_W, .accessfn = access_ttlb, .type = ARM_CP_NO_RAW,
5352 .fgt = FGT_TLBIVMALLE1,
5353 .writefn = tlbi_aa64_vmalle1_write },
5354 { .name = "TLBI_VAE1", .state = ARM_CP_STATE_AA64,
5355 .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 1,
5356 .access = PL1_W, .accessfn = access_ttlb, .type = ARM_CP_NO_RAW,
5357 .fgt = FGT_TLBIVAE1,
5358 .writefn = tlbi_aa64_vae1_write },
5359 { .name = "TLBI_ASIDE1", .state = ARM_CP_STATE_AA64,
5360 .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 2,
5361 .access = PL1_W, .accessfn = access_ttlb, .type = ARM_CP_NO_RAW,
5362 .fgt = FGT_TLBIASIDE1,
5363 .writefn = tlbi_aa64_vmalle1_write },
5364 { .name = "TLBI_VAAE1", .state = ARM_CP_STATE_AA64,
5365 .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 3,
5366 .access = PL1_W, .accessfn = access_ttlb, .type = ARM_CP_NO_RAW,
5367 .fgt = FGT_TLBIVAAE1,
5368 .writefn = tlbi_aa64_vae1_write },
5369 { .name = "TLBI_VALE1", .state = ARM_CP_STATE_AA64,
5370 .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 5,
5371 .access = PL1_W, .accessfn = access_ttlb, .type = ARM_CP_NO_RAW,
5372 .fgt = FGT_TLBIVALE1,
5373 .writefn = tlbi_aa64_vae1_write },
5374 { .name = "TLBI_VAALE1", .state = ARM_CP_STATE_AA64,
5375 .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 7,
5376 .access = PL1_W, .accessfn = access_ttlb, .type = ARM_CP_NO_RAW,
5377 .fgt = FGT_TLBIVAALE1,
5378 .writefn = tlbi_aa64_vae1_write },
5379 { .name = "TLBI_IPAS2E1IS", .state = ARM_CP_STATE_AA64,
5380 .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 0, .opc2 = 1,
5381 .access = PL2_W, .type = ARM_CP_NO_RAW,
5382 .writefn = tlbi_aa64_ipas2e1is_write },
5383 { .name = "TLBI_IPAS2LE1IS", .state = ARM_CP_STATE_AA64,
5384 .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 0, .opc2 = 5,
5385 .access = PL2_W, .type = ARM_CP_NO_RAW,
5386 .writefn = tlbi_aa64_ipas2e1is_write },
5387 { .name = "TLBI_ALLE1IS", .state = ARM_CP_STATE_AA64,
5388 .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 3, .opc2 = 4,
5389 .access = PL2_W, .type = ARM_CP_NO_RAW,
5390 .writefn = tlbi_aa64_alle1is_write },
5391 { .name = "TLBI_VMALLS12E1IS", .state = ARM_CP_STATE_AA64,
5392 .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 3, .opc2 = 6,
5393 .access = PL2_W, .type = ARM_CP_NO_RAW,
5394 .writefn = tlbi_aa64_alle1is_write },
5395 { .name = "TLBI_IPAS2E1", .state = ARM_CP_STATE_AA64,
5396 .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 4, .opc2 = 1,
5397 .access = PL2_W, .type = ARM_CP_NO_RAW,
5398 .writefn = tlbi_aa64_ipas2e1_write },
5399 { .name = "TLBI_IPAS2LE1", .state = ARM_CP_STATE_AA64,
5400 .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 4, .opc2 = 5,
5401 .access = PL2_W, .type = ARM_CP_NO_RAW,
5402 .writefn = tlbi_aa64_ipas2e1_write },
5403 { .name = "TLBI_ALLE1", .state = ARM_CP_STATE_AA64,
5404 .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 7, .opc2 = 4,
5405 .access = PL2_W, .type = ARM_CP_NO_RAW,
5406 .writefn = tlbi_aa64_alle1_write },
5407 { .name = "TLBI_VMALLS12E1", .state = ARM_CP_STATE_AA64,
5408 .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 7, .opc2 = 6,
5409 .access = PL2_W, .type = ARM_CP_NO_RAW,
5410 .writefn = tlbi_aa64_alle1is_write },
5411#ifndef CONFIG_USER_ONLY
5412
5413 { .name = "AT_S1E1R", .state = ARM_CP_STATE_AA64,
5414 .opc0 = 1, .opc1 = 0, .crn = 7, .crm = 8, .opc2 = 0,
5415 .access = PL1_W, .type = ARM_CP_NO_RAW | ARM_CP_RAISES_EXC,
5416 .fgt = FGT_ATS1E1R,
5417 .writefn = ats_write64 },
5418 { .name = "AT_S1E1W", .state = ARM_CP_STATE_AA64,
5419 .opc0 = 1, .opc1 = 0, .crn = 7, .crm = 8, .opc2 = 1,
5420 .access = PL1_W, .type = ARM_CP_NO_RAW | ARM_CP_RAISES_EXC,
5421 .fgt = FGT_ATS1E1W,
5422 .writefn = ats_write64 },
5423 { .name = "AT_S1E0R", .state = ARM_CP_STATE_AA64,
5424 .opc0 = 1, .opc1 = 0, .crn = 7, .crm = 8, .opc2 = 2,
5425 .access = PL1_W, .type = ARM_CP_NO_RAW | ARM_CP_RAISES_EXC,
5426 .fgt = FGT_ATS1E0R,
5427 .writefn = ats_write64 },
5428 { .name = "AT_S1E0W", .state = ARM_CP_STATE_AA64,
5429 .opc0 = 1, .opc1 = 0, .crn = 7, .crm = 8, .opc2 = 3,
5430 .access = PL1_W, .type = ARM_CP_NO_RAW | ARM_CP_RAISES_EXC,
5431 .fgt = FGT_ATS1E0W,
5432 .writefn = ats_write64 },
5433 { .name = "AT_S12E1R", .state = ARM_CP_STATE_AA64,
5434 .opc0 = 1, .opc1 = 4, .crn = 7, .crm = 8, .opc2 = 4,
5435 .access = PL2_W, .type = ARM_CP_NO_RAW | ARM_CP_RAISES_EXC,
5436 .writefn = ats_write64 },
5437 { .name = "AT_S12E1W", .state = ARM_CP_STATE_AA64,
5438 .opc0 = 1, .opc1 = 4, .crn = 7, .crm = 8, .opc2 = 5,
5439 .access = PL2_W, .type = ARM_CP_NO_RAW | ARM_CP_RAISES_EXC,
5440 .writefn = ats_write64 },
5441 { .name = "AT_S12E0R", .state = ARM_CP_STATE_AA64,
5442 .opc0 = 1, .opc1 = 4, .crn = 7, .crm = 8, .opc2 = 6,
5443 .access = PL2_W, .type = ARM_CP_NO_RAW | ARM_CP_RAISES_EXC,
5444 .writefn = ats_write64 },
5445 { .name = "AT_S12E0W", .state = ARM_CP_STATE_AA64,
5446 .opc0 = 1, .opc1 = 4, .crn = 7, .crm = 8, .opc2 = 7,
5447 .access = PL2_W, .type = ARM_CP_NO_RAW | ARM_CP_RAISES_EXC,
5448 .writefn = ats_write64 },
5449
5450 { .name = "AT_S1E3R", .state = ARM_CP_STATE_AA64,
5451 .opc0 = 1, .opc1 = 6, .crn = 7, .crm = 8, .opc2 = 0,
5452 .access = PL3_W, .type = ARM_CP_NO_RAW | ARM_CP_RAISES_EXC,
5453 .writefn = ats_write64 },
5454 { .name = "AT_S1E3W", .state = ARM_CP_STATE_AA64,
5455 .opc0 = 1, .opc1 = 6, .crn = 7, .crm = 8, .opc2 = 1,
5456 .access = PL3_W, .type = ARM_CP_NO_RAW | ARM_CP_RAISES_EXC,
5457 .writefn = ats_write64 },
5458 { .name = "PAR_EL1", .state = ARM_CP_STATE_AA64,
5459 .type = ARM_CP_ALIAS,
5460 .opc0 = 3, .opc1 = 0, .crn = 7, .crm = 4, .opc2 = 0,
5461 .access = PL1_RW, .resetvalue = 0,
5462 .fgt = FGT_PAR_EL1,
5463 .fieldoffset = offsetof(CPUARMState, cp15.par_el[1]),
5464 .writefn = par_write },
5465#endif
5466
5467 { .name = "TLBIMVALIS", .cp = 15, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 5,
5468 .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlbis,
5469 .writefn = tlbimva_is_write },
5470 { .name = "TLBIMVAALIS", .cp = 15, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 7,
5471 .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlbis,
5472 .writefn = tlbimvaa_is_write },
5473 { .name = "TLBIMVAL", .cp = 15, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 5,
5474 .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlb,
5475 .writefn = tlbimva_write },
5476 { .name = "TLBIMVAAL", .cp = 15, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 7,
5477 .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlb,
5478 .writefn = tlbimvaa_write },
5479 { .name = "TLBIMVALH", .cp = 15, .opc1 = 4, .crn = 8, .crm = 7, .opc2 = 5,
5480 .type = ARM_CP_NO_RAW, .access = PL2_W,
5481 .writefn = tlbimva_hyp_write },
5482 { .name = "TLBIMVALHIS",
5483 .cp = 15, .opc1 = 4, .crn = 8, .crm = 3, .opc2 = 5,
5484 .type = ARM_CP_NO_RAW, .access = PL2_W,
5485 .writefn = tlbimva_hyp_is_write },
5486 { .name = "TLBIIPAS2",
5487 .cp = 15, .opc1 = 4, .crn = 8, .crm = 4, .opc2 = 1,
5488 .type = ARM_CP_NO_RAW, .access = PL2_W,
5489 .writefn = tlbiipas2_hyp_write },
5490 { .name = "TLBIIPAS2IS",
5491 .cp = 15, .opc1 = 4, .crn = 8, .crm = 0, .opc2 = 1,
5492 .type = ARM_CP_NO_RAW, .access = PL2_W,
5493 .writefn = tlbiipas2is_hyp_write },
5494 { .name = "TLBIIPAS2L",
5495 .cp = 15, .opc1 = 4, .crn = 8, .crm = 4, .opc2 = 5,
5496 .type = ARM_CP_NO_RAW, .access = PL2_W,
5497 .writefn = tlbiipas2_hyp_write },
5498 { .name = "TLBIIPAS2LIS",
5499 .cp = 15, .opc1 = 4, .crn = 8, .crm = 0, .opc2 = 5,
5500 .type = ARM_CP_NO_RAW, .access = PL2_W,
5501 .writefn = tlbiipas2is_hyp_write },
5502
5503 { .name = "ICIALLUIS", .cp = 15, .opc1 = 0, .crn = 7, .crm = 1, .opc2 = 0,
5504 .type = ARM_CP_NOP, .access = PL1_W, .accessfn = access_ticab },
5505 { .name = "BPIALLUIS", .cp = 15, .opc1 = 0, .crn = 7, .crm = 1, .opc2 = 6,
5506 .type = ARM_CP_NOP, .access = PL1_W },
5507 { .name = "ICIALLU", .cp = 15, .opc1 = 0, .crn = 7, .crm = 5, .opc2 = 0,
5508 .type = ARM_CP_NOP, .access = PL1_W, .accessfn = access_tocu },
5509 { .name = "ICIMVAU", .cp = 15, .opc1 = 0, .crn = 7, .crm = 5, .opc2 = 1,
5510 .type = ARM_CP_NOP, .access = PL1_W, .accessfn = access_tocu },
5511 { .name = "BPIALL", .cp = 15, .opc1 = 0, .crn = 7, .crm = 5, .opc2 = 6,
5512 .type = ARM_CP_NOP, .access = PL1_W },
5513 { .name = "BPIMVA", .cp = 15, .opc1 = 0, .crn = 7, .crm = 5, .opc2 = 7,
5514 .type = ARM_CP_NOP, .access = PL1_W },
5515 { .name = "DCIMVAC", .cp = 15, .opc1 = 0, .crn = 7, .crm = 6, .opc2 = 1,
5516 .type = ARM_CP_NOP, .access = PL1_W, .accessfn = aa64_cacheop_poc_access },
5517 { .name = "DCISW", .cp = 15, .opc1 = 0, .crn = 7, .crm = 6, .opc2 = 2,
5518 .type = ARM_CP_NOP, .access = PL1_W, .accessfn = access_tsw },
5519 { .name = "DCCMVAC", .cp = 15, .opc1 = 0, .crn = 7, .crm = 10, .opc2 = 1,
5520 .type = ARM_CP_NOP, .access = PL1_W, .accessfn = aa64_cacheop_poc_access },
5521 { .name = "DCCSW", .cp = 15, .opc1 = 0, .crn = 7, .crm = 10, .opc2 = 2,
5522 .type = ARM_CP_NOP, .access = PL1_W, .accessfn = access_tsw },
5523 { .name = "DCCMVAU", .cp = 15, .opc1 = 0, .crn = 7, .crm = 11, .opc2 = 1,
5524 .type = ARM_CP_NOP, .access = PL1_W, .accessfn = access_tocu },
5525 { .name = "DCCIMVAC", .cp = 15, .opc1 = 0, .crn = 7, .crm = 14, .opc2 = 1,
5526 .type = ARM_CP_NOP, .access = PL1_W, .accessfn = aa64_cacheop_poc_access },
5527 { .name = "DCCISW", .cp = 15, .opc1 = 0, .crn = 7, .crm = 14, .opc2 = 2,
5528 .type = ARM_CP_NOP, .access = PL1_W, .accessfn = access_tsw },
5529
5530 { .name = "DACR", .cp = 15, .opc1 = 0, .crn = 3, .crm = 0, .opc2 = 0,
5531 .access = PL1_RW, .accessfn = access_tvm_trvm, .resetvalue = 0,
5532 .writefn = dacr_write, .raw_writefn = raw_write,
5533 .bank_fieldoffsets = { offsetoflow32(CPUARMState, cp15.dacr_s),
5534 offsetoflow32(CPUARMState, cp15.dacr_ns) } },
5535 { .name = "ELR_EL1", .state = ARM_CP_STATE_AA64,
5536 .type = ARM_CP_ALIAS,
5537 .opc0 = 3, .opc1 = 0, .crn = 4, .crm = 0, .opc2 = 1,
5538 .access = PL1_RW,
5539 .fieldoffset = offsetof(CPUARMState, elr_el[1]) },
5540 { .name = "SPSR_EL1", .state = ARM_CP_STATE_AA64,
5541 .type = ARM_CP_ALIAS,
5542 .opc0 = 3, .opc1 = 0, .crn = 4, .crm = 0, .opc2 = 0,
5543 .access = PL1_RW,
5544 .fieldoffset = offsetof(CPUARMState, banked_spsr[BANK_SVC]) },
5545
5546
5547
5548
5549
5550 { .name = "SP_EL0", .state = ARM_CP_STATE_AA64,
5551 .opc0 = 3, .opc1 = 0, .crn = 4, .crm = 1, .opc2 = 0,
5552 .access = PL1_RW, .accessfn = sp_el0_access,
5553 .type = ARM_CP_ALIAS,
5554 .fieldoffset = offsetof(CPUARMState, sp_el[0]) },
5555 { .name = "SP_EL1", .state = ARM_CP_STATE_AA64,
5556 .opc0 = 3, .opc1 = 4, .crn = 4, .crm = 1, .opc2 = 0,
5557 .access = PL2_RW, .type = ARM_CP_ALIAS | ARM_CP_EL3_NO_EL2_KEEP,
5558 .fieldoffset = offsetof(CPUARMState, sp_el[1]) },
5559 { .name = "SPSel", .state = ARM_CP_STATE_AA64,
5560 .opc0 = 3, .opc1 = 0, .crn = 4, .crm = 2, .opc2 = 0,
5561 .type = ARM_CP_NO_RAW,
5562 .access = PL1_RW, .readfn = spsel_read, .writefn = spsel_write },
5563 { .name = "FPEXC32_EL2", .state = ARM_CP_STATE_AA64,
5564 .opc0 = 3, .opc1 = 4, .crn = 5, .crm = 3, .opc2 = 0,
5565 .access = PL2_RW,
5566 .type = ARM_CP_ALIAS | ARM_CP_FPU | ARM_CP_EL3_NO_EL2_KEEP,
5567 .fieldoffset = offsetof(CPUARMState, vfp.xregs[ARM_VFP_FPEXC]) },
5568 { .name = "DACR32_EL2", .state = ARM_CP_STATE_AA64,
5569 .opc0 = 3, .opc1 = 4, .crn = 3, .crm = 0, .opc2 = 0,
5570 .access = PL2_RW, .resetvalue = 0, .type = ARM_CP_EL3_NO_EL2_KEEP,
5571 .writefn = dacr_write, .raw_writefn = raw_write,
5572 .fieldoffset = offsetof(CPUARMState, cp15.dacr32_el2) },
5573 { .name = "IFSR32_EL2", .state = ARM_CP_STATE_AA64,
5574 .opc0 = 3, .opc1 = 4, .crn = 5, .crm = 0, .opc2 = 1,
5575 .access = PL2_RW, .resetvalue = 0, .type = ARM_CP_EL3_NO_EL2_KEEP,
5576 .fieldoffset = offsetof(CPUARMState, cp15.ifsr32_el2) },
5577 { .name = "SPSR_IRQ", .state = ARM_CP_STATE_AA64,
5578 .type = ARM_CP_ALIAS,
5579 .opc0 = 3, .opc1 = 4, .crn = 4, .crm = 3, .opc2 = 0,
5580 .access = PL2_RW,
5581 .fieldoffset = offsetof(CPUARMState, banked_spsr[BANK_IRQ]) },
5582 { .name = "SPSR_ABT", .state = ARM_CP_STATE_AA64,
5583 .type = ARM_CP_ALIAS,
5584 .opc0 = 3, .opc1 = 4, .crn = 4, .crm = 3, .opc2 = 1,
5585 .access = PL2_RW,
5586 .fieldoffset = offsetof(CPUARMState, banked_spsr[BANK_ABT]) },
5587 { .name = "SPSR_UND", .state = ARM_CP_STATE_AA64,
5588 .type = ARM_CP_ALIAS,
5589 .opc0 = 3, .opc1 = 4, .crn = 4, .crm = 3, .opc2 = 2,
5590 .access = PL2_RW,
5591 .fieldoffset = offsetof(CPUARMState, banked_spsr[BANK_UND]) },
5592 { .name = "SPSR_FIQ", .state = ARM_CP_STATE_AA64,
5593 .type = ARM_CP_ALIAS,
5594 .opc0 = 3, .opc1 = 4, .crn = 4, .crm = 3, .opc2 = 3,
5595 .access = PL2_RW,
5596 .fieldoffset = offsetof(CPUARMState, banked_spsr[BANK_FIQ]) },
5597 { .name = "MDCR_EL3", .state = ARM_CP_STATE_AA64,
5598 .type = ARM_CP_IO,
5599 .opc0 = 3, .opc1 = 6, .crn = 1, .crm = 3, .opc2 = 1,
5600 .resetvalue = 0,
5601 .access = PL3_RW,
5602 .writefn = mdcr_el3_write,
5603 .fieldoffset = offsetof(CPUARMState, cp15.mdcr_el3) },
5604 { .name = "SDCR", .type = ARM_CP_ALIAS | ARM_CP_IO,
5605 .cp = 15, .opc1 = 0, .crn = 1, .crm = 3, .opc2 = 1,
5606 .access = PL1_RW, .accessfn = access_trap_aa32s_el1,
5607 .writefn = sdcr_write,
5608 .fieldoffset = offsetoflow32(CPUARMState, cp15.mdcr_el3) },
5609};
5610
5611static void do_hcr_write(CPUARMState *env, uint64_t value, uint64_t valid_mask)
5612{
5613 ARMCPU *cpu = env_archcpu(env);
5614
5615 if (arm_feature(env, ARM_FEATURE_V8)) {
5616 valid_mask |= MAKE_64BIT_MASK(0, 34);
5617 } else {
5618 valid_mask |= MAKE_64BIT_MASK(0, 28);
5619 }
5620
5621 if (arm_feature(env, ARM_FEATURE_EL3)) {
5622 valid_mask &= ~HCR_HCD;
5623 } else if (cpu->psci_conduit != QEMU_PSCI_CONDUIT_SMC) {
5624
5625
5626
5627
5628
5629
5630
5631
5632 valid_mask &= ~HCR_TSC;
5633 }
5634
5635 if (arm_feature(env, ARM_FEATURE_AARCH64)) {
5636 if (cpu_isar_feature(aa64_vh, cpu)) {
5637 valid_mask |= HCR_E2H;
5638 }
5639 if (cpu_isar_feature(aa64_ras, cpu)) {
5640 valid_mask |= HCR_TERR | HCR_TEA;
5641 }
5642 if (cpu_isar_feature(aa64_lor, cpu)) {
5643 valid_mask |= HCR_TLOR;
5644 }
5645 if (cpu_isar_feature(aa64_pauth, cpu)) {
5646 valid_mask |= HCR_API | HCR_APK;
5647 }
5648 if (cpu_isar_feature(aa64_mte, cpu)) {
5649 valid_mask |= HCR_ATA | HCR_DCT | HCR_TID5;
5650 }
5651 if (cpu_isar_feature(aa64_scxtnum, cpu)) {
5652 valid_mask |= HCR_ENSCXT;
5653 }
5654 if (cpu_isar_feature(aa64_fwb, cpu)) {
5655 valid_mask |= HCR_FWB;
5656 }
5657 }
5658
5659 if (cpu_isar_feature(any_evt, cpu)) {
5660 valid_mask |= HCR_TTLBIS | HCR_TTLBOS | HCR_TICAB | HCR_TOCU | HCR_TID4;
5661 } else if (cpu_isar_feature(any_half_evt, cpu)) {
5662 valid_mask |= HCR_TICAB | HCR_TOCU | HCR_TID4;
5663 }
5664
5665
5666 value &= valid_mask;
5667
5668
5669
5670
5671
5672
5673
5674
5675
5676 if ((env->cp15.hcr_el2 ^ value) &
5677 (HCR_VM | HCR_PTW | HCR_DC | HCR_DCT | HCR_FWB)) {
5678 tlb_flush(CPU(cpu));
5679 }
5680 env->cp15.hcr_el2 = value;
5681
5682
5683
5684
5685
5686
5687
5688
5689
5690
5691
5692
5693 g_assert(qemu_mutex_iothread_locked());
5694 arm_cpu_update_virq(cpu);
5695 arm_cpu_update_vfiq(cpu);
5696 arm_cpu_update_vserr(cpu);
5697}
5698
5699static void hcr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
5700{
5701 do_hcr_write(env, value, 0);
5702}
5703
5704static void hcr_writehigh(CPUARMState *env, const ARMCPRegInfo *ri,
5705 uint64_t value)
5706{
5707
5708 value = deposit64(env->cp15.hcr_el2, 32, 32, value);
5709 do_hcr_write(env, value, MAKE_64BIT_MASK(0, 32));
5710}
5711
5712static void hcr_writelow(CPUARMState *env, const ARMCPRegInfo *ri,
5713 uint64_t value)
5714{
5715
5716 value = deposit64(env->cp15.hcr_el2, 0, 32, value);
5717 do_hcr_write(env, value, MAKE_64BIT_MASK(32, 32));
5718}
5719
5720
5721
5722
5723
5724
5725uint64_t arm_hcr_el2_eff_secstate(CPUARMState *env, bool secure)
5726{
5727 uint64_t ret = env->cp15.hcr_el2;
5728
5729 if (!arm_is_el2_enabled_secstate(env, secure)) {
5730
5731
5732
5733
5734
5735
5736
5737
5738
5739
5740
5741
5742
5743
5744
5745 return 0;
5746 }
5747
5748
5749
5750
5751
5752
5753 if (!arm_el_is_aa64(env, 2)) {
5754 uint64_t aa32_valid;
5755
5756
5757
5758
5759
5760
5761 aa32_valid = MAKE_64BIT_MASK(0, 32) & ~(HCR_RW | HCR_TDZ);
5762 aa32_valid |= (HCR_CD | HCR_ID | HCR_TERR | HCR_TEA | HCR_MIOCNCE |
5763 HCR_TID4 | HCR_TICAB | HCR_TOCU | HCR_TTLBIS);
5764 ret &= aa32_valid;
5765 }
5766
5767 if (ret & HCR_TGE) {
5768
5769 if (ret & HCR_E2H) {
5770 ret &= ~(HCR_VM | HCR_FMO | HCR_IMO | HCR_AMO |
5771 HCR_BSU_MASK | HCR_DC | HCR_TWI | HCR_TWE |
5772 HCR_TID0 | HCR_TID2 | HCR_TPCP | HCR_TPU |
5773 HCR_TDZ | HCR_CD | HCR_ID | HCR_MIOCNCE |
5774 HCR_TID4 | HCR_TICAB | HCR_TOCU | HCR_ENSCXT |
5775 HCR_TTLBIS | HCR_TTLBOS | HCR_TID5);
5776 } else {
5777 ret |= HCR_FMO | HCR_IMO | HCR_AMO;
5778 }
5779 ret &= ~(HCR_SWIO | HCR_PTW | HCR_VF | HCR_VI | HCR_VSE |
5780 HCR_FB | HCR_TID1 | HCR_TID3 | HCR_TSC | HCR_TACR |
5781 HCR_TSW | HCR_TTLB | HCR_TVM | HCR_HCD | HCR_TRVM |
5782 HCR_TLOR);
5783 }
5784
5785 return ret;
5786}
5787
5788uint64_t arm_hcr_el2_eff(CPUARMState *env)
5789{
5790 if (arm_feature(env, ARM_FEATURE_M)) {
5791 return 0;
5792 }
5793 return arm_hcr_el2_eff_secstate(env, arm_is_secure_below_el3(env));
5794}
5795
5796
5797
5798
5799bool el_is_in_host(CPUARMState *env, int el)
5800{
5801 uint64_t mask;
5802
5803
5804
5805
5806
5807 if (el & 1) {
5808 return false;
5809 }
5810
5811
5812
5813
5814
5815 mask = el ? HCR_E2H : HCR_E2H | HCR_TGE;
5816 if ((env->cp15.hcr_el2 & mask) != mask) {
5817 return false;
5818 }
5819
5820
5821 return arm_is_el2_enabled(env) && arm_el_is_aa64(env, 2);
5822}
5823
5824static void hcrx_write(CPUARMState *env, const ARMCPRegInfo *ri,
5825 uint64_t value)
5826{
5827 uint64_t valid_mask = 0;
5828
5829
5830
5831
5832 env->cp15.hcrx_el2 = value & valid_mask;
5833}
5834
5835static CPAccessResult access_hxen(CPUARMState *env, const ARMCPRegInfo *ri,
5836 bool isread)
5837{
5838 if (arm_current_el(env) < 3
5839 && arm_feature(env, ARM_FEATURE_EL3)
5840 && !(env->cp15.scr_el3 & SCR_HXEN)) {
5841 return CP_ACCESS_TRAP_EL3;
5842 }
5843 return CP_ACCESS_OK;
5844}
5845
5846static const ARMCPRegInfo hcrx_el2_reginfo = {
5847 .name = "HCRX_EL2", .state = ARM_CP_STATE_AA64,
5848 .opc0 = 3, .opc1 = 4, .crn = 1, .crm = 2, .opc2 = 2,
5849 .access = PL2_RW, .writefn = hcrx_write, .accessfn = access_hxen,
5850 .fieldoffset = offsetof(CPUARMState, cp15.hcrx_el2),
5851};
5852
5853
5854uint64_t arm_hcrx_el2_eff(CPUARMState *env)
5855{
5856
5857
5858
5859
5860
5861
5862 if (!arm_is_el2_enabled(env)
5863 || (arm_feature(env, ARM_FEATURE_EL3)
5864 && !(env->cp15.scr_el3 & SCR_HXEN))) {
5865 return 0;
5866 }
5867 return env->cp15.hcrx_el2;
5868}
5869
5870static void cptr_el2_write(CPUARMState *env, const ARMCPRegInfo *ri,
5871 uint64_t value)
5872{
5873
5874
5875
5876
5877 if (arm_feature(env, ARM_FEATURE_EL3) && !arm_el_is_aa64(env, 3) &&
5878 !arm_is_secure(env) && !extract32(env->cp15.nsacr, 10, 1)) {
5879 uint64_t mask = R_HCPTR_TCP11_MASK | R_HCPTR_TCP10_MASK;
5880 value = (value & ~mask) | (env->cp15.cptr_el[2] & mask);
5881 }
5882 env->cp15.cptr_el[2] = value;
5883}
5884
5885static uint64_t cptr_el2_read(CPUARMState *env, const ARMCPRegInfo *ri)
5886{
5887
5888
5889
5890
5891 uint64_t value = env->cp15.cptr_el[2];
5892
5893 if (arm_feature(env, ARM_FEATURE_EL3) && !arm_el_is_aa64(env, 3) &&
5894 !arm_is_secure(env) && !extract32(env->cp15.nsacr, 10, 1)) {
5895 value |= R_HCPTR_TCP11_MASK | R_HCPTR_TCP10_MASK;
5896 }
5897 return value;
5898}
5899
5900static const ARMCPRegInfo el2_cp_reginfo[] = {
5901 { .name = "HCR_EL2", .state = ARM_CP_STATE_AA64,
5902 .type = ARM_CP_IO,
5903 .opc0 = 3, .opc1 = 4, .crn = 1, .crm = 1, .opc2 = 0,
5904 .access = PL2_RW, .fieldoffset = offsetof(CPUARMState, cp15.hcr_el2),
5905 .writefn = hcr_write },
5906 { .name = "HCR", .state = ARM_CP_STATE_AA32,
5907 .type = ARM_CP_ALIAS | ARM_CP_IO,
5908 .cp = 15, .opc1 = 4, .crn = 1, .crm = 1, .opc2 = 0,
5909 .access = PL2_RW, .fieldoffset = offsetof(CPUARMState, cp15.hcr_el2),
5910 .writefn = hcr_writelow },
5911 { .name = "HACR_EL2", .state = ARM_CP_STATE_BOTH,
5912 .opc0 = 3, .opc1 = 4, .crn = 1, .crm = 1, .opc2 = 7,
5913 .access = PL2_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
5914 { .name = "ELR_EL2", .state = ARM_CP_STATE_AA64,
5915 .type = ARM_CP_ALIAS,
5916 .opc0 = 3, .opc1 = 4, .crn = 4, .crm = 0, .opc2 = 1,
5917 .access = PL2_RW,
5918 .fieldoffset = offsetof(CPUARMState, elr_el[2]) },
5919 { .name = "ESR_EL2", .state = ARM_CP_STATE_BOTH,
5920 .opc0 = 3, .opc1 = 4, .crn = 5, .crm = 2, .opc2 = 0,
5921 .access = PL2_RW, .fieldoffset = offsetof(CPUARMState, cp15.esr_el[2]) },
5922 { .name = "FAR_EL2", .state = ARM_CP_STATE_BOTH,
5923 .opc0 = 3, .opc1 = 4, .crn = 6, .crm = 0, .opc2 = 0,
5924 .access = PL2_RW, .fieldoffset = offsetof(CPUARMState, cp15.far_el[2]) },
5925 { .name = "HIFAR", .state = ARM_CP_STATE_AA32,
5926 .type = ARM_CP_ALIAS,
5927 .cp = 15, .opc1 = 4, .crn = 6, .crm = 0, .opc2 = 2,
5928 .access = PL2_RW,
5929 .fieldoffset = offsetofhigh32(CPUARMState, cp15.far_el[2]) },
5930 { .name = "SPSR_EL2", .state = ARM_CP_STATE_AA64,
5931 .type = ARM_CP_ALIAS,
5932 .opc0 = 3, .opc1 = 4, .crn = 4, .crm = 0, .opc2 = 0,
5933 .access = PL2_RW,
5934 .fieldoffset = offsetof(CPUARMState, banked_spsr[BANK_HYP]) },
5935 { .name = "VBAR_EL2", .state = ARM_CP_STATE_BOTH,
5936 .opc0 = 3, .opc1 = 4, .crn = 12, .crm = 0, .opc2 = 0,
5937 .access = PL2_RW, .writefn = vbar_write,
5938 .fieldoffset = offsetof(CPUARMState, cp15.vbar_el[2]),
5939 .resetvalue = 0 },
5940 { .name = "SP_EL2", .state = ARM_CP_STATE_AA64,
5941 .opc0 = 3, .opc1 = 6, .crn = 4, .crm = 1, .opc2 = 0,
5942 .access = PL3_RW, .type = ARM_CP_ALIAS,
5943 .fieldoffset = offsetof(CPUARMState, sp_el[2]) },
5944 { .name = "CPTR_EL2", .state = ARM_CP_STATE_BOTH,
5945 .opc0 = 3, .opc1 = 4, .crn = 1, .crm = 1, .opc2 = 2,
5946 .access = PL2_RW, .accessfn = cptr_access, .resetvalue = 0,
5947 .fieldoffset = offsetof(CPUARMState, cp15.cptr_el[2]),
5948 .readfn = cptr_el2_read, .writefn = cptr_el2_write },
5949 { .name = "MAIR_EL2", .state = ARM_CP_STATE_BOTH,
5950 .opc0 = 3, .opc1 = 4, .crn = 10, .crm = 2, .opc2 = 0,
5951 .access = PL2_RW, .fieldoffset = offsetof(CPUARMState, cp15.mair_el[2]),
5952 .resetvalue = 0 },
5953 { .name = "HMAIR1", .state = ARM_CP_STATE_AA32,
5954 .cp = 15, .opc1 = 4, .crn = 10, .crm = 2, .opc2 = 1,
5955 .access = PL2_RW, .type = ARM_CP_ALIAS,
5956 .fieldoffset = offsetofhigh32(CPUARMState, cp15.mair_el[2]) },
5957 { .name = "AMAIR_EL2", .state = ARM_CP_STATE_BOTH,
5958 .opc0 = 3, .opc1 = 4, .crn = 10, .crm = 3, .opc2 = 0,
5959 .access = PL2_RW, .type = ARM_CP_CONST,
5960 .resetvalue = 0 },
5961
5962 { .name = "HAMAIR1", .state = ARM_CP_STATE_AA32,
5963 .cp = 15, .opc1 = 4, .crn = 10, .crm = 3, .opc2 = 1,
5964 .access = PL2_RW, .type = ARM_CP_CONST,
5965 .resetvalue = 0 },
5966 { .name = "AFSR0_EL2", .state = ARM_CP_STATE_BOTH,
5967 .opc0 = 3, .opc1 = 4, .crn = 5, .crm = 1, .opc2 = 0,
5968 .access = PL2_RW, .type = ARM_CP_CONST,
5969 .resetvalue = 0 },
5970 { .name = "AFSR1_EL2", .state = ARM_CP_STATE_BOTH,
5971 .opc0 = 3, .opc1 = 4, .crn = 5, .crm = 1, .opc2 = 1,
5972 .access = PL2_RW, .type = ARM_CP_CONST,
5973 .resetvalue = 0 },
5974 { .name = "TCR_EL2", .state = ARM_CP_STATE_BOTH,
5975 .opc0 = 3, .opc1 = 4, .crn = 2, .crm = 0, .opc2 = 2,
5976 .access = PL2_RW, .writefn = vmsa_tcr_el12_write,
5977 .fieldoffset = offsetof(CPUARMState, cp15.tcr_el[2]) },
5978 { .name = "VTCR", .state = ARM_CP_STATE_AA32,
5979 .cp = 15, .opc1 = 4, .crn = 2, .crm = 1, .opc2 = 2,
5980 .type = ARM_CP_ALIAS,
5981 .access = PL2_RW, .accessfn = access_el3_aa32ns,
5982 .fieldoffset = offsetoflow32(CPUARMState, cp15.vtcr_el2) },
5983 { .name = "VTCR_EL2", .state = ARM_CP_STATE_AA64,
5984 .opc0 = 3, .opc1 = 4, .crn = 2, .crm = 1, .opc2 = 2,
5985 .access = PL2_RW,
5986
5987 .fieldoffset = offsetof(CPUARMState, cp15.vtcr_el2) },
5988 { .name = "VTTBR", .state = ARM_CP_STATE_AA32,
5989 .cp = 15, .opc1 = 6, .crm = 2,
5990 .type = ARM_CP_64BIT | ARM_CP_ALIAS,
5991 .access = PL2_RW, .accessfn = access_el3_aa32ns,
5992 .fieldoffset = offsetof(CPUARMState, cp15.vttbr_el2),
5993 .writefn = vttbr_write },
5994 { .name = "VTTBR_EL2", .state = ARM_CP_STATE_AA64,
5995 .opc0 = 3, .opc1 = 4, .crn = 2, .crm = 1, .opc2 = 0,
5996 .access = PL2_RW, .writefn = vttbr_write,
5997 .fieldoffset = offsetof(CPUARMState, cp15.vttbr_el2) },
5998 { .name = "SCTLR_EL2", .state = ARM_CP_STATE_BOTH,
5999 .opc0 = 3, .opc1 = 4, .crn = 1, .crm = 0, .opc2 = 0,
6000 .access = PL2_RW, .raw_writefn = raw_write, .writefn = sctlr_write,
6001 .fieldoffset = offsetof(CPUARMState, cp15.sctlr_el[2]) },
6002 { .name = "TPIDR_EL2", .state = ARM_CP_STATE_BOTH,
6003 .opc0 = 3, .opc1 = 4, .crn = 13, .crm = 0, .opc2 = 2,
6004 .access = PL2_RW, .resetvalue = 0,
6005 .fieldoffset = offsetof(CPUARMState, cp15.tpidr_el[2]) },
6006 { .name = "TTBR0_EL2", .state = ARM_CP_STATE_AA64,
6007 .opc0 = 3, .opc1 = 4, .crn = 2, .crm = 0, .opc2 = 0,
6008 .access = PL2_RW, .resetvalue = 0, .writefn = vmsa_tcr_ttbr_el2_write,
6009 .fieldoffset = offsetof(CPUARMState, cp15.ttbr0_el[2]) },
6010 { .name = "HTTBR", .cp = 15, .opc1 = 4, .crm = 2,
6011 .access = PL2_RW, .type = ARM_CP_64BIT | ARM_CP_ALIAS,
6012 .fieldoffset = offsetof(CPUARMState, cp15.ttbr0_el[2]) },
6013 { .name = "TLBIALLNSNH",
6014 .cp = 15, .opc1 = 4, .crn = 8, .crm = 7, .opc2 = 4,
6015 .type = ARM_CP_NO_RAW, .access = PL2_W,
6016 .writefn = tlbiall_nsnh_write },
6017 { .name = "TLBIALLNSNHIS",
6018 .cp = 15, .opc1 = 4, .crn = 8, .crm = 3, .opc2 = 4,
6019 .type = ARM_CP_NO_RAW, .access = PL2_W,
6020 .writefn = tlbiall_nsnh_is_write },
6021 { .name = "TLBIALLH", .cp = 15, .opc1 = 4, .crn = 8, .crm = 7, .opc2 = 0,
6022 .type = ARM_CP_NO_RAW, .access = PL2_W,
6023 .writefn = tlbiall_hyp_write },
6024 { .name = "TLBIALLHIS", .cp = 15, .opc1 = 4, .crn = 8, .crm = 3, .opc2 = 0,
6025 .type = ARM_CP_NO_RAW, .access = PL2_W,
6026 .writefn = tlbiall_hyp_is_write },
6027 { .name = "TLBIMVAH", .cp = 15, .opc1 = 4, .crn = 8, .crm = 7, .opc2 = 1,
6028 .type = ARM_CP_NO_RAW, .access = PL2_W,
6029 .writefn = tlbimva_hyp_write },
6030 { .name = "TLBIMVAHIS", .cp = 15, .opc1 = 4, .crn = 8, .crm = 3, .opc2 = 1,
6031 .type = ARM_CP_NO_RAW, .access = PL2_W,
6032 .writefn = tlbimva_hyp_is_write },
6033 { .name = "TLBI_ALLE2", .state = ARM_CP_STATE_AA64,
6034 .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 7, .opc2 = 0,
6035 .access = PL2_W, .type = ARM_CP_NO_RAW | ARM_CP_EL3_NO_EL2_UNDEF,
6036 .writefn = tlbi_aa64_alle2_write },
6037 { .name = "TLBI_VAE2", .state = ARM_CP_STATE_AA64,
6038 .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 7, .opc2 = 1,
6039 .access = PL2_W, .type = ARM_CP_NO_RAW | ARM_CP_EL3_NO_EL2_UNDEF,
6040 .writefn = tlbi_aa64_vae2_write },
6041 { .name = "TLBI_VALE2", .state = ARM_CP_STATE_AA64,
6042 .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 7, .opc2 = 5,
6043 .access = PL2_W, .type = ARM_CP_NO_RAW | ARM_CP_EL3_NO_EL2_UNDEF,
6044 .writefn = tlbi_aa64_vae2_write },
6045 { .name = "TLBI_ALLE2IS", .state = ARM_CP_STATE_AA64,
6046 .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 3, .opc2 = 0,
6047 .access = PL2_W, .type = ARM_CP_NO_RAW | ARM_CP_EL3_NO_EL2_UNDEF,
6048 .writefn = tlbi_aa64_alle2is_write },
6049 { .name = "TLBI_VAE2IS", .state = ARM_CP_STATE_AA64,
6050 .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 3, .opc2 = 1,
6051 .access = PL2_W, .type = ARM_CP_NO_RAW | ARM_CP_EL3_NO_EL2_UNDEF,
6052 .writefn = tlbi_aa64_vae2is_write },
6053 { .name = "TLBI_VALE2IS", .state = ARM_CP_STATE_AA64,
6054 .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 3, .opc2 = 5,
6055 .access = PL2_W, .type = ARM_CP_NO_RAW | ARM_CP_EL3_NO_EL2_UNDEF,
6056 .writefn = tlbi_aa64_vae2is_write },
6057#ifndef CONFIG_USER_ONLY
6058
6059
6060
6061
6062
6063 { .name = "AT_S1E2R", .state = ARM_CP_STATE_AA64,
6064 .opc0 = 1, .opc1 = 4, .crn = 7, .crm = 8, .opc2 = 0,
6065 .access = PL2_W, .accessfn = at_s1e2_access,
6066 .type = ARM_CP_NO_RAW | ARM_CP_RAISES_EXC | ARM_CP_EL3_NO_EL2_UNDEF,
6067 .writefn = ats_write64 },
6068 { .name = "AT_S1E2W", .state = ARM_CP_STATE_AA64,
6069 .opc0 = 1, .opc1 = 4, .crn = 7, .crm = 8, .opc2 = 1,
6070 .access = PL2_W, .accessfn = at_s1e2_access,
6071 .type = ARM_CP_NO_RAW | ARM_CP_RAISES_EXC | ARM_CP_EL3_NO_EL2_UNDEF,
6072 .writefn = ats_write64 },
6073
6074
6075
6076
6077
6078
6079 { .name = "ATS1HR", .cp = 15, .opc1 = 4, .crn = 7, .crm = 8, .opc2 = 0,
6080 .access = PL2_W,
6081 .writefn = ats1h_write, .type = ARM_CP_NO_RAW | ARM_CP_RAISES_EXC },
6082 { .name = "ATS1HW", .cp = 15, .opc1 = 4, .crn = 7, .crm = 8, .opc2 = 1,
6083 .access = PL2_W,
6084 .writefn = ats1h_write, .type = ARM_CP_NO_RAW | ARM_CP_RAISES_EXC },
6085 { .name = "CNTHCTL_EL2", .state = ARM_CP_STATE_BOTH,
6086 .opc0 = 3, .opc1 = 4, .crn = 14, .crm = 1, .opc2 = 0,
6087
6088
6089
6090
6091
6092 .access = PL2_RW, .resetvalue = 3,
6093 .fieldoffset = offsetof(CPUARMState, cp15.cnthctl_el2) },
6094 { .name = "CNTVOFF_EL2", .state = ARM_CP_STATE_AA64,
6095 .opc0 = 3, .opc1 = 4, .crn = 14, .crm = 0, .opc2 = 3,
6096 .access = PL2_RW, .type = ARM_CP_IO, .resetvalue = 0,
6097 .writefn = gt_cntvoff_write,
6098 .fieldoffset = offsetof(CPUARMState, cp15.cntvoff_el2) },
6099 { .name = "CNTVOFF", .cp = 15, .opc1 = 4, .crm = 14,
6100 .access = PL2_RW, .type = ARM_CP_64BIT | ARM_CP_ALIAS | ARM_CP_IO,
6101 .writefn = gt_cntvoff_write,
6102 .fieldoffset = offsetof(CPUARMState, cp15.cntvoff_el2) },
6103 { .name = "CNTHP_CVAL_EL2", .state = ARM_CP_STATE_AA64,
6104 .opc0 = 3, .opc1 = 4, .crn = 14, .crm = 2, .opc2 = 2,
6105 .fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_HYP].cval),
6106 .type = ARM_CP_IO, .access = PL2_RW,
6107 .writefn = gt_hyp_cval_write, .raw_writefn = raw_write },
6108 { .name = "CNTHP_CVAL", .cp = 15, .opc1 = 6, .crm = 14,
6109 .fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_HYP].cval),
6110 .access = PL2_RW, .type = ARM_CP_64BIT | ARM_CP_IO,
6111 .writefn = gt_hyp_cval_write, .raw_writefn = raw_write },
6112 { .name = "CNTHP_TVAL_EL2", .state = ARM_CP_STATE_BOTH,
6113 .opc0 = 3, .opc1 = 4, .crn = 14, .crm = 2, .opc2 = 0,
6114 .type = ARM_CP_NO_RAW | ARM_CP_IO, .access = PL2_RW,
6115 .resetfn = gt_hyp_timer_reset,
6116 .readfn = gt_hyp_tval_read, .writefn = gt_hyp_tval_write },
6117 { .name = "CNTHP_CTL_EL2", .state = ARM_CP_STATE_BOTH,
6118 .type = ARM_CP_IO,
6119 .opc0 = 3, .opc1 = 4, .crn = 14, .crm = 2, .opc2 = 1,
6120 .access = PL2_RW,
6121 .fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_HYP].ctl),
6122 .resetvalue = 0,
6123 .writefn = gt_hyp_ctl_write, .raw_writefn = raw_write },
6124#endif
6125 { .name = "HPFAR", .state = ARM_CP_STATE_AA32,
6126 .cp = 15, .opc1 = 4, .crn = 6, .crm = 0, .opc2 = 4,
6127 .access = PL2_RW, .accessfn = access_el3_aa32ns,
6128 .fieldoffset = offsetof(CPUARMState, cp15.hpfar_el2) },
6129 { .name = "HPFAR_EL2", .state = ARM_CP_STATE_AA64,
6130 .opc0 = 3, .opc1 = 4, .crn = 6, .crm = 0, .opc2 = 4,
6131 .access = PL2_RW,
6132 .fieldoffset = offsetof(CPUARMState, cp15.hpfar_el2) },
6133 { .name = "HSTR_EL2", .state = ARM_CP_STATE_BOTH,
6134 .cp = 15, .opc0 = 3, .opc1 = 4, .crn = 1, .crm = 1, .opc2 = 3,
6135 .access = PL2_RW,
6136 .fieldoffset = offsetof(CPUARMState, cp15.hstr_el2) },
6137};
6138
6139static const ARMCPRegInfo el2_v8_cp_reginfo[] = {
6140 { .name = "HCR2", .state = ARM_CP_STATE_AA32,
6141 .type = ARM_CP_ALIAS | ARM_CP_IO,
6142 .cp = 15, .opc1 = 4, .crn = 1, .crm = 1, .opc2 = 4,
6143 .access = PL2_RW,
6144 .fieldoffset = offsetofhigh32(CPUARMState, cp15.hcr_el2),
6145 .writefn = hcr_writehigh },
6146};
6147
6148static CPAccessResult sel2_access(CPUARMState *env, const ARMCPRegInfo *ri,
6149 bool isread)
6150{
6151 if (arm_current_el(env) == 3 || arm_is_secure_below_el3(env)) {
6152 return CP_ACCESS_OK;
6153 }
6154 return CP_ACCESS_TRAP_UNCATEGORIZED;
6155}
6156
6157static const ARMCPRegInfo el2_sec_cp_reginfo[] = {
6158 { .name = "VSTTBR_EL2", .state = ARM_CP_STATE_AA64,
6159 .opc0 = 3, .opc1 = 4, .crn = 2, .crm = 6, .opc2 = 0,
6160 .access = PL2_RW, .accessfn = sel2_access,
6161 .fieldoffset = offsetof(CPUARMState, cp15.vsttbr_el2) },
6162 { .name = "VSTCR_EL2", .state = ARM_CP_STATE_AA64,
6163 .opc0 = 3, .opc1 = 4, .crn = 2, .crm = 6, .opc2 = 2,
6164 .access = PL2_RW, .accessfn = sel2_access,
6165 .fieldoffset = offsetof(CPUARMState, cp15.vstcr_el2) },
6166};
6167
6168static CPAccessResult nsacr_access(CPUARMState *env, const ARMCPRegInfo *ri,
6169 bool isread)
6170{
6171
6172
6173
6174
6175 if (arm_current_el(env) == 3) {
6176 return CP_ACCESS_OK;
6177 }
6178 if (arm_is_secure_below_el3(env)) {
6179 if (env->cp15.scr_el3 & SCR_EEL2) {
6180 return CP_ACCESS_TRAP_EL2;
6181 }
6182 return CP_ACCESS_TRAP_EL3;
6183 }
6184
6185 if (isread) {
6186 return CP_ACCESS_OK;
6187 }
6188 return CP_ACCESS_TRAP_UNCATEGORIZED;
6189}
6190
6191static const ARMCPRegInfo el3_cp_reginfo[] = {
6192 { .name = "SCR_EL3", .state = ARM_CP_STATE_AA64,
6193 .opc0 = 3, .opc1 = 6, .crn = 1, .crm = 1, .opc2 = 0,
6194 .access = PL3_RW, .fieldoffset = offsetof(CPUARMState, cp15.scr_el3),
6195 .resetfn = scr_reset, .writefn = scr_write },
6196 { .name = "SCR", .type = ARM_CP_ALIAS | ARM_CP_NEWEL,
6197 .cp = 15, .opc1 = 0, .crn = 1, .crm = 1, .opc2 = 0,
6198 .access = PL1_RW, .accessfn = access_trap_aa32s_el1,
6199 .fieldoffset = offsetoflow32(CPUARMState, cp15.scr_el3),
6200 .writefn = scr_write },
6201 { .name = "SDER32_EL3", .state = ARM_CP_STATE_AA64,
6202 .opc0 = 3, .opc1 = 6, .crn = 1, .crm = 1, .opc2 = 1,
6203 .access = PL3_RW, .resetvalue = 0,
6204 .fieldoffset = offsetof(CPUARMState, cp15.sder) },
6205 { .name = "SDER",
6206 .cp = 15, .opc1 = 0, .crn = 1, .crm = 1, .opc2 = 1,
6207 .access = PL3_RW, .resetvalue = 0,
6208 .fieldoffset = offsetoflow32(CPUARMState, cp15.sder) },
6209 { .name = "MVBAR", .cp = 15, .opc1 = 0, .crn = 12, .crm = 0, .opc2 = 1,
6210 .access = PL1_RW, .accessfn = access_trap_aa32s_el1,
6211 .writefn = vbar_write, .resetvalue = 0,
6212 .fieldoffset = offsetof(CPUARMState, cp15.mvbar) },
6213 { .name = "TTBR0_EL3", .state = ARM_CP_STATE_AA64,
6214 .opc0 = 3, .opc1 = 6, .crn = 2, .crm = 0, .opc2 = 0,
6215 .access = PL3_RW, .resetvalue = 0,
6216 .fieldoffset = offsetof(CPUARMState, cp15.ttbr0_el[3]) },
6217 { .name = "TCR_EL3", .state = ARM_CP_STATE_AA64,
6218 .opc0 = 3, .opc1 = 6, .crn = 2, .crm = 0, .opc2 = 2,
6219 .access = PL3_RW,
6220
6221 .resetvalue = 0,
6222 .fieldoffset = offsetof(CPUARMState, cp15.tcr_el[3]) },
6223 { .name = "ELR_EL3", .state = ARM_CP_STATE_AA64,
6224 .type = ARM_CP_ALIAS,
6225 .opc0 = 3, .opc1 = 6, .crn = 4, .crm = 0, .opc2 = 1,
6226 .access = PL3_RW,
6227 .fieldoffset = offsetof(CPUARMState, elr_el[3]) },
6228 { .name = "ESR_EL3", .state = ARM_CP_STATE_AA64,
6229 .opc0 = 3, .opc1 = 6, .crn = 5, .crm = 2, .opc2 = 0,
6230 .access = PL3_RW, .fieldoffset = offsetof(CPUARMState, cp15.esr_el[3]) },
6231 { .name = "FAR_EL3", .state = ARM_CP_STATE_AA64,
6232 .opc0 = 3, .opc1 = 6, .crn = 6, .crm = 0, .opc2 = 0,
6233 .access = PL3_RW, .fieldoffset = offsetof(CPUARMState, cp15.far_el[3]) },
6234 { .name = "SPSR_EL3", .state = ARM_CP_STATE_AA64,
6235 .type = ARM_CP_ALIAS,
6236 .opc0 = 3, .opc1 = 6, .crn = 4, .crm = 0, .opc2 = 0,
6237 .access = PL3_RW,
6238 .fieldoffset = offsetof(CPUARMState, banked_spsr[BANK_MON]) },
6239 { .name = "VBAR_EL3", .state = ARM_CP_STATE_AA64,
6240 .opc0 = 3, .opc1 = 6, .crn = 12, .crm = 0, .opc2 = 0,
6241 .access = PL3_RW, .writefn = vbar_write,
6242 .fieldoffset = offsetof(CPUARMState, cp15.vbar_el[3]),
6243 .resetvalue = 0 },
6244 { .name = "CPTR_EL3", .state = ARM_CP_STATE_AA64,
6245 .opc0 = 3, .opc1 = 6, .crn = 1, .crm = 1, .opc2 = 2,
6246 .access = PL3_RW, .accessfn = cptr_access, .resetvalue = 0,
6247 .fieldoffset = offsetof(CPUARMState, cp15.cptr_el[3]) },
6248 { .name = "TPIDR_EL3", .state = ARM_CP_STATE_AA64,
6249 .opc0 = 3, .opc1 = 6, .crn = 13, .crm = 0, .opc2 = 2,
6250 .access = PL3_RW, .resetvalue = 0,
6251 .fieldoffset = offsetof(CPUARMState, cp15.tpidr_el[3]) },
6252 { .name = "AMAIR_EL3", .state = ARM_CP_STATE_AA64,
6253 .opc0 = 3, .opc1 = 6, .crn = 10, .crm = 3, .opc2 = 0,
6254 .access = PL3_RW, .type = ARM_CP_CONST,
6255 .resetvalue = 0 },
6256 { .name = "AFSR0_EL3", .state = ARM_CP_STATE_BOTH,
6257 .opc0 = 3, .opc1 = 6, .crn = 5, .crm = 1, .opc2 = 0,
6258 .access = PL3_RW, .type = ARM_CP_CONST,
6259 .resetvalue = 0 },
6260 { .name = "AFSR1_EL3", .state = ARM_CP_STATE_BOTH,
6261 .opc0 = 3, .opc1 = 6, .crn = 5, .crm = 1, .opc2 = 1,
6262 .access = PL3_RW, .type = ARM_CP_CONST,
6263 .resetvalue = 0 },
6264 { .name = "TLBI_ALLE3IS", .state = ARM_CP_STATE_AA64,
6265 .opc0 = 1, .opc1 = 6, .crn = 8, .crm = 3, .opc2 = 0,
6266 .access = PL3_W, .type = ARM_CP_NO_RAW,
6267 .writefn = tlbi_aa64_alle3is_write },
6268 { .name = "TLBI_VAE3IS", .state = ARM_CP_STATE_AA64,
6269 .opc0 = 1, .opc1 = 6, .crn = 8, .crm = 3, .opc2 = 1,
6270 .access = PL3_W, .type = ARM_CP_NO_RAW,
6271 .writefn = tlbi_aa64_vae3is_write },
6272 { .name = "TLBI_VALE3IS", .state = ARM_CP_STATE_AA64,
6273 .opc0 = 1, .opc1 = 6, .crn = 8, .crm = 3, .opc2 = 5,
6274 .access = PL3_W, .type = ARM_CP_NO_RAW,
6275 .writefn = tlbi_aa64_vae3is_write },
6276 { .name = "TLBI_ALLE3", .state = ARM_CP_STATE_AA64,
6277 .opc0 = 1, .opc1 = 6, .crn = 8, .crm = 7, .opc2 = 0,
6278 .access = PL3_W, .type = ARM_CP_NO_RAW,
6279 .writefn = tlbi_aa64_alle3_write },
6280 { .name = "TLBI_VAE3", .state = ARM_CP_STATE_AA64,
6281 .opc0 = 1, .opc1 = 6, .crn = 8, .crm = 7, .opc2 = 1,
6282 .access = PL3_W, .type = ARM_CP_NO_RAW,
6283 .writefn = tlbi_aa64_vae3_write },
6284 { .name = "TLBI_VALE3", .state = ARM_CP_STATE_AA64,
6285 .opc0 = 1, .opc1 = 6, .crn = 8, .crm = 7, .opc2 = 5,
6286 .access = PL3_W, .type = ARM_CP_NO_RAW,
6287 .writefn = tlbi_aa64_vae3_write },
6288};
6289
6290#ifndef CONFIG_USER_ONLY
6291
6292static bool redirect_for_e2h(CPUARMState *env)
6293{
6294 return arm_current_el(env) == 2 && (arm_hcr_el2_eff(env) & HCR_E2H);
6295}
6296
6297static uint64_t el2_e2h_read(CPUARMState *env, const ARMCPRegInfo *ri)
6298{
6299 CPReadFn *readfn;
6300
6301 if (redirect_for_e2h(env)) {
6302
6303 ri = ri->opaque;
6304 readfn = ri->readfn;
6305 } else {
6306 readfn = ri->orig_readfn;
6307 }
6308 if (readfn == NULL) {
6309 readfn = raw_read;
6310 }
6311 return readfn(env, ri);
6312}
6313
6314static void el2_e2h_write(CPUARMState *env, const ARMCPRegInfo *ri,
6315 uint64_t value)
6316{
6317 CPWriteFn *writefn;
6318
6319 if (redirect_for_e2h(env)) {
6320
6321 ri = ri->opaque;
6322 writefn = ri->writefn;
6323 } else {
6324 writefn = ri->orig_writefn;
6325 }
6326 if (writefn == NULL) {
6327 writefn = raw_write;
6328 }
6329 writefn(env, ri, value);
6330}
6331
6332static void define_arm_vh_e2h_redirects_aliases(ARMCPU *cpu)
6333{
6334 struct E2HAlias {
6335 uint32_t src_key, dst_key, new_key;
6336 const char *src_name, *dst_name, *new_name;
6337 bool (*feature)(const ARMISARegisters *id);
6338 };
6339
6340#define K(op0, op1, crn, crm, op2) \
6341 ENCODE_AA64_CP_REG(CP_REG_ARM64_SYSREG_CP, crn, crm, op0, op1, op2)
6342
6343 static const struct E2HAlias aliases[] = {
6344 { K(3, 0, 1, 0, 0), K(3, 4, 1, 0, 0), K(3, 5, 1, 0, 0),
6345 "SCTLR", "SCTLR_EL2", "SCTLR_EL12" },
6346 { K(3, 0, 1, 0, 2), K(3, 4, 1, 1, 2), K(3, 5, 1, 0, 2),
6347 "CPACR", "CPTR_EL2", "CPACR_EL12" },
6348 { K(3, 0, 2, 0, 0), K(3, 4, 2, 0, 0), K(3, 5, 2, 0, 0),
6349 "TTBR0_EL1", "TTBR0_EL2", "TTBR0_EL12" },
6350 { K(3, 0, 2, 0, 1), K(3, 4, 2, 0, 1), K(3, 5, 2, 0, 1),
6351 "TTBR1_EL1", "TTBR1_EL2", "TTBR1_EL12" },
6352 { K(3, 0, 2, 0, 2), K(3, 4, 2, 0, 2), K(3, 5, 2, 0, 2),
6353 "TCR_EL1", "TCR_EL2", "TCR_EL12" },
6354 { K(3, 0, 4, 0, 0), K(3, 4, 4, 0, 0), K(3, 5, 4, 0, 0),
6355 "SPSR_EL1", "SPSR_EL2", "SPSR_EL12" },
6356 { K(3, 0, 4, 0, 1), K(3, 4, 4, 0, 1), K(3, 5, 4, 0, 1),
6357 "ELR_EL1", "ELR_EL2", "ELR_EL12" },
6358 { K(3, 0, 5, 1, 0), K(3, 4, 5, 1, 0), K(3, 5, 5, 1, 0),
6359 "AFSR0_EL1", "AFSR0_EL2", "AFSR0_EL12" },
6360 { K(3, 0, 5, 1, 1), K(3, 4, 5, 1, 1), K(3, 5, 5, 1, 1),
6361 "AFSR1_EL1", "AFSR1_EL2", "AFSR1_EL12" },
6362 { K(3, 0, 5, 2, 0), K(3, 4, 5, 2, 0), K(3, 5, 5, 2, 0),
6363 "ESR_EL1", "ESR_EL2", "ESR_EL12" },
6364 { K(3, 0, 6, 0, 0), K(3, 4, 6, 0, 0), K(3, 5, 6, 0, 0),
6365 "FAR_EL1", "FAR_EL2", "FAR_EL12" },
6366 { K(3, 0, 10, 2, 0), K(3, 4, 10, 2, 0), K(3, 5, 10, 2, 0),
6367 "MAIR_EL1", "MAIR_EL2", "MAIR_EL12" },
6368 { K(3, 0, 10, 3, 0), K(3, 4, 10, 3, 0), K(3, 5, 10, 3, 0),
6369 "AMAIR0", "AMAIR_EL2", "AMAIR_EL12" },
6370 { K(3, 0, 12, 0, 0), K(3, 4, 12, 0, 0), K(3, 5, 12, 0, 0),
6371 "VBAR", "VBAR_EL2", "VBAR_EL12" },
6372 { K(3, 0, 13, 0, 1), K(3, 4, 13, 0, 1), K(3, 5, 13, 0, 1),
6373 "CONTEXTIDR_EL1", "CONTEXTIDR_EL2", "CONTEXTIDR_EL12" },
6374 { K(3, 0, 14, 1, 0), K(3, 4, 14, 1, 0), K(3, 5, 14, 1, 0),
6375 "CNTKCTL", "CNTHCTL_EL2", "CNTKCTL_EL12" },
6376
6377
6378
6379
6380
6381
6382 { K(3, 0, 1, 2, 0), K(3, 4, 1, 2, 0), K(3, 5, 1, 2, 0),
6383 "ZCR_EL1", "ZCR_EL2", "ZCR_EL12", isar_feature_aa64_sve },
6384 { K(3, 0, 1, 2, 6), K(3, 4, 1, 2, 6), K(3, 5, 1, 2, 6),
6385 "SMCR_EL1", "SMCR_EL2", "SMCR_EL12", isar_feature_aa64_sme },
6386
6387 { K(3, 0, 5, 6, 0), K(3, 4, 5, 6, 0), K(3, 5, 5, 6, 0),
6388 "TFSR_EL1", "TFSR_EL2", "TFSR_EL12", isar_feature_aa64_mte },
6389
6390 { K(3, 0, 13, 0, 7), K(3, 4, 13, 0, 7), K(3, 5, 13, 0, 7),
6391 "SCXTNUM_EL1", "SCXTNUM_EL2", "SCXTNUM_EL12",
6392 isar_feature_aa64_scxtnum },
6393
6394
6395
6396 };
6397#undef K
6398
6399 size_t i;
6400
6401 for (i = 0; i < ARRAY_SIZE(aliases); i++) {
6402 const struct E2HAlias *a = &aliases[i];
6403 ARMCPRegInfo *src_reg, *dst_reg, *new_reg;
6404 bool ok;
6405
6406 if (a->feature && !a->feature(&cpu->isar)) {
6407 continue;
6408 }
6409
6410 src_reg = g_hash_table_lookup(cpu->cp_regs,
6411 (gpointer)(uintptr_t)a->src_key);
6412 dst_reg = g_hash_table_lookup(cpu->cp_regs,
6413 (gpointer)(uintptr_t)a->dst_key);
6414 g_assert(src_reg != NULL);
6415 g_assert(dst_reg != NULL);
6416
6417
6418 g_assert(strcmp(src_reg->name, a->src_name) == 0);
6419 g_assert(strcmp(dst_reg->name, a->dst_name) == 0);
6420
6421
6422 g_assert(src_reg->opaque == NULL);
6423
6424
6425 new_reg = g_memdup(src_reg, sizeof(ARMCPRegInfo));
6426
6427 new_reg->name = a->new_name;
6428 new_reg->type |= ARM_CP_ALIAS;
6429
6430 new_reg->access &= PL2_RW | PL3_RW;
6431
6432 ok = g_hash_table_insert(cpu->cp_regs,
6433 (gpointer)(uintptr_t)a->new_key, new_reg);
6434 g_assert(ok);
6435
6436 src_reg->opaque = dst_reg;
6437 src_reg->orig_readfn = src_reg->readfn ?: raw_read;
6438 src_reg->orig_writefn = src_reg->writefn ?: raw_write;
6439 if (!src_reg->raw_readfn) {
6440 src_reg->raw_readfn = raw_read;
6441 }
6442 if (!src_reg->raw_writefn) {
6443 src_reg->raw_writefn = raw_write;
6444 }
6445 src_reg->readfn = el2_e2h_read;
6446 src_reg->writefn = el2_e2h_write;
6447 }
6448}
6449#endif
6450
6451static CPAccessResult ctr_el0_access(CPUARMState *env, const ARMCPRegInfo *ri,
6452 bool isread)
6453{
6454 int cur_el = arm_current_el(env);
6455
6456 if (cur_el < 2) {
6457 uint64_t hcr = arm_hcr_el2_eff(env);
6458
6459 if (cur_el == 0) {
6460 if ((hcr & (HCR_E2H | HCR_TGE)) == (HCR_E2H | HCR_TGE)) {
6461 if (!(env->cp15.sctlr_el[2] & SCTLR_UCT)) {
6462 return CP_ACCESS_TRAP_EL2;
6463 }
6464 } else {
6465 if (!(env->cp15.sctlr_el[1] & SCTLR_UCT)) {
6466 return CP_ACCESS_TRAP;
6467 }
6468 if (hcr & HCR_TID2) {
6469 return CP_ACCESS_TRAP_EL2;
6470 }
6471 }
6472 } else if (hcr & HCR_TID2) {
6473 return CP_ACCESS_TRAP_EL2;
6474 }
6475 }
6476
6477 if (arm_current_el(env) < 2 && arm_hcr_el2_eff(env) & HCR_TID2) {
6478 return CP_ACCESS_TRAP_EL2;
6479 }
6480
6481 return CP_ACCESS_OK;
6482}
6483
6484
6485
6486
6487
6488static CPAccessResult access_terr(CPUARMState *env, const ARMCPRegInfo *ri,
6489 bool isread)
6490{
6491 int el = arm_current_el(env);
6492
6493 if (el < 2 && (arm_hcr_el2_eff(env) & HCR_TERR)) {
6494 return CP_ACCESS_TRAP_EL2;
6495 }
6496 if (el < 3 && (env->cp15.scr_el3 & SCR_TERR)) {
6497 return CP_ACCESS_TRAP_EL3;
6498 }
6499 return CP_ACCESS_OK;
6500}
6501
6502static uint64_t disr_read(CPUARMState *env, const ARMCPRegInfo *ri)
6503{
6504 int el = arm_current_el(env);
6505
6506 if (el < 2 && (arm_hcr_el2_eff(env) & HCR_AMO)) {
6507 return env->cp15.vdisr_el2;
6508 }
6509 if (el < 3 && (env->cp15.scr_el3 & SCR_EA)) {
6510 return 0;
6511 }
6512 return env->cp15.disr_el1;
6513}
6514
6515static void disr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t val)
6516{
6517 int el = arm_current_el(env);
6518
6519 if (el < 2 && (arm_hcr_el2_eff(env) & HCR_AMO)) {
6520 env->cp15.vdisr_el2 = val;
6521 return;
6522 }
6523 if (el < 3 && (env->cp15.scr_el3 & SCR_EA)) {
6524 return;
6525 }
6526 env->cp15.disr_el1 = val;
6527}
6528
6529
6530
6531
6532
6533
6534
6535
6536
6537
6538
6539
6540
6541
6542
6543
6544
6545
6546
6547
6548
6549
6550
6551
6552static const ARMCPRegInfo minimal_ras_reginfo[] = {
6553 { .name = "DISR_EL1", .state = ARM_CP_STATE_BOTH,
6554 .opc0 = 3, .opc1 = 0, .crn = 12, .crm = 1, .opc2 = 1,
6555 .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.disr_el1),
6556 .readfn = disr_read, .writefn = disr_write, .raw_writefn = raw_write },
6557 { .name = "ERRIDR_EL1", .state = ARM_CP_STATE_BOTH,
6558 .opc0 = 3, .opc1 = 0, .crn = 5, .crm = 3, .opc2 = 0,
6559 .access = PL1_R, .accessfn = access_terr,
6560 .fgt = FGT_ERRIDR_EL1,
6561 .type = ARM_CP_CONST, .resetvalue = 0 },
6562 { .name = "VDISR_EL2", .state = ARM_CP_STATE_BOTH,
6563 .opc0 = 3, .opc1 = 4, .crn = 12, .crm = 1, .opc2 = 1,
6564 .access = PL2_RW, .fieldoffset = offsetof(CPUARMState, cp15.vdisr_el2) },
6565 { .name = "VSESR_EL2", .state = ARM_CP_STATE_BOTH,
6566 .opc0 = 3, .opc1 = 4, .crn = 5, .crm = 2, .opc2 = 3,
6567 .access = PL2_RW, .fieldoffset = offsetof(CPUARMState, cp15.vsesr_el2) },
6568};
6569
6570
6571
6572
6573
6574
6575
6576
6577
6578
6579
6580int sve_exception_el(CPUARMState *env, int el)
6581{
6582#ifndef CONFIG_USER_ONLY
6583 if (el <= 1 && !el_is_in_host(env, el)) {
6584 switch (FIELD_EX64(env->cp15.cpacr_el1, CPACR_EL1, ZEN)) {
6585 case 1:
6586 if (el != 0) {
6587 break;
6588 }
6589
6590 case 0:
6591 case 2:
6592 return 1;
6593 }
6594 }
6595
6596 if (el <= 2 && arm_is_el2_enabled(env)) {
6597
6598 if (env->cp15.hcr_el2 & HCR_E2H) {
6599 switch (FIELD_EX64(env->cp15.cptr_el[2], CPTR_EL2, ZEN)) {
6600 case 1:
6601 if (el != 0 || !(env->cp15.hcr_el2 & HCR_TGE)) {
6602 break;
6603 }
6604
6605 case 0:
6606 case 2:
6607 return 2;
6608 }
6609 } else {
6610 if (FIELD_EX64(env->cp15.cptr_el[2], CPTR_EL2, TZ)) {
6611 return 2;
6612 }
6613 }
6614 }
6615
6616
6617 if (arm_feature(env, ARM_FEATURE_EL3)
6618 && !FIELD_EX64(env->cp15.cptr_el[3], CPTR_EL3, EZ)) {
6619 return 3;
6620 }
6621#endif
6622 return 0;
6623}
6624
6625
6626
6627
6628
6629int sme_exception_el(CPUARMState *env, int el)
6630{
6631#ifndef CONFIG_USER_ONLY
6632 if (el <= 1 && !el_is_in_host(env, el)) {
6633 switch (FIELD_EX64(env->cp15.cpacr_el1, CPACR_EL1, SMEN)) {
6634 case 1:
6635 if (el != 0) {
6636 break;
6637 }
6638
6639 case 0:
6640 case 2:
6641 return 1;
6642 }
6643 }
6644
6645 if (el <= 2 && arm_is_el2_enabled(env)) {
6646
6647 if (env->cp15.hcr_el2 & HCR_E2H) {
6648 switch (FIELD_EX64(env->cp15.cptr_el[2], CPTR_EL2, SMEN)) {
6649 case 1:
6650 if (el != 0 || !(env->cp15.hcr_el2 & HCR_TGE)) {
6651 break;
6652 }
6653
6654 case 0:
6655 case 2:
6656 return 2;
6657 }
6658 } else {
6659 if (FIELD_EX64(env->cp15.cptr_el[2], CPTR_EL2, TSM)) {
6660 return 2;
6661 }
6662 }
6663 }
6664
6665
6666 if (arm_feature(env, ARM_FEATURE_EL3)
6667 && !FIELD_EX64(env->cp15.cptr_el[3], CPTR_EL3, ESM)) {
6668 return 3;
6669 }
6670#endif
6671 return 0;
6672}
6673
6674
6675
6676
6677uint32_t sve_vqm1_for_el_sm(CPUARMState *env, int el, bool sm)
6678{
6679 ARMCPU *cpu = env_archcpu(env);
6680 uint64_t *cr = env->vfp.zcr_el;
6681 uint32_t map = cpu->sve_vq.map;
6682 uint32_t len = ARM_MAX_VQ - 1;
6683
6684 if (sm) {
6685 cr = env->vfp.smcr_el;
6686 map = cpu->sme_vq.map;
6687 }
6688
6689 if (el <= 1 && !el_is_in_host(env, el)) {
6690 len = MIN(len, 0xf & (uint32_t)cr[1]);
6691 }
6692 if (el <= 2 && arm_feature(env, ARM_FEATURE_EL2)) {
6693 len = MIN(len, 0xf & (uint32_t)cr[2]);
6694 }
6695 if (arm_feature(env, ARM_FEATURE_EL3)) {
6696 len = MIN(len, 0xf & (uint32_t)cr[3]);
6697 }
6698
6699 map &= MAKE_64BIT_MASK(0, len + 1);
6700 if (map != 0) {
6701 return 31 - clz32(map);
6702 }
6703
6704
6705 assert(sm);
6706 return ctz32(cpu->sme_vq.map);
6707}
6708
6709uint32_t sve_vqm1_for_el(CPUARMState *env, int el)
6710{
6711 return sve_vqm1_for_el_sm(env, el, FIELD_EX64(env->svcr, SVCR, SM));
6712}
6713
6714static void zcr_write(CPUARMState *env, const ARMCPRegInfo *ri,
6715 uint64_t value)
6716{
6717 int cur_el = arm_current_el(env);
6718 int old_len = sve_vqm1_for_el(env, cur_el);
6719 int new_len;
6720
6721
6722 QEMU_BUILD_BUG_ON(ARM_MAX_VQ > 16);
6723 raw_write(env, ri, value & 0xf);
6724
6725
6726
6727
6728
6729 new_len = sve_vqm1_for_el(env, cur_el);
6730 if (new_len < old_len) {
6731 aarch64_sve_narrow_vq(env, new_len + 1);
6732 }
6733}
6734
6735static const ARMCPRegInfo zcr_reginfo[] = {
6736 { .name = "ZCR_EL1", .state = ARM_CP_STATE_AA64,
6737 .opc0 = 3, .opc1 = 0, .crn = 1, .crm = 2, .opc2 = 0,
6738 .access = PL1_RW, .type = ARM_CP_SVE,
6739 .fieldoffset = offsetof(CPUARMState, vfp.zcr_el[1]),
6740 .writefn = zcr_write, .raw_writefn = raw_write },
6741 { .name = "ZCR_EL2", .state = ARM_CP_STATE_AA64,
6742 .opc0 = 3, .opc1 = 4, .crn = 1, .crm = 2, .opc2 = 0,
6743 .access = PL2_RW, .type = ARM_CP_SVE,
6744 .fieldoffset = offsetof(CPUARMState, vfp.zcr_el[2]),
6745 .writefn = zcr_write, .raw_writefn = raw_write },
6746 { .name = "ZCR_EL3", .state = ARM_CP_STATE_AA64,
6747 .opc0 = 3, .opc1 = 6, .crn = 1, .crm = 2, .opc2 = 0,
6748 .access = PL3_RW, .type = ARM_CP_SVE,
6749 .fieldoffset = offsetof(CPUARMState, vfp.zcr_el[3]),
6750 .writefn = zcr_write, .raw_writefn = raw_write },
6751};
6752
6753#ifdef TARGET_AARCH64
6754static CPAccessResult access_tpidr2(CPUARMState *env, const ARMCPRegInfo *ri,
6755 bool isread)
6756{
6757 int el = arm_current_el(env);
6758
6759 if (el == 0) {
6760 uint64_t sctlr = arm_sctlr(env, el);
6761 if (!(sctlr & SCTLR_EnTP2)) {
6762 return CP_ACCESS_TRAP;
6763 }
6764 }
6765
6766 if (el < 3
6767 && arm_feature(env, ARM_FEATURE_EL3)
6768 && !(env->cp15.scr_el3 & SCR_ENTP2)) {
6769 return CP_ACCESS_TRAP_EL3;
6770 }
6771 return CP_ACCESS_OK;
6772}
6773
6774static CPAccessResult access_esm(CPUARMState *env, const ARMCPRegInfo *ri,
6775 bool isread)
6776{
6777
6778 if (arm_current_el(env) < 3
6779 && arm_feature(env, ARM_FEATURE_EL3)
6780 && !FIELD_EX64(env->cp15.cptr_el[3], CPTR_EL3, ESM)) {
6781 return CP_ACCESS_TRAP_EL3;
6782 }
6783 return CP_ACCESS_OK;
6784}
6785
6786
6787static void arm_reset_sve_state(CPUARMState *env)
6788{
6789 memset(env->vfp.zregs, 0, sizeof(env->vfp.zregs));
6790
6791 memset(env->vfp.pregs, 0, sizeof(env->vfp.pregs));
6792 vfp_set_fpcr(env, 0x0800009f);
6793}
6794
6795void aarch64_set_svcr(CPUARMState *env, uint64_t new, uint64_t mask)
6796{
6797 uint64_t change = (env->svcr ^ new) & mask;
6798
6799 if (change == 0) {
6800 return;
6801 }
6802 env->svcr ^= change;
6803
6804 if (change & R_SVCR_SM_MASK) {
6805 arm_reset_sve_state(env);
6806 }
6807
6808
6809
6810
6811
6812
6813
6814
6815
6816 if (change & new & R_SVCR_ZA_MASK) {
6817 memset(env->zarray, 0, sizeof(env->zarray));
6818 }
6819
6820 if (tcg_enabled()) {
6821 arm_rebuild_hflags(env);
6822 }
6823}
6824
6825static void svcr_write(CPUARMState *env, const ARMCPRegInfo *ri,
6826 uint64_t value)
6827{
6828 aarch64_set_svcr(env, value, -1);
6829}
6830
6831static void smcr_write(CPUARMState *env, const ARMCPRegInfo *ri,
6832 uint64_t value)
6833{
6834 int cur_el = arm_current_el(env);
6835 int old_len = sve_vqm1_for_el(env, cur_el);
6836 int new_len;
6837
6838 QEMU_BUILD_BUG_ON(ARM_MAX_VQ > R_SMCR_LEN_MASK + 1);
6839 value &= R_SMCR_LEN_MASK | R_SMCR_FA64_MASK;
6840 raw_write(env, ri, value);
6841
6842
6843
6844
6845
6846
6847
6848
6849 new_len = sve_vqm1_for_el(env, cur_el);
6850 if (new_len < old_len) {
6851 aarch64_sve_narrow_vq(env, new_len + 1);
6852 }
6853}
6854
6855static const ARMCPRegInfo sme_reginfo[] = {
6856 { .name = "TPIDR2_EL0", .state = ARM_CP_STATE_AA64,
6857 .opc0 = 3, .opc1 = 3, .crn = 13, .crm = 0, .opc2 = 5,
6858 .access = PL0_RW, .accessfn = access_tpidr2,
6859 .fgt = FGT_NTPIDR2_EL0,
6860 .fieldoffset = offsetof(CPUARMState, cp15.tpidr2_el0) },
6861 { .name = "SVCR", .state = ARM_CP_STATE_AA64,
6862 .opc0 = 3, .opc1 = 3, .crn = 4, .crm = 2, .opc2 = 2,
6863 .access = PL0_RW, .type = ARM_CP_SME,
6864 .fieldoffset = offsetof(CPUARMState, svcr),
6865 .writefn = svcr_write, .raw_writefn = raw_write },
6866 { .name = "SMCR_EL1", .state = ARM_CP_STATE_AA64,
6867 .opc0 = 3, .opc1 = 0, .crn = 1, .crm = 2, .opc2 = 6,
6868 .access = PL1_RW, .type = ARM_CP_SME,
6869 .fieldoffset = offsetof(CPUARMState, vfp.smcr_el[1]),
6870 .writefn = smcr_write, .raw_writefn = raw_write },
6871 { .name = "SMCR_EL2", .state = ARM_CP_STATE_AA64,
6872 .opc0 = 3, .opc1 = 4, .crn = 1, .crm = 2, .opc2 = 6,
6873 .access = PL2_RW, .type = ARM_CP_SME,
6874 .fieldoffset = offsetof(CPUARMState, vfp.smcr_el[2]),
6875 .writefn = smcr_write, .raw_writefn = raw_write },
6876 { .name = "SMCR_EL3", .state = ARM_CP_STATE_AA64,
6877 .opc0 = 3, .opc1 = 6, .crn = 1, .crm = 2, .opc2 = 6,
6878 .access = PL3_RW, .type = ARM_CP_SME,
6879 .fieldoffset = offsetof(CPUARMState, vfp.smcr_el[3]),
6880 .writefn = smcr_write, .raw_writefn = raw_write },
6881 { .name = "SMIDR_EL1", .state = ARM_CP_STATE_AA64,
6882 .opc0 = 3, .opc1 = 1, .crn = 0, .crm = 0, .opc2 = 6,
6883 .access = PL1_R, .accessfn = access_aa64_tid1,
6884
6885
6886
6887
6888
6889
6890 .type = ARM_CP_CONST, .resetvalue = 0, },
6891
6892
6893
6894 { .name = "SMPRI_EL1", .state = ARM_CP_STATE_AA64,
6895 .opc0 = 3, .opc1 = 0, .crn = 1, .crm = 2, .opc2 = 4,
6896 .access = PL1_RW, .accessfn = access_esm,
6897 .fgt = FGT_NSMPRI_EL1,
6898 .type = ARM_CP_CONST, .resetvalue = 0 },
6899 { .name = "SMPRIMAP_EL2", .state = ARM_CP_STATE_AA64,
6900 .opc0 = 3, .opc1 = 4, .crn = 1, .crm = 2, .opc2 = 5,
6901 .access = PL2_RW, .accessfn = access_esm,
6902 .type = ARM_CP_CONST, .resetvalue = 0 },
6903};
6904#endif
6905
6906static void define_pmu_regs(ARMCPU *cpu)
6907{
6908
6909
6910
6911
6912
6913 unsigned int i, pmcrn = pmu_num_counters(&cpu->env);
6914 ARMCPRegInfo pmcr = {
6915 .name = "PMCR", .cp = 15, .crn = 9, .crm = 12, .opc1 = 0, .opc2 = 0,
6916 .access = PL0_RW,
6917 .fgt = FGT_PMCR_EL0,
6918 .type = ARM_CP_IO | ARM_CP_ALIAS,
6919 .fieldoffset = offsetoflow32(CPUARMState, cp15.c9_pmcr),
6920 .accessfn = pmreg_access, .writefn = pmcr_write,
6921 .raw_writefn = raw_write,
6922 };
6923 ARMCPRegInfo pmcr64 = {
6924 .name = "PMCR_EL0", .state = ARM_CP_STATE_AA64,
6925 .opc0 = 3, .opc1 = 3, .crn = 9, .crm = 12, .opc2 = 0,
6926 .access = PL0_RW, .accessfn = pmreg_access,
6927 .fgt = FGT_PMCR_EL0,
6928 .type = ARM_CP_IO,
6929 .fieldoffset = offsetof(CPUARMState, cp15.c9_pmcr),
6930 .resetvalue = cpu->isar.reset_pmcr_el0,
6931 .writefn = pmcr_write, .raw_writefn = raw_write,
6932 };
6933
6934 define_one_arm_cp_reg(cpu, &pmcr);
6935 define_one_arm_cp_reg(cpu, &pmcr64);
6936 for (i = 0; i < pmcrn; i++) {
6937 char *pmevcntr_name = g_strdup_printf("PMEVCNTR%d", i);
6938 char *pmevcntr_el0_name = g_strdup_printf("PMEVCNTR%d_EL0", i);
6939 char *pmevtyper_name = g_strdup_printf("PMEVTYPER%d", i);
6940 char *pmevtyper_el0_name = g_strdup_printf("PMEVTYPER%d_EL0", i);
6941 ARMCPRegInfo pmev_regs[] = {
6942 { .name = pmevcntr_name, .cp = 15, .crn = 14,
6943 .crm = 8 | (3 & (i >> 3)), .opc1 = 0, .opc2 = i & 7,
6944 .access = PL0_RW, .type = ARM_CP_IO | ARM_CP_ALIAS,
6945 .fgt = FGT_PMEVCNTRN_EL0,
6946 .readfn = pmevcntr_readfn, .writefn = pmevcntr_writefn,
6947 .accessfn = pmreg_access_xevcntr },
6948 { .name = pmevcntr_el0_name, .state = ARM_CP_STATE_AA64,
6949 .opc0 = 3, .opc1 = 3, .crn = 14, .crm = 8 | (3 & (i >> 3)),
6950 .opc2 = i & 7, .access = PL0_RW, .accessfn = pmreg_access_xevcntr,
6951 .type = ARM_CP_IO,
6952 .fgt = FGT_PMEVCNTRN_EL0,
6953 .readfn = pmevcntr_readfn, .writefn = pmevcntr_writefn,
6954 .raw_readfn = pmevcntr_rawread,
6955 .raw_writefn = pmevcntr_rawwrite },
6956 { .name = pmevtyper_name, .cp = 15, .crn = 14,
6957 .crm = 12 | (3 & (i >> 3)), .opc1 = 0, .opc2 = i & 7,
6958 .access = PL0_RW, .type = ARM_CP_IO | ARM_CP_ALIAS,
6959 .fgt = FGT_PMEVTYPERN_EL0,
6960 .readfn = pmevtyper_readfn, .writefn = pmevtyper_writefn,
6961 .accessfn = pmreg_access },
6962 { .name = pmevtyper_el0_name, .state = ARM_CP_STATE_AA64,
6963 .opc0 = 3, .opc1 = 3, .crn = 14, .crm = 12 | (3 & (i >> 3)),
6964 .opc2 = i & 7, .access = PL0_RW, .accessfn = pmreg_access,
6965 .fgt = FGT_PMEVTYPERN_EL0,
6966 .type = ARM_CP_IO,
6967 .readfn = pmevtyper_readfn, .writefn = pmevtyper_writefn,
6968 .raw_writefn = pmevtyper_rawwrite },
6969 };
6970 define_arm_cp_regs(cpu, pmev_regs);
6971 g_free(pmevcntr_name);
6972 g_free(pmevcntr_el0_name);
6973 g_free(pmevtyper_name);
6974 g_free(pmevtyper_el0_name);
6975 }
6976 if (cpu_isar_feature(aa32_pmuv3p1, cpu)) {
6977 ARMCPRegInfo v81_pmu_regs[] = {
6978 { .name = "PMCEID2", .state = ARM_CP_STATE_AA32,
6979 .cp = 15, .opc1 = 0, .crn = 9, .crm = 14, .opc2 = 4,
6980 .access = PL0_R, .accessfn = pmreg_access, .type = ARM_CP_CONST,
6981 .fgt = FGT_PMCEIDN_EL0,
6982 .resetvalue = extract64(cpu->pmceid0, 32, 32) },
6983 { .name = "PMCEID3", .state = ARM_CP_STATE_AA32,
6984 .cp = 15, .opc1 = 0, .crn = 9, .crm = 14, .opc2 = 5,
6985 .access = PL0_R, .accessfn = pmreg_access, .type = ARM_CP_CONST,
6986 .fgt = FGT_PMCEIDN_EL0,
6987 .resetvalue = extract64(cpu->pmceid1, 32, 32) },
6988 };
6989 define_arm_cp_regs(cpu, v81_pmu_regs);
6990 }
6991 if (cpu_isar_feature(any_pmuv3p4, cpu)) {
6992 static const ARMCPRegInfo v84_pmmir = {
6993 .name = "PMMIR_EL1", .state = ARM_CP_STATE_BOTH,
6994 .opc0 = 3, .opc1 = 0, .crn = 9, .crm = 14, .opc2 = 6,
6995 .access = PL1_R, .accessfn = pmreg_access, .type = ARM_CP_CONST,
6996 .fgt = FGT_PMMIR_EL1,
6997 .resetvalue = 0
6998 };
6999 define_one_arm_cp_reg(cpu, &v84_pmmir);
7000 }
7001}
7002
7003#ifndef CONFIG_USER_ONLY
7004
7005
7006
7007
7008
7009
7010static uint64_t id_pfr1_read(CPUARMState *env, const ARMCPRegInfo *ri)
7011{
7012 ARMCPU *cpu = env_archcpu(env);
7013 uint64_t pfr1 = cpu->isar.id_pfr1;
7014
7015 if (env->gicv3state) {
7016 pfr1 |= 1 << 28;
7017 }
7018 return pfr1;
7019}
7020
7021static uint64_t id_aa64pfr0_read(CPUARMState *env, const ARMCPRegInfo *ri)
7022{
7023 ARMCPU *cpu = env_archcpu(env);
7024 uint64_t pfr0 = cpu->isar.id_aa64pfr0;
7025
7026 if (env->gicv3state) {
7027 pfr0 |= 1 << 24;
7028 }
7029 return pfr0;
7030}
7031#endif
7032
7033
7034
7035
7036
7037static CPAccessResult access_lor_ns(CPUARMState *env,
7038 const ARMCPRegInfo *ri, bool isread)
7039{
7040 int el = arm_current_el(env);
7041
7042 if (el < 2 && (arm_hcr_el2_eff(env) & HCR_TLOR)) {
7043 return CP_ACCESS_TRAP_EL2;
7044 }
7045 if (el < 3 && (env->cp15.scr_el3 & SCR_TLOR)) {
7046 return CP_ACCESS_TRAP_EL3;
7047 }
7048 return CP_ACCESS_OK;
7049}
7050
7051static CPAccessResult access_lor_other(CPUARMState *env,
7052 const ARMCPRegInfo *ri, bool isread)
7053{
7054 if (arm_is_secure_below_el3(env)) {
7055
7056 return CP_ACCESS_TRAP;
7057 }
7058 return access_lor_ns(env, ri, isread);
7059}
7060
7061
7062
7063
7064
7065
7066static const ARMCPRegInfo lor_reginfo[] = {
7067 { .name = "LORSA_EL1", .state = ARM_CP_STATE_AA64,
7068 .opc0 = 3, .opc1 = 0, .crn = 10, .crm = 4, .opc2 = 0,
7069 .access = PL1_RW, .accessfn = access_lor_other,
7070 .fgt = FGT_LORSA_EL1,
7071 .type = ARM_CP_CONST, .resetvalue = 0 },
7072 { .name = "LOREA_EL1", .state = ARM_CP_STATE_AA64,
7073 .opc0 = 3, .opc1 = 0, .crn = 10, .crm = 4, .opc2 = 1,
7074 .access = PL1_RW, .accessfn = access_lor_other,
7075 .fgt = FGT_LOREA_EL1,
7076 .type = ARM_CP_CONST, .resetvalue = 0 },
7077 { .name = "LORN_EL1", .state = ARM_CP_STATE_AA64,
7078 .opc0 = 3, .opc1 = 0, .crn = 10, .crm = 4, .opc2 = 2,
7079 .access = PL1_RW, .accessfn = access_lor_other,
7080 .fgt = FGT_LORN_EL1,
7081 .type = ARM_CP_CONST, .resetvalue = 0 },
7082 { .name = "LORC_EL1", .state = ARM_CP_STATE_AA64,
7083 .opc0 = 3, .opc1 = 0, .crn = 10, .crm = 4, .opc2 = 3,
7084 .access = PL1_RW, .accessfn = access_lor_other,
7085 .fgt = FGT_LORC_EL1,
7086 .type = ARM_CP_CONST, .resetvalue = 0 },
7087 { .name = "LORID_EL1", .state = ARM_CP_STATE_AA64,
7088 .opc0 = 3, .opc1 = 0, .crn = 10, .crm = 4, .opc2 = 7,
7089 .access = PL1_R, .accessfn = access_lor_ns,
7090 .fgt = FGT_LORID_EL1,
7091 .type = ARM_CP_CONST, .resetvalue = 0 },
7092};
7093
7094#ifdef TARGET_AARCH64
7095static CPAccessResult access_pauth(CPUARMState *env, const ARMCPRegInfo *ri,
7096 bool isread)
7097{
7098 int el = arm_current_el(env);
7099
7100 if (el < 2 &&
7101 arm_is_el2_enabled(env) &&
7102 !(arm_hcr_el2_eff(env) & HCR_APK)) {
7103 return CP_ACCESS_TRAP_EL2;
7104 }
7105 if (el < 3 &&
7106 arm_feature(env, ARM_FEATURE_EL3) &&
7107 !(env->cp15.scr_el3 & SCR_APK)) {
7108 return CP_ACCESS_TRAP_EL3;
7109 }
7110 return CP_ACCESS_OK;
7111}
7112
7113static const ARMCPRegInfo pauth_reginfo[] = {
7114 { .name = "APDAKEYLO_EL1", .state = ARM_CP_STATE_AA64,
7115 .opc0 = 3, .opc1 = 0, .crn = 2, .crm = 2, .opc2 = 0,
7116 .access = PL1_RW, .accessfn = access_pauth,
7117 .fgt = FGT_APDAKEY,
7118 .fieldoffset = offsetof(CPUARMState, keys.apda.lo) },
7119 { .name = "APDAKEYHI_EL1", .state = ARM_CP_STATE_AA64,
7120 .opc0 = 3, .opc1 = 0, .crn = 2, .crm = 2, .opc2 = 1,
7121 .access = PL1_RW, .accessfn = access_pauth,
7122 .fgt = FGT_APDAKEY,
7123 .fieldoffset = offsetof(CPUARMState, keys.apda.hi) },
7124 { .name = "APDBKEYLO_EL1", .state = ARM_CP_STATE_AA64,
7125 .opc0 = 3, .opc1 = 0, .crn = 2, .crm = 2, .opc2 = 2,
7126 .access = PL1_RW, .accessfn = access_pauth,
7127 .fgt = FGT_APDBKEY,
7128 .fieldoffset = offsetof(CPUARMState, keys.apdb.lo) },
7129 { .name = "APDBKEYHI_EL1", .state = ARM_CP_STATE_AA64,
7130 .opc0 = 3, .opc1 = 0, .crn = 2, .crm = 2, .opc2 = 3,
7131 .access = PL1_RW, .accessfn = access_pauth,
7132 .fgt = FGT_APDBKEY,
7133 .fieldoffset = offsetof(CPUARMState, keys.apdb.hi) },
7134 { .name = "APGAKEYLO_EL1", .state = ARM_CP_STATE_AA64,
7135 .opc0 = 3, .opc1 = 0, .crn = 2, .crm = 3, .opc2 = 0,
7136 .access = PL1_RW, .accessfn = access_pauth,
7137 .fgt = FGT_APGAKEY,
7138 .fieldoffset = offsetof(CPUARMState, keys.apga.lo) },
7139 { .name = "APGAKEYHI_EL1", .state = ARM_CP_STATE_AA64,
7140 .opc0 = 3, .opc1 = 0, .crn = 2, .crm = 3, .opc2 = 1,
7141 .access = PL1_RW, .accessfn = access_pauth,
7142 .fgt = FGT_APGAKEY,
7143 .fieldoffset = offsetof(CPUARMState, keys.apga.hi) },
7144 { .name = "APIAKEYLO_EL1", .state = ARM_CP_STATE_AA64,
7145 .opc0 = 3, .opc1 = 0, .crn = 2, .crm = 1, .opc2 = 0,
7146 .access = PL1_RW, .accessfn = access_pauth,
7147 .fgt = FGT_APIAKEY,
7148 .fieldoffset = offsetof(CPUARMState, keys.apia.lo) },
7149 { .name = "APIAKEYHI_EL1", .state = ARM_CP_STATE_AA64,
7150 .opc0 = 3, .opc1 = 0, .crn = 2, .crm = 1, .opc2 = 1,
7151 .access = PL1_RW, .accessfn = access_pauth,
7152 .fgt = FGT_APIAKEY,
7153 .fieldoffset = offsetof(CPUARMState, keys.apia.hi) },
7154 { .name = "APIBKEYLO_EL1", .state = ARM_CP_STATE_AA64,
7155 .opc0 = 3, .opc1 = 0, .crn = 2, .crm = 1, .opc2 = 2,
7156 .access = PL1_RW, .accessfn = access_pauth,
7157 .fgt = FGT_APIBKEY,
7158 .fieldoffset = offsetof(CPUARMState, keys.apib.lo) },
7159 { .name = "APIBKEYHI_EL1", .state = ARM_CP_STATE_AA64,
7160 .opc0 = 3, .opc1 = 0, .crn = 2, .crm = 1, .opc2 = 3,
7161 .access = PL1_RW, .accessfn = access_pauth,
7162 .fgt = FGT_APIBKEY,
7163 .fieldoffset = offsetof(CPUARMState, keys.apib.hi) },
7164};
7165
7166static const ARMCPRegInfo tlbirange_reginfo[] = {
7167 { .name = "TLBI_RVAE1IS", .state = ARM_CP_STATE_AA64,
7168 .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 2, .opc2 = 1,
7169 .access = PL1_W, .accessfn = access_ttlbis, .type = ARM_CP_NO_RAW,
7170 .fgt = FGT_TLBIRVAE1IS,
7171 .writefn = tlbi_aa64_rvae1is_write },
7172 { .name = "TLBI_RVAAE1IS", .state = ARM_CP_STATE_AA64,
7173 .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 2, .opc2 = 3,
7174 .access = PL1_W, .accessfn = access_ttlbis, .type = ARM_CP_NO_RAW,
7175 .fgt = FGT_TLBIRVAAE1IS,
7176 .writefn = tlbi_aa64_rvae1is_write },
7177 { .name = "TLBI_RVALE1IS", .state = ARM_CP_STATE_AA64,
7178 .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 2, .opc2 = 5,
7179 .access = PL1_W, .accessfn = access_ttlbis, .type = ARM_CP_NO_RAW,
7180 .fgt = FGT_TLBIRVALE1IS,
7181 .writefn = tlbi_aa64_rvae1is_write },
7182 { .name = "TLBI_RVAALE1IS", .state = ARM_CP_STATE_AA64,
7183 .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 2, .opc2 = 7,
7184 .access = PL1_W, .accessfn = access_ttlbis, .type = ARM_CP_NO_RAW,
7185 .fgt = FGT_TLBIRVAALE1IS,
7186 .writefn = tlbi_aa64_rvae1is_write },
7187 { .name = "TLBI_RVAE1OS", .state = ARM_CP_STATE_AA64,
7188 .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 5, .opc2 = 1,
7189 .access = PL1_W, .accessfn = access_ttlbos, .type = ARM_CP_NO_RAW,
7190 .fgt = FGT_TLBIRVAE1OS,
7191 .writefn = tlbi_aa64_rvae1is_write },
7192 { .name = "TLBI_RVAAE1OS", .state = ARM_CP_STATE_AA64,
7193 .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 5, .opc2 = 3,
7194 .access = PL1_W, .accessfn = access_ttlbos, .type = ARM_CP_NO_RAW,
7195 .fgt = FGT_TLBIRVAAE1OS,
7196 .writefn = tlbi_aa64_rvae1is_write },
7197 { .name = "TLBI_RVALE1OS", .state = ARM_CP_STATE_AA64,
7198 .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 5, .opc2 = 5,
7199 .access = PL1_W, .accessfn = access_ttlbos, .type = ARM_CP_NO_RAW,
7200 .fgt = FGT_TLBIRVALE1OS,
7201 .writefn = tlbi_aa64_rvae1is_write },
7202 { .name = "TLBI_RVAALE1OS", .state = ARM_CP_STATE_AA64,
7203 .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 5, .opc2 = 7,
7204 .access = PL1_W, .accessfn = access_ttlbos, .type = ARM_CP_NO_RAW,
7205 .fgt = FGT_TLBIRVAALE1OS,
7206 .writefn = tlbi_aa64_rvae1is_write },
7207 { .name = "TLBI_RVAE1", .state = ARM_CP_STATE_AA64,
7208 .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 6, .opc2 = 1,
7209 .access = PL1_W, .accessfn = access_ttlb, .type = ARM_CP_NO_RAW,
7210 .fgt = FGT_TLBIRVAE1,
7211 .writefn = tlbi_aa64_rvae1_write },
7212 { .name = "TLBI_RVAAE1", .state = ARM_CP_STATE_AA64,
7213 .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 6, .opc2 = 3,
7214 .access = PL1_W, .accessfn = access_ttlb, .type = ARM_CP_NO_RAW,
7215 .fgt = FGT_TLBIRVAAE1,
7216 .writefn = tlbi_aa64_rvae1_write },
7217 { .name = "TLBI_RVALE1", .state = ARM_CP_STATE_AA64,
7218 .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 6, .opc2 = 5,
7219 .access = PL1_W, .accessfn = access_ttlb, .type = ARM_CP_NO_RAW,
7220 .fgt = FGT_TLBIRVALE1,
7221 .writefn = tlbi_aa64_rvae1_write },
7222 { .name = "TLBI_RVAALE1", .state = ARM_CP_STATE_AA64,
7223 .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 6, .opc2 = 7,
7224 .access = PL1_W, .accessfn = access_ttlb, .type = ARM_CP_NO_RAW,
7225 .fgt = FGT_TLBIRVAALE1,
7226 .writefn = tlbi_aa64_rvae1_write },
7227 { .name = "TLBI_RIPAS2E1IS", .state = ARM_CP_STATE_AA64,
7228 .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 0, .opc2 = 2,
7229 .access = PL2_W, .type = ARM_CP_NO_RAW,
7230 .writefn = tlbi_aa64_ripas2e1is_write },
7231 { .name = "TLBI_RIPAS2LE1IS", .state = ARM_CP_STATE_AA64,
7232 .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 0, .opc2 = 6,
7233 .access = PL2_W, .type = ARM_CP_NO_RAW,
7234 .writefn = tlbi_aa64_ripas2e1is_write },
7235 { .name = "TLBI_RVAE2IS", .state = ARM_CP_STATE_AA64,
7236 .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 2, .opc2 = 1,
7237 .access = PL2_W, .type = ARM_CP_NO_RAW | ARM_CP_EL3_NO_EL2_UNDEF,
7238 .writefn = tlbi_aa64_rvae2is_write },
7239 { .name = "TLBI_RVALE2IS", .state = ARM_CP_STATE_AA64,
7240 .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 2, .opc2 = 5,
7241 .access = PL2_W, .type = ARM_CP_NO_RAW | ARM_CP_EL3_NO_EL2_UNDEF,
7242 .writefn = tlbi_aa64_rvae2is_write },
7243 { .name = "TLBI_RIPAS2E1", .state = ARM_CP_STATE_AA64,
7244 .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 4, .opc2 = 2,
7245 .access = PL2_W, .type = ARM_CP_NO_RAW,
7246 .writefn = tlbi_aa64_ripas2e1_write },
7247 { .name = "TLBI_RIPAS2LE1", .state = ARM_CP_STATE_AA64,
7248 .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 4, .opc2 = 6,
7249 .access = PL2_W, .type = ARM_CP_NO_RAW,
7250 .writefn = tlbi_aa64_ripas2e1_write },
7251 { .name = "TLBI_RVAE2OS", .state = ARM_CP_STATE_AA64,
7252 .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 5, .opc2 = 1,
7253 .access = PL2_W, .type = ARM_CP_NO_RAW | ARM_CP_EL3_NO_EL2_UNDEF,
7254 .writefn = tlbi_aa64_rvae2is_write },
7255 { .name = "TLBI_RVALE2OS", .state = ARM_CP_STATE_AA64,
7256 .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 5, .opc2 = 5,
7257 .access = PL2_W, .type = ARM_CP_NO_RAW | ARM_CP_EL3_NO_EL2_UNDEF,
7258 .writefn = tlbi_aa64_rvae2is_write },
7259 { .name = "TLBI_RVAE2", .state = ARM_CP_STATE_AA64,
7260 .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 6, .opc2 = 1,
7261 .access = PL2_W, .type = ARM_CP_NO_RAW | ARM_CP_EL3_NO_EL2_UNDEF,
7262 .writefn = tlbi_aa64_rvae2_write },
7263 { .name = "TLBI_RVALE2", .state = ARM_CP_STATE_AA64,
7264 .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 6, .opc2 = 5,
7265 .access = PL2_W, .type = ARM_CP_NO_RAW | ARM_CP_EL3_NO_EL2_UNDEF,
7266 .writefn = tlbi_aa64_rvae2_write },
7267 { .name = "TLBI_RVAE3IS", .state = ARM_CP_STATE_AA64,
7268 .opc0 = 1, .opc1 = 6, .crn = 8, .crm = 2, .opc2 = 1,
7269 .access = PL3_W, .type = ARM_CP_NO_RAW,
7270 .writefn = tlbi_aa64_rvae3is_write },
7271 { .name = "TLBI_RVALE3IS", .state = ARM_CP_STATE_AA64,
7272 .opc0 = 1, .opc1 = 6, .crn = 8, .crm = 2, .opc2 = 5,
7273 .access = PL3_W, .type = ARM_CP_NO_RAW,
7274 .writefn = tlbi_aa64_rvae3is_write },
7275 { .name = "TLBI_RVAE3OS", .state = ARM_CP_STATE_AA64,
7276 .opc0 = 1, .opc1 = 6, .crn = 8, .crm = 5, .opc2 = 1,
7277 .access = PL3_W, .type = ARM_CP_NO_RAW,
7278 .writefn = tlbi_aa64_rvae3is_write },
7279 { .name = "TLBI_RVALE3OS", .state = ARM_CP_STATE_AA64,
7280 .opc0 = 1, .opc1 = 6, .crn = 8, .crm = 5, .opc2 = 5,
7281 .access = PL3_W, .type = ARM_CP_NO_RAW,
7282 .writefn = tlbi_aa64_rvae3is_write },
7283 { .name = "TLBI_RVAE3", .state = ARM_CP_STATE_AA64,
7284 .opc0 = 1, .opc1 = 6, .crn = 8, .crm = 6, .opc2 = 1,
7285 .access = PL3_W, .type = ARM_CP_NO_RAW,
7286 .writefn = tlbi_aa64_rvae3_write },
7287 { .name = "TLBI_RVALE3", .state = ARM_CP_STATE_AA64,
7288 .opc0 = 1, .opc1 = 6, .crn = 8, .crm = 6, .opc2 = 5,
7289 .access = PL3_W, .type = ARM_CP_NO_RAW,
7290 .writefn = tlbi_aa64_rvae3_write },
7291};
7292
7293static const ARMCPRegInfo tlbios_reginfo[] = {
7294 { .name = "TLBI_VMALLE1OS", .state = ARM_CP_STATE_AA64,
7295 .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 1, .opc2 = 0,
7296 .access = PL1_W, .accessfn = access_ttlbos, .type = ARM_CP_NO_RAW,
7297 .fgt = FGT_TLBIVMALLE1OS,
7298 .writefn = tlbi_aa64_vmalle1is_write },
7299 { .name = "TLBI_VAE1OS", .state = ARM_CP_STATE_AA64,
7300 .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 1, .opc2 = 1,
7301 .fgt = FGT_TLBIVAE1OS,
7302 .access = PL1_W, .accessfn = access_ttlbos, .type = ARM_CP_NO_RAW,
7303 .writefn = tlbi_aa64_vae1is_write },
7304 { .name = "TLBI_ASIDE1OS", .state = ARM_CP_STATE_AA64,
7305 .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 1, .opc2 = 2,
7306 .access = PL1_W, .accessfn = access_ttlbos, .type = ARM_CP_NO_RAW,
7307 .fgt = FGT_TLBIASIDE1OS,
7308 .writefn = tlbi_aa64_vmalle1is_write },
7309 { .name = "TLBI_VAAE1OS", .state = ARM_CP_STATE_AA64,
7310 .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 1, .opc2 = 3,
7311 .access = PL1_W, .accessfn = access_ttlbos, .type = ARM_CP_NO_RAW,
7312 .fgt = FGT_TLBIVAAE1OS,
7313 .writefn = tlbi_aa64_vae1is_write },
7314 { .name = "TLBI_VALE1OS", .state = ARM_CP_STATE_AA64,
7315 .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 1, .opc2 = 5,
7316 .access = PL1_W, .accessfn = access_ttlbos, .type = ARM_CP_NO_RAW,
7317 .fgt = FGT_TLBIVALE1OS,
7318 .writefn = tlbi_aa64_vae1is_write },
7319 { .name = "TLBI_VAALE1OS", .state = ARM_CP_STATE_AA64,
7320 .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 1, .opc2 = 7,
7321 .access = PL1_W, .accessfn = access_ttlbos, .type = ARM_CP_NO_RAW,
7322 .fgt = FGT_TLBIVAALE1OS,
7323 .writefn = tlbi_aa64_vae1is_write },
7324 { .name = "TLBI_ALLE2OS", .state = ARM_CP_STATE_AA64,
7325 .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 1, .opc2 = 0,
7326 .access = PL2_W, .type = ARM_CP_NO_RAW | ARM_CP_EL3_NO_EL2_UNDEF,
7327 .writefn = tlbi_aa64_alle2is_write },
7328 { .name = "TLBI_VAE2OS", .state = ARM_CP_STATE_AA64,
7329 .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 1, .opc2 = 1,
7330 .access = PL2_W, .type = ARM_CP_NO_RAW | ARM_CP_EL3_NO_EL2_UNDEF,
7331 .writefn = tlbi_aa64_vae2is_write },
7332 { .name = "TLBI_ALLE1OS", .state = ARM_CP_STATE_AA64,
7333 .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 1, .opc2 = 4,
7334 .access = PL2_W, .type = ARM_CP_NO_RAW,
7335 .writefn = tlbi_aa64_alle1is_write },
7336 { .name = "TLBI_VALE2OS", .state = ARM_CP_STATE_AA64,
7337 .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 1, .opc2 = 5,
7338 .access = PL2_W, .type = ARM_CP_NO_RAW | ARM_CP_EL3_NO_EL2_UNDEF,
7339 .writefn = tlbi_aa64_vae2is_write },
7340 { .name = "TLBI_VMALLS12E1OS", .state = ARM_CP_STATE_AA64,
7341 .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 1, .opc2 = 6,
7342 .access = PL2_W, .type = ARM_CP_NO_RAW,
7343 .writefn = tlbi_aa64_alle1is_write },
7344 { .name = "TLBI_IPAS2E1OS", .state = ARM_CP_STATE_AA64,
7345 .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 4, .opc2 = 0,
7346 .access = PL2_W, .type = ARM_CP_NOP },
7347 { .name = "TLBI_RIPAS2E1OS", .state = ARM_CP_STATE_AA64,
7348 .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 4, .opc2 = 3,
7349 .access = PL2_W, .type = ARM_CP_NOP },
7350 { .name = "TLBI_IPAS2LE1OS", .state = ARM_CP_STATE_AA64,
7351 .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 4, .opc2 = 4,
7352 .access = PL2_W, .type = ARM_CP_NOP },
7353 { .name = "TLBI_RIPAS2LE1OS", .state = ARM_CP_STATE_AA64,
7354 .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 4, .opc2 = 7,
7355 .access = PL2_W, .type = ARM_CP_NOP },
7356 { .name = "TLBI_ALLE3OS", .state = ARM_CP_STATE_AA64,
7357 .opc0 = 1, .opc1 = 6, .crn = 8, .crm = 1, .opc2 = 0,
7358 .access = PL3_W, .type = ARM_CP_NO_RAW,
7359 .writefn = tlbi_aa64_alle3is_write },
7360 { .name = "TLBI_VAE3OS", .state = ARM_CP_STATE_AA64,
7361 .opc0 = 1, .opc1 = 6, .crn = 8, .crm = 1, .opc2 = 1,
7362 .access = PL3_W, .type = ARM_CP_NO_RAW,
7363 .writefn = tlbi_aa64_vae3is_write },
7364 { .name = "TLBI_VALE3OS", .state = ARM_CP_STATE_AA64,
7365 .opc0 = 1, .opc1 = 6, .crn = 8, .crm = 1, .opc2 = 5,
7366 .access = PL3_W, .type = ARM_CP_NO_RAW,
7367 .writefn = tlbi_aa64_vae3is_write },
7368};
7369
7370static uint64_t rndr_readfn(CPUARMState *env, const ARMCPRegInfo *ri)
7371{
7372 Error *err = NULL;
7373 uint64_t ret;
7374
7375
7376 env->NF = env->CF = env->VF = 0, env->ZF = 1;
7377
7378 if (qemu_guest_getrandom(&ret, sizeof(ret), &err) < 0) {
7379
7380
7381
7382
7383
7384
7385
7386 qemu_log_mask(LOG_UNIMP, "%s: Crypto failure: %s",
7387 ri->name, error_get_pretty(err));
7388 error_free(err);
7389
7390 env->ZF = 0;
7391 return 0;
7392 }
7393 return ret;
7394}
7395
7396
7397static const ARMCPRegInfo rndr_reginfo[] = {
7398 { .name = "RNDR", .state = ARM_CP_STATE_AA64,
7399 .type = ARM_CP_NO_RAW | ARM_CP_SUPPRESS_TB_END | ARM_CP_IO,
7400 .opc0 = 3, .opc1 = 3, .crn = 2, .crm = 4, .opc2 = 0,
7401 .access = PL0_R, .readfn = rndr_readfn },
7402 { .name = "RNDRRS", .state = ARM_CP_STATE_AA64,
7403 .type = ARM_CP_NO_RAW | ARM_CP_SUPPRESS_TB_END | ARM_CP_IO,
7404 .opc0 = 3, .opc1 = 3, .crn = 2, .crm = 4, .opc2 = 1,
7405 .access = PL0_R, .readfn = rndr_readfn },
7406};
7407
7408#ifndef CONFIG_USER_ONLY
7409static void dccvap_writefn(CPUARMState *env, const ARMCPRegInfo *opaque,
7410 uint64_t value)
7411{
7412 ARMCPU *cpu = env_archcpu(env);
7413
7414 uint64_t dline_size = 4 << ((cpu->ctr >> 16) & 0xF);
7415 uint64_t vaddr_in = (uint64_t) value;
7416 uint64_t vaddr = vaddr_in & ~(dline_size - 1);
7417 void *haddr;
7418 int mem_idx = cpu_mmu_index(env, false);
7419
7420
7421 haddr = probe_read(env, vaddr, dline_size, mem_idx, GETPC());
7422 if (haddr) {
7423
7424 ram_addr_t offset;
7425 MemoryRegion *mr;
7426
7427
7428 mr = memory_region_from_host(haddr, &offset);
7429
7430 if (mr) {
7431 memory_region_writeback(mr, offset, dline_size);
7432 }
7433 }
7434}
7435
7436static const ARMCPRegInfo dcpop_reg[] = {
7437 { .name = "DC_CVAP", .state = ARM_CP_STATE_AA64,
7438 .opc0 = 1, .opc1 = 3, .crn = 7, .crm = 12, .opc2 = 1,
7439 .access = PL0_W, .type = ARM_CP_NO_RAW | ARM_CP_SUPPRESS_TB_END,
7440 .fgt = FGT_DCCVAP,
7441 .accessfn = aa64_cacheop_poc_access, .writefn = dccvap_writefn },
7442};
7443
7444static const ARMCPRegInfo dcpodp_reg[] = {
7445 { .name = "DC_CVADP", .state = ARM_CP_STATE_AA64,
7446 .opc0 = 1, .opc1 = 3, .crn = 7, .crm = 13, .opc2 = 1,
7447 .access = PL0_W, .type = ARM_CP_NO_RAW | ARM_CP_SUPPRESS_TB_END,
7448 .fgt = FGT_DCCVADP,
7449 .accessfn = aa64_cacheop_poc_access, .writefn = dccvap_writefn },
7450};
7451#endif
7452
7453static CPAccessResult access_aa64_tid5(CPUARMState *env, const ARMCPRegInfo *ri,
7454 bool isread)
7455{
7456 if ((arm_current_el(env) < 2) && (arm_hcr_el2_eff(env) & HCR_TID5)) {
7457 return CP_ACCESS_TRAP_EL2;
7458 }
7459
7460 return CP_ACCESS_OK;
7461}
7462
7463static CPAccessResult access_mte(CPUARMState *env, const ARMCPRegInfo *ri,
7464 bool isread)
7465{
7466 int el = arm_current_el(env);
7467
7468 if (el < 2 && arm_is_el2_enabled(env)) {
7469 uint64_t hcr = arm_hcr_el2_eff(env);
7470 if (!(hcr & HCR_ATA) && (!(hcr & HCR_E2H) || !(hcr & HCR_TGE))) {
7471 return CP_ACCESS_TRAP_EL2;
7472 }
7473 }
7474 if (el < 3 &&
7475 arm_feature(env, ARM_FEATURE_EL3) &&
7476 !(env->cp15.scr_el3 & SCR_ATA)) {
7477 return CP_ACCESS_TRAP_EL3;
7478 }
7479 return CP_ACCESS_OK;
7480}
7481
7482static uint64_t tco_read(CPUARMState *env, const ARMCPRegInfo *ri)
7483{
7484 return env->pstate & PSTATE_TCO;
7485}
7486
7487static void tco_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t val)
7488{
7489 env->pstate = (env->pstate & ~PSTATE_TCO) | (val & PSTATE_TCO);
7490}
7491
7492static const ARMCPRegInfo mte_reginfo[] = {
7493 { .name = "TFSRE0_EL1", .state = ARM_CP_STATE_AA64,
7494 .opc0 = 3, .opc1 = 0, .crn = 5, .crm = 6, .opc2 = 1,
7495 .access = PL1_RW, .accessfn = access_mte,
7496 .fieldoffset = offsetof(CPUARMState, cp15.tfsr_el[0]) },
7497 { .name = "TFSR_EL1", .state = ARM_CP_STATE_AA64,
7498 .opc0 = 3, .opc1 = 0, .crn = 5, .crm = 6, .opc2 = 0,
7499 .access = PL1_RW, .accessfn = access_mte,
7500 .fieldoffset = offsetof(CPUARMState, cp15.tfsr_el[1]) },
7501 { .name = "TFSR_EL2", .state = ARM_CP_STATE_AA64,
7502 .opc0 = 3, .opc1 = 4, .crn = 5, .crm = 6, .opc2 = 0,
7503 .access = PL2_RW, .accessfn = access_mte,
7504 .fieldoffset = offsetof(CPUARMState, cp15.tfsr_el[2]) },
7505 { .name = "TFSR_EL3", .state = ARM_CP_STATE_AA64,
7506 .opc0 = 3, .opc1 = 6, .crn = 5, .crm = 6, .opc2 = 0,
7507 .access = PL3_RW,
7508 .fieldoffset = offsetof(CPUARMState, cp15.tfsr_el[3]) },
7509 { .name = "RGSR_EL1", .state = ARM_CP_STATE_AA64,
7510 .opc0 = 3, .opc1 = 0, .crn = 1, .crm = 0, .opc2 = 5,
7511 .access = PL1_RW, .accessfn = access_mte,
7512 .fieldoffset = offsetof(CPUARMState, cp15.rgsr_el1) },
7513 { .name = "GCR_EL1", .state = ARM_CP_STATE_AA64,
7514 .opc0 = 3, .opc1 = 0, .crn = 1, .crm = 0, .opc2 = 6,
7515 .access = PL1_RW, .accessfn = access_mte,
7516 .fieldoffset = offsetof(CPUARMState, cp15.gcr_el1) },
7517 { .name = "GMID_EL1", .state = ARM_CP_STATE_AA64,
7518 .opc0 = 3, .opc1 = 1, .crn = 0, .crm = 0, .opc2 = 4,
7519 .access = PL1_R, .accessfn = access_aa64_tid5,
7520 .type = ARM_CP_CONST, .resetvalue = GMID_EL1_BS },
7521 { .name = "TCO", .state = ARM_CP_STATE_AA64,
7522 .opc0 = 3, .opc1 = 3, .crn = 4, .crm = 2, .opc2 = 7,
7523 .type = ARM_CP_NO_RAW,
7524 .access = PL0_RW, .readfn = tco_read, .writefn = tco_write },
7525 { .name = "DC_IGVAC", .state = ARM_CP_STATE_AA64,
7526 .opc0 = 1, .opc1 = 0, .crn = 7, .crm = 6, .opc2 = 3,
7527 .type = ARM_CP_NOP, .access = PL1_W,
7528 .fgt = FGT_DCIVAC,
7529 .accessfn = aa64_cacheop_poc_access },
7530 { .name = "DC_IGSW", .state = ARM_CP_STATE_AA64,
7531 .opc0 = 1, .opc1 = 0, .crn = 7, .crm = 6, .opc2 = 4,
7532 .fgt = FGT_DCISW,
7533 .type = ARM_CP_NOP, .access = PL1_W, .accessfn = access_tsw },
7534 { .name = "DC_IGDVAC", .state = ARM_CP_STATE_AA64,
7535 .opc0 = 1, .opc1 = 0, .crn = 7, .crm = 6, .opc2 = 5,
7536 .type = ARM_CP_NOP, .access = PL1_W,
7537 .fgt = FGT_DCIVAC,
7538 .accessfn = aa64_cacheop_poc_access },
7539 { .name = "DC_IGDSW", .state = ARM_CP_STATE_AA64,
7540 .opc0 = 1, .opc1 = 0, .crn = 7, .crm = 6, .opc2 = 6,
7541 .fgt = FGT_DCISW,
7542 .type = ARM_CP_NOP, .access = PL1_W, .accessfn = access_tsw },
7543 { .name = "DC_CGSW", .state = ARM_CP_STATE_AA64,
7544 .opc0 = 1, .opc1 = 0, .crn = 7, .crm = 10, .opc2 = 4,
7545 .fgt = FGT_DCCSW,
7546 .type = ARM_CP_NOP, .access = PL1_W, .accessfn = access_tsw },
7547 { .name = "DC_CGDSW", .state = ARM_CP_STATE_AA64,
7548 .opc0 = 1, .opc1 = 0, .crn = 7, .crm = 10, .opc2 = 6,
7549 .fgt = FGT_DCCSW,
7550 .type = ARM_CP_NOP, .access = PL1_W, .accessfn = access_tsw },
7551 { .name = "DC_CIGSW", .state = ARM_CP_STATE_AA64,
7552 .opc0 = 1, .opc1 = 0, .crn = 7, .crm = 14, .opc2 = 4,
7553 .fgt = FGT_DCCISW,
7554 .type = ARM_CP_NOP, .access = PL1_W, .accessfn = access_tsw },
7555 { .name = "DC_CIGDSW", .state = ARM_CP_STATE_AA64,
7556 .opc0 = 1, .opc1 = 0, .crn = 7, .crm = 14, .opc2 = 6,
7557 .fgt = FGT_DCCISW,
7558 .type = ARM_CP_NOP, .access = PL1_W, .accessfn = access_tsw },
7559};
7560
7561static const ARMCPRegInfo mte_tco_ro_reginfo[] = {
7562 { .name = "TCO", .state = ARM_CP_STATE_AA64,
7563 .opc0 = 3, .opc1 = 3, .crn = 4, .crm = 2, .opc2 = 7,
7564 .type = ARM_CP_CONST, .access = PL0_RW, },
7565};
7566
7567static const ARMCPRegInfo mte_el0_cacheop_reginfo[] = {
7568 { .name = "DC_CGVAC", .state = ARM_CP_STATE_AA64,
7569 .opc0 = 1, .opc1 = 3, .crn = 7, .crm = 10, .opc2 = 3,
7570 .type = ARM_CP_NOP, .access = PL0_W,
7571 .fgt = FGT_DCCVAC,
7572 .accessfn = aa64_cacheop_poc_access },
7573 { .name = "DC_CGDVAC", .state = ARM_CP_STATE_AA64,
7574 .opc0 = 1, .opc1 = 3, .crn = 7, .crm = 10, .opc2 = 5,
7575 .type = ARM_CP_NOP, .access = PL0_W,
7576 .fgt = FGT_DCCVAC,
7577 .accessfn = aa64_cacheop_poc_access },
7578 { .name = "DC_CGVAP", .state = ARM_CP_STATE_AA64,
7579 .opc0 = 1, .opc1 = 3, .crn = 7, .crm = 12, .opc2 = 3,
7580 .type = ARM_CP_NOP, .access = PL0_W,
7581 .fgt = FGT_DCCVAP,
7582 .accessfn = aa64_cacheop_poc_access },
7583 { .name = "DC_CGDVAP", .state = ARM_CP_STATE_AA64,
7584 .opc0 = 1, .opc1 = 3, .crn = 7, .crm = 12, .opc2 = 5,
7585 .type = ARM_CP_NOP, .access = PL0_W,
7586 .fgt = FGT_DCCVAP,
7587 .accessfn = aa64_cacheop_poc_access },
7588 { .name = "DC_CGVADP", .state = ARM_CP_STATE_AA64,
7589 .opc0 = 1, .opc1 = 3, .crn = 7, .crm = 13, .opc2 = 3,
7590 .type = ARM_CP_NOP, .access = PL0_W,
7591 .fgt = FGT_DCCVADP,
7592 .accessfn = aa64_cacheop_poc_access },
7593 { .name = "DC_CGDVADP", .state = ARM_CP_STATE_AA64,
7594 .opc0 = 1, .opc1 = 3, .crn = 7, .crm = 13, .opc2 = 5,
7595 .type = ARM_CP_NOP, .access = PL0_W,
7596 .fgt = FGT_DCCVADP,
7597 .accessfn = aa64_cacheop_poc_access },
7598 { .name = "DC_CIGVAC", .state = ARM_CP_STATE_AA64,
7599 .opc0 = 1, .opc1 = 3, .crn = 7, .crm = 14, .opc2 = 3,
7600 .type = ARM_CP_NOP, .access = PL0_W,
7601 .fgt = FGT_DCCIVAC,
7602 .accessfn = aa64_cacheop_poc_access },
7603 { .name = "DC_CIGDVAC", .state = ARM_CP_STATE_AA64,
7604 .opc0 = 1, .opc1 = 3, .crn = 7, .crm = 14, .opc2 = 5,
7605 .type = ARM_CP_NOP, .access = PL0_W,
7606 .fgt = FGT_DCCIVAC,
7607 .accessfn = aa64_cacheop_poc_access },
7608 { .name = "DC_GVA", .state = ARM_CP_STATE_AA64,
7609 .opc0 = 1, .opc1 = 3, .crn = 7, .crm = 4, .opc2 = 3,
7610 .access = PL0_W, .type = ARM_CP_DC_GVA,
7611#ifndef CONFIG_USER_ONLY
7612
7613 .accessfn = aa64_zva_access,
7614 .fgt = FGT_DCZVA,
7615#endif
7616 },
7617 { .name = "DC_GZVA", .state = ARM_CP_STATE_AA64,
7618 .opc0 = 1, .opc1 = 3, .crn = 7, .crm = 4, .opc2 = 4,
7619 .access = PL0_W, .type = ARM_CP_DC_GZVA,
7620#ifndef CONFIG_USER_ONLY
7621
7622 .accessfn = aa64_zva_access,
7623 .fgt = FGT_DCZVA,
7624#endif
7625 },
7626};
7627
7628static CPAccessResult access_scxtnum(CPUARMState *env, const ARMCPRegInfo *ri,
7629 bool isread)
7630{
7631 uint64_t hcr = arm_hcr_el2_eff(env);
7632 int el = arm_current_el(env);
7633
7634 if (el == 0 && !((hcr & HCR_E2H) && (hcr & HCR_TGE))) {
7635 if (env->cp15.sctlr_el[1] & SCTLR_TSCXT) {
7636 if (hcr & HCR_TGE) {
7637 return CP_ACCESS_TRAP_EL2;
7638 }
7639 return CP_ACCESS_TRAP;
7640 }
7641 } else if (el < 2 && (env->cp15.sctlr_el[2] & SCTLR_TSCXT)) {
7642 return CP_ACCESS_TRAP_EL2;
7643 }
7644 if (el < 2 && arm_is_el2_enabled(env) && !(hcr & HCR_ENSCXT)) {
7645 return CP_ACCESS_TRAP_EL2;
7646 }
7647 if (el < 3
7648 && arm_feature(env, ARM_FEATURE_EL3)
7649 && !(env->cp15.scr_el3 & SCR_ENSCXT)) {
7650 return CP_ACCESS_TRAP_EL3;
7651 }
7652 return CP_ACCESS_OK;
7653}
7654
7655static const ARMCPRegInfo scxtnum_reginfo[] = {
7656 { .name = "SCXTNUM_EL0", .state = ARM_CP_STATE_AA64,
7657 .opc0 = 3, .opc1 = 3, .crn = 13, .crm = 0, .opc2 = 7,
7658 .access = PL0_RW, .accessfn = access_scxtnum,
7659 .fgt = FGT_SCXTNUM_EL0,
7660 .fieldoffset = offsetof(CPUARMState, scxtnum_el[0]) },
7661 { .name = "SCXTNUM_EL1", .state = ARM_CP_STATE_AA64,
7662 .opc0 = 3, .opc1 = 0, .crn = 13, .crm = 0, .opc2 = 7,
7663 .access = PL1_RW, .accessfn = access_scxtnum,
7664 .fgt = FGT_SCXTNUM_EL1,
7665 .fieldoffset = offsetof(CPUARMState, scxtnum_el[1]) },
7666 { .name = "SCXTNUM_EL2", .state = ARM_CP_STATE_AA64,
7667 .opc0 = 3, .opc1 = 4, .crn = 13, .crm = 0, .opc2 = 7,
7668 .access = PL2_RW, .accessfn = access_scxtnum,
7669 .fieldoffset = offsetof(CPUARMState, scxtnum_el[2]) },
7670 { .name = "SCXTNUM_EL3", .state = ARM_CP_STATE_AA64,
7671 .opc0 = 3, .opc1 = 6, .crn = 13, .crm = 0, .opc2 = 7,
7672 .access = PL3_RW,
7673 .fieldoffset = offsetof(CPUARMState, scxtnum_el[3]) },
7674};
7675
7676static CPAccessResult access_fgt(CPUARMState *env, const ARMCPRegInfo *ri,
7677 bool isread)
7678{
7679 if (arm_current_el(env) == 2 &&
7680 arm_feature(env, ARM_FEATURE_EL3) && !(env->cp15.scr_el3 & SCR_FGTEN)) {
7681 return CP_ACCESS_TRAP_EL3;
7682 }
7683 return CP_ACCESS_OK;
7684}
7685
7686static const ARMCPRegInfo fgt_reginfo[] = {
7687 { .name = "HFGRTR_EL2", .state = ARM_CP_STATE_AA64,
7688 .opc0 = 3, .opc1 = 4, .crn = 1, .crm = 1, .opc2 = 4,
7689 .access = PL2_RW, .accessfn = access_fgt,
7690 .fieldoffset = offsetof(CPUARMState, cp15.fgt_read[FGTREG_HFGRTR]) },
7691 { .name = "HFGWTR_EL2", .state = ARM_CP_STATE_AA64,
7692 .opc0 = 3, .opc1 = 4, .crn = 1, .crm = 1, .opc2 = 5,
7693 .access = PL2_RW, .accessfn = access_fgt,
7694 .fieldoffset = offsetof(CPUARMState, cp15.fgt_write[FGTREG_HFGWTR]) },
7695 { .name = "HDFGRTR_EL2", .state = ARM_CP_STATE_AA64,
7696 .opc0 = 3, .opc1 = 4, .crn = 3, .crm = 1, .opc2 = 4,
7697 .access = PL2_RW, .accessfn = access_fgt,
7698 .fieldoffset = offsetof(CPUARMState, cp15.fgt_read[FGTREG_HDFGRTR]) },
7699 { .name = "HDFGWTR_EL2", .state = ARM_CP_STATE_AA64,
7700 .opc0 = 3, .opc1 = 4, .crn = 3, .crm = 1, .opc2 = 5,
7701 .access = PL2_RW, .accessfn = access_fgt,
7702 .fieldoffset = offsetof(CPUARMState, cp15.fgt_write[FGTREG_HDFGWTR]) },
7703 { .name = "HFGITR_EL2", .state = ARM_CP_STATE_AA64,
7704 .opc0 = 3, .opc1 = 4, .crn = 1, .crm = 1, .opc2 = 6,
7705 .access = PL2_RW, .accessfn = access_fgt,
7706 .fieldoffset = offsetof(CPUARMState, cp15.fgt_exec[FGTREG_HFGITR]) },
7707};
7708#endif
7709
7710static CPAccessResult access_predinv(CPUARMState *env, const ARMCPRegInfo *ri,
7711 bool isread)
7712{
7713 int el = arm_current_el(env);
7714
7715 if (el == 0) {
7716 uint64_t sctlr = arm_sctlr(env, el);
7717 if (!(sctlr & SCTLR_EnRCTX)) {
7718 return CP_ACCESS_TRAP;
7719 }
7720 } else if (el == 1) {
7721 uint64_t hcr = arm_hcr_el2_eff(env);
7722 if (hcr & HCR_NV) {
7723 return CP_ACCESS_TRAP_EL2;
7724 }
7725 }
7726 return CP_ACCESS_OK;
7727}
7728
7729static const ARMCPRegInfo predinv_reginfo[] = {
7730 { .name = "CFP_RCTX", .state = ARM_CP_STATE_AA64,
7731 .opc0 = 1, .opc1 = 3, .crn = 7, .crm = 3, .opc2 = 4,
7732 .fgt = FGT_CFPRCTX,
7733 .type = ARM_CP_NOP, .access = PL0_W, .accessfn = access_predinv },
7734 { .name = "DVP_RCTX", .state = ARM_CP_STATE_AA64,
7735 .opc0 = 1, .opc1 = 3, .crn = 7, .crm = 3, .opc2 = 5,
7736 .fgt = FGT_DVPRCTX,
7737 .type = ARM_CP_NOP, .access = PL0_W, .accessfn = access_predinv },
7738 { .name = "CPP_RCTX", .state = ARM_CP_STATE_AA64,
7739 .opc0 = 1, .opc1 = 3, .crn = 7, .crm = 3, .opc2 = 7,
7740 .fgt = FGT_CPPRCTX,
7741 .type = ARM_CP_NOP, .access = PL0_W, .accessfn = access_predinv },
7742
7743
7744
7745 { .name = "CFPRCTX", .state = ARM_CP_STATE_AA32,
7746 .cp = 15, .opc1 = 0, .crn = 7, .crm = 3, .opc2 = 4,
7747 .fgt = FGT_CFPRCTX,
7748 .type = ARM_CP_NOP, .access = PL0_W, .accessfn = access_predinv },
7749 { .name = "DVPRCTX", .state = ARM_CP_STATE_AA32,
7750 .cp = 15, .opc1 = 0, .crn = 7, .crm = 3, .opc2 = 5,
7751 .fgt = FGT_DVPRCTX,
7752 .type = ARM_CP_NOP, .access = PL0_W, .accessfn = access_predinv },
7753 { .name = "CPPRCTX", .state = ARM_CP_STATE_AA32,
7754 .cp = 15, .opc1 = 0, .crn = 7, .crm = 3, .opc2 = 7,
7755 .fgt = FGT_CPPRCTX,
7756 .type = ARM_CP_NOP, .access = PL0_W, .accessfn = access_predinv },
7757};
7758
7759static uint64_t ccsidr2_read(CPUARMState *env, const ARMCPRegInfo *ri)
7760{
7761
7762 return extract64(ccsidr_read(env, ri), 32, 32);
7763}
7764
7765static const ARMCPRegInfo ccsidr2_reginfo[] = {
7766 { .name = "CCSIDR2", .state = ARM_CP_STATE_BOTH,
7767 .opc0 = 3, .opc1 = 1, .crn = 0, .crm = 0, .opc2 = 2,
7768 .access = PL1_R,
7769 .accessfn = access_tid4,
7770 .readfn = ccsidr2_read, .type = ARM_CP_NO_RAW },
7771};
7772
7773static CPAccessResult access_aa64_tid3(CPUARMState *env, const ARMCPRegInfo *ri,
7774 bool isread)
7775{
7776 if ((arm_current_el(env) < 2) && (arm_hcr_el2_eff(env) & HCR_TID3)) {
7777 return CP_ACCESS_TRAP_EL2;
7778 }
7779
7780 return CP_ACCESS_OK;
7781}
7782
7783static CPAccessResult access_aa32_tid3(CPUARMState *env, const ARMCPRegInfo *ri,
7784 bool isread)
7785{
7786 if (arm_feature(env, ARM_FEATURE_V8)) {
7787 return access_aa64_tid3(env, ri, isread);
7788 }
7789
7790 return CP_ACCESS_OK;
7791}
7792
7793static CPAccessResult access_jazelle(CPUARMState *env, const ARMCPRegInfo *ri,
7794 bool isread)
7795{
7796 if (arm_current_el(env) == 1 && (arm_hcr_el2_eff(env) & HCR_TID0)) {
7797 return CP_ACCESS_TRAP_EL2;
7798 }
7799
7800 return CP_ACCESS_OK;
7801}
7802
7803static CPAccessResult access_joscr_jmcr(CPUARMState *env,
7804 const ARMCPRegInfo *ri, bool isread)
7805{
7806
7807
7808
7809
7810 if (!arm_feature(env, ARM_FEATURE_V8) &&
7811 arm_current_el(env) < 2 && !arm_is_secure_below_el3(env) &&
7812 (env->cp15.hstr_el2 & HSTR_TJDBX)) {
7813 return CP_ACCESS_TRAP_EL2;
7814 }
7815 return CP_ACCESS_OK;
7816}
7817
7818static const ARMCPRegInfo jazelle_regs[] = {
7819 { .name = "JIDR",
7820 .cp = 14, .crn = 0, .crm = 0, .opc1 = 7, .opc2 = 0,
7821 .access = PL1_R, .accessfn = access_jazelle,
7822 .type = ARM_CP_CONST, .resetvalue = 0 },
7823 { .name = "JOSCR",
7824 .cp = 14, .crn = 1, .crm = 0, .opc1 = 7, .opc2 = 0,
7825 .accessfn = access_joscr_jmcr,
7826 .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
7827 { .name = "JMCR",
7828 .cp = 14, .crn = 2, .crm = 0, .opc1 = 7, .opc2 = 0,
7829 .accessfn = access_joscr_jmcr,
7830 .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
7831};
7832
7833static const ARMCPRegInfo contextidr_el2 = {
7834 .name = "CONTEXTIDR_EL2", .state = ARM_CP_STATE_AA64,
7835 .opc0 = 3, .opc1 = 4, .crn = 13, .crm = 0, .opc2 = 1,
7836 .access = PL2_RW,
7837 .fieldoffset = offsetof(CPUARMState, cp15.contextidr_el[2])
7838};
7839
7840static const ARMCPRegInfo vhe_reginfo[] = {
7841 { .name = "TTBR1_EL2", .state = ARM_CP_STATE_AA64,
7842 .opc0 = 3, .opc1 = 4, .crn = 2, .crm = 0, .opc2 = 1,
7843 .access = PL2_RW, .writefn = vmsa_tcr_ttbr_el2_write,
7844 .fieldoffset = offsetof(CPUARMState, cp15.ttbr1_el[2]) },
7845#ifndef CONFIG_USER_ONLY
7846 { .name = "CNTHV_CVAL_EL2", .state = ARM_CP_STATE_AA64,
7847 .opc0 = 3, .opc1 = 4, .crn = 14, .crm = 3, .opc2 = 2,
7848 .fieldoffset =
7849 offsetof(CPUARMState, cp15.c14_timer[GTIMER_HYPVIRT].cval),
7850 .type = ARM_CP_IO, .access = PL2_RW,
7851 .writefn = gt_hv_cval_write, .raw_writefn = raw_write },
7852 { .name = "CNTHV_TVAL_EL2", .state = ARM_CP_STATE_BOTH,
7853 .opc0 = 3, .opc1 = 4, .crn = 14, .crm = 3, .opc2 = 0,
7854 .type = ARM_CP_NO_RAW | ARM_CP_IO, .access = PL2_RW,
7855 .resetfn = gt_hv_timer_reset,
7856 .readfn = gt_hv_tval_read, .writefn = gt_hv_tval_write },
7857 { .name = "CNTHV_CTL_EL2", .state = ARM_CP_STATE_BOTH,
7858 .type = ARM_CP_IO,
7859 .opc0 = 3, .opc1 = 4, .crn = 14, .crm = 3, .opc2 = 1,
7860 .access = PL2_RW,
7861 .fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_HYPVIRT].ctl),
7862 .writefn = gt_hv_ctl_write, .raw_writefn = raw_write },
7863 { .name = "CNTP_CTL_EL02", .state = ARM_CP_STATE_AA64,
7864 .opc0 = 3, .opc1 = 5, .crn = 14, .crm = 2, .opc2 = 1,
7865 .type = ARM_CP_IO | ARM_CP_ALIAS,
7866 .access = PL2_RW, .accessfn = e2h_access,
7867 .fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_PHYS].ctl),
7868 .writefn = gt_phys_ctl_write, .raw_writefn = raw_write },
7869 { .name = "CNTV_CTL_EL02", .state = ARM_CP_STATE_AA64,
7870 .opc0 = 3, .opc1 = 5, .crn = 14, .crm = 3, .opc2 = 1,
7871 .type = ARM_CP_IO | ARM_CP_ALIAS,
7872 .access = PL2_RW, .accessfn = e2h_access,
7873 .fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_VIRT].ctl),
7874 .writefn = gt_virt_ctl_write, .raw_writefn = raw_write },
7875 { .name = "CNTP_TVAL_EL02", .state = ARM_CP_STATE_AA64,
7876 .opc0 = 3, .opc1 = 5, .crn = 14, .crm = 2, .opc2 = 0,
7877 .type = ARM_CP_NO_RAW | ARM_CP_IO | ARM_CP_ALIAS,
7878 .access = PL2_RW, .accessfn = e2h_access,
7879 .readfn = gt_phys_tval_read, .writefn = gt_phys_tval_write },
7880 { .name = "CNTV_TVAL_EL02", .state = ARM_CP_STATE_AA64,
7881 .opc0 = 3, .opc1 = 5, .crn = 14, .crm = 3, .opc2 = 0,
7882 .type = ARM_CP_NO_RAW | ARM_CP_IO | ARM_CP_ALIAS,
7883 .access = PL2_RW, .accessfn = e2h_access,
7884 .readfn = gt_virt_tval_read, .writefn = gt_virt_tval_write },
7885 { .name = "CNTP_CVAL_EL02", .state = ARM_CP_STATE_AA64,
7886 .opc0 = 3, .opc1 = 5, .crn = 14, .crm = 2, .opc2 = 2,
7887 .type = ARM_CP_IO | ARM_CP_ALIAS,
7888 .fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_PHYS].cval),
7889 .access = PL2_RW, .accessfn = e2h_access,
7890 .writefn = gt_phys_cval_write, .raw_writefn = raw_write },
7891 { .name = "CNTV_CVAL_EL02", .state = ARM_CP_STATE_AA64,
7892 .opc0 = 3, .opc1 = 5, .crn = 14, .crm = 3, .opc2 = 2,
7893 .type = ARM_CP_IO | ARM_CP_ALIAS,
7894 .fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_VIRT].cval),
7895 .access = PL2_RW, .accessfn = e2h_access,
7896 .writefn = gt_virt_cval_write, .raw_writefn = raw_write },
7897#endif
7898};
7899
7900#ifndef CONFIG_USER_ONLY
7901static const ARMCPRegInfo ats1e1_reginfo[] = {
7902 { .name = "AT_S1E1RP", .state = ARM_CP_STATE_AA64,
7903 .opc0 = 1, .opc1 = 0, .crn = 7, .crm = 9, .opc2 = 0,
7904 .access = PL1_W, .type = ARM_CP_NO_RAW | ARM_CP_RAISES_EXC,
7905 .fgt = FGT_ATS1E1RP,
7906 .writefn = ats_write64 },
7907 { .name = "AT_S1E1WP", .state = ARM_CP_STATE_AA64,
7908 .opc0 = 1, .opc1 = 0, .crn = 7, .crm = 9, .opc2 = 1,
7909 .access = PL1_W, .type = ARM_CP_NO_RAW | ARM_CP_RAISES_EXC,
7910 .fgt = FGT_ATS1E1WP,
7911 .writefn = ats_write64 },
7912};
7913
7914static const ARMCPRegInfo ats1cp_reginfo[] = {
7915 { .name = "ATS1CPRP",
7916 .cp = 15, .opc1 = 0, .crn = 7, .crm = 9, .opc2 = 0,
7917 .access = PL1_W, .type = ARM_CP_NO_RAW | ARM_CP_RAISES_EXC,
7918 .writefn = ats_write },
7919 { .name = "ATS1CPWP",
7920 .cp = 15, .opc1 = 0, .crn = 7, .crm = 9, .opc2 = 1,
7921 .access = PL1_W, .type = ARM_CP_NO_RAW | ARM_CP_RAISES_EXC,
7922 .writefn = ats_write },
7923};
7924#endif
7925
7926
7927
7928
7929
7930
7931
7932
7933
7934
7935static const ARMCPRegInfo actlr2_hactlr2_reginfo[] = {
7936 { .name = "ACTLR2", .state = ARM_CP_STATE_AA32,
7937 .cp = 15, .opc1 = 0, .crn = 1, .crm = 0, .opc2 = 3,
7938 .access = PL1_RW, .accessfn = access_tacr,
7939 .type = ARM_CP_CONST, .resetvalue = 0 },
7940 { .name = "HACTLR2", .state = ARM_CP_STATE_AA32,
7941 .cp = 15, .opc1 = 4, .crn = 1, .crm = 0, .opc2 = 3,
7942 .access = PL2_RW, .type = ARM_CP_CONST,
7943 .resetvalue = 0 },
7944};
7945
7946void register_cp_regs_for_features(ARMCPU *cpu)
7947{
7948
7949 CPUARMState *env = &cpu->env;
7950 if (arm_feature(env, ARM_FEATURE_M)) {
7951
7952 return;
7953 }
7954
7955 define_arm_cp_regs(cpu, cp_reginfo);
7956 if (!arm_feature(env, ARM_FEATURE_V8)) {
7957
7958
7959
7960
7961 define_arm_cp_regs(cpu, not_v8_cp_reginfo);
7962 }
7963
7964 if (arm_feature(env, ARM_FEATURE_V6)) {
7965
7966 ARMCPRegInfo v6_idregs[] = {
7967 { .name = "ID_PFR0", .state = ARM_CP_STATE_BOTH,
7968 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 1, .opc2 = 0,
7969 .access = PL1_R, .type = ARM_CP_CONST,
7970 .accessfn = access_aa32_tid3,
7971 .resetvalue = cpu->isar.id_pfr0 },
7972
7973
7974
7975
7976 { .name = "ID_PFR1", .state = ARM_CP_STATE_BOTH,
7977 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 1, .opc2 = 1,
7978 .access = PL1_R, .type = ARM_CP_NO_RAW,
7979 .accessfn = access_aa32_tid3,
7980#ifdef CONFIG_USER_ONLY
7981 .type = ARM_CP_CONST,
7982 .resetvalue = cpu->isar.id_pfr1,
7983#else
7984 .type = ARM_CP_NO_RAW,
7985 .accessfn = access_aa32_tid3,
7986 .readfn = id_pfr1_read,
7987 .writefn = arm_cp_write_ignore
7988#endif
7989 },
7990 { .name = "ID_DFR0", .state = ARM_CP_STATE_BOTH,
7991 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 1, .opc2 = 2,
7992 .access = PL1_R, .type = ARM_CP_CONST,
7993 .accessfn = access_aa32_tid3,
7994 .resetvalue = cpu->isar.id_dfr0 },
7995 { .name = "ID_AFR0", .state = ARM_CP_STATE_BOTH,
7996 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 1, .opc2 = 3,
7997 .access = PL1_R, .type = ARM_CP_CONST,
7998 .accessfn = access_aa32_tid3,
7999 .resetvalue = cpu->id_afr0 },
8000 { .name = "ID_MMFR0", .state = ARM_CP_STATE_BOTH,
8001 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 1, .opc2 = 4,
8002 .access = PL1_R, .type = ARM_CP_CONST,
8003 .accessfn = access_aa32_tid3,
8004 .resetvalue = cpu->isar.id_mmfr0 },
8005 { .name = "ID_MMFR1", .state = ARM_CP_STATE_BOTH,
8006 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 1, .opc2 = 5,
8007 .access = PL1_R, .type = ARM_CP_CONST,
8008 .accessfn = access_aa32_tid3,
8009 .resetvalue = cpu->isar.id_mmfr1 },
8010 { .name = "ID_MMFR2", .state = ARM_CP_STATE_BOTH,
8011 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 1, .opc2 = 6,
8012 .access = PL1_R, .type = ARM_CP_CONST,
8013 .accessfn = access_aa32_tid3,
8014 .resetvalue = cpu->isar.id_mmfr2 },
8015 { .name = "ID_MMFR3", .state = ARM_CP_STATE_BOTH,
8016 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 1, .opc2 = 7,
8017 .access = PL1_R, .type = ARM_CP_CONST,
8018 .accessfn = access_aa32_tid3,
8019 .resetvalue = cpu->isar.id_mmfr3 },
8020 { .name = "ID_ISAR0", .state = ARM_CP_STATE_BOTH,
8021 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 0,
8022 .access = PL1_R, .type = ARM_CP_CONST,
8023 .accessfn = access_aa32_tid3,
8024 .resetvalue = cpu->isar.id_isar0 },
8025 { .name = "ID_ISAR1", .state = ARM_CP_STATE_BOTH,
8026 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 1,
8027 .access = PL1_R, .type = ARM_CP_CONST,
8028 .accessfn = access_aa32_tid3,
8029 .resetvalue = cpu->isar.id_isar1 },
8030 { .name = "ID_ISAR2", .state = ARM_CP_STATE_BOTH,
8031 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 2,
8032 .access = PL1_R, .type = ARM_CP_CONST,
8033 .accessfn = access_aa32_tid3,
8034 .resetvalue = cpu->isar.id_isar2 },
8035 { .name = "ID_ISAR3", .state = ARM_CP_STATE_BOTH,
8036 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 3,
8037 .access = PL1_R, .type = ARM_CP_CONST,
8038 .accessfn = access_aa32_tid3,
8039 .resetvalue = cpu->isar.id_isar3 },
8040 { .name = "ID_ISAR4", .state = ARM_CP_STATE_BOTH,
8041 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 4,
8042 .access = PL1_R, .type = ARM_CP_CONST,
8043 .accessfn = access_aa32_tid3,
8044 .resetvalue = cpu->isar.id_isar4 },
8045 { .name = "ID_ISAR5", .state = ARM_CP_STATE_BOTH,
8046 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 5,
8047 .access = PL1_R, .type = ARM_CP_CONST,
8048 .accessfn = access_aa32_tid3,
8049 .resetvalue = cpu->isar.id_isar5 },
8050 { .name = "ID_MMFR4", .state = ARM_CP_STATE_BOTH,
8051 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 6,
8052 .access = PL1_R, .type = ARM_CP_CONST,
8053 .accessfn = access_aa32_tid3,
8054 .resetvalue = cpu->isar.id_mmfr4 },
8055 { .name = "ID_ISAR6", .state = ARM_CP_STATE_BOTH,
8056 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 7,
8057 .access = PL1_R, .type = ARM_CP_CONST,
8058 .accessfn = access_aa32_tid3,
8059 .resetvalue = cpu->isar.id_isar6 },
8060 };
8061 define_arm_cp_regs(cpu, v6_idregs);
8062 define_arm_cp_regs(cpu, v6_cp_reginfo);
8063 } else {
8064 define_arm_cp_regs(cpu, not_v6_cp_reginfo);
8065 }
8066 if (arm_feature(env, ARM_FEATURE_V6K)) {
8067 define_arm_cp_regs(cpu, v6k_cp_reginfo);
8068 }
8069 if (arm_feature(env, ARM_FEATURE_V7MP) &&
8070 !arm_feature(env, ARM_FEATURE_PMSA)) {
8071 define_arm_cp_regs(cpu, v7mp_cp_reginfo);
8072 }
8073 if (arm_feature(env, ARM_FEATURE_V7VE)) {
8074 define_arm_cp_regs(cpu, pmovsset_cp_reginfo);
8075 }
8076 if (arm_feature(env, ARM_FEATURE_V7)) {
8077 ARMCPRegInfo clidr = {
8078 .name = "CLIDR", .state = ARM_CP_STATE_BOTH,
8079 .opc0 = 3, .crn = 0, .crm = 0, .opc1 = 1, .opc2 = 1,
8080 .access = PL1_R, .type = ARM_CP_CONST,
8081 .accessfn = access_tid4,
8082 .fgt = FGT_CLIDR_EL1,
8083 .resetvalue = cpu->clidr
8084 };
8085 define_one_arm_cp_reg(cpu, &clidr);
8086 define_arm_cp_regs(cpu, v7_cp_reginfo);
8087 define_debug_regs(cpu);
8088 define_pmu_regs(cpu);
8089 } else {
8090 define_arm_cp_regs(cpu, not_v7_cp_reginfo);
8091 }
8092 if (arm_feature(env, ARM_FEATURE_V8)) {
8093
8094
8095
8096
8097
8098
8099
8100
8101
8102 int i;
8103 ARMCPRegInfo v8_idregs[] = {
8104
8105
8106
8107
8108
8109 { .name = "ID_AA64PFR0_EL1", .state = ARM_CP_STATE_AA64,
8110 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 4, .opc2 = 0,
8111 .access = PL1_R,
8112#ifdef CONFIG_USER_ONLY
8113 .type = ARM_CP_CONST,
8114 .resetvalue = cpu->isar.id_aa64pfr0
8115#else
8116 .type = ARM_CP_NO_RAW,
8117 .accessfn = access_aa64_tid3,
8118 .readfn = id_aa64pfr0_read,
8119 .writefn = arm_cp_write_ignore
8120#endif
8121 },
8122 { .name = "ID_AA64PFR1_EL1", .state = ARM_CP_STATE_AA64,
8123 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 4, .opc2 = 1,
8124 .access = PL1_R, .type = ARM_CP_CONST,
8125 .accessfn = access_aa64_tid3,
8126 .resetvalue = cpu->isar.id_aa64pfr1},
8127 { .name = "ID_AA64PFR2_EL1_RESERVED", .state = ARM_CP_STATE_AA64,
8128 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 4, .opc2 = 2,
8129 .access = PL1_R, .type = ARM_CP_CONST,
8130 .accessfn = access_aa64_tid3,
8131 .resetvalue = 0 },
8132 { .name = "ID_AA64PFR3_EL1_RESERVED", .state = ARM_CP_STATE_AA64,
8133 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 4, .opc2 = 3,
8134 .access = PL1_R, .type = ARM_CP_CONST,
8135 .accessfn = access_aa64_tid3,
8136 .resetvalue = 0 },
8137 { .name = "ID_AA64ZFR0_EL1", .state = ARM_CP_STATE_AA64,
8138 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 4, .opc2 = 4,
8139 .access = PL1_R, .type = ARM_CP_CONST,
8140 .accessfn = access_aa64_tid3,
8141 .resetvalue = cpu->isar.id_aa64zfr0 },
8142 { .name = "ID_AA64SMFR0_EL1", .state = ARM_CP_STATE_AA64,
8143 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 4, .opc2 = 5,
8144 .access = PL1_R, .type = ARM_CP_CONST,
8145 .accessfn = access_aa64_tid3,
8146 .resetvalue = cpu->isar.id_aa64smfr0 },
8147 { .name = "ID_AA64PFR6_EL1_RESERVED", .state = ARM_CP_STATE_AA64,
8148 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 4, .opc2 = 6,
8149 .access = PL1_R, .type = ARM_CP_CONST,
8150 .accessfn = access_aa64_tid3,
8151 .resetvalue = 0 },
8152 { .name = "ID_AA64PFR7_EL1_RESERVED", .state = ARM_CP_STATE_AA64,
8153 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 4, .opc2 = 7,
8154 .access = PL1_R, .type = ARM_CP_CONST,
8155 .accessfn = access_aa64_tid3,
8156 .resetvalue = 0 },
8157 { .name = "ID_AA64DFR0_EL1", .state = ARM_CP_STATE_AA64,
8158 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 5, .opc2 = 0,
8159 .access = PL1_R, .type = ARM_CP_CONST,
8160 .accessfn = access_aa64_tid3,
8161 .resetvalue = cpu->isar.id_aa64dfr0 },
8162 { .name = "ID_AA64DFR1_EL1", .state = ARM_CP_STATE_AA64,
8163 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 5, .opc2 = 1,
8164 .access = PL1_R, .type = ARM_CP_CONST,
8165 .accessfn = access_aa64_tid3,
8166 .resetvalue = cpu->isar.id_aa64dfr1 },
8167 { .name = "ID_AA64DFR2_EL1_RESERVED", .state = ARM_CP_STATE_AA64,
8168 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 5, .opc2 = 2,
8169 .access = PL1_R, .type = ARM_CP_CONST,
8170 .accessfn = access_aa64_tid3,
8171 .resetvalue = 0 },
8172 { .name = "ID_AA64DFR3_EL1_RESERVED", .state = ARM_CP_STATE_AA64,
8173 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 5, .opc2 = 3,
8174 .access = PL1_R, .type = ARM_CP_CONST,
8175 .accessfn = access_aa64_tid3,
8176 .resetvalue = 0 },
8177 { .name = "ID_AA64AFR0_EL1", .state = ARM_CP_STATE_AA64,
8178 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 5, .opc2 = 4,
8179 .access = PL1_R, .type = ARM_CP_CONST,
8180 .accessfn = access_aa64_tid3,
8181 .resetvalue = cpu->id_aa64afr0 },
8182 { .name = "ID_AA64AFR1_EL1", .state = ARM_CP_STATE_AA64,
8183 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 5, .opc2 = 5,
8184 .access = PL1_R, .type = ARM_CP_CONST,
8185 .accessfn = access_aa64_tid3,
8186 .resetvalue = cpu->id_aa64afr1 },
8187 { .name = "ID_AA64AFR2_EL1_RESERVED", .state = ARM_CP_STATE_AA64,
8188 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 5, .opc2 = 6,
8189 .access = PL1_R, .type = ARM_CP_CONST,
8190 .accessfn = access_aa64_tid3,
8191 .resetvalue = 0 },
8192 { .name = "ID_AA64AFR3_EL1_RESERVED", .state = ARM_CP_STATE_AA64,
8193 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 5, .opc2 = 7,
8194 .access = PL1_R, .type = ARM_CP_CONST,
8195 .accessfn = access_aa64_tid3,
8196 .resetvalue = 0 },
8197 { .name = "ID_AA64ISAR0_EL1", .state = ARM_CP_STATE_AA64,
8198 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 6, .opc2 = 0,
8199 .access = PL1_R, .type = ARM_CP_CONST,
8200 .accessfn = access_aa64_tid3,
8201 .resetvalue = cpu->isar.id_aa64isar0 },
8202 { .name = "ID_AA64ISAR1_EL1", .state = ARM_CP_STATE_AA64,
8203 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 6, .opc2 = 1,
8204 .access = PL1_R, .type = ARM_CP_CONST,
8205 .accessfn = access_aa64_tid3,
8206 .resetvalue = cpu->isar.id_aa64isar1 },
8207 { .name = "ID_AA64ISAR2_EL1_RESERVED", .state = ARM_CP_STATE_AA64,
8208 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 6, .opc2 = 2,
8209 .access = PL1_R, .type = ARM_CP_CONST,
8210 .accessfn = access_aa64_tid3,
8211 .resetvalue = 0 },
8212 { .name = "ID_AA64ISAR3_EL1_RESERVED", .state = ARM_CP_STATE_AA64,
8213 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 6, .opc2 = 3,
8214 .access = PL1_R, .type = ARM_CP_CONST,
8215 .accessfn = access_aa64_tid3,
8216 .resetvalue = 0 },
8217 { .name = "ID_AA64ISAR4_EL1_RESERVED", .state = ARM_CP_STATE_AA64,
8218 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 6, .opc2 = 4,
8219 .access = PL1_R, .type = ARM_CP_CONST,
8220 .accessfn = access_aa64_tid3,
8221 .resetvalue = 0 },
8222 { .name = "ID_AA64ISAR5_EL1_RESERVED", .state = ARM_CP_STATE_AA64,
8223 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 6, .opc2 = 5,
8224 .access = PL1_R, .type = ARM_CP_CONST,
8225 .accessfn = access_aa64_tid3,
8226 .resetvalue = 0 },
8227 { .name = "ID_AA64ISAR6_EL1_RESERVED", .state = ARM_CP_STATE_AA64,
8228 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 6, .opc2 = 6,
8229 .access = PL1_R, .type = ARM_CP_CONST,
8230 .accessfn = access_aa64_tid3,
8231 .resetvalue = 0 },
8232 { .name = "ID_AA64ISAR7_EL1_RESERVED", .state = ARM_CP_STATE_AA64,
8233 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 6, .opc2 = 7,
8234 .access = PL1_R, .type = ARM_CP_CONST,
8235 .accessfn = access_aa64_tid3,
8236 .resetvalue = 0 },
8237 { .name = "ID_AA64MMFR0_EL1", .state = ARM_CP_STATE_AA64,
8238 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 7, .opc2 = 0,
8239 .access = PL1_R, .type = ARM_CP_CONST,
8240 .accessfn = access_aa64_tid3,
8241 .resetvalue = cpu->isar.id_aa64mmfr0 },
8242 { .name = "ID_AA64MMFR1_EL1", .state = ARM_CP_STATE_AA64,
8243 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 7, .opc2 = 1,
8244 .access = PL1_R, .type = ARM_CP_CONST,
8245 .accessfn = access_aa64_tid3,
8246 .resetvalue = cpu->isar.id_aa64mmfr1 },
8247 { .name = "ID_AA64MMFR2_EL1", .state = ARM_CP_STATE_AA64,
8248 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 7, .opc2 = 2,
8249 .access = PL1_R, .type = ARM_CP_CONST,
8250 .accessfn = access_aa64_tid3,
8251 .resetvalue = cpu->isar.id_aa64mmfr2 },
8252 { .name = "ID_AA64MMFR3_EL1_RESERVED", .state = ARM_CP_STATE_AA64,
8253 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 7, .opc2 = 3,
8254 .access = PL1_R, .type = ARM_CP_CONST,
8255 .accessfn = access_aa64_tid3,
8256 .resetvalue = 0 },
8257 { .name = "ID_AA64MMFR4_EL1_RESERVED", .state = ARM_CP_STATE_AA64,
8258 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 7, .opc2 = 4,
8259 .access = PL1_R, .type = ARM_CP_CONST,
8260 .accessfn = access_aa64_tid3,
8261 .resetvalue = 0 },
8262 { .name = "ID_AA64MMFR5_EL1_RESERVED", .state = ARM_CP_STATE_AA64,
8263 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 7, .opc2 = 5,
8264 .access = PL1_R, .type = ARM_CP_CONST,
8265 .accessfn = access_aa64_tid3,
8266 .resetvalue = 0 },
8267 { .name = "ID_AA64MMFR6_EL1_RESERVED", .state = ARM_CP_STATE_AA64,
8268 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 7, .opc2 = 6,
8269 .access = PL1_R, .type = ARM_CP_CONST,
8270 .accessfn = access_aa64_tid3,
8271 .resetvalue = 0 },
8272 { .name = "ID_AA64MMFR7_EL1_RESERVED", .state = ARM_CP_STATE_AA64,
8273 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 7, .opc2 = 7,
8274 .access = PL1_R, .type = ARM_CP_CONST,
8275 .accessfn = access_aa64_tid3,
8276 .resetvalue = 0 },
8277 { .name = "MVFR0_EL1", .state = ARM_CP_STATE_AA64,
8278 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 3, .opc2 = 0,
8279 .access = PL1_R, .type = ARM_CP_CONST,
8280 .accessfn = access_aa64_tid3,
8281 .resetvalue = cpu->isar.mvfr0 },
8282 { .name = "MVFR1_EL1", .state = ARM_CP_STATE_AA64,
8283 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 3, .opc2 = 1,
8284 .access = PL1_R, .type = ARM_CP_CONST,
8285 .accessfn = access_aa64_tid3,
8286 .resetvalue = cpu->isar.mvfr1 },
8287 { .name = "MVFR2_EL1", .state = ARM_CP_STATE_AA64,
8288 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 3, .opc2 = 2,
8289 .access = PL1_R, .type = ARM_CP_CONST,
8290 .accessfn = access_aa64_tid3,
8291 .resetvalue = cpu->isar.mvfr2 },
8292
8293
8294
8295
8296
8297
8298 { .name = "RES_0_C0_C3_0", .state = ARM_CP_STATE_AA32,
8299 .cp = 15, .opc1 = 0, .crn = 0, .crm = 3, .opc2 = 0,
8300 .access = PL1_R, .type = ARM_CP_CONST,
8301 .accessfn = access_aa64_tid3,
8302 .resetvalue = 0 },
8303 { .name = "RES_0_C0_C3_1", .state = ARM_CP_STATE_AA32,
8304 .cp = 15, .opc1 = 0, .crn = 0, .crm = 3, .opc2 = 1,
8305 .access = PL1_R, .type = ARM_CP_CONST,
8306 .accessfn = access_aa64_tid3,
8307 .resetvalue = 0 },
8308 { .name = "RES_0_C0_C3_2", .state = ARM_CP_STATE_AA32,
8309 .cp = 15, .opc1 = 0, .crn = 0, .crm = 3, .opc2 = 2,
8310 .access = PL1_R, .type = ARM_CP_CONST,
8311 .accessfn = access_aa64_tid3,
8312 .resetvalue = 0 },
8313
8314
8315
8316
8317
8318
8319 { .name = "RES_0_C0_C3_3", .state = ARM_CP_STATE_BOTH,
8320 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 3, .opc2 = 3,
8321 .access = PL1_R, .type = ARM_CP_CONST,
8322 .accessfn = access_aa64_tid3,
8323 .resetvalue = 0 },
8324 { .name = "ID_PFR2", .state = ARM_CP_STATE_BOTH,
8325 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 3, .opc2 = 4,
8326 .access = PL1_R, .type = ARM_CP_CONST,
8327 .accessfn = access_aa64_tid3,
8328 .resetvalue = cpu->isar.id_pfr2 },
8329 { .name = "ID_DFR1", .state = ARM_CP_STATE_BOTH,
8330 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 3, .opc2 = 5,
8331 .access = PL1_R, .type = ARM_CP_CONST,
8332 .accessfn = access_aa64_tid3,
8333 .resetvalue = cpu->isar.id_dfr1 },
8334 { .name = "ID_MMFR5", .state = ARM_CP_STATE_BOTH,
8335 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 3, .opc2 = 6,
8336 .access = PL1_R, .type = ARM_CP_CONST,
8337 .accessfn = access_aa64_tid3,
8338 .resetvalue = cpu->isar.id_mmfr5 },
8339 { .name = "RES_0_C0_C3_7", .state = ARM_CP_STATE_BOTH,
8340 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 3, .opc2 = 7,
8341 .access = PL1_R, .type = ARM_CP_CONST,
8342 .accessfn = access_aa64_tid3,
8343 .resetvalue = 0 },
8344 { .name = "PMCEID0", .state = ARM_CP_STATE_AA32,
8345 .cp = 15, .opc1 = 0, .crn = 9, .crm = 12, .opc2 = 6,
8346 .access = PL0_R, .accessfn = pmreg_access, .type = ARM_CP_CONST,
8347 .fgt = FGT_PMCEIDN_EL0,
8348 .resetvalue = extract64(cpu->pmceid0, 0, 32) },
8349 { .name = "PMCEID0_EL0", .state = ARM_CP_STATE_AA64,
8350 .opc0 = 3, .opc1 = 3, .crn = 9, .crm = 12, .opc2 = 6,
8351 .access = PL0_R, .accessfn = pmreg_access, .type = ARM_CP_CONST,
8352 .fgt = FGT_PMCEIDN_EL0,
8353 .resetvalue = cpu->pmceid0 },
8354 { .name = "PMCEID1", .state = ARM_CP_STATE_AA32,
8355 .cp = 15, .opc1 = 0, .crn = 9, .crm = 12, .opc2 = 7,
8356 .access = PL0_R, .accessfn = pmreg_access, .type = ARM_CP_CONST,
8357 .fgt = FGT_PMCEIDN_EL0,
8358 .resetvalue = extract64(cpu->pmceid1, 0, 32) },
8359 { .name = "PMCEID1_EL0", .state = ARM_CP_STATE_AA64,
8360 .opc0 = 3, .opc1 = 3, .crn = 9, .crm = 12, .opc2 = 7,
8361 .access = PL0_R, .accessfn = pmreg_access, .type = ARM_CP_CONST,
8362 .fgt = FGT_PMCEIDN_EL0,
8363 .resetvalue = cpu->pmceid1 },
8364 };
8365#ifdef CONFIG_USER_ONLY
8366 static const ARMCPRegUserSpaceInfo v8_user_idregs[] = {
8367 { .name = "ID_AA64PFR0_EL1",
8368 .exported_bits = R_ID_AA64PFR0_FP_MASK |
8369 R_ID_AA64PFR0_ADVSIMD_MASK |
8370 R_ID_AA64PFR0_SVE_MASK |
8371 R_ID_AA64PFR0_DIT_MASK,
8372 .fixed_bits = (0x1u << R_ID_AA64PFR0_EL0_SHIFT) |
8373 (0x1u << R_ID_AA64PFR0_EL1_SHIFT) },
8374 { .name = "ID_AA64PFR1_EL1",
8375 .exported_bits = R_ID_AA64PFR1_BT_MASK |
8376 R_ID_AA64PFR1_SSBS_MASK |
8377 R_ID_AA64PFR1_MTE_MASK |
8378 R_ID_AA64PFR1_SME_MASK },
8379 { .name = "ID_AA64PFR*_EL1_RESERVED",
8380 .is_glob = true },
8381 { .name = "ID_AA64ZFR0_EL1",
8382 .exported_bits = R_ID_AA64ZFR0_SVEVER_MASK |
8383 R_ID_AA64ZFR0_AES_MASK |
8384 R_ID_AA64ZFR0_BITPERM_MASK |
8385 R_ID_AA64ZFR0_BFLOAT16_MASK |
8386 R_ID_AA64ZFR0_SHA3_MASK |
8387 R_ID_AA64ZFR0_SM4_MASK |
8388 R_ID_AA64ZFR0_I8MM_MASK |
8389 R_ID_AA64ZFR0_F32MM_MASK |
8390 R_ID_AA64ZFR0_F64MM_MASK },
8391 { .name = "ID_AA64SMFR0_EL1",
8392 .exported_bits = R_ID_AA64SMFR0_F32F32_MASK |
8393 R_ID_AA64SMFR0_B16F32_MASK |
8394 R_ID_AA64SMFR0_F16F32_MASK |
8395 R_ID_AA64SMFR0_I8I32_MASK |
8396 R_ID_AA64SMFR0_F64F64_MASK |
8397 R_ID_AA64SMFR0_I16I64_MASK |
8398 R_ID_AA64SMFR0_FA64_MASK },
8399 { .name = "ID_AA64MMFR0_EL1",
8400 .exported_bits = R_ID_AA64MMFR0_ECV_MASK,
8401 .fixed_bits = (0xfu << R_ID_AA64MMFR0_TGRAN64_SHIFT) |
8402 (0xfu << R_ID_AA64MMFR0_TGRAN4_SHIFT) },
8403 { .name = "ID_AA64MMFR1_EL1",
8404 .exported_bits = R_ID_AA64MMFR1_AFP_MASK },
8405 { .name = "ID_AA64MMFR2_EL1",
8406 .exported_bits = R_ID_AA64MMFR2_AT_MASK },
8407 { .name = "ID_AA64MMFR*_EL1_RESERVED",
8408 .is_glob = true },
8409 { .name = "ID_AA64DFR0_EL1",
8410 .fixed_bits = (0x6u << R_ID_AA64DFR0_DEBUGVER_SHIFT) },
8411 { .name = "ID_AA64DFR1_EL1" },
8412 { .name = "ID_AA64DFR*_EL1_RESERVED",
8413 .is_glob = true },
8414 { .name = "ID_AA64AFR*",
8415 .is_glob = true },
8416 { .name = "ID_AA64ISAR0_EL1",
8417 .exported_bits = R_ID_AA64ISAR0_AES_MASK |
8418 R_ID_AA64ISAR0_SHA1_MASK |
8419 R_ID_AA64ISAR0_SHA2_MASK |
8420 R_ID_AA64ISAR0_CRC32_MASK |
8421 R_ID_AA64ISAR0_ATOMIC_MASK |
8422 R_ID_AA64ISAR0_RDM_MASK |
8423 R_ID_AA64ISAR0_SHA3_MASK |
8424 R_ID_AA64ISAR0_SM3_MASK |
8425 R_ID_AA64ISAR0_SM4_MASK |
8426 R_ID_AA64ISAR0_DP_MASK |
8427 R_ID_AA64ISAR0_FHM_MASK |
8428 R_ID_AA64ISAR0_TS_MASK |
8429 R_ID_AA64ISAR0_RNDR_MASK },
8430 { .name = "ID_AA64ISAR1_EL1",
8431 .exported_bits = R_ID_AA64ISAR1_DPB_MASK |
8432 R_ID_AA64ISAR1_APA_MASK |
8433 R_ID_AA64ISAR1_API_MASK |
8434 R_ID_AA64ISAR1_JSCVT_MASK |
8435 R_ID_AA64ISAR1_FCMA_MASK |
8436 R_ID_AA64ISAR1_LRCPC_MASK |
8437 R_ID_AA64ISAR1_GPA_MASK |
8438 R_ID_AA64ISAR1_GPI_MASK |
8439 R_ID_AA64ISAR1_FRINTTS_MASK |
8440 R_ID_AA64ISAR1_SB_MASK |
8441 R_ID_AA64ISAR1_BF16_MASK |
8442 R_ID_AA64ISAR1_DGH_MASK |
8443 R_ID_AA64ISAR1_I8MM_MASK },
8444 { .name = "ID_AA64ISAR2_EL1",
8445 .exported_bits = R_ID_AA64ISAR2_WFXT_MASK |
8446 R_ID_AA64ISAR2_RPRES_MASK |
8447 R_ID_AA64ISAR2_GPA3_MASK |
8448 R_ID_AA64ISAR2_APA3_MASK },
8449 { .name = "ID_AA64ISAR*_EL1_RESERVED",
8450 .is_glob = true },
8451 };
8452 modify_arm_cp_regs(v8_idregs, v8_user_idregs);
8453#endif
8454
8455 if (!arm_feature(env, ARM_FEATURE_EL3) &&
8456 !arm_feature(env, ARM_FEATURE_EL2)) {
8457 ARMCPRegInfo rvbar = {
8458 .name = "RVBAR_EL1", .state = ARM_CP_STATE_BOTH,
8459 .opc0 = 3, .opc1 = 0, .crn = 12, .crm = 0, .opc2 = 1,
8460 .access = PL1_R,
8461 .fieldoffset = offsetof(CPUARMState, cp15.rvbar),
8462 };
8463 define_one_arm_cp_reg(cpu, &rvbar);
8464 }
8465 define_arm_cp_regs(cpu, v8_idregs);
8466 define_arm_cp_regs(cpu, v8_cp_reginfo);
8467
8468 for (i = 4; i < 16; i++) {
8469
8470
8471
8472
8473
8474
8475
8476
8477
8478
8479
8480 g_autofree char *name = g_strdup_printf("RES_0_C0_C%d_X", i);
8481 ARMCPRegInfo v8_aa32_raz_idregs = {
8482 .name = name,
8483 .state = ARM_CP_STATE_AA32,
8484 .cp = 15, .opc1 = 0, .crn = 0, .crm = i, .opc2 = CP_ANY,
8485 .access = PL1_R, .type = ARM_CP_CONST,
8486 .accessfn = access_aa64_tid3,
8487 .resetvalue = 0 };
8488 define_one_arm_cp_reg(cpu, &v8_aa32_raz_idregs);
8489 }
8490 }
8491
8492
8493
8494
8495
8496
8497
8498
8499 if (arm_feature(env, ARM_FEATURE_EL2)
8500 || (arm_feature(env, ARM_FEATURE_EL3)
8501 && arm_feature(env, ARM_FEATURE_V8))) {
8502 uint64_t vmpidr_def = mpidr_read_val(env);
8503 ARMCPRegInfo vpidr_regs[] = {
8504 { .name = "VPIDR", .state = ARM_CP_STATE_AA32,
8505 .cp = 15, .opc1 = 4, .crn = 0, .crm = 0, .opc2 = 0,
8506 .access = PL2_RW, .accessfn = access_el3_aa32ns,
8507 .resetvalue = cpu->midr,
8508 .type = ARM_CP_ALIAS | ARM_CP_EL3_NO_EL2_C_NZ,
8509 .fieldoffset = offsetoflow32(CPUARMState, cp15.vpidr_el2) },
8510 { .name = "VPIDR_EL2", .state = ARM_CP_STATE_AA64,
8511 .opc0 = 3, .opc1 = 4, .crn = 0, .crm = 0, .opc2 = 0,
8512 .access = PL2_RW, .resetvalue = cpu->midr,
8513 .type = ARM_CP_EL3_NO_EL2_C_NZ,
8514 .fieldoffset = offsetof(CPUARMState, cp15.vpidr_el2) },
8515 { .name = "VMPIDR", .state = ARM_CP_STATE_AA32,
8516 .cp = 15, .opc1 = 4, .crn = 0, .crm = 0, .opc2 = 5,
8517 .access = PL2_RW, .accessfn = access_el3_aa32ns,
8518 .resetvalue = vmpidr_def,
8519 .type = ARM_CP_ALIAS | ARM_CP_EL3_NO_EL2_C_NZ,
8520 .fieldoffset = offsetoflow32(CPUARMState, cp15.vmpidr_el2) },
8521 { .name = "VMPIDR_EL2", .state = ARM_CP_STATE_AA64,
8522 .opc0 = 3, .opc1 = 4, .crn = 0, .crm = 0, .opc2 = 5,
8523 .access = PL2_RW, .resetvalue = vmpidr_def,
8524 .type = ARM_CP_EL3_NO_EL2_C_NZ,
8525 .fieldoffset = offsetof(CPUARMState, cp15.vmpidr_el2) },
8526 };
8527
8528
8529
8530
8531 ARMCPRegInfo mdcr_el2 = {
8532 .name = "MDCR_EL2", .state = ARM_CP_STATE_BOTH, .type = ARM_CP_IO,
8533 .opc0 = 3, .opc1 = 4, .crn = 1, .crm = 1, .opc2 = 1,
8534 .writefn = mdcr_el2_write,
8535 .access = PL2_RW, .resetvalue = pmu_num_counters(env),
8536 .fieldoffset = offsetof(CPUARMState, cp15.mdcr_el2),
8537 };
8538 define_one_arm_cp_reg(cpu, &mdcr_el2);
8539 define_arm_cp_regs(cpu, vpidr_regs);
8540 define_arm_cp_regs(cpu, el2_cp_reginfo);
8541 if (arm_feature(env, ARM_FEATURE_V8)) {
8542 define_arm_cp_regs(cpu, el2_v8_cp_reginfo);
8543 }
8544 if (cpu_isar_feature(aa64_sel2, cpu)) {
8545 define_arm_cp_regs(cpu, el2_sec_cp_reginfo);
8546 }
8547
8548 if (!arm_feature(env, ARM_FEATURE_EL3)) {
8549 ARMCPRegInfo rvbar[] = {
8550 {
8551 .name = "RVBAR_EL2", .state = ARM_CP_STATE_AA64,
8552 .opc0 = 3, .opc1 = 4, .crn = 12, .crm = 0, .opc2 = 1,
8553 .access = PL2_R,
8554 .fieldoffset = offsetof(CPUARMState, cp15.rvbar),
8555 },
8556 { .name = "RVBAR", .type = ARM_CP_ALIAS,
8557 .cp = 15, .opc1 = 0, .crn = 12, .crm = 0, .opc2 = 1,
8558 .access = PL2_R,
8559 .fieldoffset = offsetof(CPUARMState, cp15.rvbar),
8560 },
8561 };
8562 define_arm_cp_regs(cpu, rvbar);
8563 }
8564 }
8565
8566
8567 if (arm_feature(env, ARM_FEATURE_EL3)) {
8568 define_arm_cp_regs(cpu, el3_cp_reginfo);
8569 ARMCPRegInfo el3_regs[] = {
8570 { .name = "RVBAR_EL3", .state = ARM_CP_STATE_AA64,
8571 .opc0 = 3, .opc1 = 6, .crn = 12, .crm = 0, .opc2 = 1,
8572 .access = PL3_R,
8573 .fieldoffset = offsetof(CPUARMState, cp15.rvbar),
8574 },
8575 { .name = "SCTLR_EL3", .state = ARM_CP_STATE_AA64,
8576 .opc0 = 3, .opc1 = 6, .crn = 1, .crm = 0, .opc2 = 0,
8577 .access = PL3_RW,
8578 .raw_writefn = raw_write, .writefn = sctlr_write,
8579 .fieldoffset = offsetof(CPUARMState, cp15.sctlr_el[3]),
8580 .resetvalue = cpu->reset_sctlr },
8581 };
8582
8583 define_arm_cp_regs(cpu, el3_regs);
8584 }
8585
8586
8587
8588
8589
8590
8591
8592
8593
8594 if (arm_feature(env, ARM_FEATURE_EL3)) {
8595 if (arm_feature(env, ARM_FEATURE_AARCH64)) {
8596 static const ARMCPRegInfo nsacr = {
8597 .name = "NSACR", .type = ARM_CP_CONST,
8598 .cp = 15, .opc1 = 0, .crn = 1, .crm = 1, .opc2 = 2,
8599 .access = PL1_RW, .accessfn = nsacr_access,
8600 .resetvalue = 0xc00
8601 };
8602 define_one_arm_cp_reg(cpu, &nsacr);
8603 } else {
8604 static const ARMCPRegInfo nsacr = {
8605 .name = "NSACR",
8606 .cp = 15, .opc1 = 0, .crn = 1, .crm = 1, .opc2 = 2,
8607 .access = PL3_RW | PL1_R,
8608 .resetvalue = 0,
8609 .fieldoffset = offsetof(CPUARMState, cp15.nsacr)
8610 };
8611 define_one_arm_cp_reg(cpu, &nsacr);
8612 }
8613 } else {
8614 if (arm_feature(env, ARM_FEATURE_V8)) {
8615 static const ARMCPRegInfo nsacr = {
8616 .name = "NSACR", .type = ARM_CP_CONST,
8617 .cp = 15, .opc1 = 0, .crn = 1, .crm = 1, .opc2 = 2,
8618 .access = PL1_R,
8619 .resetvalue = 0xc00
8620 };
8621 define_one_arm_cp_reg(cpu, &nsacr);
8622 }
8623 }
8624
8625 if (arm_feature(env, ARM_FEATURE_PMSA)) {
8626 if (arm_feature(env, ARM_FEATURE_V6)) {
8627
8628 assert(arm_feature(env, ARM_FEATURE_V7));
8629 define_arm_cp_regs(cpu, vmsa_pmsa_cp_reginfo);
8630 define_arm_cp_regs(cpu, pmsav7_cp_reginfo);
8631 } else {
8632 define_arm_cp_regs(cpu, pmsav5_cp_reginfo);
8633 }
8634 } else {
8635 define_arm_cp_regs(cpu, vmsa_pmsa_cp_reginfo);
8636 define_arm_cp_regs(cpu, vmsa_cp_reginfo);
8637
8638 if (cpu_isar_feature(aa32_hpd, cpu)) {
8639 define_one_arm_cp_reg(cpu, &ttbcr2_reginfo);
8640 }
8641 }
8642 if (arm_feature(env, ARM_FEATURE_THUMB2EE)) {
8643 define_arm_cp_regs(cpu, t2ee_cp_reginfo);
8644 }
8645 if (arm_feature(env, ARM_FEATURE_GENERIC_TIMER)) {
8646 define_arm_cp_regs(cpu, generic_timer_cp_reginfo);
8647 }
8648 if (arm_feature(env, ARM_FEATURE_VAPA)) {
8649 define_arm_cp_regs(cpu, vapa_cp_reginfo);
8650 }
8651 if (arm_feature(env, ARM_FEATURE_CACHE_TEST_CLEAN)) {
8652 define_arm_cp_regs(cpu, cache_test_clean_cp_reginfo);
8653 }
8654 if (arm_feature(env, ARM_FEATURE_CACHE_DIRTY_REG)) {
8655 define_arm_cp_regs(cpu, cache_dirty_status_cp_reginfo);
8656 }
8657 if (arm_feature(env, ARM_FEATURE_CACHE_BLOCK_OPS)) {
8658 define_arm_cp_regs(cpu, cache_block_ops_cp_reginfo);
8659 }
8660 if (arm_feature(env, ARM_FEATURE_OMAPCP)) {
8661 define_arm_cp_regs(cpu, omap_cp_reginfo);
8662 }
8663 if (arm_feature(env, ARM_FEATURE_STRONGARM)) {
8664 define_arm_cp_regs(cpu, strongarm_cp_reginfo);
8665 }
8666 if (arm_feature(env, ARM_FEATURE_XSCALE)) {
8667 define_arm_cp_regs(cpu, xscale_cp_reginfo);
8668 }
8669 if (arm_feature(env, ARM_FEATURE_DUMMY_C15_REGS)) {
8670 define_arm_cp_regs(cpu, dummy_c15_cp_reginfo);
8671 }
8672 if (arm_feature(env, ARM_FEATURE_LPAE)) {
8673 define_arm_cp_regs(cpu, lpae_cp_reginfo);
8674 }
8675 if (cpu_isar_feature(aa32_jazelle, cpu)) {
8676 define_arm_cp_regs(cpu, jazelle_regs);
8677 }
8678
8679
8680
8681
8682
8683 {
8684 ARMCPRegInfo id_pre_v8_midr_cp_reginfo[] = {
8685
8686
8687
8688
8689
8690
8691
8692
8693
8694
8695 { .name = "MIDR",
8696 .cp = 15, .crn = 0, .crm = 0, .opc1 = 0, .opc2 = CP_ANY,
8697 .access = PL1_R, .resetvalue = cpu->midr,
8698 .writefn = arm_cp_write_ignore, .raw_writefn = raw_write,
8699 .readfn = midr_read,
8700 .fieldoffset = offsetof(CPUARMState, cp15.c0_cpuid),
8701 .type = ARM_CP_OVERRIDE },
8702
8703 { .name = "DUMMY",
8704 .cp = 15, .crn = 0, .crm = 3, .opc1 = 0, .opc2 = CP_ANY,
8705 .access = PL1_R, .type = ARM_CP_CONST, .resetvalue = 0 },
8706 { .name = "DUMMY",
8707 .cp = 15, .crn = 0, .crm = 4, .opc1 = 0, .opc2 = CP_ANY,
8708 .access = PL1_R, .type = ARM_CP_CONST, .resetvalue = 0 },
8709 { .name = "DUMMY",
8710 .cp = 15, .crn = 0, .crm = 5, .opc1 = 0, .opc2 = CP_ANY,
8711 .access = PL1_R, .type = ARM_CP_CONST, .resetvalue = 0 },
8712 { .name = "DUMMY",
8713 .cp = 15, .crn = 0, .crm = 6, .opc1 = 0, .opc2 = CP_ANY,
8714 .access = PL1_R, .type = ARM_CP_CONST, .resetvalue = 0 },
8715 { .name = "DUMMY",
8716 .cp = 15, .crn = 0, .crm = 7, .opc1 = 0, .opc2 = CP_ANY,
8717 .access = PL1_R, .type = ARM_CP_CONST, .resetvalue = 0 },
8718 };
8719 ARMCPRegInfo id_v8_midr_cp_reginfo[] = {
8720 { .name = "MIDR_EL1", .state = ARM_CP_STATE_BOTH,
8721 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 0, .opc2 = 0,
8722 .access = PL1_R, .type = ARM_CP_NO_RAW, .resetvalue = cpu->midr,
8723 .fgt = FGT_MIDR_EL1,
8724 .fieldoffset = offsetof(CPUARMState, cp15.c0_cpuid),
8725 .readfn = midr_read },
8726
8727 { .name = "MIDR", .type = ARM_CP_ALIAS | ARM_CP_CONST,
8728 .cp = 15, .crn = 0, .crm = 0, .opc1 = 0, .opc2 = 7,
8729 .access = PL1_R, .resetvalue = cpu->midr },
8730 { .name = "REVIDR_EL1", .state = ARM_CP_STATE_BOTH,
8731 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 0, .opc2 = 6,
8732 .access = PL1_R,
8733 .accessfn = access_aa64_tid1,
8734 .fgt = FGT_REVIDR_EL1,
8735 .type = ARM_CP_CONST, .resetvalue = cpu->revidr },
8736 };
8737 ARMCPRegInfo id_v8_midr_alias_cp_reginfo = {
8738 .name = "MIDR", .type = ARM_CP_ALIAS | ARM_CP_CONST,
8739 .cp = 15, .crn = 0, .crm = 0, .opc1 = 0, .opc2 = 4,
8740 .access = PL1_R, .resetvalue = cpu->midr
8741 };
8742 ARMCPRegInfo id_cp_reginfo[] = {
8743
8744 { .name = "CTR",
8745 .cp = 15, .crn = 0, .crm = 0, .opc1 = 0, .opc2 = 1,
8746 .access = PL1_R, .accessfn = ctr_el0_access,
8747 .type = ARM_CP_CONST, .resetvalue = cpu->ctr },
8748 { .name = "CTR_EL0", .state = ARM_CP_STATE_AA64,
8749 .opc0 = 3, .opc1 = 3, .opc2 = 1, .crn = 0, .crm = 0,
8750 .access = PL0_R, .accessfn = ctr_el0_access,
8751 .fgt = FGT_CTR_EL0,
8752 .type = ARM_CP_CONST, .resetvalue = cpu->ctr },
8753
8754 { .name = "TCMTR",
8755 .cp = 15, .crn = 0, .crm = 0, .opc1 = 0, .opc2 = 2,
8756 .access = PL1_R,
8757 .accessfn = access_aa32_tid1,
8758 .type = ARM_CP_CONST, .resetvalue = 0 },
8759 };
8760
8761 ARMCPRegInfo id_tlbtr_reginfo = {
8762 .name = "TLBTR",
8763 .cp = 15, .crn = 0, .crm = 0, .opc1 = 0, .opc2 = 3,
8764 .access = PL1_R,
8765 .accessfn = access_aa32_tid1,
8766 .type = ARM_CP_CONST, .resetvalue = 0,
8767 };
8768
8769 ARMCPRegInfo id_mpuir_reginfo = {
8770 .name = "MPUIR",
8771 .cp = 15, .crn = 0, .crm = 0, .opc1 = 0, .opc2 = 4,
8772 .access = PL1_R, .type = ARM_CP_CONST,
8773 .resetvalue = cpu->pmsav7_dregion << 8
8774 };
8775
8776 ARMCPRegInfo id_hmpuir_reginfo = {
8777 .name = "HMPUIR",
8778 .cp = 15, .opc1 = 4, .crn = 0, .crm = 0, .opc2 = 4,
8779 .access = PL2_R, .type = ARM_CP_CONST,
8780 .resetvalue = cpu->pmsav8r_hdregion
8781 };
8782 static const ARMCPRegInfo crn0_wi_reginfo = {
8783 .name = "CRN0_WI", .cp = 15, .crn = 0, .crm = CP_ANY,
8784 .opc1 = CP_ANY, .opc2 = CP_ANY, .access = PL1_W,
8785 .type = ARM_CP_NOP | ARM_CP_OVERRIDE
8786 };
8787#ifdef CONFIG_USER_ONLY
8788 static const ARMCPRegUserSpaceInfo id_v8_user_midr_cp_reginfo[] = {
8789 { .name = "MIDR_EL1",
8790 .exported_bits = R_MIDR_EL1_REVISION_MASK |
8791 R_MIDR_EL1_PARTNUM_MASK |
8792 R_MIDR_EL1_ARCHITECTURE_MASK |
8793 R_MIDR_EL1_VARIANT_MASK |
8794 R_MIDR_EL1_IMPLEMENTER_MASK },
8795 { .name = "REVIDR_EL1" },
8796 };
8797 modify_arm_cp_regs(id_v8_midr_cp_reginfo, id_v8_user_midr_cp_reginfo);
8798#endif
8799 if (arm_feature(env, ARM_FEATURE_OMAPCP) ||
8800 arm_feature(env, ARM_FEATURE_STRONGARM)) {
8801 size_t i;
8802
8803
8804
8805
8806
8807
8808 define_one_arm_cp_reg(cpu, &crn0_wi_reginfo);
8809 for (i = 0; i < ARRAY_SIZE(id_pre_v8_midr_cp_reginfo); ++i) {
8810 id_pre_v8_midr_cp_reginfo[i].access = PL1_RW;
8811 }
8812 for (i = 0; i < ARRAY_SIZE(id_cp_reginfo); ++i) {
8813 id_cp_reginfo[i].access = PL1_RW;
8814 }
8815 id_mpuir_reginfo.access = PL1_RW;
8816 id_tlbtr_reginfo.access = PL1_RW;
8817 }
8818 if (arm_feature(env, ARM_FEATURE_V8)) {
8819 define_arm_cp_regs(cpu, id_v8_midr_cp_reginfo);
8820 if (!arm_feature(env, ARM_FEATURE_PMSA)) {
8821 define_one_arm_cp_reg(cpu, &id_v8_midr_alias_cp_reginfo);
8822 }
8823 } else {
8824 define_arm_cp_regs(cpu, id_pre_v8_midr_cp_reginfo);
8825 }
8826 define_arm_cp_regs(cpu, id_cp_reginfo);
8827 if (!arm_feature(env, ARM_FEATURE_PMSA)) {
8828 define_one_arm_cp_reg(cpu, &id_tlbtr_reginfo);
8829 } else if (arm_feature(env, ARM_FEATURE_PMSA) &&
8830 arm_feature(env, ARM_FEATURE_V8)) {
8831 uint32_t i = 0;
8832 char *tmp_string;
8833
8834 define_one_arm_cp_reg(cpu, &id_mpuir_reginfo);
8835 define_one_arm_cp_reg(cpu, &id_hmpuir_reginfo);
8836 define_arm_cp_regs(cpu, pmsav8r_cp_reginfo);
8837
8838
8839 for (i = 0; i < MIN(cpu->pmsav7_dregion, 32); ++i) {
8840 uint8_t crm = 0b1000 | extract32(i, 1, 3);
8841 uint8_t opc1 = extract32(i, 4, 1);
8842 uint8_t opc2 = extract32(i, 0, 1) << 2;
8843
8844 tmp_string = g_strdup_printf("PRBAR%u", i);
8845 ARMCPRegInfo tmp_prbarn_reginfo = {
8846 .name = tmp_string, .type = ARM_CP_ALIAS | ARM_CP_NO_RAW,
8847 .cp = 15, .opc1 = opc1, .crn = 6, .crm = crm, .opc2 = opc2,
8848 .access = PL1_RW, .resetvalue = 0,
8849 .accessfn = access_tvm_trvm,
8850 .writefn = pmsav8r_regn_write, .readfn = pmsav8r_regn_read
8851 };
8852 define_one_arm_cp_reg(cpu, &tmp_prbarn_reginfo);
8853 g_free(tmp_string);
8854
8855 opc2 = extract32(i, 0, 1) << 2 | 0x1;
8856 tmp_string = g_strdup_printf("PRLAR%u", i);
8857 ARMCPRegInfo tmp_prlarn_reginfo = {
8858 .name = tmp_string, .type = ARM_CP_ALIAS | ARM_CP_NO_RAW,
8859 .cp = 15, .opc1 = opc1, .crn = 6, .crm = crm, .opc2 = opc2,
8860 .access = PL1_RW, .resetvalue = 0,
8861 .accessfn = access_tvm_trvm,
8862 .writefn = pmsav8r_regn_write, .readfn = pmsav8r_regn_read
8863 };
8864 define_one_arm_cp_reg(cpu, &tmp_prlarn_reginfo);
8865 g_free(tmp_string);
8866 }
8867
8868
8869 for (i = 0; i < MIN(cpu->pmsav8r_hdregion, 32); ++i) {
8870 uint8_t crm = 0b1000 | extract32(i, 1, 3);
8871 uint8_t opc1 = 0b100 | extract32(i, 4, 1);
8872 uint8_t opc2 = extract32(i, 0, 1) << 2;
8873
8874 tmp_string = g_strdup_printf("HPRBAR%u", i);
8875 ARMCPRegInfo tmp_hprbarn_reginfo = {
8876 .name = tmp_string,
8877 .type = ARM_CP_NO_RAW,
8878 .cp = 15, .opc1 = opc1, .crn = 6, .crm = crm, .opc2 = opc2,
8879 .access = PL2_RW, .resetvalue = 0,
8880 .writefn = pmsav8r_regn_write, .readfn = pmsav8r_regn_read
8881 };
8882 define_one_arm_cp_reg(cpu, &tmp_hprbarn_reginfo);
8883 g_free(tmp_string);
8884
8885 opc2 = extract32(i, 0, 1) << 2 | 0x1;
8886 tmp_string = g_strdup_printf("HPRLAR%u", i);
8887 ARMCPRegInfo tmp_hprlarn_reginfo = {
8888 .name = tmp_string,
8889 .type = ARM_CP_NO_RAW,
8890 .cp = 15, .opc1 = opc1, .crn = 6, .crm = crm, .opc2 = opc2,
8891 .access = PL2_RW, .resetvalue = 0,
8892 .writefn = pmsav8r_regn_write, .readfn = pmsav8r_regn_read
8893 };
8894 define_one_arm_cp_reg(cpu, &tmp_hprlarn_reginfo);
8895 g_free(tmp_string);
8896 }
8897 } else if (arm_feature(env, ARM_FEATURE_V7)) {
8898 define_one_arm_cp_reg(cpu, &id_mpuir_reginfo);
8899 }
8900 }
8901
8902 if (arm_feature(env, ARM_FEATURE_MPIDR)) {
8903 ARMCPRegInfo mpidr_cp_reginfo[] = {
8904 { .name = "MPIDR_EL1", .state = ARM_CP_STATE_BOTH,
8905 .opc0 = 3, .crn = 0, .crm = 0, .opc1 = 0, .opc2 = 5,
8906 .fgt = FGT_MPIDR_EL1,
8907 .access = PL1_R, .readfn = mpidr_read, .type = ARM_CP_NO_RAW },
8908 };
8909#ifdef CONFIG_USER_ONLY
8910 static const ARMCPRegUserSpaceInfo mpidr_user_cp_reginfo[] = {
8911 { .name = "MPIDR_EL1",
8912 .fixed_bits = 0x0000000080000000 },
8913 };
8914 modify_arm_cp_regs(mpidr_cp_reginfo, mpidr_user_cp_reginfo);
8915#endif
8916 define_arm_cp_regs(cpu, mpidr_cp_reginfo);
8917 }
8918
8919 if (arm_feature(env, ARM_FEATURE_AUXCR)) {
8920 ARMCPRegInfo auxcr_reginfo[] = {
8921 { .name = "ACTLR_EL1", .state = ARM_CP_STATE_BOTH,
8922 .opc0 = 3, .opc1 = 0, .crn = 1, .crm = 0, .opc2 = 1,
8923 .access = PL1_RW, .accessfn = access_tacr,
8924 .type = ARM_CP_CONST, .resetvalue = cpu->reset_auxcr },
8925 { .name = "ACTLR_EL2", .state = ARM_CP_STATE_BOTH,
8926 .opc0 = 3, .opc1 = 4, .crn = 1, .crm = 0, .opc2 = 1,
8927 .access = PL2_RW, .type = ARM_CP_CONST,
8928 .resetvalue = 0 },
8929 { .name = "ACTLR_EL3", .state = ARM_CP_STATE_AA64,
8930 .opc0 = 3, .opc1 = 6, .crn = 1, .crm = 0, .opc2 = 1,
8931 .access = PL3_RW, .type = ARM_CP_CONST,
8932 .resetvalue = 0 },
8933 };
8934 define_arm_cp_regs(cpu, auxcr_reginfo);
8935 if (cpu_isar_feature(aa32_ac2, cpu)) {
8936 define_arm_cp_regs(cpu, actlr2_hactlr2_reginfo);
8937 }
8938 }
8939
8940 if (arm_feature(env, ARM_FEATURE_CBAR)) {
8941
8942
8943
8944
8945
8946
8947
8948
8949
8950
8951
8952
8953
8954 if (arm_feature(env, ARM_FEATURE_AARCH64)) {
8955
8956 uint32_t cbar32 = (extract64(cpu->reset_cbar, 18, 14) << 18)
8957 | extract64(cpu->reset_cbar, 32, 12);
8958 ARMCPRegInfo cbar_reginfo[] = {
8959 { .name = "CBAR",
8960 .type = ARM_CP_CONST,
8961 .cp = 15, .crn = 15, .crm = 3, .opc1 = 1, .opc2 = 0,
8962 .access = PL1_R, .resetvalue = cbar32 },
8963 { .name = "CBAR_EL1", .state = ARM_CP_STATE_AA64,
8964 .type = ARM_CP_CONST,
8965 .opc0 = 3, .opc1 = 1, .crn = 15, .crm = 3, .opc2 = 0,
8966 .access = PL1_R, .resetvalue = cpu->reset_cbar },
8967 };
8968
8969 assert(arm_feature(env, ARM_FEATURE_CBAR_RO));
8970 define_arm_cp_regs(cpu, cbar_reginfo);
8971 } else {
8972 ARMCPRegInfo cbar = {
8973 .name = "CBAR",
8974 .cp = 15, .crn = 15, .crm = 0, .opc1 = 4, .opc2 = 0,
8975 .access = PL1_R | PL3_W, .resetvalue = cpu->reset_cbar,
8976 .fieldoffset = offsetof(CPUARMState,
8977 cp15.c15_config_base_address)
8978 };
8979 if (arm_feature(env, ARM_FEATURE_CBAR_RO)) {
8980 cbar.access = PL1_R;
8981 cbar.fieldoffset = 0;
8982 cbar.type = ARM_CP_CONST;
8983 }
8984 define_one_arm_cp_reg(cpu, &cbar);
8985 }
8986 }
8987
8988 if (arm_feature(env, ARM_FEATURE_VBAR)) {
8989 static const ARMCPRegInfo vbar_cp_reginfo[] = {
8990 { .name = "VBAR", .state = ARM_CP_STATE_BOTH,
8991 .opc0 = 3, .crn = 12, .crm = 0, .opc1 = 0, .opc2 = 0,
8992 .access = PL1_RW, .writefn = vbar_write,
8993 .fgt = FGT_VBAR_EL1,
8994 .bank_fieldoffsets = { offsetof(CPUARMState, cp15.vbar_s),
8995 offsetof(CPUARMState, cp15.vbar_ns) },
8996 .resetvalue = 0 },
8997 };
8998 define_arm_cp_regs(cpu, vbar_cp_reginfo);
8999 }
9000
9001
9002 {
9003 ARMCPRegInfo sctlr = {
9004 .name = "SCTLR", .state = ARM_CP_STATE_BOTH,
9005 .opc0 = 3, .opc1 = 0, .crn = 1, .crm = 0, .opc2 = 0,
9006 .access = PL1_RW, .accessfn = access_tvm_trvm,
9007 .fgt = FGT_SCTLR_EL1,
9008 .bank_fieldoffsets = { offsetof(CPUARMState, cp15.sctlr_s),
9009 offsetof(CPUARMState, cp15.sctlr_ns) },
9010 .writefn = sctlr_write, .resetvalue = cpu->reset_sctlr,
9011 .raw_writefn = raw_write,
9012 };
9013 if (arm_feature(env, ARM_FEATURE_XSCALE)) {
9014
9015
9016
9017
9018
9019 sctlr.type |= ARM_CP_SUPPRESS_TB_END;
9020 }
9021 define_one_arm_cp_reg(cpu, &sctlr);
9022
9023 if (arm_feature(env, ARM_FEATURE_PMSA) &&
9024 arm_feature(env, ARM_FEATURE_V8)) {
9025 ARMCPRegInfo vsctlr = {
9026 .name = "VSCTLR", .state = ARM_CP_STATE_AA32,
9027 .cp = 15, .opc1 = 4, .crn = 2, .crm = 0, .opc2 = 0,
9028 .access = PL2_RW, .resetvalue = 0x0,
9029 .fieldoffset = offsetoflow32(CPUARMState, cp15.vsctlr),
9030 };
9031 define_one_arm_cp_reg(cpu, &vsctlr);
9032 }
9033 }
9034
9035 if (cpu_isar_feature(aa64_lor, cpu)) {
9036 define_arm_cp_regs(cpu, lor_reginfo);
9037 }
9038 if (cpu_isar_feature(aa64_pan, cpu)) {
9039 define_one_arm_cp_reg(cpu, &pan_reginfo);
9040 }
9041#ifndef CONFIG_USER_ONLY
9042 if (cpu_isar_feature(aa64_ats1e1, cpu)) {
9043 define_arm_cp_regs(cpu, ats1e1_reginfo);
9044 }
9045 if (cpu_isar_feature(aa32_ats1e1, cpu)) {
9046 define_arm_cp_regs(cpu, ats1cp_reginfo);
9047 }
9048#endif
9049 if (cpu_isar_feature(aa64_uao, cpu)) {
9050 define_one_arm_cp_reg(cpu, &uao_reginfo);
9051 }
9052
9053 if (cpu_isar_feature(aa64_dit, cpu)) {
9054 define_one_arm_cp_reg(cpu, &dit_reginfo);
9055 }
9056 if (cpu_isar_feature(aa64_ssbs, cpu)) {
9057 define_one_arm_cp_reg(cpu, &ssbs_reginfo);
9058 }
9059 if (cpu_isar_feature(any_ras, cpu)) {
9060 define_arm_cp_regs(cpu, minimal_ras_reginfo);
9061 }
9062
9063 if (cpu_isar_feature(aa64_vh, cpu) ||
9064 cpu_isar_feature(aa64_debugv8p2, cpu)) {
9065 define_one_arm_cp_reg(cpu, &contextidr_el2);
9066 }
9067 if (arm_feature(env, ARM_FEATURE_EL2) && cpu_isar_feature(aa64_vh, cpu)) {
9068 define_arm_cp_regs(cpu, vhe_reginfo);
9069 }
9070
9071 if (cpu_isar_feature(aa64_sve, cpu)) {
9072 define_arm_cp_regs(cpu, zcr_reginfo);
9073 }
9074
9075 if (cpu_isar_feature(aa64_hcx, cpu)) {
9076 define_one_arm_cp_reg(cpu, &hcrx_el2_reginfo);
9077 }
9078
9079#ifdef TARGET_AARCH64
9080 if (cpu_isar_feature(aa64_sme, cpu)) {
9081 define_arm_cp_regs(cpu, sme_reginfo);
9082 }
9083 if (cpu_isar_feature(aa64_pauth, cpu)) {
9084 define_arm_cp_regs(cpu, pauth_reginfo);
9085 }
9086 if (cpu_isar_feature(aa64_rndr, cpu)) {
9087 define_arm_cp_regs(cpu, rndr_reginfo);
9088 }
9089 if (cpu_isar_feature(aa64_tlbirange, cpu)) {
9090 define_arm_cp_regs(cpu, tlbirange_reginfo);
9091 }
9092 if (cpu_isar_feature(aa64_tlbios, cpu)) {
9093 define_arm_cp_regs(cpu, tlbios_reginfo);
9094 }
9095#ifndef CONFIG_USER_ONLY
9096
9097 if (cpu_isar_feature(aa64_dcpop, cpu)) {
9098 define_one_arm_cp_reg(cpu, dcpop_reg);
9099
9100 if (cpu_isar_feature(aa64_dcpodp, cpu)) {
9101 define_one_arm_cp_reg(cpu, dcpodp_reg);
9102 }
9103 }
9104#endif
9105
9106
9107
9108
9109
9110
9111 if (cpu_isar_feature(aa64_mte, cpu)) {
9112 define_arm_cp_regs(cpu, mte_reginfo);
9113 define_arm_cp_regs(cpu, mte_el0_cacheop_reginfo);
9114 } else if (cpu_isar_feature(aa64_mte_insn_reg, cpu)) {
9115 define_arm_cp_regs(cpu, mte_tco_ro_reginfo);
9116 define_arm_cp_regs(cpu, mte_el0_cacheop_reginfo);
9117 }
9118
9119 if (cpu_isar_feature(aa64_scxtnum, cpu)) {
9120 define_arm_cp_regs(cpu, scxtnum_reginfo);
9121 }
9122
9123 if (cpu_isar_feature(aa64_fgt, cpu)) {
9124 define_arm_cp_regs(cpu, fgt_reginfo);
9125 }
9126#endif
9127
9128 if (cpu_isar_feature(any_predinv, cpu)) {
9129 define_arm_cp_regs(cpu, predinv_reginfo);
9130 }
9131
9132 if (cpu_isar_feature(any_ccidx, cpu)) {
9133 define_arm_cp_regs(cpu, ccsidr2_reginfo);
9134 }
9135
9136#ifndef CONFIG_USER_ONLY
9137
9138
9139
9140
9141 if (arm_feature(env, ARM_FEATURE_EL2) && cpu_isar_feature(aa64_vh, cpu)) {
9142 define_arm_vh_e2h_redirects_aliases(cpu);
9143 }
9144#endif
9145}
9146
9147
9148static gint arm_cpu_list_compare(gconstpointer a, gconstpointer b)
9149{
9150 ObjectClass *class_a = (ObjectClass *)a;
9151 ObjectClass *class_b = (ObjectClass *)b;
9152 const char *name_a, *name_b;
9153
9154 name_a = object_class_get_name(class_a);
9155 name_b = object_class_get_name(class_b);
9156 if (strcmp(name_a, "any-" TYPE_ARM_CPU) == 0) {
9157 return 1;
9158 } else if (strcmp(name_b, "any-" TYPE_ARM_CPU) == 0) {
9159 return -1;
9160 } else {
9161 return strcmp(name_a, name_b);
9162 }
9163}
9164
9165static void arm_cpu_list_entry(gpointer data, gpointer user_data)
9166{
9167 ObjectClass *oc = data;
9168 CPUClass *cc = CPU_CLASS(oc);
9169 const char *typename;
9170 char *name;
9171
9172 typename = object_class_get_name(oc);
9173 name = g_strndup(typename, strlen(typename) - strlen("-" TYPE_ARM_CPU));
9174 if (cc->deprecation_note) {
9175 qemu_printf(" %s (deprecated)\n", name);
9176 } else {
9177 qemu_printf(" %s\n", name);
9178 }
9179 g_free(name);
9180}
9181
9182void arm_cpu_list(void)
9183{
9184 GSList *list;
9185
9186 list = object_class_get_list(TYPE_ARM_CPU, false);
9187 list = g_slist_sort(list, arm_cpu_list_compare);
9188 qemu_printf("Available CPUs:\n");
9189 g_slist_foreach(list, arm_cpu_list_entry, NULL);
9190 g_slist_free(list);
9191}
9192
9193
9194
9195
9196
9197static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
9198 void *opaque, CPState state,
9199 CPSecureState secstate,
9200 int crm, int opc1, int opc2,
9201 const char *name)
9202{
9203 CPUARMState *env = &cpu->env;
9204 uint32_t key;
9205 ARMCPRegInfo *r2;
9206 bool is64 = r->type & ARM_CP_64BIT;
9207 bool ns = secstate & ARM_CP_SECSTATE_NS;
9208 int cp = r->cp;
9209 size_t name_len;
9210 bool make_const;
9211
9212 switch (state) {
9213 case ARM_CP_STATE_AA32:
9214
9215 if (cp == 0 && r->state == ARM_CP_STATE_BOTH) {
9216 cp = 15;
9217 }
9218 key = ENCODE_CP_REG(cp, is64, ns, r->crn, crm, opc1, opc2);
9219 break;
9220 case ARM_CP_STATE_AA64:
9221
9222
9223
9224
9225
9226
9227
9228 if (cp == 0 || r->state == ARM_CP_STATE_BOTH) {
9229 cp = CP_REG_ARM64_SYSREG_CP;
9230 }
9231 key = ENCODE_AA64_CP_REG(cp, r->crn, crm, r->opc0, opc1, opc2);
9232 break;
9233 default:
9234 g_assert_not_reached();
9235 }
9236
9237
9238 if (!(r->type & ARM_CP_OVERRIDE)) {
9239 const ARMCPRegInfo *oldreg = get_arm_cp_reginfo(cpu->cp_regs, key);
9240 if (oldreg) {
9241 assert(oldreg->type & ARM_CP_OVERRIDE);
9242 }
9243 }
9244
9245
9246
9247
9248
9249
9250 make_const = false;
9251 if (arm_feature(env, ARM_FEATURE_EL3)) {
9252
9253
9254
9255
9256 int min_el = ctz32(r->access) / 2;
9257 if (min_el == 2 && !arm_feature(env, ARM_FEATURE_EL2)) {
9258 if (r->type & ARM_CP_EL3_NO_EL2_UNDEF) {
9259 return;
9260 }
9261 make_const = !(r->type & ARM_CP_EL3_NO_EL2_KEEP);
9262 }
9263 } else {
9264 CPAccessRights max_el = (arm_feature(env, ARM_FEATURE_EL2)
9265 ? PL2_RW : PL1_RW);
9266 if ((r->access & max_el) == 0) {
9267 return;
9268 }
9269 }
9270
9271
9272 name_len = strlen(name) + 1;
9273 r2 = g_malloc(sizeof(*r2) + name_len);
9274 *r2 = *r;
9275 r2->name = memcpy(r2 + 1, name, name_len);
9276
9277
9278
9279
9280
9281 r2->cp = cp;
9282 r2->crm = crm;
9283 r2->opc1 = opc1;
9284 r2->opc2 = opc2;
9285 r2->state = state;
9286 r2->secure = secstate;
9287 if (opaque) {
9288 r2->opaque = opaque;
9289 }
9290
9291 if (make_const) {
9292
9293 int old_special = r2->type & ARM_CP_SPECIAL_MASK;
9294 assert(old_special == 0 || old_special == ARM_CP_NOP);
9295
9296
9297
9298
9299
9300 r2->type = (r2->type & ~ARM_CP_SPECIAL_MASK) | ARM_CP_CONST;
9301
9302
9303
9304
9305
9306 if (!(r->type & ARM_CP_EL3_NO_EL2_C_NZ)) {
9307 r2->resetvalue = 0;
9308 }
9309
9310
9311
9312
9313
9314 r2->readfn = NULL;
9315 r2->writefn = NULL;
9316 r2->raw_readfn = NULL;
9317 r2->raw_writefn = NULL;
9318 r2->resetfn = NULL;
9319 r2->fieldoffset = 0;
9320 r2->bank_fieldoffsets[0] = 0;
9321 r2->bank_fieldoffsets[1] = 0;
9322 } else {
9323 bool isbanked = r->bank_fieldoffsets[0] && r->bank_fieldoffsets[1];
9324
9325 if (isbanked) {
9326
9327
9328
9329
9330
9331 r2->fieldoffset = r->bank_fieldoffsets[ns];
9332 }
9333 if (state == ARM_CP_STATE_AA32) {
9334 if (isbanked) {
9335
9336
9337
9338
9339
9340
9341
9342
9343
9344
9345
9346 if ((r->state == ARM_CP_STATE_BOTH && ns) ||
9347 (arm_feature(env, ARM_FEATURE_V8) && !ns)) {
9348 r2->type |= ARM_CP_ALIAS;
9349 }
9350 } else if ((secstate != r->secure) && !ns) {
9351
9352
9353
9354
9355 r2->type |= ARM_CP_ALIAS;
9356 }
9357
9358 if (HOST_BIG_ENDIAN &&
9359 r->state == ARM_CP_STATE_BOTH && r2->fieldoffset) {
9360 r2->fieldoffset += sizeof(uint32_t);
9361 }
9362 }
9363 }
9364
9365
9366
9367
9368
9369
9370
9371
9372 if (r2->type & ARM_CP_SPECIAL_MASK) {
9373 r2->type |= ARM_CP_NO_RAW;
9374 }
9375 if (((r->crm == CP_ANY) && crm != 0) ||
9376 ((r->opc1 == CP_ANY) && opc1 != 0) ||
9377 ((r->opc2 == CP_ANY) && opc2 != 0)) {
9378 r2->type |= ARM_CP_ALIAS | ARM_CP_NO_GDB;
9379 }
9380
9381
9382
9383
9384
9385
9386 if (!(r2->type & ARM_CP_NO_RAW)) {
9387 assert(!raw_accessors_invalid(r2));
9388 }
9389
9390 g_hash_table_insert(cpu->cp_regs, (gpointer)(uintptr_t)key, r2);
9391}
9392
9393
9394void define_one_arm_cp_reg_with_opaque(ARMCPU *cpu,
9395 const ARMCPRegInfo *r, void *opaque)
9396{
9397
9398
9399
9400
9401
9402
9403
9404
9405
9406
9407
9408
9409
9410
9411
9412
9413
9414
9415
9416
9417
9418
9419
9420
9421 int crm, opc1, opc2;
9422 int crmmin = (r->crm == CP_ANY) ? 0 : r->crm;
9423 int crmmax = (r->crm == CP_ANY) ? 15 : r->crm;
9424 int opc1min = (r->opc1 == CP_ANY) ? 0 : r->opc1;
9425 int opc1max = (r->opc1 == CP_ANY) ? 7 : r->opc1;
9426 int opc2min = (r->opc2 == CP_ANY) ? 0 : r->opc2;
9427 int opc2max = (r->opc2 == CP_ANY) ? 7 : r->opc2;
9428 CPState state;
9429
9430
9431 assert(!((r->type & ARM_CP_64BIT) && (r->opc2 || r->crn)));
9432
9433 assert((r->state != ARM_CP_STATE_AA32) || (r->opc0 == 0));
9434
9435 assert((r->state != ARM_CP_STATE_AA64) || !(r->type & ARM_CP_64BIT));
9436
9437
9438
9439
9440
9441
9442
9443
9444 switch (r->state) {
9445 case ARM_CP_STATE_BOTH:
9446
9447 if (r->cp == 0) {
9448 break;
9449 }
9450
9451 case ARM_CP_STATE_AA32:
9452 if (arm_feature(&cpu->env, ARM_FEATURE_V8) &&
9453 !arm_feature(&cpu->env, ARM_FEATURE_M)) {
9454 assert(r->cp >= 14 && r->cp <= 15);
9455 } else {
9456 assert(r->cp < 8 || (r->cp >= 14 && r->cp <= 15));
9457 }
9458 break;
9459 case ARM_CP_STATE_AA64:
9460 assert(r->cp == 0 || r->cp == CP_REG_ARM64_SYSREG_CP);
9461 break;
9462 default:
9463 g_assert_not_reached();
9464 }
9465
9466
9467
9468
9469
9470
9471
9472 if (r->state != ARM_CP_STATE_AA32) {
9473 CPAccessRights mask;
9474 switch (r->opc1) {
9475 case 0:
9476
9477 mask = PL0U_R | PL1_RW;
9478 break;
9479 case 1: case 2:
9480
9481 mask = PL1_RW;
9482 break;
9483 case 3:
9484
9485 mask = PL0_RW;
9486 break;
9487 case 4:
9488 case 5:
9489
9490 mask = PL2_RW;
9491 break;
9492 case 6:
9493
9494 mask = PL3_RW;
9495 break;
9496 case 7:
9497
9498 mask = PL1_RW;
9499 break;
9500 default:
9501
9502 g_assert_not_reached();
9503 }
9504
9505 assert((r->access & ~mask) == 0);
9506 }
9507
9508
9509
9510
9511
9512 if (!(r->type & (ARM_CP_SPECIAL_MASK | ARM_CP_CONST))) {
9513 if (r->access & PL3_R) {
9514 assert((r->fieldoffset ||
9515 (r->bank_fieldoffsets[0] && r->bank_fieldoffsets[1])) ||
9516 r->readfn);
9517 }
9518 if (r->access & PL3_W) {
9519 assert((r->fieldoffset ||
9520 (r->bank_fieldoffsets[0] && r->bank_fieldoffsets[1])) ||
9521 r->writefn);
9522 }
9523 }
9524
9525 for (crm = crmmin; crm <= crmmax; crm++) {
9526 for (opc1 = opc1min; opc1 <= opc1max; opc1++) {
9527 for (opc2 = opc2min; opc2 <= opc2max; opc2++) {
9528 for (state = ARM_CP_STATE_AA32;
9529 state <= ARM_CP_STATE_AA64; state++) {
9530 if (r->state != state && r->state != ARM_CP_STATE_BOTH) {
9531 continue;
9532 }
9533 if (state == ARM_CP_STATE_AA32) {
9534
9535
9536
9537
9538 char *name;
9539
9540 switch (r->secure) {
9541 case ARM_CP_SECSTATE_S:
9542 case ARM_CP_SECSTATE_NS:
9543 add_cpreg_to_hashtable(cpu, r, opaque, state,
9544 r->secure, crm, opc1, opc2,
9545 r->name);
9546 break;
9547 case ARM_CP_SECSTATE_BOTH:
9548 name = g_strdup_printf("%s_S", r->name);
9549 add_cpreg_to_hashtable(cpu, r, opaque, state,
9550 ARM_CP_SECSTATE_S,
9551 crm, opc1, opc2, name);
9552 g_free(name);
9553 add_cpreg_to_hashtable(cpu, r, opaque, state,
9554 ARM_CP_SECSTATE_NS,
9555 crm, opc1, opc2, r->name);
9556 break;
9557 default:
9558 g_assert_not_reached();
9559 }
9560 } else {
9561
9562
9563
9564
9565 add_cpreg_to_hashtable(cpu, r, opaque, state,
9566 ARM_CP_SECSTATE_NS,
9567 crm, opc1, opc2, r->name);
9568 }
9569 }
9570 }
9571 }
9572 }
9573}
9574
9575
9576void define_arm_cp_regs_with_opaque_len(ARMCPU *cpu, const ARMCPRegInfo *regs,
9577 void *opaque, size_t len)
9578{
9579 size_t i;
9580 for (i = 0; i < len; ++i) {
9581 define_one_arm_cp_reg_with_opaque(cpu, regs + i, opaque);
9582 }
9583}
9584
9585
9586
9587
9588
9589
9590
9591
9592
9593void modify_arm_cp_regs_with_len(ARMCPRegInfo *regs, size_t regs_len,
9594 const ARMCPRegUserSpaceInfo *mods,
9595 size_t mods_len)
9596{
9597 for (size_t mi = 0; mi < mods_len; ++mi) {
9598 const ARMCPRegUserSpaceInfo *m = mods + mi;
9599 GPatternSpec *pat = NULL;
9600
9601 if (m->is_glob) {
9602 pat = g_pattern_spec_new(m->name);
9603 }
9604 for (size_t ri = 0; ri < regs_len; ++ri) {
9605 ARMCPRegInfo *r = regs + ri;
9606
9607 if (pat && g_pattern_match_string(pat, r->name)) {
9608 r->type = ARM_CP_CONST;
9609 r->access = PL0U_R;
9610 r->resetvalue = 0;
9611
9612 } else if (strcmp(r->name, m->name) == 0) {
9613 r->type = ARM_CP_CONST;
9614 r->access = PL0U_R;
9615 r->resetvalue &= m->exported_bits;
9616 r->resetvalue |= m->fixed_bits;
9617 break;
9618 }
9619 }
9620 if (pat) {
9621 g_pattern_spec_free(pat);
9622 }
9623 }
9624}
9625
9626const ARMCPRegInfo *get_arm_cp_reginfo(GHashTable *cpregs, uint32_t encoded_cp)
9627{
9628 return g_hash_table_lookup(cpregs, (gpointer)(uintptr_t)encoded_cp);
9629}
9630
9631void arm_cp_write_ignore(CPUARMState *env, const ARMCPRegInfo *ri,
9632 uint64_t value)
9633{
9634
9635}
9636
9637uint64_t arm_cp_read_zero(CPUARMState *env, const ARMCPRegInfo *ri)
9638{
9639
9640 return 0;
9641}
9642
9643void arm_cp_reset_ignore(CPUARMState *env, const ARMCPRegInfo *opaque)
9644{
9645
9646}
9647
9648static int bad_mode_switch(CPUARMState *env, int mode, CPSRWriteType write_type)
9649{
9650
9651
9652
9653
9654
9655
9656
9657 if (write_type == CPSRWriteByInstr &&
9658 ((env->uncached_cpsr & CPSR_M) == ARM_CPU_MODE_HYP ||
9659 mode == ARM_CPU_MODE_HYP)) {
9660 return 1;
9661 }
9662
9663 switch (mode) {
9664 case ARM_CPU_MODE_USR:
9665 return 0;
9666 case ARM_CPU_MODE_SYS:
9667 case ARM_CPU_MODE_SVC:
9668 case ARM_CPU_MODE_ABT:
9669 case ARM_CPU_MODE_UND:
9670 case ARM_CPU_MODE_IRQ:
9671 case ARM_CPU_MODE_FIQ:
9672
9673
9674
9675
9676
9677
9678
9679
9680 if (write_type == CPSRWriteByInstr &&
9681 (env->uncached_cpsr & CPSR_M) == ARM_CPU_MODE_MON &&
9682 (arm_hcr_el2_eff(env) & HCR_TGE)) {
9683 return 1;
9684 }
9685 return 0;
9686 case ARM_CPU_MODE_HYP:
9687 return !arm_is_el2_enabled(env) || arm_current_el(env) < 2;
9688 case ARM_CPU_MODE_MON:
9689 return arm_current_el(env) < 3;
9690 default:
9691 return 1;
9692 }
9693}
9694
9695uint32_t cpsr_read(CPUARMState *env)
9696{
9697 int ZF;
9698 ZF = (env->ZF == 0);
9699 return env->uncached_cpsr | (env->NF & 0x80000000) | (ZF << 30) |
9700 (env->CF << 29) | ((env->VF & 0x80000000) >> 3) | (env->QF << 27)
9701 | (env->thumb << 5) | ((env->condexec_bits & 3) << 25)
9702 | ((env->condexec_bits & 0xfc) << 8)
9703 | (env->GE << 16) | (env->daif & CPSR_AIF);
9704}
9705
9706void cpsr_write(CPUARMState *env, uint32_t val, uint32_t mask,
9707 CPSRWriteType write_type)
9708{
9709 uint32_t changed_daif;
9710 bool rebuild_hflags = (write_type != CPSRWriteRaw) &&
9711 (mask & (CPSR_M | CPSR_E | CPSR_IL));
9712
9713 if (mask & CPSR_NZCV) {
9714 env->ZF = (~val) & CPSR_Z;
9715 env->NF = val;
9716 env->CF = (val >> 29) & 1;
9717 env->VF = (val << 3) & 0x80000000;
9718 }
9719 if (mask & CPSR_Q) {
9720 env->QF = ((val & CPSR_Q) != 0);
9721 }
9722 if (mask & CPSR_T) {
9723 env->thumb = ((val & CPSR_T) != 0);
9724 }
9725 if (mask & CPSR_IT_0_1) {
9726 env->condexec_bits &= ~3;
9727 env->condexec_bits |= (val >> 25) & 3;
9728 }
9729 if (mask & CPSR_IT_2_7) {
9730 env->condexec_bits &= 3;
9731 env->condexec_bits |= (val >> 8) & 0xfc;
9732 }
9733 if (mask & CPSR_GE) {
9734 env->GE = (val >> 16) & 0xf;
9735 }
9736
9737
9738
9739
9740
9741
9742
9743
9744
9745
9746 if (write_type != CPSRWriteRaw && !arm_feature(env, ARM_FEATURE_V8) &&
9747 arm_feature(env, ARM_FEATURE_EL3) &&
9748 !arm_feature(env, ARM_FEATURE_EL2) &&
9749 !arm_is_secure(env)) {
9750
9751 changed_daif = (env->daif ^ val) & mask;
9752
9753 if (changed_daif & CPSR_A) {
9754
9755
9756
9757
9758 if (!(env->cp15.scr_el3 & SCR_AW)) {
9759 qemu_log_mask(LOG_GUEST_ERROR,
9760 "Ignoring attempt to switch CPSR_A flag from "
9761 "non-secure world with SCR.AW bit clear\n");
9762 mask &= ~CPSR_A;
9763 }
9764 }
9765
9766 if (changed_daif & CPSR_F) {
9767
9768
9769
9770
9771 if (!(env->cp15.scr_el3 & SCR_FW)) {
9772 qemu_log_mask(LOG_GUEST_ERROR,
9773 "Ignoring attempt to switch CPSR_F flag from "
9774 "non-secure world with SCR.FW bit clear\n");
9775 mask &= ~CPSR_F;
9776 }
9777
9778
9779
9780
9781
9782
9783 if ((A32_BANKED_CURRENT_REG_GET(env, sctlr) & SCTLR_NMFI) &&
9784 (val & CPSR_F)) {
9785 qemu_log_mask(LOG_GUEST_ERROR,
9786 "Ignoring attempt to enable CPSR_F flag "
9787 "(non-maskable FIQ [NMFI] support enabled)\n");
9788 mask &= ~CPSR_F;
9789 }
9790 }
9791 }
9792
9793 env->daif &= ~(CPSR_AIF & mask);
9794 env->daif |= val & CPSR_AIF & mask;
9795
9796 if (write_type != CPSRWriteRaw &&
9797 ((env->uncached_cpsr ^ val) & mask & CPSR_M)) {
9798 if ((env->uncached_cpsr & CPSR_M) == ARM_CPU_MODE_USR) {
9799
9800
9801
9802
9803
9804
9805
9806 mask &= ~CPSR_M;
9807 } else if (bad_mode_switch(env, val & CPSR_M, write_type)) {
9808
9809
9810
9811
9812
9813
9814
9815
9816
9817 mask &= ~CPSR_M;
9818 if (write_type != CPSRWriteByGDBStub &&
9819 arm_feature(env, ARM_FEATURE_V8)) {
9820 mask |= CPSR_IL;
9821 val |= CPSR_IL;
9822 }
9823 qemu_log_mask(LOG_GUEST_ERROR,
9824 "Illegal AArch32 mode switch attempt from %s to %s\n",
9825 aarch32_mode_name(env->uncached_cpsr),
9826 aarch32_mode_name(val));
9827 } else {
9828 qemu_log_mask(CPU_LOG_INT, "%s %s to %s PC 0x%" PRIx32 "\n",
9829 write_type == CPSRWriteExceptionReturn ?
9830 "Exception return from AArch32" :
9831 "AArch32 mode switch from",
9832 aarch32_mode_name(env->uncached_cpsr),
9833 aarch32_mode_name(val), env->regs[15]);
9834 switch_mode(env, val & CPSR_M);
9835 }
9836 }
9837 mask &= ~CACHED_CPSR_BITS;
9838 env->uncached_cpsr = (env->uncached_cpsr & ~mask) | (val & mask);
9839 if (tcg_enabled() && rebuild_hflags) {
9840 arm_rebuild_hflags(env);
9841 }
9842}
9843
9844
9845uint32_t HELPER(sxtb16)(uint32_t x)
9846{
9847 uint32_t res;
9848 res = (uint16_t)(int8_t)x;
9849 res |= (uint32_t)(int8_t)(x >> 16) << 16;
9850 return res;
9851}
9852
9853static void handle_possible_div0_trap(CPUARMState *env, uintptr_t ra)
9854{
9855
9856
9857
9858
9859 if (arm_feature(env, ARM_FEATURE_M)
9860 && (env->v7m.ccr[env->v7m.secure] & R_V7M_CCR_DIV_0_TRP_MASK)) {
9861 raise_exception_ra(env, EXCP_DIVBYZERO, 0, 1, ra);
9862 }
9863}
9864
9865uint32_t HELPER(uxtb16)(uint32_t x)
9866{
9867 uint32_t res;
9868 res = (uint16_t)(uint8_t)x;
9869 res |= (uint32_t)(uint8_t)(x >> 16) << 16;
9870 return res;
9871}
9872
9873int32_t HELPER(sdiv)(CPUARMState *env, int32_t num, int32_t den)
9874{
9875 if (den == 0) {
9876 handle_possible_div0_trap(env, GETPC());
9877 return 0;
9878 }
9879 if (num == INT_MIN && den == -1) {
9880 return INT_MIN;
9881 }
9882 return num / den;
9883}
9884
9885uint32_t HELPER(udiv)(CPUARMState *env, uint32_t num, uint32_t den)
9886{
9887 if (den == 0) {
9888 handle_possible_div0_trap(env, GETPC());
9889 return 0;
9890 }
9891 return num / den;
9892}
9893
9894uint32_t HELPER(rbit)(uint32_t x)
9895{
9896 return revbit32(x);
9897}
9898
9899#ifdef CONFIG_USER_ONLY
9900
9901static void switch_mode(CPUARMState *env, int mode)
9902{
9903 ARMCPU *cpu = env_archcpu(env);
9904
9905 if (mode != ARM_CPU_MODE_USR) {
9906 cpu_abort(CPU(cpu), "Tried to switch out of user mode\n");
9907 }
9908}
9909
9910uint32_t arm_phys_excp_target_el(CPUState *cs, uint32_t excp_idx,
9911 uint32_t cur_el, bool secure)
9912{
9913 return 1;
9914}
9915
9916void aarch64_sync_64_to_32(CPUARMState *env)
9917{
9918 g_assert_not_reached();
9919}
9920
9921#else
9922
9923static void switch_mode(CPUARMState *env, int mode)
9924{
9925 int old_mode;
9926 int i;
9927
9928 old_mode = env->uncached_cpsr & CPSR_M;
9929 if (mode == old_mode) {
9930 return;
9931 }
9932
9933 if (old_mode == ARM_CPU_MODE_FIQ) {
9934 memcpy(env->fiq_regs, env->regs + 8, 5 * sizeof(uint32_t));
9935 memcpy(env->regs + 8, env->usr_regs, 5 * sizeof(uint32_t));
9936 } else if (mode == ARM_CPU_MODE_FIQ) {
9937 memcpy(env->usr_regs, env->regs + 8, 5 * sizeof(uint32_t));
9938 memcpy(env->regs + 8, env->fiq_regs, 5 * sizeof(uint32_t));
9939 }
9940
9941 i = bank_number(old_mode);
9942 env->banked_r13[i] = env->regs[13];
9943 env->banked_spsr[i] = env->spsr;
9944
9945 i = bank_number(mode);
9946 env->regs[13] = env->banked_r13[i];
9947 env->spsr = env->banked_spsr[i];
9948
9949 env->banked_r14[r14_bank_number(old_mode)] = env->regs[14];
9950 env->regs[14] = env->banked_r14[r14_bank_number(mode)];
9951}
9952
9953
9954
9955
9956
9957
9958
9959
9960
9961
9962
9963
9964
9965
9966
9967
9968
9969
9970
9971
9972
9973
9974
9975
9976
9977
9978
9979
9980
9981
9982
9983
9984
9985
9986
9987
9988
9989
9990
9991static const int8_t target_el_table[2][2][2][2][2][4] = {
9992 {{{{{ 1, 1, 2, -1 },{ 3, -1, -1, 3 },},
9993 {{ 2, 2, 2, -1 },{ 3, -1, -1, 3 },},},
9994 {{{ 1, 1, 2, -1 },{ 3, -1, -1, 3 },},
9995 {{ 2, 2, 2, -1 },{ 3, -1, -1, 3 },},},},
9996 {{{{ 3, 3, 3, -1 },{ 3, -1, -1, 3 },},
9997 {{ 3, 3, 3, -1 },{ 3, -1, -1, 3 },},},
9998 {{{ 3, 3, 3, -1 },{ 3, -1, -1, 3 },},
9999 {{ 3, 3, 3, -1 },{ 3, -1, -1, 3 },},},},},
10000 {{{{{ 1, 1, 2, -1 },{ 1, 1, -1, 1 },},
10001 {{ 2, 2, 2, -1 },{ 2, 2, -1, 1 },},},
10002 {{{ 1, 1, 1, -1 },{ 1, 1, 1, 1 },},
10003 {{ 2, 2, 2, -1 },{ 2, 2, 2, 1 },},},},
10004 {{{{ 3, 3, 3, -1 },{ 3, 3, -1, 3 },},
10005 {{ 3, 3, 3, -1 },{ 3, 3, -1, 3 },},},
10006 {{{ 3, 3, 3, -1 },{ 3, 3, 3, 3 },},
10007 {{ 3, 3, 3, -1 },{ 3, 3, 3, 3 },},},},},
10008};
10009
10010
10011
10012
10013uint32_t arm_phys_excp_target_el(CPUState *cs, uint32_t excp_idx,
10014 uint32_t cur_el, bool secure)
10015{
10016 CPUARMState *env = cs->env_ptr;
10017 bool rw;
10018 bool scr;
10019 bool hcr;
10020 int target_el;
10021
10022 bool is64 = arm_feature(env, ARM_FEATURE_AARCH64);
10023 uint64_t hcr_el2;
10024
10025 if (arm_feature(env, ARM_FEATURE_EL3)) {
10026 rw = ((env->cp15.scr_el3 & SCR_RW) == SCR_RW);
10027 } else {
10028
10029
10030
10031
10032
10033 rw = is64;
10034 }
10035
10036 hcr_el2 = arm_hcr_el2_eff(env);
10037 switch (excp_idx) {
10038 case EXCP_IRQ:
10039 scr = ((env->cp15.scr_el3 & SCR_IRQ) == SCR_IRQ);
10040 hcr = hcr_el2 & HCR_IMO;
10041 break;
10042 case EXCP_FIQ:
10043 scr = ((env->cp15.scr_el3 & SCR_FIQ) == SCR_FIQ);
10044 hcr = hcr_el2 & HCR_FMO;
10045 break;
10046 default:
10047 scr = ((env->cp15.scr_el3 & SCR_EA) == SCR_EA);
10048 hcr = hcr_el2 & HCR_AMO;
10049 break;
10050 };
10051
10052
10053
10054
10055
10056 hcr |= (hcr_el2 & HCR_TGE) != 0;
10057
10058
10059 target_el = target_el_table[is64][scr][rw][hcr][secure][cur_el];
10060
10061 assert(target_el > 0);
10062
10063 return target_el;
10064}
10065
10066void arm_log_exception(CPUState *cs)
10067{
10068 int idx = cs->exception_index;
10069
10070 if (qemu_loglevel_mask(CPU_LOG_INT)) {
10071 const char *exc = NULL;
10072 static const char * const excnames[] = {
10073 [EXCP_UDEF] = "Undefined Instruction",
10074 [EXCP_SWI] = "SVC",
10075 [EXCP_PREFETCH_ABORT] = "Prefetch Abort",
10076 [EXCP_DATA_ABORT] = "Data Abort",
10077 [EXCP_IRQ] = "IRQ",
10078 [EXCP_FIQ] = "FIQ",
10079 [EXCP_BKPT] = "Breakpoint",
10080 [EXCP_EXCEPTION_EXIT] = "QEMU v7M exception exit",
10081 [EXCP_KERNEL_TRAP] = "QEMU intercept of kernel commpage",
10082 [EXCP_HVC] = "Hypervisor Call",
10083 [EXCP_HYP_TRAP] = "Hypervisor Trap",
10084 [EXCP_SMC] = "Secure Monitor Call",
10085 [EXCP_VIRQ] = "Virtual IRQ",
10086 [EXCP_VFIQ] = "Virtual FIQ",
10087 [EXCP_SEMIHOST] = "Semihosting call",
10088 [EXCP_NOCP] = "v7M NOCP UsageFault",
10089 [EXCP_INVSTATE] = "v7M INVSTATE UsageFault",
10090 [EXCP_STKOF] = "v8M STKOF UsageFault",
10091 [EXCP_LAZYFP] = "v7M exception during lazy FP stacking",
10092 [EXCP_LSERR] = "v8M LSERR UsageFault",
10093 [EXCP_UNALIGNED] = "v7M UNALIGNED UsageFault",
10094 [EXCP_DIVBYZERO] = "v7M DIVBYZERO UsageFault",
10095 [EXCP_VSERR] = "Virtual SERR",
10096 };
10097
10098 if (idx >= 0 && idx < ARRAY_SIZE(excnames)) {
10099 exc = excnames[idx];
10100 }
10101 if (!exc) {
10102 exc = "unknown";
10103 }
10104 qemu_log_mask(CPU_LOG_INT, "Taking exception %d [%s] on CPU %d\n",
10105 idx, exc, cs->cpu_index);
10106 }
10107}
10108
10109
10110
10111
10112
10113
10114void aarch64_sync_32_to_64(CPUARMState *env)
10115{
10116 int i;
10117 uint32_t mode = env->uncached_cpsr & CPSR_M;
10118
10119
10120 for (i = 0; i < 8; i++) {
10121 env->xregs[i] = env->regs[i];
10122 }
10123
10124
10125
10126
10127
10128 if (mode == ARM_CPU_MODE_FIQ) {
10129 for (i = 8; i < 13; i++) {
10130 env->xregs[i] = env->usr_regs[i - 8];
10131 }
10132 } else {
10133 for (i = 8; i < 13; i++) {
10134 env->xregs[i] = env->regs[i];
10135 }
10136 }
10137
10138
10139
10140
10141
10142
10143 if (mode == ARM_CPU_MODE_USR || mode == ARM_CPU_MODE_SYS) {
10144 env->xregs[13] = env->regs[13];
10145 env->xregs[14] = env->regs[14];
10146 } else {
10147 env->xregs[13] = env->banked_r13[bank_number(ARM_CPU_MODE_USR)];
10148
10149 if (mode == ARM_CPU_MODE_HYP) {
10150 env->xregs[14] = env->regs[14];
10151 } else {
10152 env->xregs[14] = env->banked_r14[r14_bank_number(ARM_CPU_MODE_USR)];
10153 }
10154 }
10155
10156 if (mode == ARM_CPU_MODE_HYP) {
10157 env->xregs[15] = env->regs[13];
10158 } else {
10159 env->xregs[15] = env->banked_r13[bank_number(ARM_CPU_MODE_HYP)];
10160 }
10161
10162 if (mode == ARM_CPU_MODE_IRQ) {
10163 env->xregs[16] = env->regs[14];
10164 env->xregs[17] = env->regs[13];
10165 } else {
10166 env->xregs[16] = env->banked_r14[r14_bank_number(ARM_CPU_MODE_IRQ)];
10167 env->xregs[17] = env->banked_r13[bank_number(ARM_CPU_MODE_IRQ)];
10168 }
10169
10170 if (mode == ARM_CPU_MODE_SVC) {
10171 env->xregs[18] = env->regs[14];
10172 env->xregs[19] = env->regs[13];
10173 } else {
10174 env->xregs[18] = env->banked_r14[r14_bank_number(ARM_CPU_MODE_SVC)];
10175 env->xregs[19] = env->banked_r13[bank_number(ARM_CPU_MODE_SVC)];
10176 }
10177
10178 if (mode == ARM_CPU_MODE_ABT) {
10179 env->xregs[20] = env->regs[14];
10180 env->xregs[21] = env->regs[13];
10181 } else {
10182 env->xregs[20] = env->banked_r14[r14_bank_number(ARM_CPU_MODE_ABT)];
10183 env->xregs[21] = env->banked_r13[bank_number(ARM_CPU_MODE_ABT)];
10184 }
10185
10186 if (mode == ARM_CPU_MODE_UND) {
10187 env->xregs[22] = env->regs[14];
10188 env->xregs[23] = env->regs[13];
10189 } else {
10190 env->xregs[22] = env->banked_r14[r14_bank_number(ARM_CPU_MODE_UND)];
10191 env->xregs[23] = env->banked_r13[bank_number(ARM_CPU_MODE_UND)];
10192 }
10193
10194
10195
10196
10197
10198
10199 if (mode == ARM_CPU_MODE_FIQ) {
10200 for (i = 24; i < 31; i++) {
10201 env->xregs[i] = env->regs[i - 16];
10202 }
10203 } else {
10204 for (i = 24; i < 29; i++) {
10205 env->xregs[i] = env->fiq_regs[i - 24];
10206 }
10207 env->xregs[29] = env->banked_r13[bank_number(ARM_CPU_MODE_FIQ)];
10208 env->xregs[30] = env->banked_r14[r14_bank_number(ARM_CPU_MODE_FIQ)];
10209 }
10210
10211 env->pc = env->regs[15];
10212}
10213
10214
10215
10216
10217
10218
10219void aarch64_sync_64_to_32(CPUARMState *env)
10220{
10221 int i;
10222 uint32_t mode = env->uncached_cpsr & CPSR_M;
10223
10224
10225 for (i = 0; i < 8; i++) {
10226 env->regs[i] = env->xregs[i];
10227 }
10228
10229
10230
10231
10232
10233 if (mode == ARM_CPU_MODE_FIQ) {
10234 for (i = 8; i < 13; i++) {
10235 env->usr_regs[i - 8] = env->xregs[i];
10236 }
10237 } else {
10238 for (i = 8; i < 13; i++) {
10239 env->regs[i] = env->xregs[i];
10240 }
10241 }
10242
10243
10244
10245
10246
10247
10248
10249 if (mode == ARM_CPU_MODE_USR || mode == ARM_CPU_MODE_SYS) {
10250 env->regs[13] = env->xregs[13];
10251 env->regs[14] = env->xregs[14];
10252 } else {
10253 env->banked_r13[bank_number(ARM_CPU_MODE_USR)] = env->xregs[13];
10254
10255
10256
10257
10258
10259 if (mode == ARM_CPU_MODE_HYP) {
10260 env->regs[14] = env->xregs[14];
10261 } else {
10262 env->banked_r14[r14_bank_number(ARM_CPU_MODE_USR)] = env->xregs[14];
10263 }
10264 }
10265
10266 if (mode == ARM_CPU_MODE_HYP) {
10267 env->regs[13] = env->xregs[15];
10268 } else {
10269 env->banked_r13[bank_number(ARM_CPU_MODE_HYP)] = env->xregs[15];
10270 }
10271
10272 if (mode == ARM_CPU_MODE_IRQ) {
10273 env->regs[14] = env->xregs[16];
10274 env->regs[13] = env->xregs[17];
10275 } else {
10276 env->banked_r14[r14_bank_number(ARM_CPU_MODE_IRQ)] = env->xregs[16];
10277 env->banked_r13[bank_number(ARM_CPU_MODE_IRQ)] = env->xregs[17];
10278 }
10279
10280 if (mode == ARM_CPU_MODE_SVC) {
10281 env->regs[14] = env->xregs[18];
10282 env->regs[13] = env->xregs[19];
10283 } else {
10284 env->banked_r14[r14_bank_number(ARM_CPU_MODE_SVC)] = env->xregs[18];
10285 env->banked_r13[bank_number(ARM_CPU_MODE_SVC)] = env->xregs[19];
10286 }
10287
10288 if (mode == ARM_CPU_MODE_ABT) {
10289 env->regs[14] = env->xregs[20];
10290 env->regs[13] = env->xregs[21];
10291 } else {
10292 env->banked_r14[r14_bank_number(ARM_CPU_MODE_ABT)] = env->xregs[20];
10293 env->banked_r13[bank_number(ARM_CPU_MODE_ABT)] = env->xregs[21];
10294 }
10295
10296 if (mode == ARM_CPU_MODE_UND) {
10297 env->regs[14] = env->xregs[22];
10298 env->regs[13] = env->xregs[23];
10299 } else {
10300 env->banked_r14[r14_bank_number(ARM_CPU_MODE_UND)] = env->xregs[22];
10301 env->banked_r13[bank_number(ARM_CPU_MODE_UND)] = env->xregs[23];
10302 }
10303
10304
10305
10306
10307
10308
10309 if (mode == ARM_CPU_MODE_FIQ) {
10310 for (i = 24; i < 31; i++) {
10311 env->regs[i - 16] = env->xregs[i];
10312 }
10313 } else {
10314 for (i = 24; i < 29; i++) {
10315 env->fiq_regs[i - 24] = env->xregs[i];
10316 }
10317 env->banked_r13[bank_number(ARM_CPU_MODE_FIQ)] = env->xregs[29];
10318 env->banked_r14[r14_bank_number(ARM_CPU_MODE_FIQ)] = env->xregs[30];
10319 }
10320
10321 env->regs[15] = env->pc;
10322}
10323
10324static void take_aarch32_exception(CPUARMState *env, int new_mode,
10325 uint32_t mask, uint32_t offset,
10326 uint32_t newpc)
10327{
10328 int new_el;
10329
10330
10331 switch_mode(env, new_mode);
10332
10333
10334
10335
10336
10337 env->pstate &= ~PSTATE_SS;
10338 env->spsr = cpsr_read(env);
10339
10340 env->condexec_bits = 0;
10341
10342 env->uncached_cpsr = (env->uncached_cpsr & ~CPSR_M) | new_mode;
10343
10344
10345 new_el = arm_current_el(env);
10346
10347
10348 env->uncached_cpsr &= ~CPSR_E;
10349 if (env->cp15.sctlr_el[new_el] & SCTLR_EE) {
10350 env->uncached_cpsr |= CPSR_E;
10351 }
10352
10353 env->uncached_cpsr &= ~(CPSR_IL | CPSR_J);
10354 env->daif |= mask;
10355
10356 if (cpu_isar_feature(aa32_ssbs, env_archcpu(env))) {
10357 if (env->cp15.sctlr_el[new_el] & SCTLR_DSSBS_32) {
10358 env->uncached_cpsr |= CPSR_SSBS;
10359 } else {
10360 env->uncached_cpsr &= ~CPSR_SSBS;
10361 }
10362 }
10363
10364 if (new_mode == ARM_CPU_MODE_HYP) {
10365 env->thumb = (env->cp15.sctlr_el[2] & SCTLR_TE) != 0;
10366 env->elr_el[2] = env->regs[15];
10367 } else {
10368
10369 if (cpu_isar_feature(aa32_pan, env_archcpu(env))) {
10370 switch (new_el) {
10371 case 3:
10372 if (!arm_is_secure_below_el3(env)) {
10373
10374 env->uncached_cpsr &= ~CPSR_PAN;
10375 break;
10376 }
10377
10378
10379 case 1:
10380
10381 if (!(env->cp15.sctlr_el[new_el] & SCTLR_SPAN)) {
10382 env->uncached_cpsr |= CPSR_PAN;
10383 }
10384 break;
10385 }
10386 }
10387
10388
10389
10390
10391 if (arm_feature(env, ARM_FEATURE_V4T)) {
10392 env->thumb =
10393 (A32_BANKED_CURRENT_REG_GET(env, sctlr) & SCTLR_TE) != 0;
10394 }
10395 env->regs[14] = env->regs[15] + offset;
10396 }
10397 env->regs[15] = newpc;
10398
10399 if (tcg_enabled()) {
10400 arm_rebuild_hflags(env);
10401 }
10402}
10403
10404static void arm_cpu_do_interrupt_aarch32_hyp(CPUState *cs)
10405{
10406
10407
10408
10409
10410
10411
10412
10413
10414
10415
10416
10417 uint32_t addr, mask;
10418 ARMCPU *cpu = ARM_CPU(cs);
10419 CPUARMState *env = &cpu->env;
10420
10421 switch (cs->exception_index) {
10422 case EXCP_UDEF:
10423 addr = 0x04;
10424 break;
10425 case EXCP_SWI:
10426 addr = 0x08;
10427 break;
10428 case EXCP_BKPT:
10429
10430 case EXCP_PREFETCH_ABORT:
10431 env->cp15.ifar_s = env->exception.vaddress;
10432 qemu_log_mask(CPU_LOG_INT, "...with HIFAR 0x%x\n",
10433 (uint32_t)env->exception.vaddress);
10434 addr = 0x0c;
10435 break;
10436 case EXCP_DATA_ABORT:
10437 env->cp15.dfar_s = env->exception.vaddress;
10438 qemu_log_mask(CPU_LOG_INT, "...with HDFAR 0x%x\n",
10439 (uint32_t)env->exception.vaddress);
10440 addr = 0x10;
10441 break;
10442 case EXCP_IRQ:
10443 addr = 0x18;
10444 break;
10445 case EXCP_FIQ:
10446 addr = 0x1c;
10447 break;
10448 case EXCP_HVC:
10449 addr = 0x08;
10450 break;
10451 case EXCP_HYP_TRAP:
10452 addr = 0x14;
10453 break;
10454 default:
10455 cpu_abort(cs, "Unhandled exception 0x%x\n", cs->exception_index);
10456 }
10457
10458 if (cs->exception_index != EXCP_IRQ && cs->exception_index != EXCP_FIQ) {
10459 if (!arm_feature(env, ARM_FEATURE_V8)) {
10460
10461
10462
10463
10464
10465 if (cs->exception_index == EXCP_PREFETCH_ABORT ||
10466 (cs->exception_index == EXCP_DATA_ABORT &&
10467 !(env->exception.syndrome & ARM_EL_ISV)) ||
10468 syn_get_ec(env->exception.syndrome) == EC_UNCATEGORIZED) {
10469 env->exception.syndrome &= ~ARM_EL_IL;
10470 }
10471 }
10472 env->cp15.esr_el[2] = env->exception.syndrome;
10473 }
10474
10475 if (arm_current_el(env) != 2 && addr < 0x14) {
10476 addr = 0x14;
10477 }
10478
10479 mask = 0;
10480 if (!(env->cp15.scr_el3 & SCR_EA)) {
10481 mask |= CPSR_A;
10482 }
10483 if (!(env->cp15.scr_el3 & SCR_IRQ)) {
10484 mask |= CPSR_I;
10485 }
10486 if (!(env->cp15.scr_el3 & SCR_FIQ)) {
10487 mask |= CPSR_F;
10488 }
10489
10490 addr += env->cp15.hvbar;
10491
10492 take_aarch32_exception(env, ARM_CPU_MODE_HYP, mask, 0, addr);
10493}
10494
10495static void arm_cpu_do_interrupt_aarch32(CPUState *cs)
10496{
10497 ARMCPU *cpu = ARM_CPU(cs);
10498 CPUARMState *env = &cpu->env;
10499 uint32_t addr;
10500 uint32_t mask;
10501 int new_mode;
10502 uint32_t offset;
10503 uint32_t moe;
10504
10505
10506 switch (syn_get_ec(env->exception.syndrome)) {
10507 case EC_BREAKPOINT:
10508 case EC_BREAKPOINT_SAME_EL:
10509 moe = 1;
10510 break;
10511 case EC_WATCHPOINT:
10512 case EC_WATCHPOINT_SAME_EL:
10513 moe = 10;
10514 break;
10515 case EC_AA32_BKPT:
10516 moe = 3;
10517 break;
10518 case EC_VECTORCATCH:
10519 moe = 5;
10520 break;
10521 default:
10522 moe = 0;
10523 break;
10524 }
10525
10526 if (moe) {
10527 env->cp15.mdscr_el1 = deposit64(env->cp15.mdscr_el1, 2, 4, moe);
10528 }
10529
10530 if (env->exception.target_el == 2) {
10531 arm_cpu_do_interrupt_aarch32_hyp(cs);
10532 return;
10533 }
10534
10535 switch (cs->exception_index) {
10536 case EXCP_UDEF:
10537 new_mode = ARM_CPU_MODE_UND;
10538 addr = 0x04;
10539 mask = CPSR_I;
10540 if (env->thumb) {
10541 offset = 2;
10542 } else {
10543 offset = 4;
10544 }
10545 break;
10546 case EXCP_SWI:
10547 new_mode = ARM_CPU_MODE_SVC;
10548 addr = 0x08;
10549 mask = CPSR_I;
10550
10551 offset = 0;
10552 break;
10553 case EXCP_BKPT:
10554
10555 case EXCP_PREFETCH_ABORT:
10556 A32_BANKED_CURRENT_REG_SET(env, ifsr, env->exception.fsr);
10557 A32_BANKED_CURRENT_REG_SET(env, ifar, env->exception.vaddress);
10558 qemu_log_mask(CPU_LOG_INT, "...with IFSR 0x%x IFAR 0x%x\n",
10559 env->exception.fsr, (uint32_t)env->exception.vaddress);
10560 new_mode = ARM_CPU_MODE_ABT;
10561 addr = 0x0c;
10562 mask = CPSR_A | CPSR_I;
10563 offset = 4;
10564 break;
10565 case EXCP_DATA_ABORT:
10566 A32_BANKED_CURRENT_REG_SET(env, dfsr, env->exception.fsr);
10567 A32_BANKED_CURRENT_REG_SET(env, dfar, env->exception.vaddress);
10568 qemu_log_mask(CPU_LOG_INT, "...with DFSR 0x%x DFAR 0x%x\n",
10569 env->exception.fsr,
10570 (uint32_t)env->exception.vaddress);
10571 new_mode = ARM_CPU_MODE_ABT;
10572 addr = 0x10;
10573 mask = CPSR_A | CPSR_I;
10574 offset = 8;
10575 break;
10576 case EXCP_IRQ:
10577 new_mode = ARM_CPU_MODE_IRQ;
10578 addr = 0x18;
10579
10580 mask = CPSR_A | CPSR_I;
10581 offset = 4;
10582 if (env->cp15.scr_el3 & SCR_IRQ) {
10583
10584 new_mode = ARM_CPU_MODE_MON;
10585 mask |= CPSR_F;
10586 }
10587 break;
10588 case EXCP_FIQ:
10589 new_mode = ARM_CPU_MODE_FIQ;
10590 addr = 0x1c;
10591
10592 mask = CPSR_A | CPSR_I | CPSR_F;
10593 if (env->cp15.scr_el3 & SCR_FIQ) {
10594
10595 new_mode = ARM_CPU_MODE_MON;
10596 }
10597 offset = 4;
10598 break;
10599 case EXCP_VIRQ:
10600 new_mode = ARM_CPU_MODE_IRQ;
10601 addr = 0x18;
10602
10603 mask = CPSR_A | CPSR_I;
10604 offset = 4;
10605 break;
10606 case EXCP_VFIQ:
10607 new_mode = ARM_CPU_MODE_FIQ;
10608 addr = 0x1c;
10609
10610 mask = CPSR_A | CPSR_I | CPSR_F;
10611 offset = 4;
10612 break;
10613 case EXCP_VSERR:
10614 {
10615
10616
10617
10618
10619
10620 ARMMMUFaultInfo fi = { .type = ARMFault_AsyncExternal, };
10621
10622 if (extended_addresses_enabled(env)) {
10623 env->exception.fsr = arm_fi_to_lfsc(&fi);
10624 } else {
10625 env->exception.fsr = arm_fi_to_sfsc(&fi);
10626 }
10627 env->exception.fsr |= env->cp15.vsesr_el2 & 0xd000;
10628 A32_BANKED_CURRENT_REG_SET(env, dfsr, env->exception.fsr);
10629 qemu_log_mask(CPU_LOG_INT, "...with IFSR 0x%x\n",
10630 env->exception.fsr);
10631
10632 new_mode = ARM_CPU_MODE_ABT;
10633 addr = 0x10;
10634 mask = CPSR_A | CPSR_I;
10635 offset = 8;
10636 }
10637 break;
10638 case EXCP_SMC:
10639 new_mode = ARM_CPU_MODE_MON;
10640 addr = 0x08;
10641 mask = CPSR_A | CPSR_I | CPSR_F;
10642 offset = 0;
10643 break;
10644 default:
10645 cpu_abort(cs, "Unhandled exception 0x%x\n", cs->exception_index);
10646 return;
10647 }
10648
10649 if (new_mode == ARM_CPU_MODE_MON) {
10650 addr += env->cp15.mvbar;
10651 } else if (A32_BANKED_CURRENT_REG_GET(env, sctlr) & SCTLR_V) {
10652
10653 addr += 0xffff0000;
10654 } else {
10655
10656
10657
10658
10659
10660
10661 addr += A32_BANKED_CURRENT_REG_GET(env, vbar);
10662 }
10663
10664 if ((env->uncached_cpsr & CPSR_M) == ARM_CPU_MODE_MON) {
10665 env->cp15.scr_el3 &= ~SCR_NS;
10666 }
10667
10668 take_aarch32_exception(env, new_mode, mask, offset, addr);
10669}
10670
10671static int aarch64_regnum(CPUARMState *env, int aarch32_reg)
10672{
10673
10674
10675
10676
10677
10678 int mode = env->uncached_cpsr & CPSR_M;
10679
10680 switch (aarch32_reg) {
10681 case 0 ... 7:
10682 return aarch32_reg;
10683 case 8 ... 12:
10684 return mode == ARM_CPU_MODE_FIQ ? aarch32_reg + 16 : aarch32_reg;
10685 case 13:
10686 switch (mode) {
10687 case ARM_CPU_MODE_USR:
10688 case ARM_CPU_MODE_SYS:
10689 return 13;
10690 case ARM_CPU_MODE_HYP:
10691 return 15;
10692 case ARM_CPU_MODE_IRQ:
10693 return 17;
10694 case ARM_CPU_MODE_SVC:
10695 return 19;
10696 case ARM_CPU_MODE_ABT:
10697 return 21;
10698 case ARM_CPU_MODE_UND:
10699 return 23;
10700 case ARM_CPU_MODE_FIQ:
10701 return 29;
10702 default:
10703 g_assert_not_reached();
10704 }
10705 case 14:
10706 switch (mode) {
10707 case ARM_CPU_MODE_USR:
10708 case ARM_CPU_MODE_SYS:
10709 case ARM_CPU_MODE_HYP:
10710 return 14;
10711 case ARM_CPU_MODE_IRQ:
10712 return 16;
10713 case ARM_CPU_MODE_SVC:
10714 return 18;
10715 case ARM_CPU_MODE_ABT:
10716 return 20;
10717 case ARM_CPU_MODE_UND:
10718 return 22;
10719 case ARM_CPU_MODE_FIQ:
10720 return 30;
10721 default:
10722 g_assert_not_reached();
10723 }
10724 case 15:
10725 return 31;
10726 default:
10727 g_assert_not_reached();
10728 }
10729}
10730
10731static uint32_t cpsr_read_for_spsr_elx(CPUARMState *env)
10732{
10733 uint32_t ret = cpsr_read(env);
10734
10735
10736 if (ret & CPSR_DIT) {
10737 ret &= ~CPSR_DIT;
10738 ret |= PSTATE_DIT;
10739 }
10740
10741 ret |= env->pstate & PSTATE_SS;
10742
10743 return ret;
10744}
10745
10746static bool syndrome_is_sync_extabt(uint32_t syndrome)
10747{
10748
10749 switch (syn_get_ec(syndrome)) {
10750 case EC_INSNABORT:
10751 case EC_INSNABORT_SAME_EL:
10752 case EC_DATAABORT:
10753 case EC_DATAABORT_SAME_EL:
10754
10755 switch (syndrome & 0x3f) {
10756 case 0x10:
10757 case 0x13:
10758 case 0x14:
10759 case 0x15:
10760 case 0x16:
10761 case 0x17:
10762 return true;
10763 default:
10764 return false;
10765 }
10766 default:
10767 return false;
10768 }
10769}
10770
10771
10772static void arm_cpu_do_interrupt_aarch64(CPUState *cs)
10773{
10774 ARMCPU *cpu = ARM_CPU(cs);
10775 CPUARMState *env = &cpu->env;
10776 unsigned int new_el = env->exception.target_el;
10777 target_ulong addr = env->cp15.vbar_el[new_el];
10778 unsigned int new_mode = aarch64_pstate_mode(new_el, true);
10779 unsigned int old_mode;
10780 unsigned int cur_el = arm_current_el(env);
10781 int rt;
10782
10783 if (tcg_enabled()) {
10784
10785
10786
10787
10788 aarch64_sve_change_el(env, cur_el, new_el, is_a64(env));
10789 }
10790
10791 if (cur_el < new_el) {
10792
10793
10794
10795
10796 bool is_aa64;
10797 uint64_t hcr;
10798
10799 switch (new_el) {
10800 case 3:
10801 is_aa64 = (env->cp15.scr_el3 & SCR_RW) != 0;
10802 break;
10803 case 2:
10804 hcr = arm_hcr_el2_eff(env);
10805 if ((hcr & (HCR_E2H | HCR_TGE)) != (HCR_E2H | HCR_TGE)) {
10806 is_aa64 = (hcr & HCR_RW) != 0;
10807 break;
10808 }
10809
10810 case 1:
10811 is_aa64 = is_a64(env);
10812 break;
10813 default:
10814 g_assert_not_reached();
10815 }
10816
10817 if (is_aa64) {
10818 addr += 0x400;
10819 } else {
10820 addr += 0x600;
10821 }
10822 } else if (pstate_read(env) & PSTATE_SP) {
10823 addr += 0x200;
10824 }
10825
10826 switch (cs->exception_index) {
10827 case EXCP_PREFETCH_ABORT:
10828 case EXCP_DATA_ABORT:
10829
10830
10831
10832
10833 if (new_el == 3 && (env->cp15.scr_el3 & SCR_EASE) &&
10834 syndrome_is_sync_extabt(env->exception.syndrome)) {
10835 addr += 0x180;
10836 }
10837 env->cp15.far_el[new_el] = env->exception.vaddress;
10838 qemu_log_mask(CPU_LOG_INT, "...with FAR 0x%" PRIx64 "\n",
10839 env->cp15.far_el[new_el]);
10840
10841 case EXCP_BKPT:
10842 case EXCP_UDEF:
10843 case EXCP_SWI:
10844 case EXCP_HVC:
10845 case EXCP_HYP_TRAP:
10846 case EXCP_SMC:
10847 switch (syn_get_ec(env->exception.syndrome)) {
10848 case EC_ADVSIMDFPACCESSTRAP:
10849
10850
10851
10852
10853
10854
10855 env->exception.syndrome &= ~MAKE_64BIT_MASK(0, 20);
10856 break;
10857 case EC_CP14RTTRAP:
10858 case EC_CP15RTTRAP:
10859 case EC_CP14DTTRAP:
10860
10861
10862
10863
10864
10865
10866
10867 rt = extract32(env->exception.syndrome, 5, 4);
10868 rt = aarch64_regnum(env, rt);
10869 env->exception.syndrome = deposit32(env->exception.syndrome,
10870 5, 5, rt);
10871 break;
10872 case EC_CP15RRTTRAP:
10873 case EC_CP14RRTTRAP:
10874
10875 rt = extract32(env->exception.syndrome, 5, 4);
10876 rt = aarch64_regnum(env, rt);
10877 env->exception.syndrome = deposit32(env->exception.syndrome,
10878 5, 5, rt);
10879 rt = extract32(env->exception.syndrome, 10, 4);
10880 rt = aarch64_regnum(env, rt);
10881 env->exception.syndrome = deposit32(env->exception.syndrome,
10882 10, 5, rt);
10883 break;
10884 }
10885 env->cp15.esr_el[new_el] = env->exception.syndrome;
10886 break;
10887 case EXCP_IRQ:
10888 case EXCP_VIRQ:
10889 addr += 0x80;
10890 break;
10891 case EXCP_FIQ:
10892 case EXCP_VFIQ:
10893 addr += 0x100;
10894 break;
10895 case EXCP_VSERR:
10896 addr += 0x180;
10897
10898 env->exception.syndrome = syn_serror(env->cp15.vsesr_el2 & 0x1ffffff);
10899 env->cp15.esr_el[new_el] = env->exception.syndrome;
10900 break;
10901 default:
10902 cpu_abort(cs, "Unhandled exception 0x%x\n", cs->exception_index);
10903 }
10904
10905 if (is_a64(env)) {
10906 old_mode = pstate_read(env);
10907 aarch64_save_sp(env, arm_current_el(env));
10908 env->elr_el[new_el] = env->pc;
10909 } else {
10910 old_mode = cpsr_read_for_spsr_elx(env);
10911 env->elr_el[new_el] = env->regs[15];
10912
10913 aarch64_sync_32_to_64(env);
10914
10915 env->condexec_bits = 0;
10916 }
10917 env->banked_spsr[aarch64_banked_spsr_index(new_el)] = old_mode;
10918
10919 qemu_log_mask(CPU_LOG_INT, "...with ELR 0x%" PRIx64 "\n",
10920 env->elr_el[new_el]);
10921
10922 if (cpu_isar_feature(aa64_pan, cpu)) {
10923
10924 new_mode |= old_mode & PSTATE_PAN;
10925 switch (new_el) {
10926 case 2:
10927
10928 if ((arm_hcr_el2_eff(env) & (HCR_E2H | HCR_TGE))
10929 != (HCR_E2H | HCR_TGE)) {
10930 break;
10931 }
10932
10933 case 1:
10934
10935
10936 if ((env->cp15.sctlr_el[new_el] & SCTLR_SPAN) == 0) {
10937 new_mode |= PSTATE_PAN;
10938 }
10939 break;
10940 }
10941 }
10942 if (cpu_isar_feature(aa64_mte, cpu)) {
10943 new_mode |= PSTATE_TCO;
10944 }
10945
10946 if (cpu_isar_feature(aa64_ssbs, cpu)) {
10947 if (env->cp15.sctlr_el[new_el] & SCTLR_DSSBS_64) {
10948 new_mode |= PSTATE_SSBS;
10949 } else {
10950 new_mode &= ~PSTATE_SSBS;
10951 }
10952 }
10953
10954 pstate_write(env, PSTATE_DAIF | new_mode);
10955 env->aarch64 = true;
10956 aarch64_restore_sp(env, new_el);
10957
10958 if (tcg_enabled()) {
10959 helper_rebuild_hflags_a64(env, new_el);
10960 }
10961
10962 env->pc = addr;
10963
10964 qemu_log_mask(CPU_LOG_INT, "...to EL%d PC 0x%" PRIx64 " PSTATE 0x%x\n",
10965 new_el, env->pc, pstate_read(env));
10966}
10967
10968
10969
10970
10971
10972
10973
10974
10975#ifdef CONFIG_TCG
10976static void tcg_handle_semihosting(CPUState *cs)
10977{
10978 ARMCPU *cpu = ARM_CPU(cs);
10979 CPUARMState *env = &cpu->env;
10980
10981 if (is_a64(env)) {
10982 qemu_log_mask(CPU_LOG_INT,
10983 "...handling as semihosting call 0x%" PRIx64 "\n",
10984 env->xregs[0]);
10985 do_common_semihosting(cs);
10986 env->pc += 4;
10987 } else {
10988 qemu_log_mask(CPU_LOG_INT,
10989 "...handling as semihosting call 0x%x\n",
10990 env->regs[0]);
10991 do_common_semihosting(cs);
10992 env->regs[15] += env->thumb ? 2 : 4;
10993 }
10994}
10995#endif
10996
10997
10998
10999
11000
11001
11002
11003
11004
11005
11006
11007void arm_cpu_do_interrupt(CPUState *cs)
11008{
11009 ARMCPU *cpu = ARM_CPU(cs);
11010 CPUARMState *env = &cpu->env;
11011 unsigned int new_el = env->exception.target_el;
11012
11013 assert(!arm_feature(env, ARM_FEATURE_M));
11014
11015 arm_log_exception(cs);
11016 qemu_log_mask(CPU_LOG_INT, "...from EL%d to EL%d\n", arm_current_el(env),
11017 new_el);
11018 if (qemu_loglevel_mask(CPU_LOG_INT)
11019 && !excp_is_internal(cs->exception_index)) {
11020 qemu_log_mask(CPU_LOG_INT, "...with ESR 0x%x/0x%" PRIx32 "\n",
11021 syn_get_ec(env->exception.syndrome),
11022 env->exception.syndrome);
11023 }
11024
11025 if (tcg_enabled() && arm_is_psci_call(cpu, cs->exception_index)) {
11026 arm_handle_psci_call(cpu);
11027 qemu_log_mask(CPU_LOG_INT, "...handled as PSCI call\n");
11028 return;
11029 }
11030
11031
11032
11033
11034
11035
11036#ifdef CONFIG_TCG
11037 if (cs->exception_index == EXCP_SEMIHOST) {
11038 tcg_handle_semihosting(cs);
11039 return;
11040 }
11041#endif
11042
11043
11044
11045
11046
11047
11048 g_assert(qemu_mutex_iothread_locked());
11049
11050 arm_call_pre_el_change_hook(cpu);
11051
11052 assert(!excp_is_internal(cs->exception_index));
11053 if (arm_el_is_aa64(env, new_el)) {
11054 arm_cpu_do_interrupt_aarch64(cs);
11055 } else {
11056 arm_cpu_do_interrupt_aarch32(cs);
11057 }
11058
11059 arm_call_el_change_hook(cpu);
11060
11061 if (!kvm_enabled()) {
11062 cs->interrupt_request |= CPU_INTERRUPT_EXITTB;
11063 }
11064}
11065#endif
11066
11067uint64_t arm_sctlr(CPUARMState *env, int el)
11068{
11069
11070 if (el == 0) {
11071 ARMMMUIdx mmu_idx = arm_mmu_idx_el(env, 0);
11072 el = mmu_idx == ARMMMUIdx_E20_0 ? 2 : 1;
11073 }
11074 return env->cp15.sctlr_el[el];
11075}
11076
11077int aa64_va_parameter_tbi(uint64_t tcr, ARMMMUIdx mmu_idx)
11078{
11079 if (regime_has_2_ranges(mmu_idx)) {
11080 return extract64(tcr, 37, 2);
11081 } else if (regime_is_stage2(mmu_idx)) {
11082 return 0;
11083 } else {
11084
11085 return extract32(tcr, 20, 1) * 3;
11086 }
11087}
11088
11089int aa64_va_parameter_tbid(uint64_t tcr, ARMMMUIdx mmu_idx)
11090{
11091 if (regime_has_2_ranges(mmu_idx)) {
11092 return extract64(tcr, 51, 2);
11093 } else if (regime_is_stage2(mmu_idx)) {
11094 return 0;
11095 } else {
11096
11097 return extract32(tcr, 29, 1) * 3;
11098 }
11099}
11100
11101int aa64_va_parameter_tcma(uint64_t tcr, ARMMMUIdx mmu_idx)
11102{
11103 if (regime_has_2_ranges(mmu_idx)) {
11104 return extract64(tcr, 57, 2);
11105 } else {
11106
11107 return extract32(tcr, 30, 1) * 3;
11108 }
11109}
11110
11111static ARMGranuleSize tg0_to_gran_size(int tg)
11112{
11113 switch (tg) {
11114 case 0:
11115 return Gran4K;
11116 case 1:
11117 return Gran64K;
11118 case 2:
11119 return Gran16K;
11120 default:
11121 return GranInvalid;
11122 }
11123}
11124
11125static ARMGranuleSize tg1_to_gran_size(int tg)
11126{
11127 switch (tg) {
11128 case 1:
11129 return Gran16K;
11130 case 2:
11131 return Gran4K;
11132 case 3:
11133 return Gran64K;
11134 default:
11135 return GranInvalid;
11136 }
11137}
11138
11139static inline bool have4k(ARMCPU *cpu, bool stage2)
11140{
11141 return stage2 ? cpu_isar_feature(aa64_tgran4_2, cpu)
11142 : cpu_isar_feature(aa64_tgran4, cpu);
11143}
11144
11145static inline bool have16k(ARMCPU *cpu, bool stage2)
11146{
11147 return stage2 ? cpu_isar_feature(aa64_tgran16_2, cpu)
11148 : cpu_isar_feature(aa64_tgran16, cpu);
11149}
11150
11151static inline bool have64k(ARMCPU *cpu, bool stage2)
11152{
11153 return stage2 ? cpu_isar_feature(aa64_tgran64_2, cpu)
11154 : cpu_isar_feature(aa64_tgran64, cpu);
11155}
11156
11157static ARMGranuleSize sanitize_gran_size(ARMCPU *cpu, ARMGranuleSize gran,
11158 bool stage2)
11159{
11160 switch (gran) {
11161 case Gran4K:
11162 if (have4k(cpu, stage2)) {
11163 return gran;
11164 }
11165 break;
11166 case Gran16K:
11167 if (have16k(cpu, stage2)) {
11168 return gran;
11169 }
11170 break;
11171 case Gran64K:
11172 if (have64k(cpu, stage2)) {
11173 return gran;
11174 }
11175 break;
11176 case GranInvalid:
11177 break;
11178 }
11179
11180
11181
11182
11183
11184
11185 if (have4k(cpu, stage2)) {
11186 return Gran4K;
11187 }
11188 if (have16k(cpu, stage2)) {
11189 return Gran16K;
11190 }
11191 assert(have64k(cpu, stage2));
11192 return Gran64K;
11193}
11194
11195ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va,
11196 ARMMMUIdx mmu_idx, bool data,
11197 bool el1_is_aa32)
11198{
11199 uint64_t tcr = regime_tcr(env, mmu_idx);
11200 bool epd, hpd, tsz_oob, ds, ha, hd;
11201 int select, tsz, tbi, max_tsz, min_tsz, ps, sh;
11202 ARMGranuleSize gran;
11203 ARMCPU *cpu = env_archcpu(env);
11204 bool stage2 = regime_is_stage2(mmu_idx);
11205
11206 if (!regime_has_2_ranges(mmu_idx)) {
11207 select = 0;
11208 tsz = extract32(tcr, 0, 6);
11209 gran = tg0_to_gran_size(extract32(tcr, 14, 2));
11210 if (stage2) {
11211
11212 hpd = false;
11213 } else {
11214 hpd = extract32(tcr, 24, 1);
11215 }
11216 epd = false;
11217 sh = extract32(tcr, 12, 2);
11218 ps = extract32(tcr, 16, 3);
11219 ha = extract32(tcr, 21, 1) && cpu_isar_feature(aa64_hafs, cpu);
11220 hd = extract32(tcr, 22, 1) && cpu_isar_feature(aa64_hdbs, cpu);
11221 ds = extract64(tcr, 32, 1);
11222 } else {
11223 bool e0pd;
11224
11225
11226
11227
11228
11229 select = extract64(va, 55, 1);
11230 if (!select) {
11231 tsz = extract32(tcr, 0, 6);
11232 gran = tg0_to_gran_size(extract32(tcr, 14, 2));
11233 epd = extract32(tcr, 7, 1);
11234 sh = extract32(tcr, 12, 2);
11235 hpd = extract64(tcr, 41, 1);
11236 e0pd = extract64(tcr, 55, 1);
11237 } else {
11238 tsz = extract32(tcr, 16, 6);
11239 gran = tg1_to_gran_size(extract32(tcr, 30, 2));
11240 epd = extract32(tcr, 23, 1);
11241 sh = extract32(tcr, 28, 2);
11242 hpd = extract64(tcr, 42, 1);
11243 e0pd = extract64(tcr, 56, 1);
11244 }
11245 ps = extract64(tcr, 32, 3);
11246 ha = extract64(tcr, 39, 1) && cpu_isar_feature(aa64_hafs, cpu);
11247 hd = extract64(tcr, 40, 1) && cpu_isar_feature(aa64_hdbs, cpu);
11248 ds = extract64(tcr, 59, 1);
11249
11250 if (e0pd && cpu_isar_feature(aa64_e0pd, cpu) &&
11251 regime_is_user(env, mmu_idx)) {
11252 epd = true;
11253 }
11254 }
11255
11256 gran = sanitize_gran_size(cpu, gran, stage2);
11257
11258 if (cpu_isar_feature(aa64_st, cpu)) {
11259 max_tsz = 48 - (gran == Gran64K);
11260 } else {
11261 max_tsz = 39;
11262 }
11263
11264
11265
11266
11267
11268 min_tsz = 16;
11269 if (gran == Gran64K) {
11270 if (cpu_isar_feature(aa64_lva, cpu)) {
11271 min_tsz = 12;
11272 }
11273 ds = false;
11274 } else if (ds) {
11275 if (regime_is_stage2(mmu_idx)) {
11276 if (gran == Gran16K) {
11277 ds = cpu_isar_feature(aa64_tgran16_2_lpa2, cpu);
11278 } else {
11279 ds = cpu_isar_feature(aa64_tgran4_2_lpa2, cpu);
11280 }
11281 } else {
11282 if (gran == Gran16K) {
11283 ds = cpu_isar_feature(aa64_tgran16_lpa2, cpu);
11284 } else {
11285 ds = cpu_isar_feature(aa64_tgran4_lpa2, cpu);
11286 }
11287 }
11288 if (ds) {
11289 min_tsz = 12;
11290 }
11291 }
11292
11293 if (stage2 && el1_is_aa32) {
11294
11295
11296
11297
11298
11299
11300 min_tsz = MIN(min_tsz, 24);
11301 }
11302
11303 if (tsz > max_tsz) {
11304 tsz = max_tsz;
11305 tsz_oob = true;
11306 } else if (tsz < min_tsz) {
11307 tsz = min_tsz;
11308 tsz_oob = true;
11309 } else {
11310 tsz_oob = false;
11311 }
11312
11313
11314 tbi = aa64_va_parameter_tbi(tcr, mmu_idx);
11315 if (!data) {
11316 tbi &= ~aa64_va_parameter_tbid(tcr, mmu_idx);
11317 }
11318 tbi = (tbi >> select) & 1;
11319
11320 return (ARMVAParameters) {
11321 .tsz = tsz,
11322 .ps = ps,
11323 .sh = sh,
11324 .select = select,
11325 .tbi = tbi,
11326 .epd = epd,
11327 .hpd = hpd,
11328 .tsz_oob = tsz_oob,
11329 .ds = ds,
11330 .ha = ha,
11331 .hd = ha && hd,
11332 .gran = gran,
11333 };
11334}
11335
11336
11337
11338
11339
11340
11341
11342
11343
11344
11345static inline uint16_t add16_sat(uint16_t a, uint16_t b)
11346{
11347 uint16_t res;
11348
11349 res = a + b;
11350 if (((res ^ a) & 0x8000) && !((a ^ b) & 0x8000)) {
11351 if (a & 0x8000) {
11352 res = 0x8000;
11353 } else {
11354 res = 0x7fff;
11355 }
11356 }
11357 return res;
11358}
11359
11360
11361static inline uint8_t add8_sat(uint8_t a, uint8_t b)
11362{
11363 uint8_t res;
11364
11365 res = a + b;
11366 if (((res ^ a) & 0x80) && !((a ^ b) & 0x80)) {
11367 if (a & 0x80) {
11368 res = 0x80;
11369 } else {
11370 res = 0x7f;
11371 }
11372 }
11373 return res;
11374}
11375
11376
11377static inline uint16_t sub16_sat(uint16_t a, uint16_t b)
11378{
11379 uint16_t res;
11380
11381 res = a - b;
11382 if (((res ^ a) & 0x8000) && ((a ^ b) & 0x8000)) {
11383 if (a & 0x8000) {
11384 res = 0x8000;
11385 } else {
11386 res = 0x7fff;
11387 }
11388 }
11389 return res;
11390}
11391
11392
11393static inline uint8_t sub8_sat(uint8_t a, uint8_t b)
11394{
11395 uint8_t res;
11396
11397 res = a - b;
11398 if (((res ^ a) & 0x80) && ((a ^ b) & 0x80)) {
11399 if (a & 0x80) {
11400 res = 0x80;
11401 } else {
11402 res = 0x7f;
11403 }
11404 }
11405 return res;
11406}
11407
11408#define ADD16(a, b, n) RESULT(add16_sat(a, b), n, 16);
11409#define SUB16(a, b, n) RESULT(sub16_sat(a, b), n, 16);
11410#define ADD8(a, b, n) RESULT(add8_sat(a, b), n, 8);
11411#define SUB8(a, b, n) RESULT(sub8_sat(a, b), n, 8);
11412#define PFX q
11413
11414#include "op_addsub.h"
11415
11416
11417static inline uint16_t add16_usat(uint16_t a, uint16_t b)
11418{
11419 uint16_t res;
11420 res = a + b;
11421 if (res < a) {
11422 res = 0xffff;
11423 }
11424 return res;
11425}
11426
11427static inline uint16_t sub16_usat(uint16_t a, uint16_t b)
11428{
11429 if (a > b) {
11430 return a - b;
11431 } else {
11432 return 0;
11433 }
11434}
11435
11436static inline uint8_t add8_usat(uint8_t a, uint8_t b)
11437{
11438 uint8_t res;
11439 res = a + b;
11440 if (res < a) {
11441 res = 0xff;
11442 }
11443 return res;
11444}
11445
11446static inline uint8_t sub8_usat(uint8_t a, uint8_t b)
11447{
11448 if (a > b) {
11449 return a - b;
11450 } else {
11451 return 0;
11452 }
11453}
11454
11455#define ADD16(a, b, n) RESULT(add16_usat(a, b), n, 16);
11456#define SUB16(a, b, n) RESULT(sub16_usat(a, b), n, 16);
11457#define ADD8(a, b, n) RESULT(add8_usat(a, b), n, 8);
11458#define SUB8(a, b, n) RESULT(sub8_usat(a, b), n, 8);
11459#define PFX uq
11460
11461#include "op_addsub.h"
11462
11463
11464#define SARITH16(a, b, n, op) do { \
11465 int32_t sum; \
11466 sum = (int32_t)(int16_t)(a) op (int32_t)(int16_t)(b); \
11467 RESULT(sum, n, 16); \
11468 if (sum >= 0) \
11469 ge |= 3 << (n * 2); \
11470 } while (0)
11471
11472#define SARITH8(a, b, n, op) do { \
11473 int32_t sum; \
11474 sum = (int32_t)(int8_t)(a) op (int32_t)(int8_t)(b); \
11475 RESULT(sum, n, 8); \
11476 if (sum >= 0) \
11477 ge |= 1 << n; \
11478 } while (0)
11479
11480
11481#define ADD16(a, b, n) SARITH16(a, b, n, +)
11482#define SUB16(a, b, n) SARITH16(a, b, n, -)
11483#define ADD8(a, b, n) SARITH8(a, b, n, +)
11484#define SUB8(a, b, n) SARITH8(a, b, n, -)
11485#define PFX s
11486#define ARITH_GE
11487
11488#include "op_addsub.h"
11489
11490
11491#define ADD16(a, b, n) do { \
11492 uint32_t sum; \
11493 sum = (uint32_t)(uint16_t)(a) + (uint32_t)(uint16_t)(b); \
11494 RESULT(sum, n, 16); \
11495 if ((sum >> 16) == 1) \
11496 ge |= 3 << (n * 2); \
11497 } while (0)
11498
11499#define ADD8(a, b, n) do { \
11500 uint32_t sum; \
11501 sum = (uint32_t)(uint8_t)(a) + (uint32_t)(uint8_t)(b); \
11502 RESULT(sum, n, 8); \
11503 if ((sum >> 8) == 1) \
11504 ge |= 1 << n; \
11505 } while (0)
11506
11507#define SUB16(a, b, n) do { \
11508 uint32_t sum; \
11509 sum = (uint32_t)(uint16_t)(a) - (uint32_t)(uint16_t)(b); \
11510 RESULT(sum, n, 16); \
11511 if ((sum >> 16) == 0) \
11512 ge |= 3 << (n * 2); \
11513 } while (0)
11514
11515#define SUB8(a, b, n) do { \
11516 uint32_t sum; \
11517 sum = (uint32_t)(uint8_t)(a) - (uint32_t)(uint8_t)(b); \
11518 RESULT(sum, n, 8); \
11519 if ((sum >> 8) == 0) \
11520 ge |= 1 << n; \
11521 } while (0)
11522
11523#define PFX u
11524#define ARITH_GE
11525
11526#include "op_addsub.h"
11527
11528
11529#define ADD16(a, b, n) \
11530 RESULT(((int32_t)(int16_t)(a) + (int32_t)(int16_t)(b)) >> 1, n, 16)
11531#define SUB16(a, b, n) \
11532 RESULT(((int32_t)(int16_t)(a) - (int32_t)(int16_t)(b)) >> 1, n, 16)
11533#define ADD8(a, b, n) \
11534 RESULT(((int32_t)(int8_t)(a) + (int32_t)(int8_t)(b)) >> 1, n, 8)
11535#define SUB8(a, b, n) \
11536 RESULT(((int32_t)(int8_t)(a) - (int32_t)(int8_t)(b)) >> 1, n, 8)
11537#define PFX sh
11538
11539#include "op_addsub.h"
11540
11541
11542#define ADD16(a, b, n) \
11543 RESULT(((uint32_t)(uint16_t)(a) + (uint32_t)(uint16_t)(b)) >> 1, n, 16)
11544#define SUB16(a, b, n) \
11545 RESULT(((uint32_t)(uint16_t)(a) - (uint32_t)(uint16_t)(b)) >> 1, n, 16)
11546#define ADD8(a, b, n) \
11547 RESULT(((uint32_t)(uint8_t)(a) + (uint32_t)(uint8_t)(b)) >> 1, n, 8)
11548#define SUB8(a, b, n) \
11549 RESULT(((uint32_t)(uint8_t)(a) - (uint32_t)(uint8_t)(b)) >> 1, n, 8)
11550#define PFX uh
11551
11552#include "op_addsub.h"
11553
11554static inline uint8_t do_usad(uint8_t a, uint8_t b)
11555{
11556 if (a > b) {
11557 return a - b;
11558 } else {
11559 return b - a;
11560 }
11561}
11562
11563
11564uint32_t HELPER(usad8)(uint32_t a, uint32_t b)
11565{
11566 uint32_t sum;
11567 sum = do_usad(a, b);
11568 sum += do_usad(a >> 8, b >> 8);
11569 sum += do_usad(a >> 16, b >> 16);
11570 sum += do_usad(a >> 24, b >> 24);
11571 return sum;
11572}
11573
11574
11575uint32_t HELPER(sel_flags)(uint32_t flags, uint32_t a, uint32_t b)
11576{
11577 uint32_t mask;
11578
11579 mask = 0;
11580 if (flags & 1) {
11581 mask |= 0xff;
11582 }
11583 if (flags & 2) {
11584 mask |= 0xff00;
11585 }
11586 if (flags & 4) {
11587 mask |= 0xff0000;
11588 }
11589 if (flags & 8) {
11590 mask |= 0xff000000;
11591 }
11592 return (a & mask) | (b & ~mask);
11593}
11594
11595
11596
11597
11598
11599
11600uint32_t HELPER(crc32)(uint32_t acc, uint32_t val, uint32_t bytes)
11601{
11602 uint8_t buf[4];
11603
11604 stl_le_p(buf, val);
11605
11606
11607 return crc32(acc ^ 0xffffffff, buf, bytes) ^ 0xffffffff;
11608}
11609
11610uint32_t HELPER(crc32c)(uint32_t acc, uint32_t val, uint32_t bytes)
11611{
11612 uint8_t buf[4];
11613
11614 stl_le_p(buf, val);
11615
11616
11617 return crc32c(acc, buf, bytes) ^ 0xffffffff;
11618}
11619
11620
11621
11622
11623
11624int fp_exception_el(CPUARMState *env, int cur_el)
11625{
11626#ifndef CONFIG_USER_ONLY
11627 uint64_t hcr_el2;
11628
11629
11630
11631
11632
11633 if (!arm_feature(env, ARM_FEATURE_V6)) {
11634 return 0;
11635 }
11636
11637 if (arm_feature(env, ARM_FEATURE_M)) {
11638
11639 if (!v7m_cpacr_pass(env, env->v7m.secure, cur_el != 0)) {
11640 return 1;
11641 }
11642
11643 if (arm_feature(env, ARM_FEATURE_M_SECURITY) && !env->v7m.secure) {
11644 if (!extract32(env->v7m.nsacr, 10, 1)) {
11645
11646 return 3;
11647 }
11648 }
11649
11650 return 0;
11651 }
11652
11653 hcr_el2 = arm_hcr_el2_eff(env);
11654
11655
11656
11657
11658
11659
11660
11661
11662 if ((hcr_el2 & (HCR_E2H | HCR_TGE)) != (HCR_E2H | HCR_TGE)) {
11663 int fpen = FIELD_EX64(env->cp15.cpacr_el1, CPACR_EL1, FPEN);
11664
11665 switch (fpen) {
11666 case 1:
11667 if (cur_el != 0) {
11668 break;
11669 }
11670
11671 case 0:
11672 case 2:
11673
11674 if (!arm_el_is_aa64(env, 3)
11675 && (cur_el == 3 || arm_is_secure_below_el3(env))) {
11676 return 3;
11677 }
11678 if (cur_el <= 1) {
11679 return 1;
11680 }
11681 break;
11682 }
11683 }
11684
11685
11686
11687
11688
11689
11690 if ((arm_feature(env, ARM_FEATURE_EL3) && !arm_el_is_aa64(env, 3) &&
11691 cur_el <= 2 && !arm_is_secure_below_el3(env))) {
11692 if (!extract32(env->cp15.nsacr, 10, 1)) {
11693
11694 return cur_el == 2 ? 2 : 1;
11695 }
11696 }
11697
11698
11699
11700
11701
11702 if (cur_el <= 2) {
11703 if (hcr_el2 & HCR_E2H) {
11704 switch (FIELD_EX64(env->cp15.cptr_el[2], CPTR_EL2, FPEN)) {
11705 case 1:
11706 if (cur_el != 0 || !(hcr_el2 & HCR_TGE)) {
11707 break;
11708 }
11709
11710 case 0:
11711 case 2:
11712 return 2;
11713 }
11714 } else if (arm_is_el2_enabled(env)) {
11715 if (FIELD_EX64(env->cp15.cptr_el[2], CPTR_EL2, TFP)) {
11716 return 2;
11717 }
11718 }
11719 }
11720
11721
11722 if (FIELD_EX64(env->cp15.cptr_el[3], CPTR_EL3, TFP)) {
11723
11724 return 3;
11725 }
11726#endif
11727 return 0;
11728}
11729
11730
11731int arm_mmu_idx_to_el(ARMMMUIdx mmu_idx)
11732{
11733 if (mmu_idx & ARM_MMU_IDX_M) {
11734 return mmu_idx & ARM_MMU_IDX_M_PRIV;
11735 }
11736
11737 switch (mmu_idx) {
11738 case ARMMMUIdx_E10_0:
11739 case ARMMMUIdx_E20_0:
11740 return 0;
11741 case ARMMMUIdx_E10_1:
11742 case ARMMMUIdx_E10_1_PAN:
11743 return 1;
11744 case ARMMMUIdx_E2:
11745 case ARMMMUIdx_E20_2:
11746 case ARMMMUIdx_E20_2_PAN:
11747 return 2;
11748 case ARMMMUIdx_E3:
11749 return 3;
11750 default:
11751 g_assert_not_reached();
11752 }
11753}
11754
11755#ifndef CONFIG_TCG
11756ARMMMUIdx arm_v7m_mmu_idx_for_secstate(CPUARMState *env, bool secstate)
11757{
11758 g_assert_not_reached();
11759}
11760#endif
11761
11762static bool arm_pan_enabled(CPUARMState *env)
11763{
11764 if (is_a64(env)) {
11765 return env->pstate & PSTATE_PAN;
11766 } else {
11767 return env->uncached_cpsr & CPSR_PAN;
11768 }
11769}
11770
11771ARMMMUIdx arm_mmu_idx_el(CPUARMState *env, int el)
11772{
11773 ARMMMUIdx idx;
11774 uint64_t hcr;
11775
11776 if (arm_feature(env, ARM_FEATURE_M)) {
11777 return arm_v7m_mmu_idx_for_secstate(env, env->v7m.secure);
11778 }
11779
11780
11781 switch (el) {
11782 case 0:
11783 hcr = arm_hcr_el2_eff(env);
11784 if ((hcr & (HCR_E2H | HCR_TGE)) == (HCR_E2H | HCR_TGE)) {
11785 idx = ARMMMUIdx_E20_0;
11786 } else {
11787 idx = ARMMMUIdx_E10_0;
11788 }
11789 break;
11790 case 1:
11791 if (arm_pan_enabled(env)) {
11792 idx = ARMMMUIdx_E10_1_PAN;
11793 } else {
11794 idx = ARMMMUIdx_E10_1;
11795 }
11796 break;
11797 case 2:
11798
11799 if (arm_hcr_el2_eff(env) & HCR_E2H) {
11800 if (arm_pan_enabled(env)) {
11801 idx = ARMMMUIdx_E20_2_PAN;
11802 } else {
11803 idx = ARMMMUIdx_E20_2;
11804 }
11805 } else {
11806 idx = ARMMMUIdx_E2;
11807 }
11808 break;
11809 case 3:
11810 return ARMMMUIdx_E3;
11811 default:
11812 g_assert_not_reached();
11813 }
11814
11815 return idx;
11816}
11817
11818ARMMMUIdx arm_mmu_idx(CPUARMState *env)
11819{
11820 return arm_mmu_idx_el(env, arm_current_el(env));
11821}
11822
11823static bool mve_no_pred(CPUARMState *env)
11824{
11825
11826
11827
11828
11829
11830
11831
11832
11833
11834
11835
11836
11837
11838
11839
11840 if (cpu_isar_feature(aa32_mve, env_archcpu(env))) {
11841 return false;
11842 }
11843 if (env->v7m.vpr) {
11844 return false;
11845 }
11846 if (env->v7m.ltpsize < 4) {
11847 return false;
11848 }
11849 return true;
11850}
11851
11852void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
11853 target_ulong *cs_base, uint32_t *pflags)
11854{
11855 CPUARMTBFlags flags;
11856
11857 assert_hflags_rebuild_correctly(env);
11858 flags = env->hflags;
11859
11860 if (EX_TBFLAG_ANY(flags, AARCH64_STATE)) {
11861 *pc = env->pc;
11862 if (cpu_isar_feature(aa64_bti, env_archcpu(env))) {
11863 DP_TBFLAG_A64(flags, BTYPE, env->btype);
11864 }
11865 } else {
11866 *pc = env->regs[15];
11867
11868 if (arm_feature(env, ARM_FEATURE_M)) {
11869 if (arm_feature(env, ARM_FEATURE_M_SECURITY) &&
11870 FIELD_EX32(env->v7m.fpccr[M_REG_S], V7M_FPCCR, S)
11871 != env->v7m.secure) {
11872 DP_TBFLAG_M32(flags, FPCCR_S_WRONG, 1);
11873 }
11874
11875 if ((env->v7m.fpccr[env->v7m.secure] & R_V7M_FPCCR_ASPEN_MASK) &&
11876 (!(env->v7m.control[M_REG_S] & R_V7M_CONTROL_FPCA_MASK) ||
11877 (env->v7m.secure &&
11878 !(env->v7m.control[M_REG_S] & R_V7M_CONTROL_SFPA_MASK)))) {
11879
11880
11881
11882
11883
11884 DP_TBFLAG_M32(flags, NEW_FP_CTXT_NEEDED, 1);
11885 }
11886
11887 bool is_secure = env->v7m.fpccr[M_REG_S] & R_V7M_FPCCR_S_MASK;
11888 if (env->v7m.fpccr[is_secure] & R_V7M_FPCCR_LSPACT_MASK) {
11889 DP_TBFLAG_M32(flags, LSPACT, 1);
11890 }
11891
11892 if (mve_no_pred(env)) {
11893 DP_TBFLAG_M32(flags, MVE_NO_PRED, 1);
11894 }
11895 } else {
11896
11897
11898
11899
11900 if (arm_feature(env, ARM_FEATURE_XSCALE)) {
11901 DP_TBFLAG_A32(flags, XSCALE_CPAR, env->cp15.c15_cpar);
11902 } else {
11903 DP_TBFLAG_A32(flags, VECLEN, env->vfp.vec_len);
11904 DP_TBFLAG_A32(flags, VECSTRIDE, env->vfp.vec_stride);
11905 }
11906 if (env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30)) {
11907 DP_TBFLAG_A32(flags, VFPEN, 1);
11908 }
11909 }
11910
11911 DP_TBFLAG_AM32(flags, THUMB, env->thumb);
11912 DP_TBFLAG_AM32(flags, CONDEXEC, env->condexec_bits);
11913 }
11914
11915
11916
11917
11918
11919
11920
11921
11922
11923
11924 if (EX_TBFLAG_ANY(flags, SS_ACTIVE) && (env->pstate & PSTATE_SS)) {
11925 DP_TBFLAG_ANY(flags, PSTATE__SS, 1);
11926 }
11927
11928 *pflags = flags.flags;
11929 *cs_base = flags.flags2;
11930}
11931
11932#ifdef TARGET_AARCH64
11933
11934
11935
11936
11937
11938
11939
11940
11941
11942
11943
11944
11945
11946
11947void aarch64_sve_narrow_vq(CPUARMState *env, unsigned vq)
11948{
11949 int i, j;
11950 uint64_t pmask;
11951
11952 assert(vq >= 1 && vq <= ARM_MAX_VQ);
11953 assert(vq <= env_archcpu(env)->sve_max_vq);
11954
11955
11956 for (i = 0; i < 32; i++) {
11957 memset(&env->vfp.zregs[i].d[2 * vq], 0, 16 * (ARM_MAX_VQ - vq));
11958 }
11959
11960
11961 pmask = 0;
11962 if (vq & 3) {
11963 pmask = ~(-1ULL << (16 * (vq & 3)));
11964 }
11965 for (j = vq / 4; j < ARM_MAX_VQ / 4; j++) {
11966 for (i = 0; i < 17; ++i) {
11967 env->vfp.pregs[i].p[j] &= pmask;
11968 }
11969 pmask = 0;
11970 }
11971}
11972
11973static uint32_t sve_vqm1_for_el_sm_ena(CPUARMState *env, int el, bool sm)
11974{
11975 int exc_el;
11976
11977 if (sm) {
11978 exc_el = sme_exception_el(env, el);
11979 } else {
11980 exc_el = sve_exception_el(env, el);
11981 }
11982 if (exc_el) {
11983 return 0;
11984 }
11985 return sve_vqm1_for_el_sm(env, el, sm);
11986}
11987
11988
11989
11990
11991void aarch64_sve_change_el(CPUARMState *env, int old_el,
11992 int new_el, bool el0_a64)
11993{
11994 ARMCPU *cpu = env_archcpu(env);
11995 int old_len, new_len;
11996 bool old_a64, new_a64, sm;
11997
11998
11999 if (!cpu_isar_feature(aa64_sve, cpu)) {
12000 return;
12001 }
12002
12003
12004 if (fp_exception_el(env, old_el) || fp_exception_el(env, new_el)) {
12005 return;
12006 }
12007
12008 old_a64 = old_el ? arm_el_is_aa64(env, old_el) : el0_a64;
12009 new_a64 = new_el ? arm_el_is_aa64(env, new_el) : el0_a64;
12010
12011
12012
12013
12014
12015
12016 sm = FIELD_EX64(env->svcr, SVCR, SM);
12017 if (old_a64 != new_a64 && sm) {
12018 arm_reset_sve_state(env);
12019 return;
12020 }
12021
12022
12023
12024
12025
12026
12027
12028
12029
12030
12031
12032
12033
12034 old_len = new_len = 0;
12035 if (old_a64) {
12036 old_len = sve_vqm1_for_el_sm_ena(env, old_el, sm);
12037 }
12038 if (new_a64) {
12039 new_len = sve_vqm1_for_el_sm_ena(env, new_el, sm);
12040 }
12041
12042
12043 if (new_len < old_len) {
12044 aarch64_sve_narrow_vq(env, new_len + 1);
12045 }
12046}
12047#endif
12048