1#include "qemu/osdep.h"
2#include "trace.h"
3#include "cpu.h"
4#include "internals.h"
5#include "exec/gdbstub.h"
6#include "exec/helper-proto.h"
7#include "qemu/host-utils.h"
8#include "sysemu/arch_init.h"
9#include "sysemu/sysemu.h"
10#include "qemu/bitops.h"
11#include "qemu/crc32c.h"
12#include "exec/exec-all.h"
13#include "exec/cpu_ldst.h"
14#include "arm_ldst.h"
15#include <zlib.h>
16#include "exec/semihost.h"
17#include "sysemu/kvm.h"
18
19#define ARM_CPU_FREQ 1000000000
20
21#ifndef CONFIG_USER_ONLY
22static bool get_phys_addr(CPUARMState *env, target_ulong address,
23 int access_type, ARMMMUIdx mmu_idx,
24 hwaddr *phys_ptr, MemTxAttrs *attrs, int *prot,
25 target_ulong *page_size, uint32_t *fsr,
26 ARMMMUFaultInfo *fi);
27
28static bool get_phys_addr_lpae(CPUARMState *env, target_ulong address,
29 int access_type, ARMMMUIdx mmu_idx,
30 hwaddr *phys_ptr, MemTxAttrs *txattrs, int *prot,
31 target_ulong *page_size_ptr, uint32_t *fsr,
32 ARMMMUFaultInfo *fi);
33
34
35#define PMCRD 0x8
36#define PMCRC 0x4
37#define PMCRE 0x1
38#endif
39
40static int vfp_gdb_get_reg(CPUARMState *env, uint8_t *buf, int reg)
41{
42 int nregs;
43
44
45 nregs = arm_feature(env, ARM_FEATURE_VFP3) ? 32 : 16;
46 if (reg < nregs) {
47 stfq_le_p(buf, env->vfp.regs[reg]);
48 return 8;
49 }
50 if (arm_feature(env, ARM_FEATURE_NEON)) {
51
52 nregs += 16;
53 if (reg < nregs) {
54 stfq_le_p(buf, env->vfp.regs[(reg - 32) * 2]);
55 stfq_le_p(buf + 8, env->vfp.regs[(reg - 32) * 2 + 1]);
56 return 16;
57 }
58 }
59 switch (reg - nregs) {
60 case 0: stl_p(buf, env->vfp.xregs[ARM_VFP_FPSID]); return 4;
61 case 1: stl_p(buf, env->vfp.xregs[ARM_VFP_FPSCR]); return 4;
62 case 2: stl_p(buf, env->vfp.xregs[ARM_VFP_FPEXC]); return 4;
63 }
64 return 0;
65}
66
67static int vfp_gdb_set_reg(CPUARMState *env, uint8_t *buf, int reg)
68{
69 int nregs;
70
71 nregs = arm_feature(env, ARM_FEATURE_VFP3) ? 32 : 16;
72 if (reg < nregs) {
73 env->vfp.regs[reg] = ldfq_le_p(buf);
74 return 8;
75 }
76 if (arm_feature(env, ARM_FEATURE_NEON)) {
77 nregs += 16;
78 if (reg < nregs) {
79 env->vfp.regs[(reg - 32) * 2] = ldfq_le_p(buf);
80 env->vfp.regs[(reg - 32) * 2 + 1] = ldfq_le_p(buf + 8);
81 return 16;
82 }
83 }
84 switch (reg - nregs) {
85 case 0: env->vfp.xregs[ARM_VFP_FPSID] = ldl_p(buf); return 4;
86 case 1: env->vfp.xregs[ARM_VFP_FPSCR] = ldl_p(buf); return 4;
87 case 2: env->vfp.xregs[ARM_VFP_FPEXC] = ldl_p(buf) & (1 << 30); return 4;
88 }
89 return 0;
90}
91
92static int arm_sys_gdb_get_reg(CPUARMState *env, uint8_t *buf, int reg)
93{
94 switch (reg) {
95 case 0:
96
97 stl_p(buf, env->cp15.tcr_el[3].raw_tcr);
98 return 4;
99 case 1:
100
101 stl_p(buf, env->cp15.ttbr0_s);
102 return 4;
103 case 2:
104
105 stl_p(buf, env->cp15.ttbr1_s);
106 return 4;
107 default:
108 return 0;
109 }
110}
111
112static int arm_sys_gdb_set_reg(CPUARMState *env, uint8_t *buf, int reg)
113{
114 switch (reg) {
115 case 0:
116
117 return 0;
118 case 1:
119
120 env->cp15.ttbr0_s = ldl_p(buf);
121 return 4;
122 case 2:
123
124 env->cp15.ttbr1_s = ldl_p(buf);
125 return 4;
126 default:
127 return 0;
128 }
129}
130
131static int aarch64_fpu_gdb_get_reg(CPUARMState *env, uint8_t *buf, int reg)
132{
133 switch (reg) {
134 case 0 ... 31:
135
136 stfq_le_p(buf, env->vfp.regs[reg * 2]);
137 stfq_le_p(buf + 8, env->vfp.regs[reg * 2 + 1]);
138 return 16;
139 case 32:
140
141 stl_p(buf, vfp_get_fpsr(env));
142 return 4;
143 case 33:
144
145 stl_p(buf, vfp_get_fpcr(env));
146 return 4;
147 default:
148 return 0;
149 }
150}
151
152static int aarch64_fpu_gdb_set_reg(CPUARMState *env, uint8_t *buf, int reg)
153{
154 switch (reg) {
155 case 0 ... 31:
156
157 env->vfp.regs[reg * 2] = ldfq_le_p(buf);
158 env->vfp.regs[reg * 2 + 1] = ldfq_le_p(buf + 8);
159 return 16;
160 case 32:
161
162 vfp_set_fpsr(env, ldl_p(buf));
163 return 4;
164 case 33:
165
166 vfp_set_fpcr(env, ldl_p(buf));
167 return 4;
168 default:
169 return 0;
170 }
171}
172
173static int aarch64_elx_gdb_get_reg(CPUARMState *env, uint8_t *buf, int reg, int el)
174{
175 switch (reg) {
176 case 0:
177 stfq_le_p(buf, env->elr_el[el]);
178 return 8;
179 case 1:
180 stfq_le_p(buf, env->cp15.esr_el[el]);
181 return 8;
182 case 2:
183 stfq_le_p(buf, env->banked_spsr[aarch64_banked_spsr_index(el)]);
184 return 8;
185 case 3:
186 stfq_le_p(buf, env->cp15.ttbr0_el[el]);
187 return 8;
188 case 4:
189 if (el == 1) {
190 stfq_le_p(buf, env->cp15.ttbr1_el[el]);
191 return 8;
192 }
193
194 default:
195 return 0;
196 }
197}
198
199static int aarch64_elx_gdb_set_reg(CPUARMState *env, uint8_t *buf, int reg, int el)
200{
201 switch (reg) {
202 case 0:
203 env->elr_el[el] = ldfq_le_p(buf);
204 return 8;
205 case 1:
206 env->cp15.esr_el[el] = ldfq_le_p(buf);
207 return 8;
208 case 2:
209 env->banked_spsr[aarch64_banked_spsr_index(el)] = ldfq_le_p(buf);
210 return 8;
211 case 3:
212 env->cp15.ttbr0_el[el] = ldfq_le_p(buf);
213 return 8;
214 case 4:
215 if (el == 1) {
216 env->cp15.ttbr1_el[el] = ldfq_le_p(buf);
217 return 8;
218 }
219
220 default:
221 return 0;
222 }
223}
224
225static int aarch64_el1_gdb_get_reg(CPUARMState *env, uint8_t *buf, int reg)
226{
227 return aarch64_elx_gdb_get_reg(env, buf, reg, 1);
228}
229
230static int aarch64_el1_gdb_set_reg(CPUARMState *env, uint8_t *buf, int reg)
231{
232 return aarch64_elx_gdb_set_reg(env, buf, reg, 1);
233}
234
235static int aarch64_el2_gdb_get_reg(CPUARMState *env, uint8_t *buf, int reg)
236{
237 return aarch64_elx_gdb_get_reg(env, buf, reg, 2);
238}
239
240static int aarch64_el2_gdb_set_reg(CPUARMState *env, uint8_t *buf, int reg)
241{
242 return aarch64_elx_gdb_set_reg(env, buf, reg, 2);
243}
244
245static int aarch64_el3_gdb_get_reg(CPUARMState *env, uint8_t *buf, int reg)
246{
247 return aarch64_elx_gdb_get_reg(env, buf, reg, 3);
248}
249
250static int aarch64_el3_gdb_set_reg(CPUARMState *env, uint8_t *buf, int reg)
251{
252 return aarch64_elx_gdb_set_reg(env, buf, reg, 3);
253}
254
255static uint64_t raw_read(CPUARMState *env, const ARMCPRegInfo *ri)
256{
257 assert(ri->fieldoffset);
258 if (cpreg_field_is_64bit(ri)) {
259 return CPREG_FIELD64(env, ri);
260 } else {
261 return CPREG_FIELD32(env, ri);
262 }
263}
264
265static void raw_write(CPUARMState *env, const ARMCPRegInfo *ri,
266 uint64_t value)
267{
268 assert(ri->fieldoffset);
269 if (cpreg_field_is_64bit(ri)) {
270 CPREG_FIELD64(env, ri) = value;
271 } else {
272 CPREG_FIELD32(env, ri) = value;
273 }
274}
275
276static void *raw_ptr(CPUARMState *env, const ARMCPRegInfo *ri)
277{
278 return (char *)env + ri->fieldoffset;
279}
280
281uint64_t read_raw_cp_reg(CPUARMState *env, const ARMCPRegInfo *ri)
282{
283
284 if (ri->type & ARM_CP_CONST) {
285 return ri->resetvalue;
286 } else if (ri->raw_readfn) {
287 return ri->raw_readfn(env, ri);
288 } else if (ri->readfn) {
289 return ri->readfn(env, ri);
290 } else {
291 return raw_read(env, ri);
292 }
293}
294
295static void write_raw_cp_reg(CPUARMState *env, const ARMCPRegInfo *ri,
296 uint64_t v)
297{
298
299
300
301
302
303 if (ri->type & ARM_CP_CONST) {
304 return;
305 } else if (ri->raw_writefn) {
306 ri->raw_writefn(env, ri, v);
307 } else if (ri->writefn) {
308 ri->writefn(env, ri, v);
309 } else {
310 raw_write(env, ri, v);
311 }
312}
313
314static bool raw_accessors_invalid(const ARMCPRegInfo *ri)
315{
316
317
318
319
320
321
322
323
324
325
326
327 if ((ri->type & ARM_CP_CONST) ||
328 ri->fieldoffset ||
329 ((ri->raw_writefn || ri->writefn) && (ri->raw_readfn || ri->readfn))) {
330 return false;
331 }
332 return true;
333}
334
335bool write_cpustate_to_list(ARMCPU *cpu)
336{
337
338 int i;
339 bool ok = true;
340
341 for (i = 0; i < cpu->cpreg_array_len; i++) {
342 uint32_t regidx = kvm_to_cpreg_id(cpu->cpreg_indexes[i]);
343 const ARMCPRegInfo *ri;
344
345 ri = get_arm_cp_reginfo(cpu->cp_regs, regidx);
346 if (!ri) {
347 ok = false;
348 continue;
349 }
350 if (ri->type & ARM_CP_NO_RAW) {
351 continue;
352 }
353 cpu->cpreg_values[i] = read_raw_cp_reg(&cpu->env, ri);
354 }
355 return ok;
356}
357
358bool write_list_to_cpustate(ARMCPU *cpu)
359{
360 int i;
361 bool ok = true;
362
363 for (i = 0; i < cpu->cpreg_array_len; i++) {
364 uint32_t regidx = kvm_to_cpreg_id(cpu->cpreg_indexes[i]);
365 uint64_t v = cpu->cpreg_values[i];
366 const ARMCPRegInfo *ri;
367
368 ri = get_arm_cp_reginfo(cpu->cp_regs, regidx);
369 if (!ri) {
370 ok = false;
371 continue;
372 }
373 if (ri->type & ARM_CP_NO_RAW) {
374 continue;
375 }
376
377
378
379
380 write_raw_cp_reg(&cpu->env, ri, v);
381 if (read_raw_cp_reg(&cpu->env, ri) != v) {
382 ok = false;
383 }
384 }
385 return ok;
386}
387
388static void add_cpreg_to_list(gpointer key, gpointer opaque)
389{
390 ARMCPU *cpu = opaque;
391 uint64_t regidx;
392 const ARMCPRegInfo *ri;
393
394 regidx = *(uint32_t *)key;
395 ri = get_arm_cp_reginfo(cpu->cp_regs, regidx);
396
397 if (!(ri->type & (ARM_CP_NO_RAW|ARM_CP_ALIAS))) {
398 cpu->cpreg_indexes[cpu->cpreg_array_len] = cpreg_to_kvm_id(regidx);
399
400 cpu->cpreg_array_len++;
401 }
402}
403
404static void count_cpreg(gpointer key, gpointer opaque)
405{
406 ARMCPU *cpu = opaque;
407 uint64_t regidx;
408 const ARMCPRegInfo *ri;
409
410 regidx = *(uint32_t *)key;
411 ri = get_arm_cp_reginfo(cpu->cp_regs, regidx);
412
413 if (!(ri->type & (ARM_CP_NO_RAW|ARM_CP_ALIAS))) {
414 cpu->cpreg_array_len++;
415 }
416}
417
418static gint cpreg_key_compare(gconstpointer a, gconstpointer b)
419{
420 uint64_t aidx = cpreg_to_kvm_id(*(uint32_t *)a);
421 uint64_t bidx = cpreg_to_kvm_id(*(uint32_t *)b);
422
423 if (aidx > bidx) {
424 return 1;
425 }
426 if (aidx < bidx) {
427 return -1;
428 }
429 return 0;
430}
431
432void init_cpreg_list(ARMCPU *cpu)
433{
434
435
436
437 GList *keys;
438 int arraylen;
439
440 keys = g_hash_table_get_keys(cpu->cp_regs);
441 keys = g_list_sort(keys, cpreg_key_compare);
442
443 cpu->cpreg_array_len = 0;
444
445 g_list_foreach(keys, count_cpreg, cpu);
446
447 arraylen = cpu->cpreg_array_len;
448 cpu->cpreg_indexes = g_new(uint64_t, arraylen);
449 cpu->cpreg_values = g_new(uint64_t, arraylen);
450 cpu->cpreg_vmstate_indexes = g_new(uint64_t, arraylen);
451 cpu->cpreg_vmstate_values = g_new(uint64_t, arraylen);
452 cpu->cpreg_vmstate_array_len = cpu->cpreg_array_len;
453 cpu->cpreg_array_len = 0;
454
455 g_list_foreach(keys, add_cpreg_to_list, cpu);
456
457 assert(cpu->cpreg_array_len == arraylen);
458
459 g_list_free(keys);
460}
461
462
463
464
465
466
467
468
469static CPAccessResult access_el3_aa32ns(CPUARMState *env,
470 const ARMCPRegInfo *ri,
471 bool isread)
472{
473 bool secure = arm_is_secure_below_el3(env);
474
475 assert(!arm_el_is_aa64(env, 3));
476 if (secure) {
477 return CP_ACCESS_TRAP_UNCATEGORIZED;
478 }
479 return CP_ACCESS_OK;
480}
481
482static CPAccessResult access_el3_aa32ns_aa64any(CPUARMState *env,
483 const ARMCPRegInfo *ri,
484 bool isread)
485{
486 if (!arm_el_is_aa64(env, 3)) {
487 return access_el3_aa32ns(env, ri, isread);
488 }
489 return CP_ACCESS_OK;
490}
491
492
493
494
495
496
497static CPAccessResult access_trap_aa32s_el1(CPUARMState *env,
498 const ARMCPRegInfo *ri,
499 bool isread)
500{
501 if (arm_current_el(env) == 3) {
502 return CP_ACCESS_OK;
503 }
504 if (arm_is_secure_below_el3(env)) {
505 return CP_ACCESS_TRAP_EL3;
506 }
507
508 return CP_ACCESS_TRAP_UNCATEGORIZED;
509}
510
511
512
513
514static CPAccessResult access_tdosa(CPUARMState *env, const ARMCPRegInfo *ri,
515 bool isread)
516{
517 int el = arm_current_el(env);
518
519 if (el < 2 && (env->cp15.mdcr_el2 & MDCR_TDOSA)
520 && !arm_is_secure_below_el3(env)) {
521 return CP_ACCESS_TRAP_EL2;
522 }
523 if (el < 3 && (env->cp15.mdcr_el3 & MDCR_TDOSA)) {
524 return CP_ACCESS_TRAP_EL3;
525 }
526 return CP_ACCESS_OK;
527}
528
529
530
531
532static CPAccessResult access_tdra(CPUARMState *env, const ARMCPRegInfo *ri,
533 bool isread)
534{
535 int el = arm_current_el(env);
536
537 if (el < 2 && (env->cp15.mdcr_el2 & MDCR_TDRA)
538 && !arm_is_secure_below_el3(env)) {
539 return CP_ACCESS_TRAP_EL2;
540 }
541 if (el < 3 && (env->cp15.mdcr_el3 & MDCR_TDA)) {
542 return CP_ACCESS_TRAP_EL3;
543 }
544 return CP_ACCESS_OK;
545}
546
547
548
549
550static CPAccessResult access_tda(CPUARMState *env, const ARMCPRegInfo *ri,
551 bool isread)
552{
553 int el = arm_current_el(env);
554
555 if (el < 2 && (env->cp15.mdcr_el2 & MDCR_TDA)
556 && !arm_is_secure_below_el3(env)) {
557 return CP_ACCESS_TRAP_EL2;
558 }
559 if (el < 3 && (env->cp15.mdcr_el3 & MDCR_TDA)) {
560 return CP_ACCESS_TRAP_EL3;
561 }
562 return CP_ACCESS_OK;
563}
564
565
566
567
568static CPAccessResult access_tpm(CPUARMState *env, const ARMCPRegInfo *ri,
569 bool isread)
570{
571 int el = arm_current_el(env);
572
573 if (el < 2 && (env->cp15.mdcr_el2 & MDCR_TPM)
574 && !arm_is_secure_below_el3(env)) {
575 return CP_ACCESS_TRAP_EL2;
576 }
577 if (el < 3 && (env->cp15.mdcr_el3 & MDCR_TPM)) {
578 return CP_ACCESS_TRAP_EL3;
579 }
580 return CP_ACCESS_OK;
581}
582
583static void dacr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
584{
585 ARMCPU *cpu = arm_env_get_cpu(env);
586
587 raw_write(env, ri, value);
588 tlb_flush(CPU(cpu), 1);
589}
590
591static void fcse_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
592{
593 ARMCPU *cpu = arm_env_get_cpu(env);
594
595 if (raw_read(env, ri) != value) {
596
597
598
599 tlb_flush(CPU(cpu), 1);
600 raw_write(env, ri, value);
601 }
602}
603
604static void contextidr_write(CPUARMState *env, const ARMCPRegInfo *ri,
605 uint64_t value)
606{
607 ARMCPU *cpu = arm_env_get_cpu(env);
608
609 if (raw_read(env, ri) != value && !arm_feature(env, ARM_FEATURE_MPU)
610 && !extended_addresses_enabled(env)) {
611
612
613
614
615 tlb_flush(CPU(cpu), 1);
616 }
617 raw_write(env, ri, value);
618}
619
620static void tlbiall_write(CPUARMState *env, const ARMCPRegInfo *ri,
621 uint64_t value)
622{
623
624 ARMCPU *cpu = arm_env_get_cpu(env);
625
626 tlb_flush(CPU(cpu), 1);
627}
628
629static void tlbimva_write(CPUARMState *env, const ARMCPRegInfo *ri,
630 uint64_t value)
631{
632
633 ARMCPU *cpu = arm_env_get_cpu(env);
634
635 tlb_flush_page(CPU(cpu), value & TARGET_PAGE_MASK);
636}
637
638static void tlbiasid_write(CPUARMState *env, const ARMCPRegInfo *ri,
639 uint64_t value)
640{
641
642 ARMCPU *cpu = arm_env_get_cpu(env);
643
644 tlb_flush(CPU(cpu), value == 0);
645}
646
647static void tlbimvaa_write(CPUARMState *env, const ARMCPRegInfo *ri,
648 uint64_t value)
649{
650
651 ARMCPU *cpu = arm_env_get_cpu(env);
652
653 tlb_flush_page(CPU(cpu), value & TARGET_PAGE_MASK);
654}
655
656
657static void tlbiall_is_write(CPUARMState *env, const ARMCPRegInfo *ri,
658 uint64_t value)
659{
660 CPUState *other_cs;
661
662 CPU_FOREACH(other_cs) {
663 tlb_flush(other_cs, 1);
664 }
665}
666
667static void tlbiasid_is_write(CPUARMState *env, const ARMCPRegInfo *ri,
668 uint64_t value)
669{
670 CPUState *other_cs;
671
672 CPU_FOREACH(other_cs) {
673 tlb_flush(other_cs, value == 0);
674 }
675}
676
677static void tlbimva_is_write(CPUARMState *env, const ARMCPRegInfo *ri,
678 uint64_t value)
679{
680 CPUState *other_cs;
681
682 CPU_FOREACH(other_cs) {
683 tlb_flush_page(other_cs, value & TARGET_PAGE_MASK);
684 }
685}
686
687static void tlbimvaa_is_write(CPUARMState *env, const ARMCPRegInfo *ri,
688 uint64_t value)
689{
690 CPUState *other_cs;
691
692 CPU_FOREACH(other_cs) {
693 tlb_flush_page(other_cs, value & TARGET_PAGE_MASK);
694 }
695}
696
697static void tlbiall_nsnh_write(CPUARMState *env, const ARMCPRegInfo *ri,
698 uint64_t value)
699{
700 CPUState *cs = ENV_GET_CPU(env);
701
702 tlb_flush_by_mmuidx(cs, ARMMMUIdx_S12NSE1, ARMMMUIdx_S12NSE0,
703 ARMMMUIdx_S2NS, -1);
704}
705
706static void tlbiall_nsnh_is_write(CPUARMState *env, const ARMCPRegInfo *ri,
707 uint64_t value)
708{
709 CPUState *other_cs;
710
711 CPU_FOREACH(other_cs) {
712 tlb_flush_by_mmuidx(other_cs, ARMMMUIdx_S12NSE1,
713 ARMMMUIdx_S12NSE0, ARMMMUIdx_S2NS, -1);
714 }
715}
716
717static void tlbiipas2_write(CPUARMState *env, const ARMCPRegInfo *ri,
718 uint64_t value)
719{
720
721
722
723
724
725
726 CPUState *cs = ENV_GET_CPU(env);
727 uint64_t pageaddr;
728
729 if (!arm_feature(env, ARM_FEATURE_EL2) || !(env->cp15.scr_el3 & SCR_NS)) {
730 return;
731 }
732
733 pageaddr = sextract64(value << 12, 0, 40);
734
735 tlb_flush_page_by_mmuidx(cs, pageaddr, ARMMMUIdx_S2NS, -1);
736}
737
738static void tlbiipas2_is_write(CPUARMState *env, const ARMCPRegInfo *ri,
739 uint64_t value)
740{
741 CPUState *other_cs;
742 uint64_t pageaddr;
743
744 if (!arm_feature(env, ARM_FEATURE_EL2) || !(env->cp15.scr_el3 & SCR_NS)) {
745 return;
746 }
747
748 pageaddr = sextract64(value << 12, 0, 40);
749
750 CPU_FOREACH(other_cs) {
751 tlb_flush_page_by_mmuidx(other_cs, pageaddr, ARMMMUIdx_S2NS, -1);
752 }
753}
754
755static void tlbiall_hyp_write(CPUARMState *env, const ARMCPRegInfo *ri,
756 uint64_t value)
757{
758 CPUState *cs = ENV_GET_CPU(env);
759
760 tlb_flush_by_mmuidx(cs, ARMMMUIdx_S1E2, -1);
761}
762
763static void tlbiall_hyp_is_write(CPUARMState *env, const ARMCPRegInfo *ri,
764 uint64_t value)
765{
766 CPUState *other_cs;
767
768 CPU_FOREACH(other_cs) {
769 tlb_flush_by_mmuidx(other_cs, ARMMMUIdx_S1E2, -1);
770 }
771}
772
773static void tlbimva_hyp_write(CPUARMState *env, const ARMCPRegInfo *ri,
774 uint64_t value)
775{
776 CPUState *cs = ENV_GET_CPU(env);
777 uint64_t pageaddr = value & ~MAKE_64BIT_MASK(0, 12);
778
779 tlb_flush_page_by_mmuidx(cs, pageaddr, ARMMMUIdx_S1E2, -1);
780}
781
782static void tlbimva_hyp_is_write(CPUARMState *env, const ARMCPRegInfo *ri,
783 uint64_t value)
784{
785 CPUState *other_cs;
786 uint64_t pageaddr = value & ~MAKE_64BIT_MASK(0, 12);
787
788 CPU_FOREACH(other_cs) {
789 tlb_flush_page_by_mmuidx(other_cs, pageaddr, ARMMMUIdx_S1E2, -1);
790 }
791}
792
793static const ARMCPRegInfo cp_reginfo[] = {
794
795
796
797
798
799 { .name = "FCSEIDR(NS)",
800 .cp = 15, .opc1 = 0, .crn = 13, .crm = 0, .opc2 = 0,
801 .access = PL1_RW, .secure = ARM_CP_SECSTATE_NS,
802 .fieldoffset = offsetof(CPUARMState, cp15.fcseidr_ns),
803 .resetvalue = 0, .writefn = fcse_write, .raw_writefn = raw_write, },
804 { .name = "FCSEIDR(S)",
805 .cp = 15, .opc1 = 0, .crn = 13, .crm = 0, .opc2 = 0,
806 .access = PL1_RW, .secure = ARM_CP_SECSTATE_S,
807 .fieldoffset = offsetof(CPUARMState, cp15.fcseidr_s),
808 .resetvalue = 0, .writefn = fcse_write, .raw_writefn = raw_write, },
809
810
811
812
813
814
815 { .name = "CONTEXTIDR_EL1", .state = ARM_CP_STATE_BOTH,
816 .opc0 = 3, .opc1 = 0, .crn = 13, .crm = 0, .opc2 = 1,
817 .access = PL1_RW, .secure = ARM_CP_SECSTATE_NS,
818 .fieldoffset = offsetof(CPUARMState, cp15.contextidr_el[1]),
819 .resetvalue = 0, .writefn = contextidr_write, .raw_writefn = raw_write, },
820 { .name = "CONTEXTIDR(S)", .state = ARM_CP_STATE_AA32,
821 .cp = 15, .opc1 = 0, .crn = 13, .crm = 0, .opc2 = 1,
822 .access = PL1_RW, .secure = ARM_CP_SECSTATE_S,
823 .fieldoffset = offsetof(CPUARMState, cp15.contextidr_s),
824 .resetvalue = 0, .writefn = contextidr_write, .raw_writefn = raw_write, },
825 REGINFO_SENTINEL
826};
827
828static const ARMCPRegInfo not_v8_cp_reginfo[] = {
829
830
831
832
833 { .name = "DACR",
834 .cp = 15, .opc1 = CP_ANY, .crn = 3, .crm = CP_ANY, .opc2 = CP_ANY,
835 .access = PL1_RW, .resetvalue = 0,
836 .writefn = dacr_write, .raw_writefn = raw_write,
837 .bank_fieldoffsets = { offsetoflow32(CPUARMState, cp15.dacr_s),
838 offsetoflow32(CPUARMState, cp15.dacr_ns) } },
839
840
841
842 { .name = "TLB_LOCKDOWN", .cp = 15, .crn = 10, .crm = 0,
843 .opc1 = CP_ANY, .opc2 = CP_ANY, .access = PL1_RW, .type = ARM_CP_NOP },
844 { .name = "TLB_LOCKDOWN", .cp = 15, .crn = 10, .crm = 1,
845 .opc1 = CP_ANY, .opc2 = CP_ANY, .access = PL1_RW, .type = ARM_CP_NOP },
846 { .name = "TLB_LOCKDOWN", .cp = 15, .crn = 10, .crm = 4,
847 .opc1 = CP_ANY, .opc2 = CP_ANY, .access = PL1_RW, .type = ARM_CP_NOP },
848 { .name = "TLB_LOCKDOWN", .cp = 15, .crn = 10, .crm = 8,
849 .opc1 = CP_ANY, .opc2 = CP_ANY, .access = PL1_RW, .type = ARM_CP_NOP },
850
851 { .name = "CACHEMAINT", .cp = 15, .crn = 7, .crm = CP_ANY,
852 .opc1 = 0, .opc2 = CP_ANY, .access = PL1_W,
853 .type = ARM_CP_NOP | ARM_CP_OVERRIDE },
854 REGINFO_SENTINEL
855};
856
857static const ARMCPRegInfo not_v6_cp_reginfo[] = {
858
859
860
861 { .name = "WFI_v5", .cp = 15, .crn = 7, .crm = 8, .opc1 = 0, .opc2 = 2,
862 .access = PL1_W, .type = ARM_CP_WFI },
863 REGINFO_SENTINEL
864};
865
866static const ARMCPRegInfo not_v7_cp_reginfo[] = {
867
868
869
870 { .name = "WFI_v6", .cp = 15, .crn = 7, .crm = 0, .opc1 = 0, .opc2 = 4,
871 .access = PL1_W, .type = ARM_CP_WFI },
872
873
874
875
876 { .name = "DLOCKDOWN", .cp = 15, .crn = 9, .crm = 0, .opc1 = 0, .opc2 = 0,
877 .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.c9_data),
878 .resetvalue = 0 },
879 { .name = "ILOCKDOWN", .cp = 15, .crn = 9, .crm = 0, .opc1 = 0, .opc2 = 1,
880 .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.c9_insn),
881 .resetvalue = 0 },
882
883 { .name = "DUMMY", .cp = 15, .crn = 0, .crm = 0, .opc1 = 1, .opc2 = CP_ANY,
884 .access = PL1_R, .type = ARM_CP_CONST | ARM_CP_NO_RAW,
885 .resetvalue = 0 },
886
887
888
889
890
891 { .name = "DBGDIDR", .cp = 14, .crn = 0, .crm = 0, .opc1 = 0, .opc2 = 0,
892 .access = PL0_R, .type = ARM_CP_CONST, .resetvalue = 0 },
893
894
895
896 { .name = "TLBIALL", .cp = 15, .crn = 8, .crm = CP_ANY,
897 .opc1 = CP_ANY, .opc2 = 0, .access = PL1_W, .writefn = tlbiall_write,
898 .type = ARM_CP_NO_RAW },
899 { .name = "TLBIMVA", .cp = 15, .crn = 8, .crm = CP_ANY,
900 .opc1 = CP_ANY, .opc2 = 1, .access = PL1_W, .writefn = tlbimva_write,
901 .type = ARM_CP_NO_RAW },
902 { .name = "TLBIASID", .cp = 15, .crn = 8, .crm = CP_ANY,
903 .opc1 = CP_ANY, .opc2 = 2, .access = PL1_W, .writefn = tlbiasid_write,
904 .type = ARM_CP_NO_RAW },
905 { .name = "TLBIMVAA", .cp = 15, .crn = 8, .crm = CP_ANY,
906 .opc1 = CP_ANY, .opc2 = 3, .access = PL1_W, .writefn = tlbimvaa_write,
907 .type = ARM_CP_NO_RAW },
908 { .name = "PRRR", .cp = 15, .crn = 10, .crm = 2,
909 .opc1 = 0, .opc2 = 0, .access = PL1_RW, .type = ARM_CP_NOP },
910 { .name = "NMRR", .cp = 15, .crn = 10, .crm = 2,
911 .opc1 = 0, .opc2 = 1, .access = PL1_RW, .type = ARM_CP_NOP },
912 REGINFO_SENTINEL
913};
914
915static void cpacr_write(CPUARMState *env, const ARMCPRegInfo *ri,
916 uint64_t value)
917{
918 uint32_t mask = 0;
919
920
921 if (!arm_feature(env, ARM_FEATURE_V8)) {
922
923
924
925
926 if (arm_feature(env, ARM_FEATURE_VFP)) {
927
928 mask |= (1 << 31) | (1 << 30) | (0xf << 20);
929
930 if (!arm_feature(env, ARM_FEATURE_NEON)) {
931
932 value |= (1 << 31);
933 }
934
935
936
937
938 if (!arm_feature(env, ARM_FEATURE_NEON) ||
939 !arm_feature(env, ARM_FEATURE_VFP3)) {
940
941 value |= (1 << 30);
942 }
943 }
944 value &= mask;
945 }
946 env->cp15.cpacr_el1 = value;
947}
948
949static CPAccessResult cpacr_access(CPUARMState *env, const ARMCPRegInfo *ri,
950 bool isread)
951{
952 if (arm_feature(env, ARM_FEATURE_V8)) {
953
954 if (arm_current_el(env) == 1 &&
955 (env->cp15.cptr_el[2] & CPTR_TCPAC) && !arm_is_secure(env)) {
956 return CP_ACCESS_TRAP_EL2;
957
958 } else if (arm_current_el(env) < 3 &&
959 (env->cp15.cptr_el[3] & CPTR_TCPAC)) {
960 return CP_ACCESS_TRAP_EL3;
961 }
962 }
963
964 return CP_ACCESS_OK;
965}
966
967static CPAccessResult cptr_access(CPUARMState *env, const ARMCPRegInfo *ri,
968 bool isread)
969{
970
971 if (arm_current_el(env) == 2 && (env->cp15.cptr_el[3] & CPTR_TCPAC)) {
972 return CP_ACCESS_TRAP_EL3;
973 }
974
975 return CP_ACCESS_OK;
976}
977
978static const ARMCPRegInfo v6_cp_reginfo[] = {
979
980 { .name = "MVA_prefetch",
981 .cp = 15, .crn = 7, .crm = 13, .opc1 = 0, .opc2 = 1,
982 .access = PL1_W, .type = ARM_CP_NOP },
983
984
985
986
987 { .name = "ISB", .cp = 15, .crn = 7, .crm = 5, .opc1 = 0, .opc2 = 4,
988 .access = PL0_W, .type = ARM_CP_NO_RAW, .writefn = arm_cp_write_ignore },
989 { .name = "DSB", .cp = 15, .crn = 7, .crm = 10, .opc1 = 0, .opc2 = 4,
990 .access = PL0_W, .type = ARM_CP_NOP },
991 { .name = "DMB", .cp = 15, .crn = 7, .crm = 10, .opc1 = 0, .opc2 = 5,
992 .access = PL0_W, .type = ARM_CP_NOP },
993 { .name = "IFAR", .cp = 15, .crn = 6, .crm = 0, .opc1 = 0, .opc2 = 2,
994 .access = PL1_RW,
995 .bank_fieldoffsets = { offsetof(CPUARMState, cp15.ifar_s),
996 offsetof(CPUARMState, cp15.ifar_ns) },
997 .resetvalue = 0, },
998
999
1000
1001 { .name = "WFAR", .cp = 15, .crn = 6, .crm = 0, .opc1 = 0, .opc2 = 1,
1002 .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0, },
1003 { .name = "CPACR", .state = ARM_CP_STATE_BOTH, .opc0 = 3,
1004 .crn = 1, .crm = 0, .opc1 = 0, .opc2 = 2, .accessfn = cpacr_access,
1005 .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.cpacr_el1),
1006 .resetvalue = 0, .writefn = cpacr_write },
1007 REGINFO_SENTINEL
1008};
1009
1010static CPAccessResult pmreg_access(CPUARMState *env, const ARMCPRegInfo *ri,
1011 bool isread)
1012{
1013
1014
1015
1016
1017 int el = arm_current_el(env);
1018
1019 if (el == 0 && !env->cp15.c9_pmuserenr) {
1020 return CP_ACCESS_TRAP;
1021 }
1022 if (el < 2 && (env->cp15.mdcr_el2 & MDCR_TPM)
1023 && !arm_is_secure_below_el3(env)) {
1024 return CP_ACCESS_TRAP_EL2;
1025 }
1026 if (el < 3 && (env->cp15.mdcr_el3 & MDCR_TPM)) {
1027 return CP_ACCESS_TRAP_EL3;
1028 }
1029
1030 return CP_ACCESS_OK;
1031}
1032
1033#ifndef CONFIG_USER_ONLY
1034
1035static inline bool arm_ccnt_enabled(CPUARMState *env)
1036{
1037
1038
1039 if (!(env->cp15.c9_pmcr & PMCRE)) {
1040 return false;
1041 }
1042
1043 return true;
1044}
1045
1046void pmccntr_sync(CPUARMState *env)
1047{
1048 uint64_t temp_ticks;
1049
1050 temp_ticks = muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL),
1051 ARM_CPU_FREQ, NANOSECONDS_PER_SECOND);
1052
1053 if (env->cp15.c9_pmcr & PMCRD) {
1054
1055 temp_ticks /= 64;
1056 }
1057
1058 if (arm_ccnt_enabled(env)) {
1059 env->cp15.c15_ccnt = temp_ticks - env->cp15.c15_ccnt;
1060 }
1061}
1062
1063static void pmcr_write(CPUARMState *env, const ARMCPRegInfo *ri,
1064 uint64_t value)
1065{
1066 pmccntr_sync(env);
1067
1068 if (value & PMCRC) {
1069
1070 env->cp15.c15_ccnt = 0;
1071 }
1072
1073
1074 env->cp15.c9_pmcr &= ~0x39;
1075 env->cp15.c9_pmcr |= (value & 0x39);
1076
1077 pmccntr_sync(env);
1078}
1079
1080static uint64_t pmccntr_read(CPUARMState *env, const ARMCPRegInfo *ri)
1081{
1082 uint64_t total_ticks;
1083
1084 if (!arm_ccnt_enabled(env)) {
1085
1086 return env->cp15.c15_ccnt;
1087 }
1088
1089 total_ticks = muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL),
1090 ARM_CPU_FREQ, NANOSECONDS_PER_SECOND);
1091
1092 if (env->cp15.c9_pmcr & PMCRD) {
1093
1094 total_ticks /= 64;
1095 }
1096 return total_ticks - env->cp15.c15_ccnt;
1097}
1098
1099static void pmccntr_write(CPUARMState *env, const ARMCPRegInfo *ri,
1100 uint64_t value)
1101{
1102 uint64_t total_ticks;
1103
1104 if (!arm_ccnt_enabled(env)) {
1105
1106 env->cp15.c15_ccnt = value;
1107 return;
1108 }
1109
1110 total_ticks = muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL),
1111 ARM_CPU_FREQ, NANOSECONDS_PER_SECOND);
1112
1113 if (env->cp15.c9_pmcr & PMCRD) {
1114
1115 total_ticks /= 64;
1116 }
1117 env->cp15.c15_ccnt = total_ticks - value;
1118}
1119
1120static void pmccntr_write32(CPUARMState *env, const ARMCPRegInfo *ri,
1121 uint64_t value)
1122{
1123 uint64_t cur_val = pmccntr_read(env, NULL);
1124
1125 pmccntr_write(env, ri, deposit64(cur_val, 0, 32, value));
1126}
1127
1128#else
1129
1130void pmccntr_sync(CPUARMState *env)
1131{
1132}
1133
1134#endif
1135
1136static void pmccfiltr_write(CPUARMState *env, const ARMCPRegInfo *ri,
1137 uint64_t value)
1138{
1139 pmccntr_sync(env);
1140 env->cp15.pmccfiltr_el0 = value & 0x7E000000;
1141 pmccntr_sync(env);
1142}
1143
1144static void pmcntenset_write(CPUARMState *env, const ARMCPRegInfo *ri,
1145 uint64_t value)
1146{
1147 value &= (1 << 31);
1148 env->cp15.c9_pmcnten |= value;
1149}
1150
1151static void pmcntenclr_write(CPUARMState *env, const ARMCPRegInfo *ri,
1152 uint64_t value)
1153{
1154 value &= (1 << 31);
1155 env->cp15.c9_pmcnten &= ~value;
1156}
1157
1158static void pmovsr_write(CPUARMState *env, const ARMCPRegInfo *ri,
1159 uint64_t value)
1160{
1161 env->cp15.c9_pmovsr &= ~value;
1162}
1163
1164static void pmxevtyper_write(CPUARMState *env, const ARMCPRegInfo *ri,
1165 uint64_t value)
1166{
1167 env->cp15.c9_pmxevtyper = value & 0xff;
1168}
1169
1170static void pmuserenr_write(CPUARMState *env, const ARMCPRegInfo *ri,
1171 uint64_t value)
1172{
1173 env->cp15.c9_pmuserenr = value & 1;
1174}
1175
1176static void pmintenset_write(CPUARMState *env, const ARMCPRegInfo *ri,
1177 uint64_t value)
1178{
1179
1180 value &= (1 << 31);
1181 env->cp15.c9_pminten |= value;
1182}
1183
1184static void pmintenclr_write(CPUARMState *env, const ARMCPRegInfo *ri,
1185 uint64_t value)
1186{
1187 value &= (1 << 31);
1188 env->cp15.c9_pminten &= ~value;
1189}
1190
1191static void vbar_write(CPUARMState *env, const ARMCPRegInfo *ri,
1192 uint64_t value)
1193{
1194
1195
1196
1197
1198
1199
1200 raw_write(env, ri, value & ~0x1FULL);
1201}
1202
1203static void scr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
1204{
1205
1206
1207
1208
1209 uint32_t valid_mask = SCR_AARCH64_MASK | SCR_AARCH32_MASK;
1210
1211 if (!arm_feature(env, ARM_FEATURE_EL2)) {
1212 valid_mask &= ~SCR_HCE;
1213
1214
1215
1216
1217
1218
1219
1220 if (arm_feature(env, ARM_FEATURE_V7) &&
1221 !arm_feature(env, ARM_FEATURE_V8)) {
1222 valid_mask &= ~SCR_SMD;
1223 }
1224 }
1225
1226
1227 value &= valid_mask;
1228 raw_write(env, ri, value);
1229}
1230
1231static uint64_t ccsidr_read(CPUARMState *env, const ARMCPRegInfo *ri)
1232{
1233 ARMCPU *cpu = arm_env_get_cpu(env);
1234
1235
1236
1237
1238 uint32_t index = A32_BANKED_REG_GET(env, csselr,
1239 ri->secure & ARM_CP_SECSTATE_S);
1240
1241 return cpu->ccsidr[index];
1242}
1243
1244static void csselr_write(CPUARMState *env, const ARMCPRegInfo *ri,
1245 uint64_t value)
1246{
1247 raw_write(env, ri, value & 0xf);
1248}
1249
1250static uint64_t isr_read(CPUARMState *env, const ARMCPRegInfo *ri)
1251{
1252 CPUState *cs = ENV_GET_CPU(env);
1253 uint64_t ret = 0;
1254
1255 if (cs->interrupt_request & CPU_INTERRUPT_HARD) {
1256 ret |= CPSR_I;
1257 }
1258 if (cs->interrupt_request & CPU_INTERRUPT_FIQ) {
1259 ret |= CPSR_F;
1260 }
1261
1262 return ret;
1263}
1264
1265static const ARMCPRegInfo v7_cp_reginfo[] = {
1266
1267 { .name = "NOP", .cp = 15, .crn = 7, .crm = 0, .opc1 = 0, .opc2 = 4,
1268 .access = PL1_W, .type = ARM_CP_NOP },
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280 { .name = "PMCNTENSET", .cp = 15, .crn = 9, .crm = 12, .opc1 = 0, .opc2 = 1,
1281 .access = PL0_RW, .type = ARM_CP_ALIAS,
1282 .fieldoffset = offsetoflow32(CPUARMState, cp15.c9_pmcnten),
1283 .writefn = pmcntenset_write,
1284 .accessfn = pmreg_access,
1285 .raw_writefn = raw_write },
1286 { .name = "PMCNTENSET_EL0", .state = ARM_CP_STATE_AA64,
1287 .opc0 = 3, .opc1 = 3, .crn = 9, .crm = 12, .opc2 = 1,
1288 .access = PL0_RW, .accessfn = pmreg_access,
1289 .fieldoffset = offsetof(CPUARMState, cp15.c9_pmcnten), .resetvalue = 0,
1290 .writefn = pmcntenset_write, .raw_writefn = raw_write },
1291 { .name = "PMCNTENCLR", .cp = 15, .crn = 9, .crm = 12, .opc1 = 0, .opc2 = 2,
1292 .access = PL0_RW,
1293 .fieldoffset = offsetoflow32(CPUARMState, cp15.c9_pmcnten),
1294 .accessfn = pmreg_access,
1295 .writefn = pmcntenclr_write,
1296 .type = ARM_CP_ALIAS },
1297 { .name = "PMCNTENCLR_EL0", .state = ARM_CP_STATE_AA64,
1298 .opc0 = 3, .opc1 = 3, .crn = 9, .crm = 12, .opc2 = 2,
1299 .access = PL0_RW, .accessfn = pmreg_access,
1300 .type = ARM_CP_ALIAS,
1301 .fieldoffset = offsetof(CPUARMState, cp15.c9_pmcnten),
1302 .writefn = pmcntenclr_write },
1303 { .name = "PMOVSR", .cp = 15, .crn = 9, .crm = 12, .opc1 = 0, .opc2 = 3,
1304 .access = PL0_RW, .fieldoffset = offsetof(CPUARMState, cp15.c9_pmovsr),
1305 .accessfn = pmreg_access,
1306 .writefn = pmovsr_write,
1307 .raw_writefn = raw_write },
1308 { .name = "PMOVSCLR_EL0", .state = ARM_CP_STATE_AA64,
1309 .opc0 = 3, .opc1 = 3, .crn = 9, .crm = 12, .opc2 = 3,
1310 .access = PL0_RW, .accessfn = pmreg_access,
1311 .type = ARM_CP_ALIAS,
1312 .fieldoffset = offsetof(CPUARMState, cp15.c9_pmovsr),
1313 .writefn = pmovsr_write,
1314 .raw_writefn = raw_write },
1315
1316 { .name = "PMSWINC", .cp = 15, .crn = 9, .crm = 12, .opc1 = 0, .opc2 = 4,
1317 .access = PL0_W, .accessfn = pmreg_access, .type = ARM_CP_NOP },
1318
1319
1320
1321 { .name = "PMSELR", .cp = 15, .crn = 9, .crm = 12, .opc1 = 0, .opc2 = 5,
1322 .access = PL0_RW, .type = ARM_CP_CONST, .resetvalue = 0,
1323 .accessfn = pmreg_access },
1324#ifndef CONFIG_USER_ONLY
1325 { .name = "PMCCNTR", .cp = 15, .crn = 9, .crm = 13, .opc1 = 0, .opc2 = 0,
1326 .access = PL0_RW, .resetvalue = 0, .type = ARM_CP_IO,
1327 .readfn = pmccntr_read, .writefn = pmccntr_write32,
1328 .accessfn = pmreg_access },
1329 { .name = "PMCCNTR_EL0", .state = ARM_CP_STATE_AA64,
1330 .opc0 = 3, .opc1 = 3, .crn = 9, .crm = 13, .opc2 = 0,
1331 .access = PL0_RW, .accessfn = pmreg_access,
1332 .type = ARM_CP_IO,
1333 .readfn = pmccntr_read, .writefn = pmccntr_write, },
1334#endif
1335 { .name = "PMCCFILTR_EL0", .state = ARM_CP_STATE_AA64,
1336 .opc0 = 3, .opc1 = 3, .crn = 14, .crm = 15, .opc2 = 7,
1337 .writefn = pmccfiltr_write,
1338 .access = PL0_RW, .accessfn = pmreg_access,
1339 .type = ARM_CP_IO,
1340 .fieldoffset = offsetof(CPUARMState, cp15.pmccfiltr_el0),
1341 .resetvalue = 0, },
1342 { .name = "PMXEVTYPER", .cp = 15, .crn = 9, .crm = 13, .opc1 = 0, .opc2 = 1,
1343 .access = PL0_RW,
1344 .fieldoffset = offsetof(CPUARMState, cp15.c9_pmxevtyper),
1345 .accessfn = pmreg_access, .writefn = pmxevtyper_write,
1346 .raw_writefn = raw_write },
1347
1348 { .name = "PMXEVCNTR", .cp = 15, .crn = 9, .crm = 13, .opc1 = 0, .opc2 = 2,
1349 .access = PL0_RW, .type = ARM_CP_CONST, .resetvalue = 0,
1350 .accessfn = pmreg_access },
1351 { .name = "PMUSERENR", .cp = 15, .crn = 9, .crm = 14, .opc1 = 0, .opc2 = 0,
1352 .access = PL0_R | PL1_RW, .accessfn = access_tpm,
1353 .fieldoffset = offsetof(CPUARMState, cp15.c9_pmuserenr),
1354 .resetvalue = 0,
1355 .writefn = pmuserenr_write, .raw_writefn = raw_write },
1356 { .name = "PMUSERENR_EL0", .state = ARM_CP_STATE_AA64,
1357 .opc0 = 3, .opc1 = 3, .crn = 9, .crm = 14, .opc2 = 0,
1358 .access = PL0_R | PL1_RW, .accessfn = access_tpm, .type = ARM_CP_ALIAS,
1359 .fieldoffset = offsetof(CPUARMState, cp15.c9_pmuserenr),
1360 .resetvalue = 0,
1361 .writefn = pmuserenr_write, .raw_writefn = raw_write },
1362 { .name = "PMINTENSET", .cp = 15, .crn = 9, .crm = 14, .opc1 = 0, .opc2 = 1,
1363 .access = PL1_RW, .accessfn = access_tpm,
1364 .fieldoffset = offsetof(CPUARMState, cp15.c9_pminten),
1365 .resetvalue = 0,
1366 .writefn = pmintenset_write, .raw_writefn = raw_write },
1367 { .name = "PMINTENCLR", .cp = 15, .crn = 9, .crm = 14, .opc1 = 0, .opc2 = 2,
1368 .access = PL1_RW, .accessfn = access_tpm, .type = ARM_CP_ALIAS,
1369 .fieldoffset = offsetof(CPUARMState, cp15.c9_pminten),
1370 .writefn = pmintenclr_write, },
1371 { .name = "PMINTENCLR_EL1", .state = ARM_CP_STATE_AA64,
1372 .opc0 = 3, .opc1 = 0, .crn = 9, .crm = 14, .opc2 = 2,
1373 .access = PL1_RW, .accessfn = access_tpm, .type = ARM_CP_ALIAS,
1374 .fieldoffset = offsetof(CPUARMState, cp15.c9_pminten),
1375 .writefn = pmintenclr_write },
1376 { .name = "VBAR", .state = ARM_CP_STATE_BOTH,
1377 .opc0 = 3, .crn = 12, .crm = 0, .opc1 = 0, .opc2 = 0,
1378 .access = PL1_RW, .writefn = vbar_write,
1379 .bank_fieldoffsets = { offsetof(CPUARMState, cp15.vbar_s),
1380 offsetof(CPUARMState, cp15.vbar_ns) },
1381 .resetvalue = 0 },
1382 { .name = "CCSIDR", .state = ARM_CP_STATE_BOTH,
1383 .opc0 = 3, .crn = 0, .crm = 0, .opc1 = 1, .opc2 = 0,
1384 .access = PL1_R, .readfn = ccsidr_read, .type = ARM_CP_NO_RAW },
1385 { .name = "CSSELR", .state = ARM_CP_STATE_BOTH,
1386 .opc0 = 3, .crn = 0, .crm = 0, .opc1 = 2, .opc2 = 0,
1387 .access = PL1_RW, .writefn = csselr_write, .resetvalue = 0,
1388 .bank_fieldoffsets = { offsetof(CPUARMState, cp15.csselr_s),
1389 offsetof(CPUARMState, cp15.csselr_ns) } },
1390
1391
1392
1393 { .name = "AIDR", .state = ARM_CP_STATE_BOTH,
1394 .opc0 = 3, .opc1 = 1, .crn = 0, .crm = 0, .opc2 = 7,
1395 .access = PL1_R, .type = ARM_CP_CONST, .resetvalue = 0 },
1396
1397
1398
1399 { .name = "AFSR0_EL1", .state = ARM_CP_STATE_BOTH,
1400 .opc0 = 3, .opc1 = 0, .crn = 5, .crm = 1, .opc2 = 0,
1401 .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
1402 { .name = "AFSR1_EL1", .state = ARM_CP_STATE_BOTH,
1403 .opc0 = 3, .opc1 = 0, .crn = 5, .crm = 1, .opc2 = 1,
1404 .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
1405
1406
1407
1408 { .name = "MAIR_EL1", .state = ARM_CP_STATE_AA64,
1409 .opc0 = 3, .opc1 = 0, .crn = 10, .crm = 2, .opc2 = 0,
1410 .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.mair_el[1]),
1411 .resetvalue = 0 },
1412 { .name = "MAIR_EL3", .state = ARM_CP_STATE_AA64,
1413 .opc0 = 3, .opc1 = 6, .crn = 10, .crm = 2, .opc2 = 0,
1414 .access = PL3_RW, .fieldoffset = offsetof(CPUARMState, cp15.mair_el[3]),
1415 .resetvalue = 0 },
1416
1417
1418
1419
1420
1421
1422
1423 { .name = "MAIR0", .state = ARM_CP_STATE_AA32,
1424 .cp = 15, .opc1 = 0, .crn = 10, .crm = 2, .opc2 = 0, .access = PL1_RW,
1425 .bank_fieldoffsets = { offsetof(CPUARMState, cp15.mair0_s),
1426 offsetof(CPUARMState, cp15.mair0_ns) },
1427 .resetfn = arm_cp_reset_ignore },
1428 { .name = "MAIR1", .state = ARM_CP_STATE_AA32,
1429 .cp = 15, .opc1 = 0, .crn = 10, .crm = 2, .opc2 = 1, .access = PL1_RW,
1430 .bank_fieldoffsets = { offsetof(CPUARMState, cp15.mair1_s),
1431 offsetof(CPUARMState, cp15.mair1_ns) },
1432 .resetfn = arm_cp_reset_ignore },
1433 { .name = "ISR_EL1", .state = ARM_CP_STATE_BOTH,
1434 .opc0 = 3, .opc1 = 0, .crn = 12, .crm = 1, .opc2 = 0,
1435 .type = ARM_CP_NO_RAW, .access = PL1_R, .readfn = isr_read },
1436
1437 { .name = "ITLBIALL", .cp = 15, .opc1 = 0, .crn = 8, .crm = 5, .opc2 = 0,
1438 .type = ARM_CP_NO_RAW, .access = PL1_W, .writefn = tlbiall_write },
1439 { .name = "ITLBIMVA", .cp = 15, .opc1 = 0, .crn = 8, .crm = 5, .opc2 = 1,
1440 .type = ARM_CP_NO_RAW, .access = PL1_W, .writefn = tlbimva_write },
1441 { .name = "ITLBIASID", .cp = 15, .opc1 = 0, .crn = 8, .crm = 5, .opc2 = 2,
1442 .type = ARM_CP_NO_RAW, .access = PL1_W, .writefn = tlbiasid_write },
1443
1444 { .name = "DTLBIALL", .cp = 15, .opc1 = 0, .crn = 8, .crm = 6, .opc2 = 0,
1445 .type = ARM_CP_NO_RAW, .access = PL1_W, .writefn = tlbiall_write },
1446 { .name = "DTLBIMVA", .cp = 15, .opc1 = 0, .crn = 8, .crm = 6, .opc2 = 1,
1447 .type = ARM_CP_NO_RAW, .access = PL1_W, .writefn = tlbimva_write },
1448 { .name = "DTLBIASID", .cp = 15, .opc1 = 0, .crn = 8, .crm = 6, .opc2 = 2,
1449 .type = ARM_CP_NO_RAW, .access = PL1_W, .writefn = tlbiasid_write },
1450
1451 { .name = "TLBIALL", .cp = 15, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 0,
1452 .type = ARM_CP_NO_RAW, .access = PL1_W, .writefn = tlbiall_write },
1453 { .name = "TLBIMVA", .cp = 15, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 1,
1454 .type = ARM_CP_NO_RAW, .access = PL1_W, .writefn = tlbimva_write },
1455 { .name = "TLBIASID", .cp = 15, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 2,
1456 .type = ARM_CP_NO_RAW, .access = PL1_W, .writefn = tlbiasid_write },
1457 { .name = "TLBIMVAA", .cp = 15, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 3,
1458 .type = ARM_CP_NO_RAW, .access = PL1_W, .writefn = tlbimvaa_write },
1459 REGINFO_SENTINEL
1460};
1461
1462static const ARMCPRegInfo v7mp_cp_reginfo[] = {
1463
1464 { .name = "TLBIALLIS", .cp = 15, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 0,
1465 .type = ARM_CP_NO_RAW, .access = PL1_W, .writefn = tlbiall_is_write },
1466 { .name = "TLBIMVAIS", .cp = 15, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 1,
1467 .type = ARM_CP_NO_RAW, .access = PL1_W, .writefn = tlbimva_is_write },
1468 { .name = "TLBIASIDIS", .cp = 15, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 2,
1469 .type = ARM_CP_NO_RAW, .access = PL1_W,
1470 .writefn = tlbiasid_is_write },
1471 { .name = "TLBIMVAAIS", .cp = 15, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 3,
1472 .type = ARM_CP_NO_RAW, .access = PL1_W,
1473 .writefn = tlbimvaa_is_write },
1474 REGINFO_SENTINEL
1475};
1476
1477static void teecr_write(CPUARMState *env, const ARMCPRegInfo *ri,
1478 uint64_t value)
1479{
1480 value &= 1;
1481 env->teecr = value;
1482}
1483
1484static CPAccessResult teehbr_access(CPUARMState *env, const ARMCPRegInfo *ri,
1485 bool isread)
1486{
1487 if (arm_current_el(env) == 0 && (env->teecr & 1)) {
1488 return CP_ACCESS_TRAP;
1489 }
1490 return CP_ACCESS_OK;
1491}
1492
1493static const ARMCPRegInfo t2ee_cp_reginfo[] = {
1494 { .name = "TEECR", .cp = 14, .crn = 0, .crm = 0, .opc1 = 6, .opc2 = 0,
1495 .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, teecr),
1496 .resetvalue = 0,
1497 .writefn = teecr_write },
1498 { .name = "TEEHBR", .cp = 14, .crn = 1, .crm = 0, .opc1 = 6, .opc2 = 0,
1499 .access = PL0_RW, .fieldoffset = offsetof(CPUARMState, teehbr),
1500 .accessfn = teehbr_access, .resetvalue = 0 },
1501 REGINFO_SENTINEL
1502};
1503
1504static const ARMCPRegInfo v6k_cp_reginfo[] = {
1505 { .name = "TPIDR_EL0", .state = ARM_CP_STATE_AA64,
1506 .opc0 = 3, .opc1 = 3, .opc2 = 2, .crn = 13, .crm = 0,
1507 .access = PL0_RW,
1508 .fieldoffset = offsetof(CPUARMState, cp15.tpidr_el[0]), .resetvalue = 0 },
1509 { .name = "TPIDRURW", .cp = 15, .crn = 13, .crm = 0, .opc1 = 0, .opc2 = 2,
1510 .access = PL0_RW,
1511 .bank_fieldoffsets = { offsetoflow32(CPUARMState, cp15.tpidrurw_s),
1512 offsetoflow32(CPUARMState, cp15.tpidrurw_ns) },
1513 .resetfn = arm_cp_reset_ignore },
1514 { .name = "TPIDRRO_EL0", .state = ARM_CP_STATE_AA64,
1515 .opc0 = 3, .opc1 = 3, .opc2 = 3, .crn = 13, .crm = 0,
1516 .access = PL0_R|PL1_W,
1517 .fieldoffset = offsetof(CPUARMState, cp15.tpidrro_el[0]),
1518 .resetvalue = 0},
1519 { .name = "TPIDRURO", .cp = 15, .crn = 13, .crm = 0, .opc1 = 0, .opc2 = 3,
1520 .access = PL0_R|PL1_W,
1521 .bank_fieldoffsets = { offsetoflow32(CPUARMState, cp15.tpidruro_s),
1522 offsetoflow32(CPUARMState, cp15.tpidruro_ns) },
1523 .resetfn = arm_cp_reset_ignore },
1524 { .name = "TPIDR_EL1", .state = ARM_CP_STATE_AA64,
1525 .opc0 = 3, .opc1 = 0, .opc2 = 4, .crn = 13, .crm = 0,
1526 .access = PL1_RW,
1527 .fieldoffset = offsetof(CPUARMState, cp15.tpidr_el[1]), .resetvalue = 0 },
1528 { .name = "TPIDRPRW", .opc1 = 0, .cp = 15, .crn = 13, .crm = 0, .opc2 = 4,
1529 .access = PL1_RW,
1530 .bank_fieldoffsets = { offsetoflow32(CPUARMState, cp15.tpidrprw_s),
1531 offsetoflow32(CPUARMState, cp15.tpidrprw_ns) },
1532 .resetvalue = 0 },
1533 REGINFO_SENTINEL
1534};
1535
1536#ifndef CONFIG_USER_ONLY
1537
1538static CPAccessResult gt_cntfrq_access(CPUARMState *env, const ARMCPRegInfo *ri,
1539 bool isread)
1540{
1541
1542
1543
1544 int el = arm_current_el(env);
1545
1546 switch (el) {
1547 case 0:
1548 if (!extract32(env->cp15.c14_cntkctl, 0, 2)) {
1549 return CP_ACCESS_TRAP;
1550 }
1551 break;
1552 case 1:
1553 if (!isread && ri->state == ARM_CP_STATE_AA32 &&
1554 arm_is_secure_below_el3(env)) {
1555
1556 return CP_ACCESS_TRAP_UNCATEGORIZED;
1557 }
1558 break;
1559 case 2:
1560 case 3:
1561 break;
1562 }
1563
1564 if (!isread && el < arm_highest_el(env)) {
1565 return CP_ACCESS_TRAP_UNCATEGORIZED;
1566 }
1567
1568 return CP_ACCESS_OK;
1569}
1570
1571static CPAccessResult gt_counter_access(CPUARMState *env, int timeridx,
1572 bool isread)
1573{
1574 unsigned int cur_el = arm_current_el(env);
1575 bool secure = arm_is_secure(env);
1576
1577
1578 if (cur_el == 0 &&
1579 !extract32(env->cp15.c14_cntkctl, timeridx, 1)) {
1580 return CP_ACCESS_TRAP;
1581 }
1582
1583 if (arm_feature(env, ARM_FEATURE_EL2) &&
1584 timeridx == GTIMER_PHYS && !secure && cur_el < 2 &&
1585 !extract32(env->cp15.cnthctl_el2, 0, 1)) {
1586 return CP_ACCESS_TRAP_EL2;
1587 }
1588 return CP_ACCESS_OK;
1589}
1590
1591static CPAccessResult gt_timer_access(CPUARMState *env, int timeridx,
1592 bool isread)
1593{
1594 unsigned int cur_el = arm_current_el(env);
1595 bool secure = arm_is_secure(env);
1596
1597
1598
1599
1600 if (cur_el == 0 &&
1601 !extract32(env->cp15.c14_cntkctl, 9 - timeridx, 1)) {
1602 return CP_ACCESS_TRAP;
1603 }
1604
1605 if (arm_feature(env, ARM_FEATURE_EL2) &&
1606 timeridx == GTIMER_PHYS && !secure && cur_el < 2 &&
1607 !extract32(env->cp15.cnthctl_el2, 1, 1)) {
1608 return CP_ACCESS_TRAP_EL2;
1609 }
1610 return CP_ACCESS_OK;
1611}
1612
1613static CPAccessResult gt_pct_access(CPUARMState *env,
1614 const ARMCPRegInfo *ri,
1615 bool isread)
1616{
1617 return gt_counter_access(env, GTIMER_PHYS, isread);
1618}
1619
1620static CPAccessResult gt_vct_access(CPUARMState *env,
1621 const ARMCPRegInfo *ri,
1622 bool isread)
1623{
1624 return gt_counter_access(env, GTIMER_VIRT, isread);
1625}
1626
1627static CPAccessResult gt_ptimer_access(CPUARMState *env, const ARMCPRegInfo *ri,
1628 bool isread)
1629{
1630 return gt_timer_access(env, GTIMER_PHYS, isread);
1631}
1632
1633static CPAccessResult gt_vtimer_access(CPUARMState *env, const ARMCPRegInfo *ri,
1634 bool isread)
1635{
1636 return gt_timer_access(env, GTIMER_VIRT, isread);
1637}
1638
1639static CPAccessResult gt_stimer_access(CPUARMState *env,
1640 const ARMCPRegInfo *ri,
1641 bool isread)
1642{
1643
1644
1645
1646
1647 switch (arm_current_el(env)) {
1648 case 1:
1649 if (!arm_is_secure(env)) {
1650 return CP_ACCESS_TRAP;
1651 }
1652 if (!(env->cp15.scr_el3 & SCR_ST)) {
1653 return CP_ACCESS_TRAP_EL3;
1654 }
1655 return CP_ACCESS_OK;
1656 case 0:
1657 case 2:
1658 return CP_ACCESS_TRAP;
1659 case 3:
1660 return CP_ACCESS_OK;
1661 default:
1662 g_assert_not_reached();
1663 }
1664}
1665
1666static uint64_t gt_get_countervalue(CPUARMState *env)
1667{
1668 return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) / GTIMER_SCALE;
1669}
1670
1671static void gt_recalc_timer(ARMCPU *cpu, int timeridx)
1672{
1673 ARMGenericTimer *gt = &cpu->env.cp15.c14_timer[timeridx];
1674
1675 if (gt->ctl & 1) {
1676
1677
1678
1679 uint64_t offset = timeridx == GTIMER_VIRT ?
1680 cpu->env.cp15.cntvoff_el2 : 0;
1681 uint64_t count = gt_get_countervalue(&cpu->env);
1682
1683 int istatus = count - offset >= gt->cval;
1684 uint64_t nexttick;
1685 int irqstate;
1686
1687 gt->ctl = deposit32(gt->ctl, 2, 1, istatus);
1688
1689 irqstate = (istatus && !(gt->ctl & 2));
1690 qemu_set_irq(cpu->gt_timer_outputs[timeridx], irqstate);
1691
1692 if (istatus) {
1693
1694 nexttick = UINT64_MAX;
1695 } else {
1696
1697 nexttick = gt->cval + offset;
1698 }
1699
1700
1701
1702
1703
1704 if (nexttick > INT64_MAX / GTIMER_SCALE) {
1705 nexttick = INT64_MAX / GTIMER_SCALE;
1706 }
1707 timer_mod(cpu->gt_timer[timeridx], nexttick);
1708 trace_arm_gt_recalc(timeridx, irqstate, nexttick);
1709 } else {
1710
1711 gt->ctl &= ~4;
1712 qemu_set_irq(cpu->gt_timer_outputs[timeridx], 0);
1713 timer_del(cpu->gt_timer[timeridx]);
1714 trace_arm_gt_recalc_disabled(timeridx);
1715 }
1716}
1717
1718static void gt_timer_reset(CPUARMState *env, const ARMCPRegInfo *ri,
1719 int timeridx)
1720{
1721 ARMCPU *cpu = arm_env_get_cpu(env);
1722
1723 timer_del(cpu->gt_timer[timeridx]);
1724}
1725
1726static uint64_t gt_cnt_read(CPUARMState *env, const ARMCPRegInfo *ri)
1727{
1728 return gt_get_countervalue(env);
1729}
1730
1731static uint64_t gt_virt_cnt_read(CPUARMState *env, const ARMCPRegInfo *ri)
1732{
1733 return gt_get_countervalue(env) - env->cp15.cntvoff_el2;
1734}
1735
1736static void gt_cval_write(CPUARMState *env, const ARMCPRegInfo *ri,
1737 int timeridx,
1738 uint64_t value)
1739{
1740 trace_arm_gt_cval_write(timeridx, value);
1741 env->cp15.c14_timer[timeridx].cval = value;
1742 gt_recalc_timer(arm_env_get_cpu(env), timeridx);
1743}
1744
1745static uint64_t gt_tval_read(CPUARMState *env, const ARMCPRegInfo *ri,
1746 int timeridx)
1747{
1748 uint64_t offset = timeridx == GTIMER_VIRT ? env->cp15.cntvoff_el2 : 0;
1749
1750 return (uint32_t)(env->cp15.c14_timer[timeridx].cval -
1751 (gt_get_countervalue(env) - offset));
1752}
1753
1754static void gt_tval_write(CPUARMState *env, const ARMCPRegInfo *ri,
1755 int timeridx,
1756 uint64_t value)
1757{
1758 uint64_t offset = timeridx == GTIMER_VIRT ? env->cp15.cntvoff_el2 : 0;
1759
1760 trace_arm_gt_tval_write(timeridx, value);
1761 env->cp15.c14_timer[timeridx].cval = gt_get_countervalue(env) - offset +
1762 sextract64(value, 0, 32);
1763 gt_recalc_timer(arm_env_get_cpu(env), timeridx);
1764}
1765
1766static void gt_ctl_write(CPUARMState *env, const ARMCPRegInfo *ri,
1767 int timeridx,
1768 uint64_t value)
1769{
1770 ARMCPU *cpu = arm_env_get_cpu(env);
1771 uint32_t oldval = env->cp15.c14_timer[timeridx].ctl;
1772
1773 trace_arm_gt_ctl_write(timeridx, value);
1774 env->cp15.c14_timer[timeridx].ctl = deposit64(oldval, 0, 2, value);
1775 if ((oldval ^ value) & 1) {
1776
1777 gt_recalc_timer(cpu, timeridx);
1778 } else if ((oldval ^ value) & 2) {
1779
1780
1781
1782 int irqstate = (oldval & 4) && !(value & 2);
1783
1784 trace_arm_gt_imask_toggle(timeridx, irqstate);
1785 qemu_set_irq(cpu->gt_timer_outputs[timeridx], irqstate);
1786 }
1787}
1788
1789static void gt_phys_timer_reset(CPUARMState *env, const ARMCPRegInfo *ri)
1790{
1791 gt_timer_reset(env, ri, GTIMER_PHYS);
1792}
1793
1794static void gt_phys_cval_write(CPUARMState *env, const ARMCPRegInfo *ri,
1795 uint64_t value)
1796{
1797 gt_cval_write(env, ri, GTIMER_PHYS, value);
1798}
1799
1800static uint64_t gt_phys_tval_read(CPUARMState *env, const ARMCPRegInfo *ri)
1801{
1802 return gt_tval_read(env, ri, GTIMER_PHYS);
1803}
1804
1805static void gt_phys_tval_write(CPUARMState *env, const ARMCPRegInfo *ri,
1806 uint64_t value)
1807{
1808 gt_tval_write(env, ri, GTIMER_PHYS, value);
1809}
1810
1811static void gt_phys_ctl_write(CPUARMState *env, const ARMCPRegInfo *ri,
1812 uint64_t value)
1813{
1814 gt_ctl_write(env, ri, GTIMER_PHYS, value);
1815}
1816
1817static void gt_virt_timer_reset(CPUARMState *env, const ARMCPRegInfo *ri)
1818{
1819 gt_timer_reset(env, ri, GTIMER_VIRT);
1820}
1821
1822static void gt_virt_cval_write(CPUARMState *env, const ARMCPRegInfo *ri,
1823 uint64_t value)
1824{
1825 gt_cval_write(env, ri, GTIMER_VIRT, value);
1826}
1827
1828static uint64_t gt_virt_tval_read(CPUARMState *env, const ARMCPRegInfo *ri)
1829{
1830 return gt_tval_read(env, ri, GTIMER_VIRT);
1831}
1832
1833static void gt_virt_tval_write(CPUARMState *env, const ARMCPRegInfo *ri,
1834 uint64_t value)
1835{
1836 gt_tval_write(env, ri, GTIMER_VIRT, value);
1837}
1838
1839static void gt_virt_ctl_write(CPUARMState *env, const ARMCPRegInfo *ri,
1840 uint64_t value)
1841{
1842 gt_ctl_write(env, ri, GTIMER_VIRT, value);
1843}
1844
1845static void gt_cntvoff_write(CPUARMState *env, const ARMCPRegInfo *ri,
1846 uint64_t value)
1847{
1848 ARMCPU *cpu = arm_env_get_cpu(env);
1849
1850 trace_arm_gt_cntvoff_write(value);
1851 raw_write(env, ri, value);
1852 gt_recalc_timer(cpu, GTIMER_VIRT);
1853}
1854
1855static void gt_hyp_timer_reset(CPUARMState *env, const ARMCPRegInfo *ri)
1856{
1857 gt_timer_reset(env, ri, GTIMER_HYP);
1858}
1859
1860static void gt_hyp_cval_write(CPUARMState *env, const ARMCPRegInfo *ri,
1861 uint64_t value)
1862{
1863 gt_cval_write(env, ri, GTIMER_HYP, value);
1864}
1865
1866static uint64_t gt_hyp_tval_read(CPUARMState *env, const ARMCPRegInfo *ri)
1867{
1868 return gt_tval_read(env, ri, GTIMER_HYP);
1869}
1870
1871static void gt_hyp_tval_write(CPUARMState *env, const ARMCPRegInfo *ri,
1872 uint64_t value)
1873{
1874 gt_tval_write(env, ri, GTIMER_HYP, value);
1875}
1876
1877static void gt_hyp_ctl_write(CPUARMState *env, const ARMCPRegInfo *ri,
1878 uint64_t value)
1879{
1880 gt_ctl_write(env, ri, GTIMER_HYP, value);
1881}
1882
1883static void gt_sec_timer_reset(CPUARMState *env, const ARMCPRegInfo *ri)
1884{
1885 gt_timer_reset(env, ri, GTIMER_SEC);
1886}
1887
1888static void gt_sec_cval_write(CPUARMState *env, const ARMCPRegInfo *ri,
1889 uint64_t value)
1890{
1891 gt_cval_write(env, ri, GTIMER_SEC, value);
1892}
1893
1894static uint64_t gt_sec_tval_read(CPUARMState *env, const ARMCPRegInfo *ri)
1895{
1896 return gt_tval_read(env, ri, GTIMER_SEC);
1897}
1898
1899static void gt_sec_tval_write(CPUARMState *env, const ARMCPRegInfo *ri,
1900 uint64_t value)
1901{
1902 gt_tval_write(env, ri, GTIMER_SEC, value);
1903}
1904
1905static void gt_sec_ctl_write(CPUARMState *env, const ARMCPRegInfo *ri,
1906 uint64_t value)
1907{
1908 gt_ctl_write(env, ri, GTIMER_SEC, value);
1909}
1910
1911void arm_gt_ptimer_cb(void *opaque)
1912{
1913 ARMCPU *cpu = opaque;
1914
1915 gt_recalc_timer(cpu, GTIMER_PHYS);
1916}
1917
1918void arm_gt_vtimer_cb(void *opaque)
1919{
1920 ARMCPU *cpu = opaque;
1921
1922 gt_recalc_timer(cpu, GTIMER_VIRT);
1923}
1924
1925void arm_gt_htimer_cb(void *opaque)
1926{
1927 ARMCPU *cpu = opaque;
1928
1929 gt_recalc_timer(cpu, GTIMER_HYP);
1930}
1931
1932void arm_gt_stimer_cb(void *opaque)
1933{
1934 ARMCPU *cpu = opaque;
1935
1936 gt_recalc_timer(cpu, GTIMER_SEC);
1937}
1938
1939static const ARMCPRegInfo generic_timer_cp_reginfo[] = {
1940
1941
1942
1943
1944 { .name = "CNTFRQ", .cp = 15, .crn = 14, .crm = 0, .opc1 = 0, .opc2 = 0,
1945 .type = ARM_CP_ALIAS,
1946 .access = PL1_RW | PL0_R, .accessfn = gt_cntfrq_access,
1947 .fieldoffset = offsetoflow32(CPUARMState, cp15.c14_cntfrq),
1948 },
1949 { .name = "CNTFRQ_EL0", .state = ARM_CP_STATE_AA64,
1950 .opc0 = 3, .opc1 = 3, .crn = 14, .crm = 0, .opc2 = 0,
1951 .access = PL1_RW | PL0_R, .accessfn = gt_cntfrq_access,
1952 .fieldoffset = offsetof(CPUARMState, cp15.c14_cntfrq),
1953 .resetvalue = (1000 * 1000 * 1000) / GTIMER_SCALE,
1954 },
1955
1956 { .name = "CNTKCTL", .state = ARM_CP_STATE_BOTH,
1957 .opc0 = 3, .opc1 = 0, .crn = 14, .crm = 1, .opc2 = 0,
1958 .access = PL1_RW,
1959 .fieldoffset = offsetof(CPUARMState, cp15.c14_cntkctl),
1960 .resetvalue = 0,
1961 },
1962
1963 { .name = "CNTP_CTL", .cp = 15, .crn = 14, .crm = 2, .opc1 = 0, .opc2 = 1,
1964 .secure = ARM_CP_SECSTATE_NS,
1965 .type = ARM_CP_IO | ARM_CP_ALIAS, .access = PL1_RW | PL0_R,
1966 .accessfn = gt_ptimer_access,
1967 .fieldoffset = offsetoflow32(CPUARMState,
1968 cp15.c14_timer[GTIMER_PHYS].ctl),
1969 .writefn = gt_phys_ctl_write, .raw_writefn = raw_write,
1970 },
1971 { .name = "CNTP_CTL(S)",
1972 .cp = 15, .crn = 14, .crm = 2, .opc1 = 0, .opc2 = 1,
1973 .secure = ARM_CP_SECSTATE_S,
1974 .type = ARM_CP_IO | ARM_CP_ALIAS, .access = PL1_RW | PL0_R,
1975 .accessfn = gt_ptimer_access,
1976 .fieldoffset = offsetoflow32(CPUARMState,
1977 cp15.c14_timer[GTIMER_SEC].ctl),
1978 .writefn = gt_sec_ctl_write, .raw_writefn = raw_write,
1979 },
1980 { .name = "CNTP_CTL_EL0", .state = ARM_CP_STATE_AA64,
1981 .opc0 = 3, .opc1 = 3, .crn = 14, .crm = 2, .opc2 = 1,
1982 .type = ARM_CP_IO, .access = PL1_RW | PL0_R,
1983 .accessfn = gt_ptimer_access,
1984 .fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_PHYS].ctl),
1985 .resetvalue = 0,
1986 .writefn = gt_phys_ctl_write, .raw_writefn = raw_write,
1987 },
1988 { .name = "CNTV_CTL", .cp = 15, .crn = 14, .crm = 3, .opc1 = 0, .opc2 = 1,
1989 .type = ARM_CP_IO | ARM_CP_ALIAS, .access = PL1_RW | PL0_R,
1990 .accessfn = gt_vtimer_access,
1991 .fieldoffset = offsetoflow32(CPUARMState,
1992 cp15.c14_timer[GTIMER_VIRT].ctl),
1993 .writefn = gt_virt_ctl_write, .raw_writefn = raw_write,
1994 },
1995 { .name = "CNTV_CTL_EL0", .state = ARM_CP_STATE_AA64,
1996 .opc0 = 3, .opc1 = 3, .crn = 14, .crm = 3, .opc2 = 1,
1997 .type = ARM_CP_IO, .access = PL1_RW | PL0_R,
1998 .accessfn = gt_vtimer_access,
1999 .fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_VIRT].ctl),
2000 .resetvalue = 0,
2001 .writefn = gt_virt_ctl_write, .raw_writefn = raw_write,
2002 },
2003
2004 { .name = "CNTP_TVAL", .cp = 15, .crn = 14, .crm = 2, .opc1 = 0, .opc2 = 0,
2005 .secure = ARM_CP_SECSTATE_NS,
2006 .type = ARM_CP_NO_RAW | ARM_CP_IO, .access = PL1_RW | PL0_R,
2007 .accessfn = gt_ptimer_access,
2008 .readfn = gt_phys_tval_read, .writefn = gt_phys_tval_write,
2009 },
2010 { .name = "CNTP_TVAL(S)",
2011 .cp = 15, .crn = 14, .crm = 2, .opc1 = 0, .opc2 = 0,
2012 .secure = ARM_CP_SECSTATE_S,
2013 .type = ARM_CP_NO_RAW | ARM_CP_IO, .access = PL1_RW | PL0_R,
2014 .accessfn = gt_ptimer_access,
2015 .readfn = gt_sec_tval_read, .writefn = gt_sec_tval_write,
2016 },
2017 { .name = "CNTP_TVAL_EL0", .state = ARM_CP_STATE_AA64,
2018 .opc0 = 3, .opc1 = 3, .crn = 14, .crm = 2, .opc2 = 0,
2019 .type = ARM_CP_NO_RAW | ARM_CP_IO, .access = PL1_RW | PL0_R,
2020 .accessfn = gt_ptimer_access, .resetfn = gt_phys_timer_reset,
2021 .readfn = gt_phys_tval_read, .writefn = gt_phys_tval_write,
2022 },
2023 { .name = "CNTV_TVAL", .cp = 15, .crn = 14, .crm = 3, .opc1 = 0, .opc2 = 0,
2024 .type = ARM_CP_NO_RAW | ARM_CP_IO, .access = PL1_RW | PL0_R,
2025 .accessfn = gt_vtimer_access,
2026 .readfn = gt_virt_tval_read, .writefn = gt_virt_tval_write,
2027 },
2028 { .name = "CNTV_TVAL_EL0", .state = ARM_CP_STATE_AA64,
2029 .opc0 = 3, .opc1 = 3, .crn = 14, .crm = 3, .opc2 = 0,
2030 .type = ARM_CP_NO_RAW | ARM_CP_IO, .access = PL1_RW | PL0_R,
2031 .accessfn = gt_vtimer_access, .resetfn = gt_virt_timer_reset,
2032 .readfn = gt_virt_tval_read, .writefn = gt_virt_tval_write,
2033 },
2034
2035 { .name = "CNTPCT", .cp = 15, .crm = 14, .opc1 = 0,
2036 .access = PL0_R, .type = ARM_CP_64BIT | ARM_CP_NO_RAW | ARM_CP_IO,
2037 .accessfn = gt_pct_access,
2038 .readfn = gt_cnt_read, .resetfn = arm_cp_reset_ignore,
2039 },
2040 { .name = "CNTPCT_EL0", .state = ARM_CP_STATE_AA64,
2041 .opc0 = 3, .opc1 = 3, .crn = 14, .crm = 0, .opc2 = 1,
2042 .access = PL0_R, .type = ARM_CP_NO_RAW | ARM_CP_IO,
2043 .accessfn = gt_pct_access, .readfn = gt_cnt_read,
2044 },
2045 { .name = "CNTVCT", .cp = 15, .crm = 14, .opc1 = 1,
2046 .access = PL0_R, .type = ARM_CP_64BIT | ARM_CP_NO_RAW | ARM_CP_IO,
2047 .accessfn = gt_vct_access,
2048 .readfn = gt_virt_cnt_read, .resetfn = arm_cp_reset_ignore,
2049 },
2050 { .name = "CNTVCT_EL0", .state = ARM_CP_STATE_AA64,
2051 .opc0 = 3, .opc1 = 3, .crn = 14, .crm = 0, .opc2 = 2,
2052 .access = PL0_R, .type = ARM_CP_NO_RAW | ARM_CP_IO,
2053 .accessfn = gt_vct_access, .readfn = gt_virt_cnt_read,
2054 },
2055
2056 { .name = "CNTP_CVAL", .cp = 15, .crm = 14, .opc1 = 2,
2057 .secure = ARM_CP_SECSTATE_NS,
2058 .access = PL1_RW | PL0_R,
2059 .type = ARM_CP_64BIT | ARM_CP_IO | ARM_CP_ALIAS,
2060 .fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_PHYS].cval),
2061 .accessfn = gt_ptimer_access,
2062 .writefn = gt_phys_cval_write, .raw_writefn = raw_write,
2063 },
2064 { .name = "CNTP_CVAL(S)", .cp = 15, .crm = 14, .opc1 = 2,
2065 .secure = ARM_CP_SECSTATE_S,
2066 .access = PL1_RW | PL0_R,
2067 .type = ARM_CP_64BIT | ARM_CP_IO | ARM_CP_ALIAS,
2068 .fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_SEC].cval),
2069 .accessfn = gt_ptimer_access,
2070 .writefn = gt_sec_cval_write, .raw_writefn = raw_write,
2071 },
2072 { .name = "CNTP_CVAL_EL0", .state = ARM_CP_STATE_AA64,
2073 .opc0 = 3, .opc1 = 3, .crn = 14, .crm = 2, .opc2 = 2,
2074 .access = PL1_RW | PL0_R,
2075 .type = ARM_CP_IO,
2076 .fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_PHYS].cval),
2077 .resetvalue = 0, .accessfn = gt_ptimer_access,
2078 .writefn = gt_phys_cval_write, .raw_writefn = raw_write,
2079 },
2080 { .name = "CNTV_CVAL", .cp = 15, .crm = 14, .opc1 = 3,
2081 .access = PL1_RW | PL0_R,
2082 .type = ARM_CP_64BIT | ARM_CP_IO | ARM_CP_ALIAS,
2083 .fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_VIRT].cval),
2084 .accessfn = gt_vtimer_access,
2085 .writefn = gt_virt_cval_write, .raw_writefn = raw_write,
2086 },
2087 { .name = "CNTV_CVAL_EL0", .state = ARM_CP_STATE_AA64,
2088 .opc0 = 3, .opc1 = 3, .crn = 14, .crm = 3, .opc2 = 2,
2089 .access = PL1_RW | PL0_R,
2090 .type = ARM_CP_IO,
2091 .fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_VIRT].cval),
2092 .resetvalue = 0, .accessfn = gt_vtimer_access,
2093 .writefn = gt_virt_cval_write, .raw_writefn = raw_write,
2094 },
2095
2096
2097
2098 { .name = "CNTPS_TVAL_EL1", .state = ARM_CP_STATE_AA64,
2099 .opc0 = 3, .opc1 = 7, .crn = 14, .crm = 2, .opc2 = 0,
2100 .type = ARM_CP_NO_RAW | ARM_CP_IO, .access = PL1_RW,
2101 .accessfn = gt_stimer_access,
2102 .readfn = gt_sec_tval_read,
2103 .writefn = gt_sec_tval_write,
2104 .resetfn = gt_sec_timer_reset,
2105 },
2106 { .name = "CNTPS_CTL_EL1", .state = ARM_CP_STATE_AA64,
2107 .opc0 = 3, .opc1 = 7, .crn = 14, .crm = 2, .opc2 = 1,
2108 .type = ARM_CP_IO, .access = PL1_RW,
2109 .accessfn = gt_stimer_access,
2110 .fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_SEC].ctl),
2111 .resetvalue = 0,
2112 .writefn = gt_sec_ctl_write, .raw_writefn = raw_write,
2113 },
2114 { .name = "CNTPS_CVAL_EL1", .state = ARM_CP_STATE_AA64,
2115 .opc0 = 3, .opc1 = 7, .crn = 14, .crm = 2, .opc2 = 2,
2116 .type = ARM_CP_IO, .access = PL1_RW,
2117 .accessfn = gt_stimer_access,
2118 .fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_SEC].cval),
2119 .writefn = gt_sec_cval_write, .raw_writefn = raw_write,
2120 },
2121 REGINFO_SENTINEL
2122};
2123
2124#else
2125
2126
2127
2128
2129static const ARMCPRegInfo generic_timer_cp_reginfo[] = {
2130 REGINFO_SENTINEL
2131};
2132
2133#endif
2134
2135static void par_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
2136{
2137 if (arm_feature(env, ARM_FEATURE_LPAE)) {
2138 raw_write(env, ri, value);
2139 } else if (arm_feature(env, ARM_FEATURE_V7)) {
2140 raw_write(env, ri, value & 0xfffff6ff);
2141 } else {
2142 raw_write(env, ri, value & 0xfffff1ff);
2143 }
2144}
2145
2146#ifndef CONFIG_USER_ONLY
2147
2148static inline uint32_t regime_el(CPUARMState *env, ARMMMUIdx mmu_idx)
2149{
2150 switch (mmu_idx) {
2151 case ARMMMUIdx_S2NS:
2152 case ARMMMUIdx_S1E2:
2153 case ARMMMUIdx_S12NSE0:
2154 case ARMMMUIdx_S12NSE1:
2155 return 2;
2156 case ARMMMUIdx_S1E3:
2157 return 3;
2158 case ARMMMUIdx_S1SE0:
2159 return arm_el_is_aa64(env, 3) ? 1 : 3;
2160 case ARMMMUIdx_S1SE1:
2161 case ARMMMUIdx_S1NSE0:
2162 case ARMMMUIdx_S1NSE1:
2163 return 1;
2164 default:
2165 g_assert_not_reached();
2166 }
2167}
2168
2169
2170static inline TCR *regime_tcr(CPUARMState *env, ARMMMUIdx mmu_idx)
2171{
2172 if (mmu_idx == ARMMMUIdx_S2NS) {
2173 return &env->cp15.vtcr_el2;
2174 }
2175 return &env->cp15.tcr_el[regime_el(env, mmu_idx)];
2176}
2177
2178
2179
2180
2181static CPAccessResult ats_access(CPUARMState *env, const ARMCPRegInfo *ri,
2182 bool isread)
2183{
2184 if (ri->opc2 & 4) {
2185
2186
2187
2188
2189
2190 if (arm_current_el(env) == 1) {
2191 if (arm_is_secure_below_el3(env)) {
2192 return CP_ACCESS_TRAP_UNCATEGORIZED_EL3;
2193 }
2194 return CP_ACCESS_TRAP_UNCATEGORIZED;
2195 }
2196 }
2197 return CP_ACCESS_OK;
2198}
2199
2200static uint64_t do_ats_write(CPUARMState *env, uint64_t value,
2201 int access_type, ARMMMUIdx mmu_idx)
2202{
2203 hwaddr phys_addr;
2204 target_ulong page_size;
2205 int prot;
2206 uint32_t fsr;
2207 bool ret;
2208 uint64_t par64;
2209 MemTxAttrs attrs = {};
2210 ARMMMUFaultInfo fi = {};
2211
2212 ret = get_phys_addr(env, value, access_type, mmu_idx,
2213 &phys_addr, &attrs, &prot, &page_size, &fsr, &fi);
2214 if (extended_addresses_enabled_el(env, regime_el(env, mmu_idx),
2215 regime_tcr(env, mmu_idx))) {
2216
2217
2218
2219
2220 par64 = (1 << 11);
2221 if (!ret) {
2222 par64 |= phys_addr & ~0xfffULL;
2223 if (!attrs.secure) {
2224 par64 |= (1 << 9);
2225 }
2226
2227 } else {
2228 par64 |= 1;
2229 par64 |= (fsr & 0x3f) << 1;
2230
2231
2232
2233
2234 }
2235 } else {
2236
2237
2238
2239
2240 if (!ret) {
2241
2242 if (page_size == (1 << 24)
2243 && arm_feature(env, ARM_FEATURE_V7)) {
2244 par64 = (phys_addr & 0xff000000) | (1 << 1);
2245 } else {
2246 par64 = phys_addr & 0xfffff000;
2247 }
2248 if (!attrs.secure) {
2249 par64 |= (1 << 9);
2250 }
2251 } else {
2252 par64 = ((fsr & (1 << 10)) >> 5) | ((fsr & (1 << 12)) >> 6) |
2253 ((fsr & 0xf) << 1) | 1;
2254 }
2255 }
2256 return par64;
2257}
2258
2259static void ats_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
2260{
2261 int access_type = ri->opc2 & 1;
2262 uint64_t par64;
2263 ARMMMUIdx mmu_idx;
2264 int el = arm_current_el(env);
2265 bool secure = arm_is_secure_below_el3(env);
2266
2267 switch (ri->opc2 & 6) {
2268 case 0:
2269
2270 switch (el) {
2271 case 3:
2272 mmu_idx = ARMMMUIdx_S1E3;
2273 break;
2274 case 2:
2275 mmu_idx = ARMMMUIdx_S1NSE1;
2276 break;
2277 case 1:
2278 mmu_idx = secure ? ARMMMUIdx_S1SE1 : ARMMMUIdx_S1NSE1;
2279 break;
2280 default:
2281 g_assert_not_reached();
2282 }
2283 break;
2284 case 2:
2285
2286 switch (el) {
2287 case 3:
2288 mmu_idx = ARMMMUIdx_S1SE0;
2289 break;
2290 case 2:
2291 mmu_idx = ARMMMUIdx_S1NSE0;
2292 break;
2293 case 1:
2294 mmu_idx = secure ? ARMMMUIdx_S1SE0 : ARMMMUIdx_S1NSE0;
2295 break;
2296 default:
2297 g_assert_not_reached();
2298 }
2299 break;
2300 case 4:
2301
2302 mmu_idx = ARMMMUIdx_S12NSE1;
2303 break;
2304 case 6:
2305
2306 mmu_idx = ARMMMUIdx_S12NSE0;
2307 break;
2308 default:
2309 g_assert_not_reached();
2310 }
2311
2312 par64 = do_ats_write(env, value, access_type, mmu_idx);
2313
2314 A32_BANKED_CURRENT_REG_SET(env, par, par64);
2315}
2316
2317static void ats1h_write(CPUARMState *env, const ARMCPRegInfo *ri,
2318 uint64_t value)
2319{
2320 int access_type = ri->opc2 & 1;
2321 uint64_t par64;
2322
2323 par64 = do_ats_write(env, value, access_type, ARMMMUIdx_S2NS);
2324
2325 A32_BANKED_CURRENT_REG_SET(env, par, par64);
2326}
2327
2328static CPAccessResult at_s1e2_access(CPUARMState *env, const ARMCPRegInfo *ri,
2329 bool isread)
2330{
2331 if (arm_current_el(env) == 3 && !(env->cp15.scr_el3 & SCR_NS)) {
2332 return CP_ACCESS_TRAP;
2333 }
2334 return CP_ACCESS_OK;
2335}
2336
2337static void ats_write64(CPUARMState *env, const ARMCPRegInfo *ri,
2338 uint64_t value)
2339{
2340 int access_type = ri->opc2 & 1;
2341 ARMMMUIdx mmu_idx;
2342 int secure = arm_is_secure_below_el3(env);
2343
2344 switch (ri->opc2 & 6) {
2345 case 0:
2346 switch (ri->opc1) {
2347 case 0:
2348 mmu_idx = secure ? ARMMMUIdx_S1SE1 : ARMMMUIdx_S1NSE1;
2349 break;
2350 case 4:
2351 mmu_idx = ARMMMUIdx_S1E2;
2352 break;
2353 case 6:
2354 mmu_idx = ARMMMUIdx_S1E3;
2355 break;
2356 default:
2357 g_assert_not_reached();
2358 }
2359 break;
2360 case 2:
2361 mmu_idx = secure ? ARMMMUIdx_S1SE0 : ARMMMUIdx_S1NSE0;
2362 break;
2363 case 4:
2364 mmu_idx = secure ? ARMMMUIdx_S1SE1 : ARMMMUIdx_S12NSE1;
2365 break;
2366 case 6:
2367 mmu_idx = secure ? ARMMMUIdx_S1SE0 : ARMMMUIdx_S12NSE0;
2368 break;
2369 default:
2370 g_assert_not_reached();
2371 }
2372
2373 env->cp15.par_el[1] = do_ats_write(env, value, access_type, mmu_idx);
2374}
2375#endif
2376
2377static const ARMCPRegInfo vapa_cp_reginfo[] = {
2378 { .name = "PAR", .cp = 15, .crn = 7, .crm = 4, .opc1 = 0, .opc2 = 0,
2379 .access = PL1_RW, .resetvalue = 0,
2380 .bank_fieldoffsets = { offsetoflow32(CPUARMState, cp15.par_s),
2381 offsetoflow32(CPUARMState, cp15.par_ns) },
2382 .writefn = par_write },
2383#ifndef CONFIG_USER_ONLY
2384
2385 { .name = "ATS", .cp = 15, .crn = 7, .crm = 8, .opc1 = 0, .opc2 = CP_ANY,
2386 .access = PL1_W, .accessfn = ats_access,
2387 .writefn = ats_write, .type = ARM_CP_NO_RAW },
2388#endif
2389 REGINFO_SENTINEL
2390};
2391
2392
2393static uint32_t simple_mpu_ap_bits(uint32_t val)
2394{
2395 uint32_t ret;
2396 uint32_t mask;
2397 int i;
2398 ret = 0;
2399 mask = 3;
2400 for (i = 0; i < 16; i += 2) {
2401 ret |= (val >> i) & mask;
2402 mask <<= 2;
2403 }
2404 return ret;
2405}
2406
2407
2408static uint32_t extended_mpu_ap_bits(uint32_t val)
2409{
2410 uint32_t ret;
2411 uint32_t mask;
2412 int i;
2413 ret = 0;
2414 mask = 3;
2415 for (i = 0; i < 16; i += 2) {
2416 ret |= (val & mask) << i;
2417 mask <<= 2;
2418 }
2419 return ret;
2420}
2421
2422static void pmsav5_data_ap_write(CPUARMState *env, const ARMCPRegInfo *ri,
2423 uint64_t value)
2424{
2425 env->cp15.pmsav5_data_ap = extended_mpu_ap_bits(value);
2426}
2427
2428static uint64_t pmsav5_data_ap_read(CPUARMState *env, const ARMCPRegInfo *ri)
2429{
2430 return simple_mpu_ap_bits(env->cp15.pmsav5_data_ap);
2431}
2432
2433static void pmsav5_insn_ap_write(CPUARMState *env, const ARMCPRegInfo *ri,
2434 uint64_t value)
2435{
2436 env->cp15.pmsav5_insn_ap = extended_mpu_ap_bits(value);
2437}
2438
2439static uint64_t pmsav5_insn_ap_read(CPUARMState *env, const ARMCPRegInfo *ri)
2440{
2441 return simple_mpu_ap_bits(env->cp15.pmsav5_insn_ap);
2442}
2443
2444static uint64_t pmsav7_read(CPUARMState *env, const ARMCPRegInfo *ri)
2445{
2446 uint32_t *u32p = *(uint32_t **)raw_ptr(env, ri);
2447
2448 if (!u32p) {
2449 return 0;
2450 }
2451
2452 u32p += env->cp15.c6_rgnr;
2453 return *u32p;
2454}
2455
2456static void pmsav7_write(CPUARMState *env, const ARMCPRegInfo *ri,
2457 uint64_t value)
2458{
2459 ARMCPU *cpu = arm_env_get_cpu(env);
2460 uint32_t *u32p = *(uint32_t **)raw_ptr(env, ri);
2461
2462 if (!u32p) {
2463 return;
2464 }
2465
2466 u32p += env->cp15.c6_rgnr;
2467 tlb_flush(CPU(cpu), 1);
2468 *u32p = value;
2469}
2470
2471static void pmsav7_reset(CPUARMState *env, const ARMCPRegInfo *ri)
2472{
2473 ARMCPU *cpu = arm_env_get_cpu(env);
2474 uint32_t *u32p = *(uint32_t **)raw_ptr(env, ri);
2475
2476 if (!u32p) {
2477 return;
2478 }
2479
2480 memset(u32p, 0, sizeof(*u32p) * cpu->pmsav7_dregion);
2481}
2482
2483static void pmsav7_rgnr_write(CPUARMState *env, const ARMCPRegInfo *ri,
2484 uint64_t value)
2485{
2486 ARMCPU *cpu = arm_env_get_cpu(env);
2487 uint32_t nrgs = cpu->pmsav7_dregion;
2488
2489 if (value >= nrgs) {
2490 qemu_log_mask(LOG_GUEST_ERROR,
2491 "PMSAv7 RGNR write >= # supported regions, %" PRIu32
2492 " > %" PRIu32 "\n", (uint32_t)value, nrgs);
2493 return;
2494 }
2495
2496 raw_write(env, ri, value);
2497}
2498
2499static const ARMCPRegInfo pmsav7_cp_reginfo[] = {
2500 { .name = "DRBAR", .cp = 15, .crn = 6, .opc1 = 0, .crm = 1, .opc2 = 0,
2501 .access = PL1_RW, .type = ARM_CP_NO_RAW,
2502 .fieldoffset = offsetof(CPUARMState, pmsav7.drbar),
2503 .readfn = pmsav7_read, .writefn = pmsav7_write, .resetfn = pmsav7_reset },
2504 { .name = "DRSR", .cp = 15, .crn = 6, .opc1 = 0, .crm = 1, .opc2 = 2,
2505 .access = PL1_RW, .type = ARM_CP_NO_RAW,
2506 .fieldoffset = offsetof(CPUARMState, pmsav7.drsr),
2507 .readfn = pmsav7_read, .writefn = pmsav7_write, .resetfn = pmsav7_reset },
2508 { .name = "DRACR", .cp = 15, .crn = 6, .opc1 = 0, .crm = 1, .opc2 = 4,
2509 .access = PL1_RW, .type = ARM_CP_NO_RAW,
2510 .fieldoffset = offsetof(CPUARMState, pmsav7.dracr),
2511 .readfn = pmsav7_read, .writefn = pmsav7_write, .resetfn = pmsav7_reset },
2512 { .name = "RGNR", .cp = 15, .crn = 6, .opc1 = 0, .crm = 2, .opc2 = 0,
2513 .access = PL1_RW,
2514 .fieldoffset = offsetof(CPUARMState, cp15.c6_rgnr),
2515 .writefn = pmsav7_rgnr_write },
2516 REGINFO_SENTINEL
2517};
2518
2519static const ARMCPRegInfo pmsav5_cp_reginfo[] = {
2520 { .name = "DATA_AP", .cp = 15, .crn = 5, .crm = 0, .opc1 = 0, .opc2 = 0,
2521 .access = PL1_RW, .type = ARM_CP_ALIAS,
2522 .fieldoffset = offsetof(CPUARMState, cp15.pmsav5_data_ap),
2523 .readfn = pmsav5_data_ap_read, .writefn = pmsav5_data_ap_write, },
2524 { .name = "INSN_AP", .cp = 15, .crn = 5, .crm = 0, .opc1 = 0, .opc2 = 1,
2525 .access = PL1_RW, .type = ARM_CP_ALIAS,
2526 .fieldoffset = offsetof(CPUARMState, cp15.pmsav5_insn_ap),
2527 .readfn = pmsav5_insn_ap_read, .writefn = pmsav5_insn_ap_write, },
2528 { .name = "DATA_EXT_AP", .cp = 15, .crn = 5, .crm = 0, .opc1 = 0, .opc2 = 2,
2529 .access = PL1_RW,
2530 .fieldoffset = offsetof(CPUARMState, cp15.pmsav5_data_ap),
2531 .resetvalue = 0, },
2532 { .name = "INSN_EXT_AP", .cp = 15, .crn = 5, .crm = 0, .opc1 = 0, .opc2 = 3,
2533 .access = PL1_RW,
2534 .fieldoffset = offsetof(CPUARMState, cp15.pmsav5_insn_ap),
2535 .resetvalue = 0, },
2536 { .name = "DCACHE_CFG", .cp = 15, .crn = 2, .crm = 0, .opc1 = 0, .opc2 = 0,
2537 .access = PL1_RW,
2538 .fieldoffset = offsetof(CPUARMState, cp15.c2_data), .resetvalue = 0, },
2539 { .name = "ICACHE_CFG", .cp = 15, .crn = 2, .crm = 0, .opc1 = 0, .opc2 = 1,
2540 .access = PL1_RW,
2541 .fieldoffset = offsetof(CPUARMState, cp15.c2_insn), .resetvalue = 0, },
2542
2543 { .name = "946_PRBS0", .cp = 15, .crn = 6, .crm = 0, .opc1 = 0,
2544 .opc2 = CP_ANY, .access = PL1_RW, .resetvalue = 0,
2545 .fieldoffset = offsetof(CPUARMState, cp15.c6_region[0]) },
2546 { .name = "946_PRBS1", .cp = 15, .crn = 6, .crm = 1, .opc1 = 0,
2547 .opc2 = CP_ANY, .access = PL1_RW, .resetvalue = 0,
2548 .fieldoffset = offsetof(CPUARMState, cp15.c6_region[1]) },
2549 { .name = "946_PRBS2", .cp = 15, .crn = 6, .crm = 2, .opc1 = 0,
2550 .opc2 = CP_ANY, .access = PL1_RW, .resetvalue = 0,
2551 .fieldoffset = offsetof(CPUARMState, cp15.c6_region[2]) },
2552 { .name = "946_PRBS3", .cp = 15, .crn = 6, .crm = 3, .opc1 = 0,
2553 .opc2 = CP_ANY, .access = PL1_RW, .resetvalue = 0,
2554 .fieldoffset = offsetof(CPUARMState, cp15.c6_region[3]) },
2555 { .name = "946_PRBS4", .cp = 15, .crn = 6, .crm = 4, .opc1 = 0,
2556 .opc2 = CP_ANY, .access = PL1_RW, .resetvalue = 0,
2557 .fieldoffset = offsetof(CPUARMState, cp15.c6_region[4]) },
2558 { .name = "946_PRBS5", .cp = 15, .crn = 6, .crm = 5, .opc1 = 0,
2559 .opc2 = CP_ANY, .access = PL1_RW, .resetvalue = 0,
2560 .fieldoffset = offsetof(CPUARMState, cp15.c6_region[5]) },
2561 { .name = "946_PRBS6", .cp = 15, .crn = 6, .crm = 6, .opc1 = 0,
2562 .opc2 = CP_ANY, .access = PL1_RW, .resetvalue = 0,
2563 .fieldoffset = offsetof(CPUARMState, cp15.c6_region[6]) },
2564 { .name = "946_PRBS7", .cp = 15, .crn = 6, .crm = 7, .opc1 = 0,
2565 .opc2 = CP_ANY, .access = PL1_RW, .resetvalue = 0,
2566 .fieldoffset = offsetof(CPUARMState, cp15.c6_region[7]) },
2567 REGINFO_SENTINEL
2568};
2569
2570static void vmsa_ttbcr_raw_write(CPUARMState *env, const ARMCPRegInfo *ri,
2571 uint64_t value)
2572{
2573 TCR *tcr = raw_ptr(env, ri);
2574 int maskshift = extract32(value, 0, 3);
2575
2576 if (!arm_feature(env, ARM_FEATURE_V8)) {
2577 if (arm_feature(env, ARM_FEATURE_LPAE) && (value & TTBCR_EAE)) {
2578
2579
2580 value &= ~((7 << 19) | (3 << 14) | (0xf << 3));
2581 } else if (arm_feature(env, ARM_FEATURE_EL3)) {
2582
2583
2584
2585
2586 value &= TTBCR_PD1 | TTBCR_PD0 | TTBCR_N;
2587 } else {
2588 value &= TTBCR_N;
2589 }
2590 }
2591
2592
2593
2594
2595
2596
2597
2598 tcr->raw_tcr = value;
2599 tcr->mask = ~(((uint32_t)0xffffffffu) >> maskshift);
2600 tcr->base_mask = ~((uint32_t)0x3fffu >> maskshift);
2601}
2602
2603static void vmsa_ttbcr_write(CPUARMState *env, const ARMCPRegInfo *ri,
2604 uint64_t value)
2605{
2606 ARMCPU *cpu = arm_env_get_cpu(env);
2607
2608 if (arm_feature(env, ARM_FEATURE_LPAE)) {
2609
2610
2611
2612 tlb_flush(CPU(cpu), 1);
2613 }
2614 vmsa_ttbcr_raw_write(env, ri, value);
2615}
2616
2617static void vmsa_ttbcr_reset(CPUARMState *env, const ARMCPRegInfo *ri)
2618{
2619 TCR *tcr = raw_ptr(env, ri);
2620
2621
2622
2623
2624 tcr->raw_tcr = 0;
2625 tcr->mask = 0;
2626 tcr->base_mask = 0xffffc000u;
2627}
2628
2629static void vmsa_tcr_el1_write(CPUARMState *env, const ARMCPRegInfo *ri,
2630 uint64_t value)
2631{
2632 ARMCPU *cpu = arm_env_get_cpu(env);
2633 TCR *tcr = raw_ptr(env, ri);
2634
2635
2636 tlb_flush(CPU(cpu), 1);
2637 tcr->raw_tcr = value;
2638}
2639
2640static void vmsa_ttbr_write(CPUARMState *env, const ARMCPRegInfo *ri,
2641 uint64_t value)
2642{
2643
2644
2645
2646 if (cpreg_field_is_64bit(ri)) {
2647 ARMCPU *cpu = arm_env_get_cpu(env);
2648
2649 tlb_flush(CPU(cpu), 1);
2650 }
2651 raw_write(env, ri, value);
2652}
2653
2654static void vttbr_write(CPUARMState *env, const ARMCPRegInfo *ri,
2655 uint64_t value)
2656{
2657 ARMCPU *cpu = arm_env_get_cpu(env);
2658 CPUState *cs = CPU(cpu);
2659
2660
2661 if (raw_read(env, ri) != value) {
2662 tlb_flush_by_mmuidx(cs, ARMMMUIdx_S12NSE1, ARMMMUIdx_S12NSE0,
2663 ARMMMUIdx_S2NS, -1);
2664 raw_write(env, ri, value);
2665 }
2666}
2667
2668static const ARMCPRegInfo vmsa_pmsa_cp_reginfo[] = {
2669 { .name = "DFSR", .cp = 15, .crn = 5, .crm = 0, .opc1 = 0, .opc2 = 0,
2670 .access = PL1_RW, .type = ARM_CP_ALIAS,
2671 .bank_fieldoffsets = { offsetoflow32(CPUARMState, cp15.dfsr_s),
2672 offsetoflow32(CPUARMState, cp15.dfsr_ns) }, },
2673 { .name = "IFSR", .cp = 15, .crn = 5, .crm = 0, .opc1 = 0, .opc2 = 1,
2674 .access = PL1_RW, .resetvalue = 0,
2675 .bank_fieldoffsets = { offsetoflow32(CPUARMState, cp15.ifsr_s),
2676 offsetoflow32(CPUARMState, cp15.ifsr_ns) } },
2677 { .name = "DFAR", .cp = 15, .opc1 = 0, .crn = 6, .crm = 0, .opc2 = 0,
2678 .access = PL1_RW, .resetvalue = 0,
2679 .bank_fieldoffsets = { offsetof(CPUARMState, cp15.dfar_s),
2680 offsetof(CPUARMState, cp15.dfar_ns) } },
2681 { .name = "FAR_EL1", .state = ARM_CP_STATE_AA64,
2682 .opc0 = 3, .crn = 6, .crm = 0, .opc1 = 0, .opc2 = 0,
2683 .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.far_el[1]),
2684 .resetvalue = 0, },
2685 REGINFO_SENTINEL
2686};
2687
2688static const ARMCPRegInfo vmsa_cp_reginfo[] = {
2689 { .name = "ESR_EL1", .state = ARM_CP_STATE_AA64,
2690 .opc0 = 3, .crn = 5, .crm = 2, .opc1 = 0, .opc2 = 0,
2691 .access = PL1_RW,
2692 .fieldoffset = offsetof(CPUARMState, cp15.esr_el[1]), .resetvalue = 0, },
2693 { .name = "TTBR0_EL1", .state = ARM_CP_STATE_BOTH,
2694 .opc0 = 3, .opc1 = 0, .crn = 2, .crm = 0, .opc2 = 0,
2695 .access = PL1_RW, .writefn = vmsa_ttbr_write, .resetvalue = 0,
2696 .bank_fieldoffsets = { offsetof(CPUARMState, cp15.ttbr0_s),
2697 offsetof(CPUARMState, cp15.ttbr0_ns) } },
2698 { .name = "TTBR1_EL1", .state = ARM_CP_STATE_BOTH,
2699 .opc0 = 3, .opc1 = 0, .crn = 2, .crm = 0, .opc2 = 1,
2700 .access = PL1_RW, .writefn = vmsa_ttbr_write, .resetvalue = 0,
2701 .bank_fieldoffsets = { offsetof(CPUARMState, cp15.ttbr1_s),
2702 offsetof(CPUARMState, cp15.ttbr1_ns) } },
2703 { .name = "TCR_EL1", .state = ARM_CP_STATE_AA64,
2704 .opc0 = 3, .crn = 2, .crm = 0, .opc1 = 0, .opc2 = 2,
2705 .access = PL1_RW, .writefn = vmsa_tcr_el1_write,
2706 .resetfn = vmsa_ttbcr_reset, .raw_writefn = raw_write,
2707 .fieldoffset = offsetof(CPUARMState, cp15.tcr_el[1]) },
2708 { .name = "TTBCR", .cp = 15, .crn = 2, .crm = 0, .opc1 = 0, .opc2 = 2,
2709 .access = PL1_RW, .type = ARM_CP_ALIAS, .writefn = vmsa_ttbcr_write,
2710 .raw_writefn = vmsa_ttbcr_raw_write,
2711 .bank_fieldoffsets = { offsetoflow32(CPUARMState, cp15.tcr_el[3]),
2712 offsetoflow32(CPUARMState, cp15.tcr_el[1])} },
2713 REGINFO_SENTINEL
2714};
2715
2716static void omap_ticonfig_write(CPUARMState *env, const ARMCPRegInfo *ri,
2717 uint64_t value)
2718{
2719 env->cp15.c15_ticonfig = value & 0xe7;
2720
2721 env->cp15.c0_cpuid = (value & (1 << 5)) ?
2722 ARM_CPUID_TI915T : ARM_CPUID_TI925T;
2723}
2724
2725static void omap_threadid_write(CPUARMState *env, const ARMCPRegInfo *ri,
2726 uint64_t value)
2727{
2728 env->cp15.c15_threadid = value & 0xffff;
2729}
2730
2731static void omap_wfi_write(CPUARMState *env, const ARMCPRegInfo *ri,
2732 uint64_t value)
2733{
2734
2735 cpu_interrupt(CPU(arm_env_get_cpu(env)), CPU_INTERRUPT_HALT);
2736}
2737
2738static void omap_cachemaint_write(CPUARMState *env, const ARMCPRegInfo *ri,
2739 uint64_t value)
2740{
2741
2742
2743
2744 env->cp15.c15_i_max = 0x000;
2745 env->cp15.c15_i_min = 0xff0;
2746}
2747
2748static const ARMCPRegInfo omap_cp_reginfo[] = {
2749 { .name = "DFSR", .cp = 15, .crn = 5, .crm = CP_ANY,
2750 .opc1 = CP_ANY, .opc2 = CP_ANY, .access = PL1_RW, .type = ARM_CP_OVERRIDE,
2751 .fieldoffset = offsetoflow32(CPUARMState, cp15.esr_el[1]),
2752 .resetvalue = 0, },
2753 { .name = "", .cp = 15, .crn = 15, .crm = 0, .opc1 = 0, .opc2 = 0,
2754 .access = PL1_RW, .type = ARM_CP_NOP },
2755 { .name = "TICONFIG", .cp = 15, .crn = 15, .crm = 1, .opc1 = 0, .opc2 = 0,
2756 .access = PL1_RW,
2757 .fieldoffset = offsetof(CPUARMState, cp15.c15_ticonfig), .resetvalue = 0,
2758 .writefn = omap_ticonfig_write },
2759 { .name = "IMAX", .cp = 15, .crn = 15, .crm = 2, .opc1 = 0, .opc2 = 0,
2760 .access = PL1_RW,
2761 .fieldoffset = offsetof(CPUARMState, cp15.c15_i_max), .resetvalue = 0, },
2762 { .name = "IMIN", .cp = 15, .crn = 15, .crm = 3, .opc1 = 0, .opc2 = 0,
2763 .access = PL1_RW, .resetvalue = 0xff0,
2764 .fieldoffset = offsetof(CPUARMState, cp15.c15_i_min) },
2765 { .name = "THREADID", .cp = 15, .crn = 15, .crm = 4, .opc1 = 0, .opc2 = 0,
2766 .access = PL1_RW,
2767 .fieldoffset = offsetof(CPUARMState, cp15.c15_threadid), .resetvalue = 0,
2768 .writefn = omap_threadid_write },
2769 { .name = "TI925T_STATUS", .cp = 15, .crn = 15,
2770 .crm = 8, .opc1 = 0, .opc2 = 0, .access = PL1_RW,
2771 .type = ARM_CP_NO_RAW,
2772 .readfn = arm_cp_read_zero, .writefn = omap_wfi_write, },
2773
2774
2775
2776
2777
2778 { .name = "OMAP_CACHEMAINT", .cp = 15, .crn = 7, .crm = CP_ANY,
2779 .opc1 = 0, .opc2 = CP_ANY, .access = PL1_W,
2780 .type = ARM_CP_OVERRIDE | ARM_CP_NO_RAW,
2781 .writefn = omap_cachemaint_write },
2782 { .name = "C9", .cp = 15, .crn = 9,
2783 .crm = CP_ANY, .opc1 = CP_ANY, .opc2 = CP_ANY, .access = PL1_RW,
2784 .type = ARM_CP_CONST | ARM_CP_OVERRIDE, .resetvalue = 0 },
2785 REGINFO_SENTINEL
2786};
2787
2788static void xscale_cpar_write(CPUARMState *env, const ARMCPRegInfo *ri,
2789 uint64_t value)
2790{
2791 env->cp15.c15_cpar = value & 0x3fff;
2792}
2793
2794static const ARMCPRegInfo xscale_cp_reginfo[] = {
2795 { .name = "XSCALE_CPAR",
2796 .cp = 15, .crn = 15, .crm = 1, .opc1 = 0, .opc2 = 0, .access = PL1_RW,
2797 .fieldoffset = offsetof(CPUARMState, cp15.c15_cpar), .resetvalue = 0,
2798 .writefn = xscale_cpar_write, },
2799 { .name = "XSCALE_AUXCR",
2800 .cp = 15, .crn = 1, .crm = 0, .opc1 = 0, .opc2 = 1, .access = PL1_RW,
2801 .fieldoffset = offsetof(CPUARMState, cp15.c1_xscaleauxcr),
2802 .resetvalue = 0, },
2803
2804
2805
2806 { .name = "XSCALE_LOCK_ICACHE_LINE",
2807 .cp = 15, .opc1 = 0, .crn = 9, .crm = 1, .opc2 = 0,
2808 .access = PL1_W, .type = ARM_CP_NOP },
2809 { .name = "XSCALE_UNLOCK_ICACHE",
2810 .cp = 15, .opc1 = 0, .crn = 9, .crm = 1, .opc2 = 1,
2811 .access = PL1_W, .type = ARM_CP_NOP },
2812 { .name = "XSCALE_DCACHE_LOCK",
2813 .cp = 15, .opc1 = 0, .crn = 9, .crm = 2, .opc2 = 0,
2814 .access = PL1_RW, .type = ARM_CP_NOP },
2815 { .name = "XSCALE_UNLOCK_DCACHE",
2816 .cp = 15, .opc1 = 0, .crn = 9, .crm = 2, .opc2 = 1,
2817 .access = PL1_W, .type = ARM_CP_NOP },
2818 REGINFO_SENTINEL
2819};
2820
2821static const ARMCPRegInfo dummy_c15_cp_reginfo[] = {
2822
2823
2824
2825
2826
2827 { .name = "C15_IMPDEF", .cp = 15, .crn = 15,
2828 .crm = CP_ANY, .opc1 = CP_ANY, .opc2 = CP_ANY,
2829 .access = PL1_RW,
2830 .type = ARM_CP_CONST | ARM_CP_NO_RAW | ARM_CP_OVERRIDE,
2831 .resetvalue = 0 },
2832 REGINFO_SENTINEL
2833};
2834
2835static const ARMCPRegInfo cache_dirty_status_cp_reginfo[] = {
2836
2837 { .name = "CDSR", .cp = 15, .crn = 7, .crm = 10, .opc1 = 0, .opc2 = 6,
2838 .access = PL1_R, .type = ARM_CP_CONST | ARM_CP_NO_RAW,
2839 .resetvalue = 0 },
2840 REGINFO_SENTINEL
2841};
2842
2843static const ARMCPRegInfo cache_block_ops_cp_reginfo[] = {
2844
2845 { .name = "BXSR", .cp = 15, .crn = 7, .crm = 12, .opc1 = 0, .opc2 = 4,
2846 .access = PL0_R, .type = ARM_CP_CONST | ARM_CP_NO_RAW,
2847 .resetvalue = 0 },
2848
2849 { .name = "IICR", .cp = 15, .crm = 5, .opc1 = 0,
2850 .access = PL1_W, .type = ARM_CP_NOP|ARM_CP_64BIT },
2851 { .name = "IDCR", .cp = 15, .crm = 6, .opc1 = 0,
2852 .access = PL1_W, .type = ARM_CP_NOP|ARM_CP_64BIT },
2853 { .name = "CDCR", .cp = 15, .crm = 12, .opc1 = 0,
2854 .access = PL0_W, .type = ARM_CP_NOP|ARM_CP_64BIT },
2855 { .name = "PIR", .cp = 15, .crm = 12, .opc1 = 1,
2856 .access = PL0_W, .type = ARM_CP_NOP|ARM_CP_64BIT },
2857 { .name = "PDR", .cp = 15, .crm = 12, .opc1 = 2,
2858 .access = PL0_W, .type = ARM_CP_NOP|ARM_CP_64BIT },
2859 { .name = "CIDCR", .cp = 15, .crm = 14, .opc1 = 0,
2860 .access = PL1_W, .type = ARM_CP_NOP|ARM_CP_64BIT },
2861 REGINFO_SENTINEL
2862};
2863
2864static const ARMCPRegInfo cache_test_clean_cp_reginfo[] = {
2865
2866
2867
2868 { .name = "TC_DCACHE", .cp = 15, .crn = 7, .crm = 10, .opc1 = 0, .opc2 = 3,
2869 .access = PL0_R, .type = ARM_CP_CONST | ARM_CP_NO_RAW,
2870 .resetvalue = (1 << 30) },
2871 { .name = "TCI_DCACHE", .cp = 15, .crn = 7, .crm = 14, .opc1 = 0, .opc2 = 3,
2872 .access = PL0_R, .type = ARM_CP_CONST | ARM_CP_NO_RAW,
2873 .resetvalue = (1 << 30) },
2874 REGINFO_SENTINEL
2875};
2876
2877static const ARMCPRegInfo strongarm_cp_reginfo[] = {
2878
2879 { .name = "C9_READBUFFER", .cp = 15, .crn = 9,
2880 .crm = CP_ANY, .opc1 = CP_ANY, .opc2 = CP_ANY,
2881 .access = PL1_RW, .resetvalue = 0,
2882 .type = ARM_CP_CONST | ARM_CP_OVERRIDE | ARM_CP_NO_RAW },
2883 REGINFO_SENTINEL
2884};
2885
2886static uint64_t midr_read(CPUARMState *env, const ARMCPRegInfo *ri)
2887{
2888 ARMCPU *cpu = arm_env_get_cpu(env);
2889 unsigned int cur_el = arm_current_el(env);
2890 bool secure = arm_is_secure(env);
2891
2892 if (arm_feature(&cpu->env, ARM_FEATURE_EL2) && !secure && cur_el == 1) {
2893 return env->cp15.vpidr_el2;
2894 }
2895 return raw_read(env, ri);
2896}
2897
2898uint64_t mpidr_read_val(CPUARMState *env)
2899{
2900 ARMCPU *cpu = ARM_CPU(arm_env_get_cpu(env));
2901 uint64_t mpidr = cpu->mp_affinity;
2902
2903 if (arm_feature(env, ARM_FEATURE_V7MP)) {
2904 mpidr |= (1U << 31);
2905
2906
2907
2908
2909 if (cpu->mp_is_up) {
2910 mpidr |= (1u << 30);
2911 }
2912 }
2913 return mpidr;
2914}
2915
2916static uint64_t mpidr_read(CPUARMState *env, const ARMCPRegInfo *ri)
2917{
2918 unsigned int cur_el = arm_current_el(env);
2919 bool secure = arm_is_secure(env);
2920
2921 if (arm_feature(env, ARM_FEATURE_EL2) && !secure && cur_el == 1) {
2922 return env->cp15.vmpidr_el2;
2923 }
2924 return mpidr_read_val(env);
2925}
2926
2927static const ARMCPRegInfo mpidr_cp_reginfo[] = {
2928 { .name = "MPIDR", .state = ARM_CP_STATE_BOTH,
2929 .opc0 = 3, .crn = 0, .crm = 0, .opc1 = 0, .opc2 = 5,
2930 .access = PL1_R, .readfn = mpidr_read, .type = ARM_CP_NO_RAW },
2931 REGINFO_SENTINEL
2932};
2933
2934static const ARMCPRegInfo lpae_cp_reginfo[] = {
2935
2936 { .name = "AMAIR0", .state = ARM_CP_STATE_BOTH,
2937 .opc0 = 3, .crn = 10, .crm = 3, .opc1 = 0, .opc2 = 0,
2938 .access = PL1_RW, .type = ARM_CP_CONST,
2939 .resetvalue = 0 },
2940
2941 { .name = "AMAIR1", .cp = 15, .crn = 10, .crm = 3, .opc1 = 0, .opc2 = 1,
2942 .access = PL1_RW, .type = ARM_CP_CONST,
2943 .resetvalue = 0 },
2944 { .name = "PAR", .cp = 15, .crm = 7, .opc1 = 0,
2945 .access = PL1_RW, .type = ARM_CP_64BIT, .resetvalue = 0,
2946 .bank_fieldoffsets = { offsetof(CPUARMState, cp15.par_s),
2947 offsetof(CPUARMState, cp15.par_ns)} },
2948 { .name = "TTBR0", .cp = 15, .crm = 2, .opc1 = 0,
2949 .access = PL1_RW, .type = ARM_CP_64BIT | ARM_CP_ALIAS,
2950 .bank_fieldoffsets = { offsetof(CPUARMState, cp15.ttbr0_s),
2951 offsetof(CPUARMState, cp15.ttbr0_ns) },
2952 .writefn = vmsa_ttbr_write, },
2953 { .name = "TTBR1", .cp = 15, .crm = 2, .opc1 = 1,
2954 .access = PL1_RW, .type = ARM_CP_64BIT | ARM_CP_ALIAS,
2955 .bank_fieldoffsets = { offsetof(CPUARMState, cp15.ttbr1_s),
2956 offsetof(CPUARMState, cp15.ttbr1_ns) },
2957 .writefn = vmsa_ttbr_write, },
2958 REGINFO_SENTINEL
2959};
2960
2961static uint64_t aa64_fpcr_read(CPUARMState *env, const ARMCPRegInfo *ri)
2962{
2963 return vfp_get_fpcr(env);
2964}
2965
2966static void aa64_fpcr_write(CPUARMState *env, const ARMCPRegInfo *ri,
2967 uint64_t value)
2968{
2969 vfp_set_fpcr(env, value);
2970}
2971
2972static uint64_t aa64_fpsr_read(CPUARMState *env, const ARMCPRegInfo *ri)
2973{
2974 return vfp_get_fpsr(env);
2975}
2976
2977static void aa64_fpsr_write(CPUARMState *env, const ARMCPRegInfo *ri,
2978 uint64_t value)
2979{
2980 vfp_set_fpsr(env, value);
2981}
2982
2983static CPAccessResult aa64_daif_access(CPUARMState *env, const ARMCPRegInfo *ri,
2984 bool isread)
2985{
2986 if (arm_current_el(env) == 0 && !(env->cp15.sctlr_el[1] & SCTLR_UMA)) {
2987 return CP_ACCESS_TRAP;
2988 }
2989 return CP_ACCESS_OK;
2990}
2991
2992static void aa64_daif_write(CPUARMState *env, const ARMCPRegInfo *ri,
2993 uint64_t value)
2994{
2995 env->daif = value & PSTATE_DAIF;
2996}
2997
2998static CPAccessResult aa64_cacheop_access(CPUARMState *env,
2999 const ARMCPRegInfo *ri,
3000 bool isread)
3001{
3002
3003
3004
3005 if (arm_current_el(env) == 0 && !(env->cp15.sctlr_el[1] & SCTLR_UCI)) {
3006 return CP_ACCESS_TRAP;
3007 }
3008 return CP_ACCESS_OK;
3009}
3010
3011
3012
3013
3014
3015static void tlbi_aa64_vmalle1_write(CPUARMState *env, const ARMCPRegInfo *ri,
3016 uint64_t value)
3017{
3018 ARMCPU *cpu = arm_env_get_cpu(env);
3019 CPUState *cs = CPU(cpu);
3020
3021 if (arm_is_secure_below_el3(env)) {
3022 tlb_flush_by_mmuidx(cs, ARMMMUIdx_S1SE1, ARMMMUIdx_S1SE0, -1);
3023 } else {
3024 tlb_flush_by_mmuidx(cs, ARMMMUIdx_S12NSE1, ARMMMUIdx_S12NSE0, -1);
3025 }
3026}
3027
3028static void tlbi_aa64_vmalle1is_write(CPUARMState *env, const ARMCPRegInfo *ri,
3029 uint64_t value)
3030{
3031 bool sec = arm_is_secure_below_el3(env);
3032 CPUState *other_cs;
3033
3034 CPU_FOREACH(other_cs) {
3035 if (sec) {
3036 tlb_flush_by_mmuidx(other_cs, ARMMMUIdx_S1SE1, ARMMMUIdx_S1SE0, -1);
3037 } else {
3038 tlb_flush_by_mmuidx(other_cs, ARMMMUIdx_S12NSE1,
3039 ARMMMUIdx_S12NSE0, -1);
3040 }
3041 }
3042}
3043
3044static void tlbi_aa64_alle1_write(CPUARMState *env, const ARMCPRegInfo *ri,
3045 uint64_t value)
3046{
3047
3048
3049
3050
3051 ARMCPU *cpu = arm_env_get_cpu(env);
3052 CPUState *cs = CPU(cpu);
3053
3054 if (arm_is_secure_below_el3(env)) {
3055 tlb_flush_by_mmuidx(cs, ARMMMUIdx_S1SE1, ARMMMUIdx_S1SE0, -1);
3056 } else {
3057 if (arm_feature(env, ARM_FEATURE_EL2)) {
3058 tlb_flush_by_mmuidx(cs, ARMMMUIdx_S12NSE1, ARMMMUIdx_S12NSE0,
3059 ARMMMUIdx_S2NS, -1);
3060 } else {
3061 tlb_flush_by_mmuidx(cs, ARMMMUIdx_S12NSE1, ARMMMUIdx_S12NSE0, -1);
3062 }
3063 }
3064}
3065
3066static void tlbi_aa64_alle2_write(CPUARMState *env, const ARMCPRegInfo *ri,
3067 uint64_t value)
3068{
3069 ARMCPU *cpu = arm_env_get_cpu(env);
3070 CPUState *cs = CPU(cpu);
3071
3072 tlb_flush_by_mmuidx(cs, ARMMMUIdx_S1E2, -1);
3073}
3074
3075static void tlbi_aa64_alle3_write(CPUARMState *env, const ARMCPRegInfo *ri,
3076 uint64_t value)
3077{
3078 ARMCPU *cpu = arm_env_get_cpu(env);
3079 CPUState *cs = CPU(cpu);
3080
3081 tlb_flush_by_mmuidx(cs, ARMMMUIdx_S1E3, -1);
3082}
3083
3084static void tlbi_aa64_alle1is_write(CPUARMState *env, const ARMCPRegInfo *ri,
3085 uint64_t value)
3086{
3087
3088
3089
3090
3091 bool sec = arm_is_secure_below_el3(env);
3092 bool has_el2 = arm_feature(env, ARM_FEATURE_EL2);
3093 CPUState *other_cs;
3094
3095 CPU_FOREACH(other_cs) {
3096 if (sec) {
3097 tlb_flush_by_mmuidx(other_cs, ARMMMUIdx_S1SE1, ARMMMUIdx_S1SE0, -1);
3098 } else if (has_el2) {
3099 tlb_flush_by_mmuidx(other_cs, ARMMMUIdx_S12NSE1,
3100 ARMMMUIdx_S12NSE0, ARMMMUIdx_S2NS, -1);
3101 } else {
3102 tlb_flush_by_mmuidx(other_cs, ARMMMUIdx_S12NSE1,
3103 ARMMMUIdx_S12NSE0, -1);
3104 }
3105 }
3106}
3107
3108static void tlbi_aa64_alle2is_write(CPUARMState *env, const ARMCPRegInfo *ri,
3109 uint64_t value)
3110{
3111 CPUState *other_cs;
3112
3113 CPU_FOREACH(other_cs) {
3114 tlb_flush_by_mmuidx(other_cs, ARMMMUIdx_S1E2, -1);
3115 }
3116}
3117
3118static void tlbi_aa64_alle3is_write(CPUARMState *env, const ARMCPRegInfo *ri,
3119 uint64_t value)
3120{
3121 CPUState *other_cs;
3122
3123 CPU_FOREACH(other_cs) {
3124 tlb_flush_by_mmuidx(other_cs, ARMMMUIdx_S1E3, -1);
3125 }
3126}
3127
3128static void tlbi_aa64_vae1_write(CPUARMState *env, const ARMCPRegInfo *ri,
3129 uint64_t value)
3130{
3131
3132
3133
3134
3135
3136 ARMCPU *cpu = arm_env_get_cpu(env);
3137 CPUState *cs = CPU(cpu);
3138 uint64_t pageaddr = sextract64(value << 12, 0, 56);
3139
3140 if (arm_is_secure_below_el3(env)) {
3141 tlb_flush_page_by_mmuidx(cs, pageaddr, ARMMMUIdx_S1SE1,
3142 ARMMMUIdx_S1SE0, -1);
3143 } else {
3144 tlb_flush_page_by_mmuidx(cs, pageaddr, ARMMMUIdx_S12NSE1,
3145 ARMMMUIdx_S12NSE0, -1);
3146 }
3147}
3148
3149static void tlbi_aa64_vae2_write(CPUARMState *env, const ARMCPRegInfo *ri,
3150 uint64_t value)
3151{
3152
3153
3154
3155
3156 ARMCPU *cpu = arm_env_get_cpu(env);
3157 CPUState *cs = CPU(cpu);
3158 uint64_t pageaddr = sextract64(value << 12, 0, 56);
3159
3160 tlb_flush_page_by_mmuidx(cs, pageaddr, ARMMMUIdx_S1E2, -1);
3161}
3162
3163static void tlbi_aa64_vae3_write(CPUARMState *env, const ARMCPRegInfo *ri,
3164 uint64_t value)
3165{
3166
3167
3168
3169
3170 ARMCPU *cpu = arm_env_get_cpu(env);
3171 CPUState *cs = CPU(cpu);
3172 uint64_t pageaddr = sextract64(value << 12, 0, 56);
3173
3174 tlb_flush_page_by_mmuidx(cs, pageaddr, ARMMMUIdx_S1E3, -1);
3175}
3176
3177static void tlbi_aa64_vae1is_write(CPUARMState *env, const ARMCPRegInfo *ri,
3178 uint64_t value)
3179{
3180 bool sec = arm_is_secure_below_el3(env);
3181 CPUState *other_cs;
3182 uint64_t pageaddr = sextract64(value << 12, 0, 56);
3183
3184 CPU_FOREACH(other_cs) {
3185 if (sec) {
3186 tlb_flush_page_by_mmuidx(other_cs, pageaddr, ARMMMUIdx_S1SE1,
3187 ARMMMUIdx_S1SE0, -1);
3188 } else {
3189 tlb_flush_page_by_mmuidx(other_cs, pageaddr, ARMMMUIdx_S12NSE1,
3190 ARMMMUIdx_S12NSE0, -1);
3191 }
3192 }
3193}
3194
3195static void tlbi_aa64_vae2is_write(CPUARMState *env, const ARMCPRegInfo *ri,
3196 uint64_t value)
3197{
3198 CPUState *other_cs;
3199 uint64_t pageaddr = sextract64(value << 12, 0, 56);
3200
3201 CPU_FOREACH(other_cs) {
3202 tlb_flush_page_by_mmuidx(other_cs, pageaddr, ARMMMUIdx_S1E2, -1);
3203 }
3204}
3205
3206static void tlbi_aa64_vae3is_write(CPUARMState *env, const ARMCPRegInfo *ri,
3207 uint64_t value)
3208{
3209 CPUState *other_cs;
3210 uint64_t pageaddr = sextract64(value << 12, 0, 56);
3211
3212 CPU_FOREACH(other_cs) {
3213 tlb_flush_page_by_mmuidx(other_cs, pageaddr, ARMMMUIdx_S1E3, -1);
3214 }
3215}
3216
3217static void tlbi_aa64_ipas2e1_write(CPUARMState *env, const ARMCPRegInfo *ri,
3218 uint64_t value)
3219{
3220
3221
3222
3223
3224
3225
3226 ARMCPU *cpu = arm_env_get_cpu(env);
3227 CPUState *cs = CPU(cpu);
3228 uint64_t pageaddr;
3229
3230 if (!arm_feature(env, ARM_FEATURE_EL2) || !(env->cp15.scr_el3 & SCR_NS)) {
3231 return;
3232 }
3233
3234 pageaddr = sextract64(value << 12, 0, 48);
3235
3236 tlb_flush_page_by_mmuidx(cs, pageaddr, ARMMMUIdx_S2NS, -1);
3237}
3238
3239static void tlbi_aa64_ipas2e1is_write(CPUARMState *env, const ARMCPRegInfo *ri,
3240 uint64_t value)
3241{
3242 CPUState *other_cs;
3243 uint64_t pageaddr;
3244
3245 if (!arm_feature(env, ARM_FEATURE_EL2) || !(env->cp15.scr_el3 & SCR_NS)) {
3246 return;
3247 }
3248
3249 pageaddr = sextract64(value << 12, 0, 48);
3250
3251 CPU_FOREACH(other_cs) {
3252 tlb_flush_page_by_mmuidx(other_cs, pageaddr, ARMMMUIdx_S2NS, -1);
3253 }
3254}
3255
3256static CPAccessResult aa64_zva_access(CPUARMState *env, const ARMCPRegInfo *ri,
3257 bool isread)
3258{
3259
3260
3261
3262 if (arm_current_el(env) == 0 && !(env->cp15.sctlr_el[1] & SCTLR_DZE)) {
3263 return CP_ACCESS_TRAP;
3264 }
3265 return CP_ACCESS_OK;
3266}
3267
3268static uint64_t aa64_dczid_read(CPUARMState *env, const ARMCPRegInfo *ri)
3269{
3270 ARMCPU *cpu = arm_env_get_cpu(env);
3271 int dzp_bit = 1 << 4;
3272
3273
3274 if (aa64_zva_access(env, NULL, false) == CP_ACCESS_OK) {
3275 dzp_bit = 0;
3276 }
3277 return cpu->dcz_blocksize | dzp_bit;
3278}
3279
3280static CPAccessResult sp_el0_access(CPUARMState *env, const ARMCPRegInfo *ri,
3281 bool isread)
3282{
3283 if (!(env->pstate & PSTATE_SP)) {
3284
3285
3286
3287 return CP_ACCESS_TRAP_UNCATEGORIZED;
3288 }
3289 return CP_ACCESS_OK;
3290}
3291
3292static uint64_t spsel_read(CPUARMState *env, const ARMCPRegInfo *ri)
3293{
3294 return env->pstate & PSTATE_SP;
3295}
3296
3297static void spsel_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t val)
3298{
3299 update_spsel(env, val);
3300}
3301
3302static void sctlr_write(CPUARMState *env, const ARMCPRegInfo *ri,
3303 uint64_t value)
3304{
3305 ARMCPU *cpu = arm_env_get_cpu(env);
3306
3307 if (raw_read(env, ri) == value) {
3308
3309
3310
3311 return;
3312 }
3313
3314 raw_write(env, ri, value);
3315
3316
3317 tlb_flush(CPU(cpu), 1);
3318}
3319
3320static CPAccessResult fpexc32_access(CPUARMState *env, const ARMCPRegInfo *ri,
3321 bool isread)
3322{
3323 if ((env->cp15.cptr_el[2] & CPTR_TFP) && arm_current_el(env) == 2) {
3324 return CP_ACCESS_TRAP_FP_EL2;
3325 }
3326 if (env->cp15.cptr_el[3] & CPTR_TFP) {
3327 return CP_ACCESS_TRAP_FP_EL3;
3328 }
3329 return CP_ACCESS_OK;
3330}
3331
3332static void sdcr_write(CPUARMState *env, const ARMCPRegInfo *ri,
3333 uint64_t value)
3334{
3335 env->cp15.mdcr_el3 = value & SDCR_VALID_MASK;
3336}
3337
3338static const ARMCPRegInfo v8_cp_reginfo[] = {
3339
3340
3341
3342 { .name = "NZCV", .state = ARM_CP_STATE_AA64,
3343 .opc0 = 3, .opc1 = 3, .opc2 = 0, .crn = 4, .crm = 2,
3344 .access = PL0_RW, .type = ARM_CP_NZCV },
3345 { .name = "DAIF", .state = ARM_CP_STATE_AA64,
3346 .opc0 = 3, .opc1 = 3, .opc2 = 1, .crn = 4, .crm = 2,
3347 .type = ARM_CP_NO_RAW,
3348 .access = PL0_RW, .accessfn = aa64_daif_access,
3349 .fieldoffset = offsetof(CPUARMState, daif),
3350 .writefn = aa64_daif_write, .resetfn = arm_cp_reset_ignore },
3351 { .name = "FPCR", .state = ARM_CP_STATE_AA64,
3352 .opc0 = 3, .opc1 = 3, .opc2 = 0, .crn = 4, .crm = 4,
3353 .access = PL0_RW, .readfn = aa64_fpcr_read, .writefn = aa64_fpcr_write },
3354 { .name = "FPSR", .state = ARM_CP_STATE_AA64,
3355 .opc0 = 3, .opc1 = 3, .opc2 = 1, .crn = 4, .crm = 4,
3356 .access = PL0_RW, .readfn = aa64_fpsr_read, .writefn = aa64_fpsr_write },
3357 { .name = "DCZID_EL0", .state = ARM_CP_STATE_AA64,
3358 .opc0 = 3, .opc1 = 3, .opc2 = 7, .crn = 0, .crm = 0,
3359 .access = PL0_R, .type = ARM_CP_NO_RAW,
3360 .readfn = aa64_dczid_read },
3361 { .name = "DC_ZVA", .state = ARM_CP_STATE_AA64,
3362 .opc0 = 1, .opc1 = 3, .crn = 7, .crm = 4, .opc2 = 1,
3363 .access = PL0_W, .type = ARM_CP_DC_ZVA,
3364#ifndef CONFIG_USER_ONLY
3365
3366 .accessfn = aa64_zva_access,
3367#endif
3368 },
3369 { .name = "CURRENTEL", .state = ARM_CP_STATE_AA64,
3370 .opc0 = 3, .opc1 = 0, .opc2 = 2, .crn = 4, .crm = 2,
3371 .access = PL1_R, .type = ARM_CP_CURRENTEL },
3372
3373 { .name = "IC_IALLUIS", .state = ARM_CP_STATE_AA64,
3374 .opc0 = 1, .opc1 = 0, .crn = 7, .crm = 1, .opc2 = 0,
3375 .access = PL1_W, .type = ARM_CP_NOP },
3376 { .name = "IC_IALLU", .state = ARM_CP_STATE_AA64,
3377 .opc0 = 1, .opc1 = 0, .crn = 7, .crm = 5, .opc2 = 0,
3378 .access = PL1_W, .type = ARM_CP_NOP },
3379 { .name = "IC_IVAU", .state = ARM_CP_STATE_AA64,
3380 .opc0 = 1, .opc1 = 3, .crn = 7, .crm = 5, .opc2 = 1,
3381 .access = PL0_W, .type = ARM_CP_NOP,
3382 .accessfn = aa64_cacheop_access },
3383 { .name = "DC_IVAC", .state = ARM_CP_STATE_AA64,
3384 .opc0 = 1, .opc1 = 0, .crn = 7, .crm = 6, .opc2 = 1,
3385 .access = PL1_W, .type = ARM_CP_NOP },
3386 { .name = "DC_ISW", .state = ARM_CP_STATE_AA64,
3387 .opc0 = 1, .opc1 = 0, .crn = 7, .crm = 6, .opc2 = 2,
3388 .access = PL1_W, .type = ARM_CP_NOP },
3389 { .name = "DC_CVAC", .state = ARM_CP_STATE_AA64,
3390 .opc0 = 1, .opc1 = 3, .crn = 7, .crm = 10, .opc2 = 1,
3391 .access = PL0_W, .type = ARM_CP_NOP,
3392 .accessfn = aa64_cacheop_access },
3393 { .name = "DC_CSW", .state = ARM_CP_STATE_AA64,
3394 .opc0 = 1, .opc1 = 0, .crn = 7, .crm = 10, .opc2 = 2,
3395 .access = PL1_W, .type = ARM_CP_NOP },
3396 { .name = "DC_CVAU", .state = ARM_CP_STATE_AA64,
3397 .opc0 = 1, .opc1 = 3, .crn = 7, .crm = 11, .opc2 = 1,
3398 .access = PL0_W, .type = ARM_CP_NOP,
3399 .accessfn = aa64_cacheop_access },
3400 { .name = "DC_CIVAC", .state = ARM_CP_STATE_AA64,
3401 .opc0 = 1, .opc1 = 3, .crn = 7, .crm = 14, .opc2 = 1,
3402 .access = PL0_W, .type = ARM_CP_NOP,
3403 .accessfn = aa64_cacheop_access },
3404 { .name = "DC_CISW", .state = ARM_CP_STATE_AA64,
3405 .opc0 = 1, .opc1 = 0, .crn = 7, .crm = 14, .opc2 = 2,
3406 .access = PL1_W, .type = ARM_CP_NOP },
3407
3408 { .name = "TLBI_VMALLE1IS", .state = ARM_CP_STATE_AA64,
3409 .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 0,
3410 .access = PL1_W, .type = ARM_CP_NO_RAW,
3411 .writefn = tlbi_aa64_vmalle1is_write },
3412 { .name = "TLBI_VAE1IS", .state = ARM_CP_STATE_AA64,
3413 .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 1,
3414 .access = PL1_W, .type = ARM_CP_NO_RAW,
3415 .writefn = tlbi_aa64_vae1is_write },
3416 { .name = "TLBI_ASIDE1IS", .state = ARM_CP_STATE_AA64,
3417 .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 2,
3418 .access = PL1_W, .type = ARM_CP_NO_RAW,
3419 .writefn = tlbi_aa64_vmalle1is_write },
3420 { .name = "TLBI_VAAE1IS", .state = ARM_CP_STATE_AA64,
3421 .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 3,
3422 .access = PL1_W, .type = ARM_CP_NO_RAW,
3423 .writefn = tlbi_aa64_vae1is_write },
3424 { .name = "TLBI_VALE1IS", .state = ARM_CP_STATE_AA64,
3425 .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 5,
3426 .access = PL1_W, .type = ARM_CP_NO_RAW,
3427 .writefn = tlbi_aa64_vae1is_write },
3428 { .name = "TLBI_VAALE1IS", .state = ARM_CP_STATE_AA64,
3429 .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 7,
3430 .access = PL1_W, .type = ARM_CP_NO_RAW,
3431 .writefn = tlbi_aa64_vae1is_write },
3432 { .name = "TLBI_VMALLE1", .state = ARM_CP_STATE_AA64,
3433 .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 0,
3434 .access = PL1_W, .type = ARM_CP_NO_RAW,
3435 .writefn = tlbi_aa64_vmalle1_write },
3436 { .name = "TLBI_VAE1", .state = ARM_CP_STATE_AA64,
3437 .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 1,
3438 .access = PL1_W, .type = ARM_CP_NO_RAW,
3439 .writefn = tlbi_aa64_vae1_write },
3440 { .name = "TLBI_ASIDE1", .state = ARM_CP_STATE_AA64,
3441 .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 2,
3442 .access = PL1_W, .type = ARM_CP_NO_RAW,
3443 .writefn = tlbi_aa64_vmalle1_write },
3444 { .name = "TLBI_VAAE1", .state = ARM_CP_STATE_AA64,
3445 .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 3,
3446 .access = PL1_W, .type = ARM_CP_NO_RAW,
3447 .writefn = tlbi_aa64_vae1_write },
3448 { .name = "TLBI_VALE1", .state = ARM_CP_STATE_AA64,
3449 .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 5,
3450 .access = PL1_W, .type = ARM_CP_NO_RAW,
3451 .writefn = tlbi_aa64_vae1_write },
3452 { .name = "TLBI_VAALE1", .state = ARM_CP_STATE_AA64,
3453 .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 7,
3454 .access = PL1_W, .type = ARM_CP_NO_RAW,
3455 .writefn = tlbi_aa64_vae1_write },
3456 { .name = "TLBI_IPAS2E1IS", .state = ARM_CP_STATE_AA64,
3457 .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 0, .opc2 = 1,
3458 .access = PL2_W, .type = ARM_CP_NO_RAW,
3459 .writefn = tlbi_aa64_ipas2e1is_write },
3460 { .name = "TLBI_IPAS2LE1IS", .state = ARM_CP_STATE_AA64,
3461 .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 0, .opc2 = 5,
3462 .access = PL2_W, .type = ARM_CP_NO_RAW,
3463 .writefn = tlbi_aa64_ipas2e1is_write },
3464 { .name = "TLBI_ALLE1IS", .state = ARM_CP_STATE_AA64,
3465 .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 3, .opc2 = 4,
3466 .access = PL2_W, .type = ARM_CP_NO_RAW,
3467 .writefn = tlbi_aa64_alle1is_write },
3468 { .name = "TLBI_VMALLS12E1IS", .state = ARM_CP_STATE_AA64,
3469 .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 3, .opc2 = 6,
3470 .access = PL2_W, .type = ARM_CP_NO_RAW,
3471 .writefn = tlbi_aa64_alle1is_write },
3472 { .name = "TLBI_IPAS2E1", .state = ARM_CP_STATE_AA64,
3473 .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 4, .opc2 = 1,
3474 .access = PL2_W, .type = ARM_CP_NO_RAW,
3475 .writefn = tlbi_aa64_ipas2e1_write },
3476 { .name = "TLBI_IPAS2LE1", .state = ARM_CP_STATE_AA64,
3477 .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 4, .opc2 = 5,
3478 .access = PL2_W, .type = ARM_CP_NO_RAW,
3479 .writefn = tlbi_aa64_ipas2e1_write },
3480 { .name = "TLBI_ALLE1", .state = ARM_CP_STATE_AA64,
3481 .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 7, .opc2 = 4,
3482 .access = PL2_W, .type = ARM_CP_NO_RAW,
3483 .writefn = tlbi_aa64_alle1_write },
3484 { .name = "TLBI_VMALLS12E1", .state = ARM_CP_STATE_AA64,
3485 .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 7, .opc2 = 6,
3486 .access = PL2_W, .type = ARM_CP_NO_RAW,
3487 .writefn = tlbi_aa64_alle1is_write },
3488#ifndef CONFIG_USER_ONLY
3489
3490 { .name = "AT_S1E1R", .state = ARM_CP_STATE_AA64,
3491 .opc0 = 1, .opc1 = 0, .crn = 7, .crm = 8, .opc2 = 0,
3492 .access = PL1_W, .type = ARM_CP_NO_RAW, .writefn = ats_write64 },
3493 { .name = "AT_S1E1W", .state = ARM_CP_STATE_AA64,
3494 .opc0 = 1, .opc1 = 0, .crn = 7, .crm = 8, .opc2 = 1,
3495 .access = PL1_W, .type = ARM_CP_NO_RAW, .writefn = ats_write64 },
3496 { .name = "AT_S1E0R", .state = ARM_CP_STATE_AA64,
3497 .opc0 = 1, .opc1 = 0, .crn = 7, .crm = 8, .opc2 = 2,
3498 .access = PL1_W, .type = ARM_CP_NO_RAW, .writefn = ats_write64 },
3499 { .name = "AT_S1E0W", .state = ARM_CP_STATE_AA64,
3500 .opc0 = 1, .opc1 = 0, .crn = 7, .crm = 8, .opc2 = 3,
3501 .access = PL1_W, .type = ARM_CP_NO_RAW, .writefn = ats_write64 },
3502 { .name = "AT_S12E1R", .state = ARM_CP_STATE_AA64,
3503 .opc0 = 1, .opc1 = 4, .crn = 7, .crm = 8, .opc2 = 4,
3504 .access = PL2_W, .type = ARM_CP_NO_RAW, .writefn = ats_write64 },
3505 { .name = "AT_S12E1W", .state = ARM_CP_STATE_AA64,
3506 .opc0 = 1, .opc1 = 4, .crn = 7, .crm = 8, .opc2 = 5,
3507 .access = PL2_W, .type = ARM_CP_NO_RAW, .writefn = ats_write64 },
3508 { .name = "AT_S12E0R", .state = ARM_CP_STATE_AA64,
3509 .opc0 = 1, .opc1 = 4, .crn = 7, .crm = 8, .opc2 = 6,
3510 .access = PL2_W, .type = ARM_CP_NO_RAW, .writefn = ats_write64 },
3511 { .name = "AT_S12E0W", .state = ARM_CP_STATE_AA64,
3512 .opc0 = 1, .opc1 = 4, .crn = 7, .crm = 8, .opc2 = 7,
3513 .access = PL2_W, .type = ARM_CP_NO_RAW, .writefn = ats_write64 },
3514
3515 { .name = "AT_S1E3R", .state = ARM_CP_STATE_AA64,
3516 .opc0 = 1, .opc1 = 6, .crn = 7, .crm = 8, .opc2 = 0,
3517 .access = PL3_W, .type = ARM_CP_NO_RAW, .writefn = ats_write64 },
3518 { .name = "AT_S1E3W", .state = ARM_CP_STATE_AA64,
3519 .opc0 = 1, .opc1 = 6, .crn = 7, .crm = 8, .opc2 = 1,
3520 .access = PL3_W, .type = ARM_CP_NO_RAW, .writefn = ats_write64 },
3521 { .name = "PAR_EL1", .state = ARM_CP_STATE_AA64,
3522 .type = ARM_CP_ALIAS,
3523 .opc0 = 3, .opc1 = 0, .crn = 7, .crm = 4, .opc2 = 0,
3524 .access = PL1_RW, .resetvalue = 0,
3525 .fieldoffset = offsetof(CPUARMState, cp15.par_el[1]),
3526 .writefn = par_write },
3527#endif
3528
3529 { .name = "TLBIMVALIS", .cp = 15, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 5,
3530 .type = ARM_CP_NO_RAW, .access = PL1_W, .writefn = tlbimva_is_write },
3531 { .name = "TLBIMVAALIS", .cp = 15, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 7,
3532 .type = ARM_CP_NO_RAW, .access = PL1_W,
3533 .writefn = tlbimvaa_is_write },
3534 { .name = "TLBIMVAL", .cp = 15, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 5,
3535 .type = ARM_CP_NO_RAW, .access = PL1_W, .writefn = tlbimva_write },
3536 { .name = "TLBIMVAAL", .cp = 15, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 7,
3537 .type = ARM_CP_NO_RAW, .access = PL1_W, .writefn = tlbimvaa_write },
3538 { .name = "TLBIMVALH", .cp = 15, .opc1 = 4, .crn = 8, .crm = 7, .opc2 = 5,
3539 .type = ARM_CP_NO_RAW, .access = PL2_W,
3540 .writefn = tlbimva_hyp_write },
3541 { .name = "TLBIMVALHIS",
3542 .cp = 15, .opc1 = 4, .crn = 8, .crm = 3, .opc2 = 5,
3543 .type = ARM_CP_NO_RAW, .access = PL2_W,
3544 .writefn = tlbimva_hyp_is_write },
3545 { .name = "TLBIIPAS2",
3546 .cp = 15, .opc1 = 4, .crn = 8, .crm = 4, .opc2 = 1,
3547 .type = ARM_CP_NO_RAW, .access = PL2_W,
3548 .writefn = tlbiipas2_write },
3549 { .name = "TLBIIPAS2IS",
3550 .cp = 15, .opc1 = 4, .crn = 8, .crm = 0, .opc2 = 1,
3551 .type = ARM_CP_NO_RAW, .access = PL2_W,
3552 .writefn = tlbiipas2_is_write },
3553 { .name = "TLBIIPAS2L",
3554 .cp = 15, .opc1 = 4, .crn = 8, .crm = 4, .opc2 = 5,
3555 .type = ARM_CP_NO_RAW, .access = PL2_W,
3556 .writefn = tlbiipas2_write },
3557 { .name = "TLBIIPAS2LIS",
3558 .cp = 15, .opc1 = 4, .crn = 8, .crm = 0, .opc2 = 5,
3559 .type = ARM_CP_NO_RAW, .access = PL2_W,
3560 .writefn = tlbiipas2_is_write },
3561
3562 { .name = "ICIALLUIS", .cp = 15, .opc1 = 0, .crn = 7, .crm = 1, .opc2 = 0,
3563 .type = ARM_CP_NOP, .access = PL1_W },
3564 { .name = "BPIALLUIS", .cp = 15, .opc1 = 0, .crn = 7, .crm = 1, .opc2 = 6,
3565 .type = ARM_CP_NOP, .access = PL1_W },
3566 { .name = "ICIALLU", .cp = 15, .opc1 = 0, .crn = 7, .crm = 5, .opc2 = 0,
3567 .type = ARM_CP_NOP, .access = PL1_W },
3568 { .name = "ICIMVAU", .cp = 15, .opc1 = 0, .crn = 7, .crm = 5, .opc2 = 1,
3569 .type = ARM_CP_NOP, .access = PL1_W },
3570 { .name = "BPIALL", .cp = 15, .opc1 = 0, .crn = 7, .crm = 5, .opc2 = 6,
3571 .type = ARM_CP_NOP, .access = PL1_W },
3572 { .name = "BPIMVA", .cp = 15, .opc1 = 0, .crn = 7, .crm = 5, .opc2 = 7,
3573 .type = ARM_CP_NOP, .access = PL1_W },
3574 { .name = "DCIMVAC", .cp = 15, .opc1 = 0, .crn = 7, .crm = 6, .opc2 = 1,
3575 .type = ARM_CP_NOP, .access = PL1_W },
3576 { .name = "DCISW", .cp = 15, .opc1 = 0, .crn = 7, .crm = 6, .opc2 = 2,
3577 .type = ARM_CP_NOP, .access = PL1_W },
3578 { .name = "DCCMVAC", .cp = 15, .opc1 = 0, .crn = 7, .crm = 10, .opc2 = 1,
3579 .type = ARM_CP_NOP, .access = PL1_W },
3580 { .name = "DCCSW", .cp = 15, .opc1 = 0, .crn = 7, .crm = 10, .opc2 = 2,
3581 .type = ARM_CP_NOP, .access = PL1_W },
3582 { .name = "DCCMVAU", .cp = 15, .opc1 = 0, .crn = 7, .crm = 11, .opc2 = 1,
3583 .type = ARM_CP_NOP, .access = PL1_W },
3584 { .name = "DCCIMVAC", .cp = 15, .opc1 = 0, .crn = 7, .crm = 14, .opc2 = 1,
3585 .type = ARM_CP_NOP, .access = PL1_W },
3586 { .name = "DCCISW", .cp = 15, .opc1 = 0, .crn = 7, .crm = 14, .opc2 = 2,
3587 .type = ARM_CP_NOP, .access = PL1_W },
3588
3589 { .name = "DACR", .cp = 15, .opc1 = 0, .crn = 3, .crm = 0, .opc2 = 0,
3590 .access = PL1_RW, .resetvalue = 0,
3591 .writefn = dacr_write, .raw_writefn = raw_write,
3592 .bank_fieldoffsets = { offsetoflow32(CPUARMState, cp15.dacr_s),
3593 offsetoflow32(CPUARMState, cp15.dacr_ns) } },
3594 { .name = "ELR_EL1", .state = ARM_CP_STATE_AA64,
3595 .type = ARM_CP_ALIAS,
3596 .opc0 = 3, .opc1 = 0, .crn = 4, .crm = 0, .opc2 = 1,
3597 .access = PL1_RW,
3598 .fieldoffset = offsetof(CPUARMState, elr_el[1]) },
3599 { .name = "SPSR_EL1", .state = ARM_CP_STATE_AA64,
3600 .type = ARM_CP_ALIAS,
3601 .opc0 = 3, .opc1 = 0, .crn = 4, .crm = 0, .opc2 = 0,
3602 .access = PL1_RW,
3603 .fieldoffset = offsetof(CPUARMState, banked_spsr[BANK_SVC]) },
3604
3605
3606
3607
3608 { .name = "SP_EL0", .state = ARM_CP_STATE_AA64,
3609 .opc0 = 3, .opc1 = 0, .crn = 4, .crm = 1, .opc2 = 0,
3610 .access = PL1_RW, .accessfn = sp_el0_access,
3611 .type = ARM_CP_ALIAS,
3612 .fieldoffset = offsetof(CPUARMState, sp_el[0]) },
3613 { .name = "SP_EL1", .state = ARM_CP_STATE_AA64,
3614 .opc0 = 3, .opc1 = 4, .crn = 4, .crm = 1, .opc2 = 0,
3615 .access = PL2_RW, .type = ARM_CP_ALIAS,
3616 .fieldoffset = offsetof(CPUARMState, sp_el[1]) },
3617 { .name = "SPSel", .state = ARM_CP_STATE_AA64,
3618 .opc0 = 3, .opc1 = 0, .crn = 4, .crm = 2, .opc2 = 0,
3619 .type = ARM_CP_NO_RAW,
3620 .access = PL1_RW, .readfn = spsel_read, .writefn = spsel_write },
3621 { .name = "FPEXC32_EL2", .state = ARM_CP_STATE_AA64,
3622 .opc0 = 3, .opc1 = 4, .crn = 5, .crm = 3, .opc2 = 0,
3623 .type = ARM_CP_ALIAS,
3624 .fieldoffset = offsetof(CPUARMState, vfp.xregs[ARM_VFP_FPEXC]),
3625 .access = PL2_RW, .accessfn = fpexc32_access },
3626 { .name = "DACR32_EL2", .state = ARM_CP_STATE_AA64,
3627 .opc0 = 3, .opc1 = 4, .crn = 3, .crm = 0, .opc2 = 0,
3628 .access = PL2_RW, .resetvalue = 0,
3629 .writefn = dacr_write, .raw_writefn = raw_write,
3630 .fieldoffset = offsetof(CPUARMState, cp15.dacr32_el2) },
3631 { .name = "IFSR32_EL2", .state = ARM_CP_STATE_AA64,
3632 .opc0 = 3, .opc1 = 4, .crn = 5, .crm = 0, .opc2 = 1,
3633 .access = PL2_RW, .resetvalue = 0,
3634 .fieldoffset = offsetof(CPUARMState, cp15.ifsr32_el2) },
3635 { .name = "SPSR_IRQ", .state = ARM_CP_STATE_AA64,
3636 .type = ARM_CP_ALIAS,
3637 .opc0 = 3, .opc1 = 4, .crn = 4, .crm = 3, .opc2 = 0,
3638 .access = PL2_RW,
3639 .fieldoffset = offsetof(CPUARMState, banked_spsr[BANK_IRQ]) },
3640 { .name = "SPSR_ABT", .state = ARM_CP_STATE_AA64,
3641 .type = ARM_CP_ALIAS,
3642 .opc0 = 3, .opc1 = 4, .crn = 4, .crm = 3, .opc2 = 1,
3643 .access = PL2_RW,
3644 .fieldoffset = offsetof(CPUARMState, banked_spsr[BANK_ABT]) },
3645 { .name = "SPSR_UND", .state = ARM_CP_STATE_AA64,
3646 .type = ARM_CP_ALIAS,
3647 .opc0 = 3, .opc1 = 4, .crn = 4, .crm = 3, .opc2 = 2,
3648 .access = PL2_RW,
3649 .fieldoffset = offsetof(CPUARMState, banked_spsr[BANK_UND]) },
3650 { .name = "SPSR_FIQ", .state = ARM_CP_STATE_AA64,
3651 .type = ARM_CP_ALIAS,
3652 .opc0 = 3, .opc1 = 4, .crn = 4, .crm = 3, .opc2 = 3,
3653 .access = PL2_RW,
3654 .fieldoffset = offsetof(CPUARMState, banked_spsr[BANK_FIQ]) },
3655 { .name = "MDCR_EL3", .state = ARM_CP_STATE_AA64,
3656 .opc0 = 3, .opc1 = 6, .crn = 1, .crm = 3, .opc2 = 1,
3657 .resetvalue = 0,
3658 .access = PL3_RW, .fieldoffset = offsetof(CPUARMState, cp15.mdcr_el3) },
3659 { .name = "SDCR", .type = ARM_CP_ALIAS,
3660 .cp = 15, .opc1 = 0, .crn = 1, .crm = 3, .opc2 = 1,
3661 .access = PL1_RW, .accessfn = access_trap_aa32s_el1,
3662 .writefn = sdcr_write,
3663 .fieldoffset = offsetoflow32(CPUARMState, cp15.mdcr_el3) },
3664 REGINFO_SENTINEL
3665};
3666
3667
3668static const ARMCPRegInfo el3_no_el2_cp_reginfo[] = {
3669 { .name = "VBAR_EL2", .state = ARM_CP_STATE_AA64,
3670 .opc0 = 3, .opc1 = 4, .crn = 12, .crm = 0, .opc2 = 0,
3671 .access = PL2_RW,
3672 .readfn = arm_cp_read_zero, .writefn = arm_cp_write_ignore },
3673 { .name = "HCR_EL2", .state = ARM_CP_STATE_AA64,
3674 .type = ARM_CP_NO_RAW,
3675 .opc0 = 3, .opc1 = 4, .crn = 1, .crm = 1, .opc2 = 0,
3676 .access = PL2_RW,
3677 .readfn = arm_cp_read_zero, .writefn = arm_cp_write_ignore },
3678 { .name = "CPTR_EL2", .state = ARM_CP_STATE_BOTH,
3679 .opc0 = 3, .opc1 = 4, .crn = 1, .crm = 1, .opc2 = 2,
3680 .access = PL2_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
3681 { .name = "MAIR_EL2", .state = ARM_CP_STATE_BOTH,
3682 .opc0 = 3, .opc1 = 4, .crn = 10, .crm = 2, .opc2 = 0,
3683 .access = PL2_RW, .type = ARM_CP_CONST,
3684 .resetvalue = 0 },
3685 { .name = "HMAIR1", .state = ARM_CP_STATE_AA32,
3686 .opc1 = 4, .crn = 10, .crm = 2, .opc2 = 1,
3687 .access = PL2_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
3688 { .name = "AMAIR_EL2", .state = ARM_CP_STATE_BOTH,
3689 .opc0 = 3, .opc1 = 4, .crn = 10, .crm = 3, .opc2 = 0,
3690 .access = PL2_RW, .type = ARM_CP_CONST,
3691 .resetvalue = 0 },
3692 { .name = "HMAIR1", .state = ARM_CP_STATE_AA32,
3693 .opc1 = 4, .crn = 10, .crm = 3, .opc2 = 1,
3694 .access = PL2_RW, .type = ARM_CP_CONST,
3695 .resetvalue = 0 },
3696 { .name = "AFSR0_EL2", .state = ARM_CP_STATE_BOTH,
3697 .opc0 = 3, .opc1 = 4, .crn = 5, .crm = 1, .opc2 = 0,
3698 .access = PL2_RW, .type = ARM_CP_CONST,
3699 .resetvalue = 0 },
3700 { .name = "AFSR1_EL2", .state = ARM_CP_STATE_BOTH,
3701 .opc0 = 3, .opc1 = 4, .crn = 5, .crm = 1, .opc2 = 1,
3702 .access = PL2_RW, .type = ARM_CP_CONST,
3703 .resetvalue = 0 },
3704 { .name = "TCR_EL2", .state = ARM_CP_STATE_BOTH,
3705 .opc0 = 3, .opc1 = 4, .crn = 2, .crm = 0, .opc2 = 2,
3706 .access = PL2_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
3707 { .name = "VTCR_EL2", .state = ARM_CP_STATE_BOTH,
3708 .opc0 = 3, .opc1 = 4, .crn = 2, .crm = 1, .opc2 = 2,
3709 .access = PL2_RW, .accessfn = access_el3_aa32ns_aa64any,
3710 .type = ARM_CP_CONST, .resetvalue = 0 },
3711 { .name = "VTTBR", .state = ARM_CP_STATE_AA32,
3712 .cp = 15, .opc1 = 6, .crm = 2,
3713 .access = PL2_RW, .accessfn = access_el3_aa32ns,
3714 .type = ARM_CP_CONST | ARM_CP_64BIT, .resetvalue = 0 },
3715 { .name = "VTTBR_EL2", .state = ARM_CP_STATE_AA64,
3716 .opc0 = 3, .opc1 = 4, .crn = 2, .crm = 1, .opc2 = 0,
3717 .access = PL2_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
3718 { .name = "SCTLR_EL2", .state = ARM_CP_STATE_BOTH,
3719 .opc0 = 3, .opc1 = 4, .crn = 1, .crm = 0, .opc2 = 0,
3720 .access = PL2_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
3721 { .name = "TPIDR_EL2", .state = ARM_CP_STATE_BOTH,
3722 .opc0 = 3, .opc1 = 4, .crn = 13, .crm = 0, .opc2 = 2,
3723 .access = PL2_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
3724 { .name = "TTBR0_EL2", .state = ARM_CP_STATE_AA64,
3725 .opc0 = 3, .opc1 = 4, .crn = 2, .crm = 0, .opc2 = 0,
3726 .access = PL2_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
3727 { .name = "HTTBR", .cp = 15, .opc1 = 4, .crm = 2,
3728 .access = PL2_RW, .type = ARM_CP_64BIT | ARM_CP_CONST,
3729 .resetvalue = 0 },
3730 { .name = "CNTHCTL_EL2", .state = ARM_CP_STATE_BOTH,
3731 .opc0 = 3, .opc1 = 4, .crn = 14, .crm = 1, .opc2 = 0,
3732 .access = PL2_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
3733 { .name = "CNTVOFF_EL2", .state = ARM_CP_STATE_AA64,
3734 .opc0 = 3, .opc1 = 4, .crn = 14, .crm = 0, .opc2 = 3,
3735 .access = PL2_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
3736 { .name = "CNTVOFF", .cp = 15, .opc1 = 4, .crm = 14,
3737 .access = PL2_RW, .type = ARM_CP_64BIT | ARM_CP_CONST,
3738 .resetvalue = 0 },
3739 { .name = "CNTHP_CVAL_EL2", .state = ARM_CP_STATE_AA64,
3740 .opc0 = 3, .opc1 = 4, .crn = 14, .crm = 2, .opc2 = 2,
3741 .access = PL2_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
3742 { .name = "CNTHP_CVAL", .cp = 15, .opc1 = 6, .crm = 14,
3743 .access = PL2_RW, .type = ARM_CP_64BIT | ARM_CP_CONST,
3744 .resetvalue = 0 },
3745 { .name = "CNTHP_TVAL_EL2", .state = ARM_CP_STATE_BOTH,
3746 .opc0 = 3, .opc1 = 4, .crn = 14, .crm = 2, .opc2 = 0,
3747 .access = PL2_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
3748 { .name = "CNTHP_CTL_EL2", .state = ARM_CP_STATE_BOTH,
3749 .opc0 = 3, .opc1 = 4, .crn = 14, .crm = 2, .opc2 = 1,
3750 .access = PL2_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
3751 { .name = "MDCR_EL2", .state = ARM_CP_STATE_BOTH,
3752 .opc0 = 3, .opc1 = 4, .crn = 1, .crm = 1, .opc2 = 1,
3753 .access = PL2_RW, .accessfn = access_tda,
3754 .type = ARM_CP_CONST, .resetvalue = 0 },
3755 { .name = "HPFAR_EL2", .state = ARM_CP_STATE_BOTH,
3756 .opc0 = 3, .opc1 = 4, .crn = 6, .crm = 0, .opc2 = 4,
3757 .access = PL2_RW, .accessfn = access_el3_aa32ns_aa64any,
3758 .type = ARM_CP_CONST, .resetvalue = 0 },
3759 { .name = "HSTR_EL2", .state = ARM_CP_STATE_BOTH,
3760 .opc0 = 3, .opc1 = 4, .crn = 1, .crm = 1, .opc2 = 3,
3761 .access = PL2_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
3762 REGINFO_SENTINEL
3763};
3764
3765static void hcr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
3766{
3767 ARMCPU *cpu = arm_env_get_cpu(env);
3768 uint64_t valid_mask = HCR_MASK;
3769
3770 if (arm_feature(env, ARM_FEATURE_EL3)) {
3771 valid_mask &= ~HCR_HCD;
3772 } else {
3773 valid_mask &= ~HCR_TSC;
3774 }
3775
3776
3777 value &= valid_mask;
3778
3779
3780
3781
3782
3783
3784 if ((raw_read(env, ri) ^ value) & (HCR_VM | HCR_PTW | HCR_DC)) {
3785 tlb_flush(CPU(cpu), 1);
3786 }
3787 raw_write(env, ri, value);
3788}
3789
3790static const ARMCPRegInfo el2_cp_reginfo[] = {
3791 { .name = "HCR_EL2", .state = ARM_CP_STATE_AA64,
3792 .opc0 = 3, .opc1 = 4, .crn = 1, .crm = 1, .opc2 = 0,
3793 .access = PL2_RW, .fieldoffset = offsetof(CPUARMState, cp15.hcr_el2),
3794 .writefn = hcr_write },
3795 { .name = "ELR_EL2", .state = ARM_CP_STATE_AA64,
3796 .type = ARM_CP_ALIAS,
3797 .opc0 = 3, .opc1 = 4, .crn = 4, .crm = 0, .opc2 = 1,
3798 .access = PL2_RW,
3799 .fieldoffset = offsetof(CPUARMState, elr_el[2]) },
3800 { .name = "ESR_EL2", .state = ARM_CP_STATE_AA64,
3801 .opc0 = 3, .opc1 = 4, .crn = 5, .crm = 2, .opc2 = 0,
3802 .access = PL2_RW, .fieldoffset = offsetof(CPUARMState, cp15.esr_el[2]) },
3803 { .name = "FAR_EL2", .state = ARM_CP_STATE_AA64,
3804 .opc0 = 3, .opc1 = 4, .crn = 6, .crm = 0, .opc2 = 0,
3805 .access = PL2_RW, .fieldoffset = offsetof(CPUARMState, cp15.far_el[2]) },
3806 { .name = "SPSR_EL2", .state = ARM_CP_STATE_AA64,
3807 .type = ARM_CP_ALIAS,
3808 .opc0 = 3, .opc1 = 4, .crn = 4, .crm = 0, .opc2 = 0,
3809 .access = PL2_RW,
3810 .fieldoffset = offsetof(CPUARMState, banked_spsr[BANK_HYP]) },
3811 { .name = "VBAR_EL2", .state = ARM_CP_STATE_AA64,
3812 .opc0 = 3, .opc1 = 4, .crn = 12, .crm = 0, .opc2 = 0,
3813 .access = PL2_RW, .writefn = vbar_write,
3814 .fieldoffset = offsetof(CPUARMState, cp15.vbar_el[2]),
3815 .resetvalue = 0 },
3816 { .name = "SP_EL2", .state = ARM_CP_STATE_AA64,
3817 .opc0 = 3, .opc1 = 6, .crn = 4, .crm = 1, .opc2 = 0,
3818 .access = PL3_RW, .type = ARM_CP_ALIAS,
3819 .fieldoffset = offsetof(CPUARMState, sp_el[2]) },
3820 { .name = "CPTR_EL2", .state = ARM_CP_STATE_BOTH,
3821 .opc0 = 3, .opc1 = 4, .crn = 1, .crm = 1, .opc2 = 2,
3822 .access = PL2_RW, .accessfn = cptr_access, .resetvalue = 0,
3823 .fieldoffset = offsetof(CPUARMState, cp15.cptr_el[2]) },
3824 { .name = "MAIR_EL2", .state = ARM_CP_STATE_BOTH,
3825 .opc0 = 3, .opc1 = 4, .crn = 10, .crm = 2, .opc2 = 0,
3826 .access = PL2_RW, .fieldoffset = offsetof(CPUARMState, cp15.mair_el[2]),
3827 .resetvalue = 0 },
3828 { .name = "HMAIR1", .state = ARM_CP_STATE_AA32,
3829 .opc1 = 4, .crn = 10, .crm = 2, .opc2 = 1,
3830 .access = PL2_RW, .type = ARM_CP_ALIAS,
3831 .fieldoffset = offsetofhigh32(CPUARMState, cp15.mair_el[2]) },
3832 { .name = "AMAIR_EL2", .state = ARM_CP_STATE_BOTH,
3833 .opc0 = 3, .opc1 = 4, .crn = 10, .crm = 3, .opc2 = 0,
3834 .access = PL2_RW, .type = ARM_CP_CONST,
3835 .resetvalue = 0 },
3836
3837 { .name = "HMAIR1", .state = ARM_CP_STATE_AA32,
3838 .opc1 = 4, .crn = 10, .crm = 3, .opc2 = 1,
3839 .access = PL2_RW, .type = ARM_CP_CONST,
3840 .resetvalue = 0 },
3841 { .name = "AFSR0_EL2", .state = ARM_CP_STATE_BOTH,
3842 .opc0 = 3, .opc1 = 4, .crn = 5, .crm = 1, .opc2 = 0,
3843 .access = PL2_RW, .type = ARM_CP_CONST,
3844 .resetvalue = 0 },
3845 { .name = "AFSR1_EL2", .state = ARM_CP_STATE_BOTH,
3846 .opc0 = 3, .opc1 = 4, .crn = 5, .crm = 1, .opc2 = 1,
3847 .access = PL2_RW, .type = ARM_CP_CONST,
3848 .resetvalue = 0 },
3849 { .name = "TCR_EL2", .state = ARM_CP_STATE_BOTH,
3850 .opc0 = 3, .opc1 = 4, .crn = 2, .crm = 0, .opc2 = 2,
3851 .access = PL2_RW,
3852
3853
3854
3855 .fieldoffset = offsetof(CPUARMState, cp15.tcr_el[2]) },
3856 { .name = "VTCR", .state = ARM_CP_STATE_AA32,
3857 .cp = 15, .opc1 = 4, .crn = 2, .crm = 1, .opc2 = 2,
3858 .type = ARM_CP_ALIAS,
3859 .access = PL2_RW, .accessfn = access_el3_aa32ns,
3860 .fieldoffset = offsetof(CPUARMState, cp15.vtcr_el2) },
3861 { .name = "VTCR_EL2", .state = ARM_CP_STATE_AA64,
3862 .opc0 = 3, .opc1 = 4, .crn = 2, .crm = 1, .opc2 = 2,
3863 .access = PL2_RW,
3864
3865
3866
3867 .fieldoffset = offsetof(CPUARMState, cp15.vtcr_el2) },
3868 { .name = "VTTBR", .state = ARM_CP_STATE_AA32,
3869 .cp = 15, .opc1 = 6, .crm = 2,
3870 .type = ARM_CP_64BIT | ARM_CP_ALIAS,
3871 .access = PL2_RW, .accessfn = access_el3_aa32ns,
3872 .fieldoffset = offsetof(CPUARMState, cp15.vttbr_el2),
3873 .writefn = vttbr_write },
3874 { .name = "VTTBR_EL2", .state = ARM_CP_STATE_AA64,
3875 .opc0 = 3, .opc1 = 4, .crn = 2, .crm = 1, .opc2 = 0,
3876 .access = PL2_RW, .writefn = vttbr_write,
3877 .fieldoffset = offsetof(CPUARMState, cp15.vttbr_el2) },
3878 { .name = "SCTLR_EL2", .state = ARM_CP_STATE_BOTH,
3879 .opc0 = 3, .opc1 = 4, .crn = 1, .crm = 0, .opc2 = 0,
3880 .access = PL2_RW, .raw_writefn = raw_write, .writefn = sctlr_write,
3881 .fieldoffset = offsetof(CPUARMState, cp15.sctlr_el[2]) },
3882 { .name = "TPIDR_EL2", .state = ARM_CP_STATE_BOTH,
3883 .opc0 = 3, .opc1 = 4, .crn = 13, .crm = 0, .opc2 = 2,
3884 .access = PL2_RW, .resetvalue = 0,
3885 .fieldoffset = offsetof(CPUARMState, cp15.tpidr_el[2]) },
3886 { .name = "TTBR0_EL2", .state = ARM_CP_STATE_AA64,
3887 .opc0 = 3, .opc1 = 4, .crn = 2, .crm = 0, .opc2 = 0,
3888 .access = PL2_RW, .resetvalue = 0,
3889 .fieldoffset = offsetof(CPUARMState, cp15.ttbr0_el[2]) },
3890 { .name = "HTTBR", .cp = 15, .opc1 = 4, .crm = 2,
3891 .access = PL2_RW, .type = ARM_CP_64BIT | ARM_CP_ALIAS,
3892 .fieldoffset = offsetof(CPUARMState, cp15.ttbr0_el[2]) },
3893 { .name = "TLBIALLNSNH",
3894 .cp = 15, .opc1 = 4, .crn = 8, .crm = 7, .opc2 = 4,
3895 .type = ARM_CP_NO_RAW, .access = PL2_W,
3896 .writefn = tlbiall_nsnh_write },
3897 { .name = "TLBIALLNSNHIS",
3898 .cp = 15, .opc1 = 4, .crn = 8, .crm = 3, .opc2 = 4,
3899 .type = ARM_CP_NO_RAW, .access = PL2_W,
3900 .writefn = tlbiall_nsnh_is_write },
3901 { .name = "TLBIALLH", .cp = 15, .opc1 = 4, .crn = 8, .crm = 7, .opc2 = 0,
3902 .type = ARM_CP_NO_RAW, .access = PL2_W,
3903 .writefn = tlbiall_hyp_write },
3904 { .name = "TLBIALLHIS", .cp = 15, .opc1 = 4, .crn = 8, .crm = 3, .opc2 = 0,
3905 .type = ARM_CP_NO_RAW, .access = PL2_W,
3906 .writefn = tlbiall_hyp_is_write },
3907 { .name = "TLBIMVAH", .cp = 15, .opc1 = 4, .crn = 8, .crm = 7, .opc2 = 1,
3908 .type = ARM_CP_NO_RAW, .access = PL2_W,
3909 .writefn = tlbimva_hyp_write },
3910 { .name = "TLBIMVAHIS", .cp = 15, .opc1 = 4, .crn = 8, .crm = 3, .opc2 = 1,
3911 .type = ARM_CP_NO_RAW, .access = PL2_W,
3912 .writefn = tlbimva_hyp_is_write },
3913 { .name = "TLBI_ALLE2", .state = ARM_CP_STATE_AA64,
3914 .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 7, .opc2 = 0,
3915 .type = ARM_CP_NO_RAW, .access = PL2_W,
3916 .writefn = tlbi_aa64_alle2_write },
3917 { .name = "TLBI_VAE2", .state = ARM_CP_STATE_AA64,
3918 .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 7, .opc2 = 1,
3919 .type = ARM_CP_NO_RAW, .access = PL2_W,
3920 .writefn = tlbi_aa64_vae2_write },
3921 { .name = "TLBI_VALE2", .state = ARM_CP_STATE_AA64,
3922 .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 7, .opc2 = 5,
3923 .access = PL2_W, .type = ARM_CP_NO_RAW,
3924 .writefn = tlbi_aa64_vae2_write },
3925 { .name = "TLBI_ALLE2IS", .state = ARM_CP_STATE_AA64,
3926 .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 3, .opc2 = 0,
3927 .access = PL2_W, .type = ARM_CP_NO_RAW,
3928 .writefn = tlbi_aa64_alle2is_write },
3929 { .name = "TLBI_VAE2IS", .state = ARM_CP_STATE_AA64,
3930 .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 3, .opc2 = 1,
3931 .type = ARM_CP_NO_RAW, .access = PL2_W,
3932 .writefn = tlbi_aa64_vae2is_write },
3933 { .name = "TLBI_VALE2IS", .state = ARM_CP_STATE_AA64,
3934 .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 3, .opc2 = 5,
3935 .access = PL2_W, .type = ARM_CP_NO_RAW,
3936 .writefn = tlbi_aa64_vae2is_write },
3937#ifndef CONFIG_USER_ONLY
3938
3939
3940
3941
3942 { .name = "AT_S1E2R", .state = ARM_CP_STATE_AA64,
3943 .opc0 = 1, .opc1 = 4, .crn = 7, .crm = 8, .opc2 = 0,
3944 .access = PL2_W, .accessfn = at_s1e2_access,
3945 .type = ARM_CP_NO_RAW, .writefn = ats_write64 },
3946 { .name = "AT_S1E2W", .state = ARM_CP_STATE_AA64,
3947 .opc0 = 1, .opc1 = 4, .crn = 7, .crm = 8, .opc2 = 1,
3948 .access = PL2_W, .accessfn = at_s1e2_access,
3949 .type = ARM_CP_NO_RAW, .writefn = ats_write64 },
3950
3951
3952
3953
3954
3955 { .name = "ATS1HR", .cp = 15, .opc1 = 4, .crn = 7, .crm = 8, .opc2 = 0,
3956 .access = PL2_W,
3957 .writefn = ats1h_write, .type = ARM_CP_NO_RAW },
3958 { .name = "ATS1HW", .cp = 15, .opc1 = 4, .crn = 7, .crm = 8, .opc2 = 1,
3959 .access = PL2_W,
3960 .writefn = ats1h_write, .type = ARM_CP_NO_RAW },
3961 { .name = "CNTHCTL_EL2", .state = ARM_CP_STATE_BOTH,
3962 .opc0 = 3, .opc1 = 4, .crn = 14, .crm = 1, .opc2 = 0,
3963
3964
3965
3966
3967 .access = PL2_RW, .resetvalue = 3,
3968 .fieldoffset = offsetof(CPUARMState, cp15.cnthctl_el2) },
3969 { .name = "CNTVOFF_EL2", .state = ARM_CP_STATE_AA64,
3970 .opc0 = 3, .opc1 = 4, .crn = 14, .crm = 0, .opc2 = 3,
3971 .access = PL2_RW, .type = ARM_CP_IO, .resetvalue = 0,
3972 .writefn = gt_cntvoff_write,
3973 .fieldoffset = offsetof(CPUARMState, cp15.cntvoff_el2) },
3974 { .name = "CNTVOFF", .cp = 15, .opc1 = 4, .crm = 14,
3975 .access = PL2_RW, .type = ARM_CP_64BIT | ARM_CP_ALIAS | ARM_CP_IO,
3976 .writefn = gt_cntvoff_write,
3977 .fieldoffset = offsetof(CPUARMState, cp15.cntvoff_el2) },
3978 { .name = "CNTHP_CVAL_EL2", .state = ARM_CP_STATE_AA64,
3979 .opc0 = 3, .opc1 = 4, .crn = 14, .crm = 2, .opc2 = 2,
3980 .fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_HYP].cval),
3981 .type = ARM_CP_IO, .access = PL2_RW,
3982 .writefn = gt_hyp_cval_write, .raw_writefn = raw_write },
3983 { .name = "CNTHP_CVAL", .cp = 15, .opc1 = 6, .crm = 14,
3984 .fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_HYP].cval),
3985 .access = PL2_RW, .type = ARM_CP_64BIT | ARM_CP_IO,
3986 .writefn = gt_hyp_cval_write, .raw_writefn = raw_write },
3987 { .name = "CNTHP_TVAL_EL2", .state = ARM_CP_STATE_BOTH,
3988 .opc0 = 3, .opc1 = 4, .crn = 14, .crm = 2, .opc2 = 0,
3989 .type = ARM_CP_NO_RAW | ARM_CP_IO, .access = PL2_RW,
3990 .resetfn = gt_hyp_timer_reset,
3991 .readfn = gt_hyp_tval_read, .writefn = gt_hyp_tval_write },
3992 { .name = "CNTHP_CTL_EL2", .state = ARM_CP_STATE_BOTH,
3993 .type = ARM_CP_IO,
3994 .opc0 = 3, .opc1 = 4, .crn = 14, .crm = 2, .opc2 = 1,
3995 .access = PL2_RW,
3996 .fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_HYP].ctl),
3997 .resetvalue = 0,
3998 .writefn = gt_hyp_ctl_write, .raw_writefn = raw_write },
3999#endif
4000
4001
4002
4003
4004
4005 { .name = "MDCR_EL2", .state = ARM_CP_STATE_BOTH,
4006 .opc0 = 3, .opc1 = 4, .crn = 1, .crm = 1, .opc2 = 1,
4007 .access = PL2_RW, .resetvalue = 0,
4008 .fieldoffset = offsetof(CPUARMState, cp15.mdcr_el2), },
4009 { .name = "HPFAR", .state = ARM_CP_STATE_AA32,
4010 .cp = 15, .opc1 = 4, .crn = 6, .crm = 0, .opc2 = 4,
4011 .access = PL2_RW, .accessfn = access_el3_aa32ns,
4012 .fieldoffset = offsetof(CPUARMState, cp15.hpfar_el2) },
4013 { .name = "HPFAR_EL2", .state = ARM_CP_STATE_AA64,
4014 .opc0 = 3, .opc1 = 4, .crn = 6, .crm = 0, .opc2 = 4,
4015 .access = PL2_RW,
4016 .fieldoffset = offsetof(CPUARMState, cp15.hpfar_el2) },
4017 { .name = "HSTR_EL2", .state = ARM_CP_STATE_BOTH,
4018 .cp = 15, .opc0 = 3, .opc1 = 4, .crn = 1, .crm = 1, .opc2 = 3,
4019 .access = PL2_RW,
4020 .fieldoffset = offsetof(CPUARMState, cp15.hstr_el2) },
4021 REGINFO_SENTINEL
4022};
4023
4024static CPAccessResult nsacr_access(CPUARMState *env, const ARMCPRegInfo *ri,
4025 bool isread)
4026{
4027
4028
4029
4030 if (arm_current_el(env) == 3) {
4031 return CP_ACCESS_OK;
4032 }
4033 if (arm_is_secure_below_el3(env)) {
4034 return CP_ACCESS_TRAP_EL3;
4035 }
4036
4037 if (isread) {
4038 return CP_ACCESS_OK;
4039 }
4040 return CP_ACCESS_TRAP_UNCATEGORIZED;
4041}
4042
4043static const ARMCPRegInfo el3_cp_reginfo[] = {
4044 { .name = "SCR_EL3", .state = ARM_CP_STATE_AA64,
4045 .opc0 = 3, .opc1 = 6, .crn = 1, .crm = 1, .opc2 = 0,
4046 .access = PL3_RW, .fieldoffset = offsetof(CPUARMState, cp15.scr_el3),
4047 .resetvalue = 0, .writefn = scr_write },
4048 { .name = "SCR", .type = ARM_CP_ALIAS,
4049 .cp = 15, .opc1 = 0, .crn = 1, .crm = 1, .opc2 = 0,
4050 .access = PL1_RW, .accessfn = access_trap_aa32s_el1,
4051 .fieldoffset = offsetoflow32(CPUARMState, cp15.scr_el3),
4052 .writefn = scr_write },
4053 { .name = "SDER32_EL3", .state = ARM_CP_STATE_AA64,
4054 .opc0 = 3, .opc1 = 6, .crn = 1, .crm = 1, .opc2 = 1,
4055 .access = PL3_RW, .resetvalue = 0,
4056 .fieldoffset = offsetof(CPUARMState, cp15.sder) },
4057 { .name = "SDER",
4058 .cp = 15, .opc1 = 0, .crn = 1, .crm = 1, .opc2 = 1,
4059 .access = PL3_RW, .resetvalue = 0,
4060 .fieldoffset = offsetoflow32(CPUARMState, cp15.sder) },
4061 { .name = "MVBAR", .cp = 15, .opc1 = 0, .crn = 12, .crm = 0, .opc2 = 1,
4062 .access = PL1_RW, .accessfn = access_trap_aa32s_el1,
4063 .writefn = vbar_write, .resetvalue = 0,
4064 .fieldoffset = offsetof(CPUARMState, cp15.mvbar) },
4065 { .name = "TTBR0_EL3", .state = ARM_CP_STATE_AA64,
4066 .opc0 = 3, .opc1 = 6, .crn = 2, .crm = 0, .opc2 = 0,
4067 .access = PL3_RW, .writefn = vmsa_ttbr_write, .resetvalue = 0,
4068 .fieldoffset = offsetof(CPUARMState, cp15.ttbr0_el[3]) },
4069 { .name = "TCR_EL3", .state = ARM_CP_STATE_AA64,
4070 .opc0 = 3, .opc1 = 6, .crn = 2, .crm = 0, .opc2 = 2,
4071 .access = PL3_RW,
4072
4073
4074
4075
4076
4077 .resetfn = vmsa_ttbcr_reset, .raw_writefn = vmsa_ttbcr_raw_write,
4078 .fieldoffset = offsetof(CPUARMState, cp15.tcr_el[3]) },
4079 { .name = "ELR_EL3", .state = ARM_CP_STATE_AA64,
4080 .type = ARM_CP_ALIAS,
4081 .opc0 = 3, .opc1 = 6, .crn = 4, .crm = 0, .opc2 = 1,
4082 .access = PL3_RW,
4083 .fieldoffset = offsetof(CPUARMState, elr_el[3]) },
4084 { .name = "ESR_EL3", .state = ARM_CP_STATE_AA64,
4085 .opc0 = 3, .opc1 = 6, .crn = 5, .crm = 2, .opc2 = 0,
4086 .access = PL3_RW, .fieldoffset = offsetof(CPUARMState, cp15.esr_el[3]) },
4087 { .name = "FAR_EL3", .state = ARM_CP_STATE_AA64,
4088 .opc0 = 3, .opc1 = 6, .crn = 6, .crm = 0, .opc2 = 0,
4089 .access = PL3_RW, .fieldoffset = offsetof(CPUARMState, cp15.far_el[3]) },
4090 { .name = "SPSR_EL3", .state = ARM_CP_STATE_AA64,
4091 .type = ARM_CP_ALIAS,
4092 .opc0 = 3, .opc1 = 6, .crn = 4, .crm = 0, .opc2 = 0,
4093 .access = PL3_RW,
4094 .fieldoffset = offsetof(CPUARMState, banked_spsr[BANK_MON]) },
4095 { .name = "VBAR_EL3", .state = ARM_CP_STATE_AA64,
4096 .opc0 = 3, .opc1 = 6, .crn = 12, .crm = 0, .opc2 = 0,
4097 .access = PL3_RW, .writefn = vbar_write,
4098 .fieldoffset = offsetof(CPUARMState, cp15.vbar_el[3]),
4099 .resetvalue = 0 },
4100 { .name = "CPTR_EL3", .state = ARM_CP_STATE_AA64,
4101 .opc0 = 3, .opc1 = 6, .crn = 1, .crm = 1, .opc2 = 2,
4102 .access = PL3_RW, .accessfn = cptr_access, .resetvalue = 0,
4103 .fieldoffset = offsetof(CPUARMState, cp15.cptr_el[3]) },
4104 { .name = "TPIDR_EL3", .state = ARM_CP_STATE_AA64,
4105 .opc0 = 3, .opc1 = 6, .crn = 13, .crm = 0, .opc2 = 2,
4106 .access = PL3_RW, .resetvalue = 0,
4107 .fieldoffset = offsetof(CPUARMState, cp15.tpidr_el[3]) },
4108 { .name = "AMAIR_EL3", .state = ARM_CP_STATE_AA64,
4109 .opc0 = 3, .opc1 = 6, .crn = 10, .crm = 3, .opc2 = 0,
4110 .access = PL3_RW, .type = ARM_CP_CONST,
4111 .resetvalue = 0 },
4112 { .name = "AFSR0_EL3", .state = ARM_CP_STATE_BOTH,
4113 .opc0 = 3, .opc1 = 6, .crn = 5, .crm = 1, .opc2 = 0,
4114 .access = PL3_RW, .type = ARM_CP_CONST,
4115 .resetvalue = 0 },
4116 { .name = "AFSR1_EL3", .state = ARM_CP_STATE_BOTH,
4117 .opc0 = 3, .opc1 = 6, .crn = 5, .crm = 1, .opc2 = 1,
4118 .access = PL3_RW, .type = ARM_CP_CONST,
4119 .resetvalue = 0 },
4120 { .name = "TLBI_ALLE3IS", .state = ARM_CP_STATE_AA64,
4121 .opc0 = 1, .opc1 = 6, .crn = 8, .crm = 3, .opc2 = 0,
4122 .access = PL3_W, .type = ARM_CP_NO_RAW,
4123 .writefn = tlbi_aa64_alle3is_write },
4124 { .name = "TLBI_VAE3IS", .state = ARM_CP_STATE_AA64,
4125 .opc0 = 1, .opc1 = 6, .crn = 8, .crm = 3, .opc2 = 1,
4126 .access = PL3_W, .type = ARM_CP_NO_RAW,
4127 .writefn = tlbi_aa64_vae3is_write },
4128 { .name = "TLBI_VALE3IS", .state = ARM_CP_STATE_AA64,
4129 .opc0 = 1, .opc1 = 6, .crn = 8, .crm = 3, .opc2 = 5,
4130 .access = PL3_W, .type = ARM_CP_NO_RAW,
4131 .writefn = tlbi_aa64_vae3is_write },
4132 { .name = "TLBI_ALLE3", .state = ARM_CP_STATE_AA64,
4133 .opc0 = 1, .opc1 = 6, .crn = 8, .crm = 7, .opc2 = 0,
4134 .access = PL3_W, .type = ARM_CP_NO_RAW,
4135 .writefn = tlbi_aa64_alle3_write },
4136 { .name = "TLBI_VAE3", .state = ARM_CP_STATE_AA64,
4137 .opc0 = 1, .opc1 = 6, .crn = 8, .crm = 7, .opc2 = 1,
4138 .access = PL3_W, .type = ARM_CP_NO_RAW,
4139 .writefn = tlbi_aa64_vae3_write },
4140 { .name = "TLBI_VALE3", .state = ARM_CP_STATE_AA64,
4141 .opc0 = 1, .opc1 = 6, .crn = 8, .crm = 7, .opc2 = 5,
4142 .access = PL3_W, .type = ARM_CP_NO_RAW,
4143 .writefn = tlbi_aa64_vae3_write },
4144 REGINFO_SENTINEL
4145};
4146
4147static CPAccessResult ctr_el0_access(CPUARMState *env, const ARMCPRegInfo *ri,
4148 bool isread)
4149{
4150
4151
4152
4153 if (arm_current_el(env) == 0 && !(env->cp15.sctlr_el[1] & SCTLR_UCT)) {
4154 return CP_ACCESS_TRAP;
4155 }
4156 return CP_ACCESS_OK;
4157}
4158
4159static void dcc_write(CPUARMState *env, const ARMCPRegInfo *ri,
4160 uint64_t value)
4161{
4162 putchar(value);
4163}
4164
4165static void oslar_write(CPUARMState *env, const ARMCPRegInfo *ri,
4166 uint64_t value)
4167{
4168
4169
4170
4171 int oslock;
4172
4173 if (ri->state == ARM_CP_STATE_AA32) {
4174 oslock = (value == 0xC5ACCE55);
4175 } else {
4176 oslock = value & 1;
4177 }
4178
4179 env->cp15.oslsr_el1 = deposit32(env->cp15.oslsr_el1, 1, 1, oslock);
4180}
4181
4182static const ARMCPRegInfo debug_cp_reginfo[] = {
4183
4184
4185
4186
4187
4188
4189 { .name = "DBGDRAR", .cp = 14, .crn = 1, .crm = 0, .opc1 = 0, .opc2 = 0,
4190 .access = PL0_R, .accessfn = access_tdra,
4191 .type = ARM_CP_CONST, .resetvalue = 0 },
4192 { .name = "MDRAR_EL1", .state = ARM_CP_STATE_AA64,
4193 .opc0 = 2, .opc1 = 0, .crn = 1, .crm = 0, .opc2 = 0,
4194 .access = PL1_R, .accessfn = access_tdra,
4195 .type = ARM_CP_CONST, .resetvalue = 0 },
4196 { .name = "DBGDSAR", .cp = 14, .crn = 2, .crm = 0, .opc1 = 0, .opc2 = 0,
4197 .access = PL0_R, .accessfn = access_tdra,
4198 .type = ARM_CP_CONST, .resetvalue = 0 },
4199
4200 { .name = "MDSCR_EL1", .state = ARM_CP_STATE_BOTH,
4201 .cp = 14, .opc0 = 2, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 2,
4202 .access = PL1_RW, .accessfn = access_tda,
4203 .fieldoffset = offsetof(CPUARMState, cp15.mdscr_el1),
4204 .resetvalue = 0 },
4205
4206
4207
4208 { .name = "MDCCSR_EL0", .state = ARM_CP_STATE_BOTH,
4209 .cp = 14, .opc0 = 2, .opc1 = 0, .crn = 0, .crm = 1, .opc2 = 0,
4210 .type = ARM_CP_ALIAS,
4211 .access = PL1_R, .accessfn = access_tda,
4212 .fieldoffset = offsetof(CPUARMState, cp15.mdscr_el1), },
4213 { .name = "OSLAR_EL1", .state = ARM_CP_STATE_BOTH,
4214 .cp = 14, .opc0 = 2, .opc1 = 0, .crn = 1, .crm = 0, .opc2 = 4,
4215 .access = PL1_W, .type = ARM_CP_NO_RAW,
4216 .accessfn = access_tdosa,
4217 .writefn = oslar_write },
4218 { .name = "OSLSR_EL1", .state = ARM_CP_STATE_BOTH,
4219 .cp = 14, .opc0 = 2, .opc1 = 0, .crn = 1, .crm = 1, .opc2 = 4,
4220 .access = PL1_R, .resetvalue = 10,
4221 .accessfn = access_tdosa,
4222 .fieldoffset = offsetof(CPUARMState, cp15.oslsr_el1) },
4223
4224 { .name = "OSDLR_EL1", .state = ARM_CP_STATE_BOTH,
4225 .cp = 14, .opc0 = 2, .opc1 = 0, .crn = 1, .crm = 3, .opc2 = 4,
4226 .access = PL1_RW, .accessfn = access_tdosa,
4227 .type = ARM_CP_NOP },
4228
4229
4230
4231 { .name = "DBGVCR",
4232 .cp = 14, .opc1 = 0, .crn = 0, .crm = 7, .opc2 = 0,
4233 .access = PL1_RW, .accessfn = access_tda,
4234 .type = ARM_CP_NOP },
4235
4236
4237
4238
4239 { .name = "MDCCINT_EL1", .state = ARM_CP_STATE_BOTH,
4240 .cp = 14, .opc0 = 2, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 0,
4241 .access = PL1_RW, .accessfn = access_tda,
4242 .type = ARM_CP_NOP },
4243 { .name = "DBGDTRTX_EL0", .state = ARM_CP_STATE_AA64,
4244 .opc0 = 2, .opc1 = 3, .crn = 0, .crm = 5, .opc2 = 0,
4245 .access = PL0_W, .writefn = dcc_write, .type = ARM_CP_NO_RAW },
4246 { .name = "MDCCSR_EL0", .state = ARM_CP_STATE_AA64,
4247 .opc0 = 2, .opc1 = 3, .crn = 0, .crm = 1, .opc2 = 0,
4248 .access = PL0_R, .type = ARM_CP_CONST, .resetvalue = 0 },
4249 REGINFO_SENTINEL
4250};
4251
4252static const ARMCPRegInfo debug_lpae_cp_reginfo[] = {
4253
4254 { .name = "DBGDRAR", .cp = 14, .crm = 1, .opc1 = 0,
4255 .access = PL0_R, .type = ARM_CP_CONST|ARM_CP_64BIT, .resetvalue = 0 },
4256 { .name = "DBGDSAR", .cp = 14, .crm = 2, .opc1 = 0,
4257 .access = PL0_R, .type = ARM_CP_CONST|ARM_CP_64BIT, .resetvalue = 0 },
4258 REGINFO_SENTINEL
4259};
4260
4261void hw_watchpoint_update(ARMCPU *cpu, int n)
4262{
4263 CPUARMState *env = &cpu->env;
4264 vaddr len = 0;
4265 vaddr wvr = env->cp15.dbgwvr[n];
4266 uint64_t wcr = env->cp15.dbgwcr[n];
4267 int mask;
4268 int flags = BP_CPU | BP_STOP_BEFORE_ACCESS;
4269
4270 if (env->cpu_watchpoint[n]) {
4271 cpu_watchpoint_remove_by_ref(CPU(cpu), env->cpu_watchpoint[n]);
4272 env->cpu_watchpoint[n] = NULL;
4273 }
4274
4275 if (!extract64(wcr, 0, 1)) {
4276
4277 return;
4278 }
4279
4280 switch (extract64(wcr, 3, 2)) {
4281 case 0:
4282
4283 return;
4284 case 1:
4285 flags |= BP_MEM_READ;
4286 break;
4287 case 2:
4288 flags |= BP_MEM_WRITE;
4289 break;
4290 case 3:
4291 flags |= BP_MEM_ACCESS;
4292 break;
4293 }
4294
4295
4296
4297
4298
4299 mask = extract64(wcr, 24, 4);
4300 if (mask == 1 || mask == 2) {
4301
4302
4303
4304
4305 return;
4306 } else if (mask) {
4307
4308 len = 1ULL << mask;
4309
4310
4311
4312
4313 wvr &= ~(len - 1);
4314 } else {
4315
4316 int bas = extract64(wcr, 5, 8);
4317 int basstart;
4318
4319 if (bas == 0) {
4320
4321 return;
4322 }
4323
4324 if (extract64(wvr, 2, 1)) {
4325
4326
4327
4328 bas &= 0xf;
4329 }
4330
4331
4332
4333
4334
4335 basstart = ctz32(bas);
4336 len = cto32(bas >> basstart);
4337 wvr += basstart;
4338 }
4339
4340 cpu_watchpoint_insert(CPU(cpu), wvr, len, flags,
4341 &env->cpu_watchpoint[n]);
4342}
4343
4344void hw_watchpoint_update_all(ARMCPU *cpu)
4345{
4346 int i;
4347 CPUARMState *env = &cpu->env;
4348
4349
4350
4351
4352 cpu_watchpoint_remove_all(CPU(cpu), BP_CPU);
4353 memset(env->cpu_watchpoint, 0, sizeof(env->cpu_watchpoint));
4354
4355 for (i = 0; i < ARRAY_SIZE(cpu->env.cpu_watchpoint); i++) {
4356 hw_watchpoint_update(cpu, i);
4357 }
4358}
4359
4360static void dbgwvr_write(CPUARMState *env, const ARMCPRegInfo *ri,
4361 uint64_t value)
4362{
4363 ARMCPU *cpu = arm_env_get_cpu(env);
4364 int i = ri->crm;
4365
4366
4367
4368
4369
4370 value = sextract64(value, 0, 49) & ~3ULL;
4371
4372 raw_write(env, ri, value);
4373 hw_watchpoint_update(cpu, i);
4374}
4375
4376static void dbgwcr_write(CPUARMState *env, const ARMCPRegInfo *ri,
4377 uint64_t value)
4378{
4379 ARMCPU *cpu = arm_env_get_cpu(env);
4380 int i = ri->crm;
4381
4382 raw_write(env, ri, value);
4383 hw_watchpoint_update(cpu, i);
4384}
4385
4386void hw_breakpoint_update(ARMCPU *cpu, int n)
4387{
4388 CPUARMState *env = &cpu->env;
4389 uint64_t bvr = env->cp15.dbgbvr[n];
4390 uint64_t bcr = env->cp15.dbgbcr[n];
4391 vaddr addr;
4392 int bt;
4393 int flags = BP_CPU;
4394
4395 if (env->cpu_breakpoint[n]) {
4396 cpu_breakpoint_remove_by_ref(CPU(cpu), env->cpu_breakpoint[n]);
4397 env->cpu_breakpoint[n] = NULL;
4398 }
4399
4400 if (!extract64(bcr, 0, 1)) {
4401
4402 return;
4403 }
4404
4405 bt = extract64(bcr, 20, 4);
4406
4407 switch (bt) {
4408 case 4:
4409 case 5:
4410 qemu_log_mask(LOG_UNIMP,
4411 "arm: address mismatch breakpoint types not implemented");
4412 return;
4413 case 0:
4414 case 1:
4415 {
4416
4417
4418
4419
4420
4421
4422
4423
4424
4425
4426
4427
4428
4429
4430
4431 int bas = extract64(bcr, 5, 4);
4432 addr = sextract64(bvr, 0, 49) & ~3ULL;
4433 if (bas == 0) {
4434 return;
4435 }
4436 if (bas == 0xc) {
4437 addr += 2;
4438 }
4439 break;
4440 }
4441 case 2:
4442 case 8:
4443 case 10:
4444 qemu_log_mask(LOG_UNIMP,
4445 "arm: unlinked context breakpoint types not implemented");
4446 return;
4447 case 9:
4448 case 11:
4449 case 3:
4450 default:
4451
4452
4453
4454
4455
4456 return;
4457 }
4458
4459 cpu_breakpoint_insert(CPU(cpu), addr, flags, &env->cpu_breakpoint[n]);
4460}
4461
4462void hw_breakpoint_update_all(ARMCPU *cpu)
4463{
4464 int i;
4465 CPUARMState *env = &cpu->env;
4466
4467
4468
4469
4470 cpu_breakpoint_remove_all(CPU(cpu), BP_CPU);
4471 memset(env->cpu_breakpoint, 0, sizeof(env->cpu_breakpoint));
4472
4473 for (i = 0; i < ARRAY_SIZE(cpu->env.cpu_breakpoint); i++) {
4474 hw_breakpoint_update(cpu, i);
4475 }
4476}
4477
4478static void dbgbvr_write(CPUARMState *env, const ARMCPRegInfo *ri,
4479 uint64_t value)
4480{
4481 ARMCPU *cpu = arm_env_get_cpu(env);
4482 int i = ri->crm;
4483
4484 raw_write(env, ri, value);
4485 hw_breakpoint_update(cpu, i);
4486}
4487
4488static void dbgbcr_write(CPUARMState *env, const ARMCPRegInfo *ri,
4489 uint64_t value)
4490{
4491 ARMCPU *cpu = arm_env_get_cpu(env);
4492 int i = ri->crm;
4493
4494
4495
4496
4497 value = deposit64(value, 6, 1, extract64(value, 5, 1));
4498 value = deposit64(value, 8, 1, extract64(value, 7, 1));
4499
4500 raw_write(env, ri, value);
4501 hw_breakpoint_update(cpu, i);
4502}
4503
4504static void define_debug_regs(ARMCPU *cpu)
4505{
4506
4507
4508
4509 int i;
4510 int wrps, brps, ctx_cmps;
4511 ARMCPRegInfo dbgdidr = {
4512 .name = "DBGDIDR", .cp = 14, .crn = 0, .crm = 0, .opc1 = 0, .opc2 = 0,
4513 .access = PL0_R, .accessfn = access_tda,
4514 .type = ARM_CP_CONST, .resetvalue = cpu->dbgdidr,
4515 };
4516
4517
4518 brps = extract32(cpu->dbgdidr, 24, 4);
4519 wrps = extract32(cpu->dbgdidr, 28, 4);
4520 ctx_cmps = extract32(cpu->dbgdidr, 20, 4);
4521
4522 assert(ctx_cmps <= brps);
4523
4524
4525
4526
4527
4528 if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) {
4529 assert(extract32(cpu->id_aa64dfr0, 12, 4) == brps);
4530 assert(extract32(cpu->id_aa64dfr0, 20, 4) == wrps);
4531 assert(extract32(cpu->id_aa64dfr0, 28, 4) == ctx_cmps);
4532 }
4533
4534 define_one_arm_cp_reg(cpu, &dbgdidr);
4535 define_arm_cp_regs(cpu, debug_cp_reginfo);
4536
4537 if (arm_feature(&cpu->env, ARM_FEATURE_LPAE)) {
4538 define_arm_cp_regs(cpu, debug_lpae_cp_reginfo);
4539 }
4540
4541 for (i = 0; i < brps + 1; i++) {
4542 ARMCPRegInfo dbgregs[] = {
4543 { .name = "DBGBVR", .state = ARM_CP_STATE_BOTH,
4544 .cp = 14, .opc0 = 2, .opc1 = 0, .crn = 0, .crm = i, .opc2 = 4,
4545 .access = PL1_RW, .accessfn = access_tda,
4546 .fieldoffset = offsetof(CPUARMState, cp15.dbgbvr[i]),
4547 .writefn = dbgbvr_write, .raw_writefn = raw_write
4548 },
4549 { .name = "DBGBCR", .state = ARM_CP_STATE_BOTH,
4550 .cp = 14, .opc0 = 2, .opc1 = 0, .crn = 0, .crm = i, .opc2 = 5,
4551 .access = PL1_RW, .accessfn = access_tda,
4552 .fieldoffset = offsetof(CPUARMState, cp15.dbgbcr[i]),
4553 .writefn = dbgbcr_write, .raw_writefn = raw_write
4554 },
4555 REGINFO_SENTINEL
4556 };
4557 define_arm_cp_regs(cpu, dbgregs);
4558 }
4559
4560 for (i = 0; i < wrps + 1; i++) {
4561 ARMCPRegInfo dbgregs[] = {
4562 { .name = "DBGWVR", .state = ARM_CP_STATE_BOTH,
4563 .cp = 14, .opc0 = 2, .opc1 = 0, .crn = 0, .crm = i, .opc2 = 6,
4564 .access = PL1_RW, .accessfn = access_tda,
4565 .fieldoffset = offsetof(CPUARMState, cp15.dbgwvr[i]),
4566 .writefn = dbgwvr_write, .raw_writefn = raw_write
4567 },
4568 { .name = "DBGWCR", .state = ARM_CP_STATE_BOTH,
4569 .cp = 14, .opc0 = 2, .opc1 = 0, .crn = 0, .crm = i, .opc2 = 7,
4570 .access = PL1_RW, .accessfn = access_tda,
4571 .fieldoffset = offsetof(CPUARMState, cp15.dbgwcr[i]),
4572 .writefn = dbgwcr_write, .raw_writefn = raw_write
4573 },
4574 REGINFO_SENTINEL
4575 };
4576 define_arm_cp_regs(cpu, dbgregs);
4577 }
4578}
4579
4580void register_cp_regs_for_features(ARMCPU *cpu)
4581{
4582
4583 CPUARMState *env = &cpu->env;
4584 if (arm_feature(env, ARM_FEATURE_M)) {
4585
4586 return;
4587 }
4588
4589 define_arm_cp_regs(cpu, cp_reginfo);
4590 if (!arm_feature(env, ARM_FEATURE_V8)) {
4591
4592
4593
4594 define_arm_cp_regs(cpu, not_v8_cp_reginfo);
4595 }
4596
4597 if (arm_feature(env, ARM_FEATURE_V6)) {
4598
4599 ARMCPRegInfo v6_idregs[] = {
4600 { .name = "ID_PFR0", .state = ARM_CP_STATE_BOTH,
4601 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 1, .opc2 = 0,
4602 .access = PL1_R, .type = ARM_CP_CONST,
4603 .resetvalue = cpu->id_pfr0 },
4604 { .name = "ID_PFR1", .state = ARM_CP_STATE_BOTH,
4605 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 1, .opc2 = 1,
4606 .access = PL1_R, .type = ARM_CP_CONST,
4607 .resetvalue = cpu->id_pfr1 },
4608 { .name = "ID_DFR0", .state = ARM_CP_STATE_BOTH,
4609 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 1, .opc2 = 2,
4610 .access = PL1_R, .type = ARM_CP_CONST,
4611 .resetvalue = cpu->id_dfr0 },
4612 { .name = "ID_AFR0", .state = ARM_CP_STATE_BOTH,
4613 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 1, .opc2 = 3,
4614 .access = PL1_R, .type = ARM_CP_CONST,
4615 .resetvalue = cpu->id_afr0 },
4616 { .name = "ID_MMFR0", .state = ARM_CP_STATE_BOTH,
4617 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 1, .opc2 = 4,
4618 .access = PL1_R, .type = ARM_CP_CONST,
4619 .resetvalue = cpu->id_mmfr0 },
4620 { .name = "ID_MMFR1", .state = ARM_CP_STATE_BOTH,
4621 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 1, .opc2 = 5,
4622 .access = PL1_R, .type = ARM_CP_CONST,
4623 .resetvalue = cpu->id_mmfr1 },
4624 { .name = "ID_MMFR2", .state = ARM_CP_STATE_BOTH,
4625 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 1, .opc2 = 6,
4626 .access = PL1_R, .type = ARM_CP_CONST,
4627 .resetvalue = cpu->id_mmfr2 },
4628 { .name = "ID_MMFR3", .state = ARM_CP_STATE_BOTH,
4629 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 1, .opc2 = 7,
4630 .access = PL1_R, .type = ARM_CP_CONST,
4631 .resetvalue = cpu->id_mmfr3 },
4632 { .name = "ID_ISAR0", .state = ARM_CP_STATE_BOTH,
4633 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 0,
4634 .access = PL1_R, .type = ARM_CP_CONST,
4635 .resetvalue = cpu->id_isar0 },
4636 { .name = "ID_ISAR1", .state = ARM_CP_STATE_BOTH,
4637 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 1,
4638 .access = PL1_R, .type = ARM_CP_CONST,
4639 .resetvalue = cpu->id_isar1 },
4640 { .name = "ID_ISAR2", .state = ARM_CP_STATE_BOTH,
4641 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 2,
4642 .access = PL1_R, .type = ARM_CP_CONST,
4643 .resetvalue = cpu->id_isar2 },
4644 { .name = "ID_ISAR3", .state = ARM_CP_STATE_BOTH,
4645 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 3,
4646 .access = PL1_R, .type = ARM_CP_CONST,
4647 .resetvalue = cpu->id_isar3 },
4648 { .name = "ID_ISAR4", .state = ARM_CP_STATE_BOTH,
4649 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 4,
4650 .access = PL1_R, .type = ARM_CP_CONST,
4651 .resetvalue = cpu->id_isar4 },
4652 { .name = "ID_ISAR5", .state = ARM_CP_STATE_BOTH,
4653 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 5,
4654 .access = PL1_R, .type = ARM_CP_CONST,
4655 .resetvalue = cpu->id_isar5 },
4656 { .name = "ID_MMFR4", .state = ARM_CP_STATE_BOTH,
4657 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 6,
4658 .access = PL1_R, .type = ARM_CP_CONST,
4659 .resetvalue = cpu->id_mmfr4 },
4660
4661 { .name = "ID_ISAR7_RESERVED", .state = ARM_CP_STATE_BOTH,
4662 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 7,
4663 .access = PL1_R, .type = ARM_CP_CONST,
4664 .resetvalue = 0 },
4665 REGINFO_SENTINEL
4666 };
4667 define_arm_cp_regs(cpu, v6_idregs);
4668 define_arm_cp_regs(cpu, v6_cp_reginfo);
4669 } else {
4670 define_arm_cp_regs(cpu, not_v6_cp_reginfo);
4671 }
4672 if (arm_feature(env, ARM_FEATURE_V6K)) {
4673 define_arm_cp_regs(cpu, v6k_cp_reginfo);
4674 }
4675 if (arm_feature(env, ARM_FEATURE_V7MP) &&
4676 !arm_feature(env, ARM_FEATURE_MPU)) {
4677 define_arm_cp_regs(cpu, v7mp_cp_reginfo);
4678 }
4679 if (arm_feature(env, ARM_FEATURE_V7)) {
4680
4681
4682
4683
4684#ifndef CONFIG_USER_ONLY
4685 ARMCPRegInfo pmcr = {
4686 .name = "PMCR", .cp = 15, .crn = 9, .crm = 12, .opc1 = 0, .opc2 = 0,
4687 .access = PL0_RW,
4688 .type = ARM_CP_IO | ARM_CP_ALIAS,
4689 .fieldoffset = offsetoflow32(CPUARMState, cp15.c9_pmcr),
4690 .accessfn = pmreg_access, .writefn = pmcr_write,
4691 .raw_writefn = raw_write,
4692 };
4693 ARMCPRegInfo pmcr64 = {
4694 .name = "PMCR_EL0", .state = ARM_CP_STATE_AA64,
4695 .opc0 = 3, .opc1 = 3, .crn = 9, .crm = 12, .opc2 = 0,
4696 .access = PL0_RW, .accessfn = pmreg_access,
4697 .type = ARM_CP_IO,
4698 .fieldoffset = offsetof(CPUARMState, cp15.c9_pmcr),
4699 .resetvalue = cpu->midr & 0xff000000,
4700 .writefn = pmcr_write, .raw_writefn = raw_write,
4701 };
4702 define_one_arm_cp_reg(cpu, &pmcr);
4703 define_one_arm_cp_reg(cpu, &pmcr64);
4704#endif
4705 ARMCPRegInfo clidr = {
4706 .name = "CLIDR", .state = ARM_CP_STATE_BOTH,
4707 .opc0 = 3, .crn = 0, .crm = 0, .opc1 = 1, .opc2 = 1,
4708 .access = PL1_R, .type = ARM_CP_CONST, .resetvalue = cpu->clidr
4709 };
4710 define_one_arm_cp_reg(cpu, &clidr);
4711 define_arm_cp_regs(cpu, v7_cp_reginfo);
4712 define_debug_regs(cpu);
4713 } else {
4714 define_arm_cp_regs(cpu, not_v7_cp_reginfo);
4715 }
4716 if (arm_feature(env, ARM_FEATURE_V8)) {
4717
4718
4719
4720
4721
4722 ARMCPRegInfo v8_idregs[] = {
4723 { .name = "ID_AA64PFR0_EL1", .state = ARM_CP_STATE_AA64,
4724 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 4, .opc2 = 0,
4725 .access = PL1_R, .type = ARM_CP_CONST,
4726 .resetvalue = cpu->id_aa64pfr0 },
4727 { .name = "ID_AA64PFR1_EL1", .state = ARM_CP_STATE_AA64,
4728 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 4, .opc2 = 1,
4729 .access = PL1_R, .type = ARM_CP_CONST,
4730 .resetvalue = cpu->id_aa64pfr1},
4731 { .name = "ID_AA64PFR2_EL1_RESERVED", .state = ARM_CP_STATE_AA64,
4732 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 4, .opc2 = 2,
4733 .access = PL1_R, .type = ARM_CP_CONST,
4734 .resetvalue = 0 },
4735 { .name = "ID_AA64PFR3_EL1_RESERVED", .state = ARM_CP_STATE_AA64,
4736 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 4, .opc2 = 3,
4737 .access = PL1_R, .type = ARM_CP_CONST,
4738 .resetvalue = 0 },
4739 { .name = "ID_AA64PFR4_EL1_RESERVED", .state = ARM_CP_STATE_AA64,
4740 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 4, .opc2 = 4,
4741 .access = PL1_R, .type = ARM_CP_CONST,
4742 .resetvalue = 0 },
4743 { .name = "ID_AA64PFR5_EL1_RESERVED", .state = ARM_CP_STATE_AA64,
4744 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 4, .opc2 = 5,
4745 .access = PL1_R, .type = ARM_CP_CONST,
4746 .resetvalue = 0 },
4747 { .name = "ID_AA64PFR6_EL1_RESERVED", .state = ARM_CP_STATE_AA64,
4748 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 4, .opc2 = 6,
4749 .access = PL1_R, .type = ARM_CP_CONST,
4750 .resetvalue = 0 },
4751 { .name = "ID_AA64PFR7_EL1_RESERVED", .state = ARM_CP_STATE_AA64,
4752 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 4, .opc2 = 7,
4753 .access = PL1_R, .type = ARM_CP_CONST,
4754 .resetvalue = 0 },
4755 { .name = "ID_AA64DFR0_EL1", .state = ARM_CP_STATE_AA64,
4756 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 5, .opc2 = 0,
4757 .access = PL1_R, .type = ARM_CP_CONST,
4758
4759
4760
4761
4762
4763 .resetvalue = cpu->id_aa64dfr0 & ~0xf00 },
4764 { .name = "ID_AA64DFR1_EL1", .state = ARM_CP_STATE_AA64,
4765 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 5, .opc2 = 1,
4766 .access = PL1_R, .type = ARM_CP_CONST,
4767 .resetvalue = cpu->id_aa64dfr1 },
4768 { .name = "ID_AA64DFR2_EL1_RESERVED", .state = ARM_CP_STATE_AA64,
4769 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 5, .opc2 = 2,
4770 .access = PL1_R, .type = ARM_CP_CONST,
4771 .resetvalue = 0 },
4772 { .name = "ID_AA64DFR3_EL1_RESERVED", .state = ARM_CP_STATE_AA64,
4773 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 5, .opc2 = 3,
4774 .access = PL1_R, .type = ARM_CP_CONST,
4775 .resetvalue = 0 },
4776 { .name = "ID_AA64AFR0_EL1", .state = ARM_CP_STATE_AA64,
4777 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 5, .opc2 = 4,
4778 .access = PL1_R, .type = ARM_CP_CONST,
4779 .resetvalue = cpu->id_aa64afr0 },
4780 { .name = "ID_AA64AFR1_EL1", .state = ARM_CP_STATE_AA64,
4781 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 5, .opc2 = 5,
4782 .access = PL1_R, .type = ARM_CP_CONST,
4783 .resetvalue = cpu->id_aa64afr1 },
4784 { .name = "ID_AA64AFR2_EL1_RESERVED", .state = ARM_CP_STATE_AA64,
4785 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 5, .opc2 = 6,
4786 .access = PL1_R, .type = ARM_CP_CONST,
4787 .resetvalue = 0 },
4788 { .name = "ID_AA64AFR3_EL1_RESERVED", .state = ARM_CP_STATE_AA64,
4789 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 5, .opc2 = 7,
4790 .access = PL1_R, .type = ARM_CP_CONST,
4791 .resetvalue = 0 },
4792 { .name = "ID_AA64ISAR0_EL1", .state = ARM_CP_STATE_AA64,
4793 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 6, .opc2 = 0,
4794 .access = PL1_R, .type = ARM_CP_CONST,
4795 .resetvalue = cpu->id_aa64isar0 },
4796 { .name = "ID_AA64ISAR1_EL1", .state = ARM_CP_STATE_AA64,
4797 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 6, .opc2 = 1,
4798 .access = PL1_R, .type = ARM_CP_CONST,
4799 .resetvalue = cpu->id_aa64isar1 },
4800 { .name = "ID_AA64ISAR2_EL1_RESERVED", .state = ARM_CP_STATE_AA64,
4801 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 6, .opc2 = 2,
4802 .access = PL1_R, .type = ARM_CP_CONST,
4803 .resetvalue = 0 },
4804 { .name = "ID_AA64ISAR3_EL1_RESERVED", .state = ARM_CP_STATE_AA64,
4805 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 6, .opc2 = 3,
4806 .access = PL1_R, .type = ARM_CP_CONST,
4807 .resetvalue = 0 },
4808 { .name = "ID_AA64ISAR4_EL1_RESERVED", .state = ARM_CP_STATE_AA64,
4809 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 6, .opc2 = 4,
4810 .access = PL1_R, .type = ARM_CP_CONST,
4811 .resetvalue = 0 },
4812 { .name = "ID_AA64ISAR5_EL1_RESERVED", .state = ARM_CP_STATE_AA64,
4813 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 6, .opc2 = 5,
4814 .access = PL1_R, .type = ARM_CP_CONST,
4815 .resetvalue = 0 },
4816 { .name = "ID_AA64ISAR6_EL1_RESERVED", .state = ARM_CP_STATE_AA64,
4817 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 6, .opc2 = 6,
4818 .access = PL1_R, .type = ARM_CP_CONST,
4819 .resetvalue = 0 },
4820 { .name = "ID_AA64ISAR7_EL1_RESERVED", .state = ARM_CP_STATE_AA64,
4821 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 6, .opc2 = 7,
4822 .access = PL1_R, .type = ARM_CP_CONST,
4823 .resetvalue = 0 },
4824 { .name = "ID_AA64MMFR0_EL1", .state = ARM_CP_STATE_AA64,
4825 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 7, .opc2 = 0,
4826 .access = PL1_R, .type = ARM_CP_CONST,
4827 .resetvalue = cpu->id_aa64mmfr0 },
4828 { .name = "ID_AA64MMFR1_EL1", .state = ARM_CP_STATE_AA64,
4829 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 7, .opc2 = 1,
4830 .access = PL1_R, .type = ARM_CP_CONST,
4831 .resetvalue = cpu->id_aa64mmfr1 },
4832 { .name = "ID_AA64MMFR2_EL1_RESERVED", .state = ARM_CP_STATE_AA64,
4833 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 7, .opc2 = 2,
4834 .access = PL1_R, .type = ARM_CP_CONST,
4835 .resetvalue = 0 },
4836 { .name = "ID_AA64MMFR3_EL1_RESERVED", .state = ARM_CP_STATE_AA64,
4837 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 7, .opc2 = 3,
4838 .access = PL1_R, .type = ARM_CP_CONST,
4839 .resetvalue = 0 },
4840 { .name = "ID_AA64MMFR4_EL1_RESERVED", .state = ARM_CP_STATE_AA64,
4841 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 7, .opc2 = 4,
4842 .access = PL1_R, .type = ARM_CP_CONST,
4843 .resetvalue = 0 },
4844 { .name = "ID_AA64MMFR5_EL1_RESERVED", .state = ARM_CP_STATE_AA64,
4845 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 7, .opc2 = 5,
4846 .access = PL1_R, .type = ARM_CP_CONST,
4847 .resetvalue = 0 },
4848 { .name = "ID_AA64MMFR6_EL1_RESERVED", .state = ARM_CP_STATE_AA64,
4849 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 7, .opc2 = 6,
4850 .access = PL1_R, .type = ARM_CP_CONST,
4851 .resetvalue = 0 },
4852 { .name = "ID_AA64MMFR7_EL1_RESERVED", .state = ARM_CP_STATE_AA64,
4853 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 7, .opc2 = 7,
4854 .access = PL1_R, .type = ARM_CP_CONST,
4855 .resetvalue = 0 },
4856 { .name = "MVFR0_EL1", .state = ARM_CP_STATE_AA64,
4857 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 3, .opc2 = 0,
4858 .access = PL1_R, .type = ARM_CP_CONST,
4859 .resetvalue = cpu->mvfr0 },
4860 { .name = "MVFR1_EL1", .state = ARM_CP_STATE_AA64,
4861 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 3, .opc2 = 1,
4862 .access = PL1_R, .type = ARM_CP_CONST,
4863 .resetvalue = cpu->mvfr1 },
4864 { .name = "MVFR2_EL1", .state = ARM_CP_STATE_AA64,
4865 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 3, .opc2 = 2,
4866 .access = PL1_R, .type = ARM_CP_CONST,
4867 .resetvalue = cpu->mvfr2 },
4868 { .name = "MVFR3_EL1_RESERVED", .state = ARM_CP_STATE_AA64,
4869 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 3, .opc2 = 3,
4870 .access = PL1_R, .type = ARM_CP_CONST,
4871 .resetvalue = 0 },
4872 { .name = "MVFR4_EL1_RESERVED", .state = ARM_CP_STATE_AA64,
4873 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 3, .opc2 = 4,
4874 .access = PL1_R, .type = ARM_CP_CONST,
4875 .resetvalue = 0 },
4876 { .name = "MVFR5_EL1_RESERVED", .state = ARM_CP_STATE_AA64,
4877 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 3, .opc2 = 5,
4878 .access = PL1_R, .type = ARM_CP_CONST,
4879 .resetvalue = 0 },
4880 { .name = "MVFR6_EL1_RESERVED", .state = ARM_CP_STATE_AA64,
4881 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 3, .opc2 = 6,
4882 .access = PL1_R, .type = ARM_CP_CONST,
4883 .resetvalue = 0 },
4884 { .name = "MVFR7_EL1_RESERVED", .state = ARM_CP_STATE_AA64,
4885 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 3, .opc2 = 7,
4886 .access = PL1_R, .type = ARM_CP_CONST,
4887 .resetvalue = 0 },
4888 { .name = "PMCEID0", .state = ARM_CP_STATE_AA32,
4889 .cp = 15, .opc1 = 0, .crn = 9, .crm = 12, .opc2 = 6,
4890 .access = PL0_R, .accessfn = pmreg_access, .type = ARM_CP_CONST,
4891 .resetvalue = cpu->pmceid0 },
4892 { .name = "PMCEID0_EL0", .state = ARM_CP_STATE_AA64,
4893 .opc0 = 3, .opc1 = 3, .crn = 9, .crm = 12, .opc2 = 6,
4894 .access = PL0_R, .accessfn = pmreg_access, .type = ARM_CP_CONST,
4895 .resetvalue = cpu->pmceid0 },
4896 { .name = "PMCEID1", .state = ARM_CP_STATE_AA32,
4897 .cp = 15, .opc1 = 0, .crn = 9, .crm = 12, .opc2 = 7,
4898 .access = PL0_R, .accessfn = pmreg_access, .type = ARM_CP_CONST,
4899 .resetvalue = cpu->pmceid1 },
4900 { .name = "PMCEID1_EL0", .state = ARM_CP_STATE_AA64,
4901 .opc0 = 3, .opc1 = 3, .crn = 9, .crm = 12, .opc2 = 7,
4902 .access = PL0_R, .accessfn = pmreg_access, .type = ARM_CP_CONST,
4903 .resetvalue = cpu->pmceid1 },
4904 REGINFO_SENTINEL
4905 };
4906
4907 if (!arm_feature(env, ARM_FEATURE_EL3) &&
4908 !arm_feature(env, ARM_FEATURE_EL2)) {
4909 ARMCPRegInfo rvbar = {
4910 .name = "RVBAR_EL1", .state = ARM_CP_STATE_AA64,
4911 .opc0 = 3, .opc1 = 0, .crn = 12, .crm = 0, .opc2 = 1,
4912 .type = ARM_CP_CONST, .access = PL1_R, .resetvalue = cpu->rvbar
4913 };
4914 define_one_arm_cp_reg(cpu, &rvbar);
4915 }
4916 define_arm_cp_regs(cpu, v8_idregs);
4917 define_arm_cp_regs(cpu, v8_cp_reginfo);
4918 }
4919 if (arm_feature(env, ARM_FEATURE_EL2)) {
4920 uint64_t vmpidr_def = mpidr_read_val(env);
4921 ARMCPRegInfo vpidr_regs[] = {
4922 { .name = "VPIDR", .state = ARM_CP_STATE_AA32,
4923 .cp = 15, .opc1 = 4, .crn = 0, .crm = 0, .opc2 = 0,
4924 .access = PL2_RW, .accessfn = access_el3_aa32ns,
4925 .resetvalue = cpu->midr,
4926 .fieldoffset = offsetof(CPUARMState, cp15.vpidr_el2) },
4927 { .name = "VPIDR_EL2", .state = ARM_CP_STATE_AA64,
4928 .opc0 = 3, .opc1 = 4, .crn = 0, .crm = 0, .opc2 = 0,
4929 .access = PL2_RW, .resetvalue = cpu->midr,
4930 .fieldoffset = offsetof(CPUARMState, cp15.vpidr_el2) },
4931 { .name = "VMPIDR", .state = ARM_CP_STATE_AA32,
4932 .cp = 15, .opc1 = 4, .crn = 0, .crm = 0, .opc2 = 5,
4933 .access = PL2_RW, .accessfn = access_el3_aa32ns,
4934 .resetvalue = vmpidr_def,
4935 .fieldoffset = offsetof(CPUARMState, cp15.vmpidr_el2) },
4936 { .name = "VMPIDR_EL2", .state = ARM_CP_STATE_AA64,
4937 .opc0 = 3, .opc1 = 4, .crn = 0, .crm = 0, .opc2 = 5,
4938 .access = PL2_RW,
4939 .resetvalue = vmpidr_def,
4940 .fieldoffset = offsetof(CPUARMState, cp15.vmpidr_el2) },
4941 REGINFO_SENTINEL
4942 };
4943 define_arm_cp_regs(cpu, vpidr_regs);
4944 define_arm_cp_regs(cpu, el2_cp_reginfo);
4945
4946 if (!arm_feature(env, ARM_FEATURE_EL3)) {
4947 ARMCPRegInfo rvbar = {
4948 .name = "RVBAR_EL2", .state = ARM_CP_STATE_AA64,
4949 .opc0 = 3, .opc1 = 4, .crn = 12, .crm = 0, .opc2 = 1,
4950 .type = ARM_CP_CONST, .access = PL2_R, .resetvalue = cpu->rvbar
4951 };
4952 define_one_arm_cp_reg(cpu, &rvbar);
4953 }
4954 } else {
4955
4956
4957
4958 if (arm_feature(env, ARM_FEATURE_EL3)) {
4959
4960
4961
4962 ARMCPRegInfo vpidr_regs[] = {
4963 { .name = "VPIDR_EL2", .state = ARM_CP_STATE_BOTH,
4964 .opc0 = 3, .opc1 = 4, .crn = 0, .crm = 0, .opc2 = 0,
4965 .access = PL2_RW, .accessfn = access_el3_aa32ns_aa64any,
4966 .type = ARM_CP_CONST, .resetvalue = cpu->midr,
4967 .fieldoffset = offsetof(CPUARMState, cp15.vpidr_el2) },
4968 { .name = "VMPIDR_EL2", .state = ARM_CP_STATE_BOTH,
4969 .opc0 = 3, .opc1 = 4, .crn = 0, .crm = 0, .opc2 = 5,
4970 .access = PL2_RW, .accessfn = access_el3_aa32ns_aa64any,
4971 .type = ARM_CP_NO_RAW,
4972 .writefn = arm_cp_write_ignore, .readfn = mpidr_read },
4973 REGINFO_SENTINEL
4974 };
4975 define_arm_cp_regs(cpu, vpidr_regs);
4976 define_arm_cp_regs(cpu, el3_no_el2_cp_reginfo);
4977 }
4978 }
4979 if (arm_feature(env, ARM_FEATURE_EL3)) {
4980 define_arm_cp_regs(cpu, el3_cp_reginfo);
4981 ARMCPRegInfo el3_regs[] = {
4982 { .name = "RVBAR_EL3", .state = ARM_CP_STATE_AA64,
4983 .opc0 = 3, .opc1 = 6, .crn = 12, .crm = 0, .opc2 = 1,
4984 .type = ARM_CP_CONST, .access = PL3_R, .resetvalue = cpu->rvbar },
4985 { .name = "SCTLR_EL3", .state = ARM_CP_STATE_AA64,
4986 .opc0 = 3, .opc1 = 6, .crn = 1, .crm = 0, .opc2 = 0,
4987 .access = PL3_RW,
4988 .raw_writefn = raw_write, .writefn = sctlr_write,
4989 .fieldoffset = offsetof(CPUARMState, cp15.sctlr_el[3]),
4990 .resetvalue = cpu->reset_sctlr },
4991 REGINFO_SENTINEL
4992 };
4993
4994 define_arm_cp_regs(cpu, el3_regs);
4995 }
4996
4997
4998
4999
5000
5001
5002
5003
5004 if (arm_feature(env, ARM_FEATURE_EL3)) {
5005 if (arm_feature(env, ARM_FEATURE_AARCH64)) {
5006 ARMCPRegInfo nsacr = {
5007 .name = "NSACR", .type = ARM_CP_CONST,
5008 .cp = 15, .opc1 = 0, .crn = 1, .crm = 1, .opc2 = 2,
5009 .access = PL1_RW, .accessfn = nsacr_access,
5010 .resetvalue = 0xc00
5011 };
5012 define_one_arm_cp_reg(cpu, &nsacr);
5013 } else {
5014 ARMCPRegInfo nsacr = {
5015 .name = "NSACR",
5016 .cp = 15, .opc1 = 0, .crn = 1, .crm = 1, .opc2 = 2,
5017 .access = PL3_RW | PL1_R,
5018 .resetvalue = 0,
5019 .fieldoffset = offsetof(CPUARMState, cp15.nsacr)
5020 };
5021 define_one_arm_cp_reg(cpu, &nsacr);
5022 }
5023 } else {
5024 if (arm_feature(env, ARM_FEATURE_V8)) {
5025 ARMCPRegInfo nsacr = {
5026 .name = "NSACR", .type = ARM_CP_CONST,
5027 .cp = 15, .opc1 = 0, .crn = 1, .crm = 1, .opc2 = 2,
5028 .access = PL1_R,
5029 .resetvalue = 0xc00
5030 };
5031 define_one_arm_cp_reg(cpu, &nsacr);
5032 }
5033 }
5034
5035 if (arm_feature(env, ARM_FEATURE_MPU)) {
5036 if (arm_feature(env, ARM_FEATURE_V6)) {
5037
5038 assert(arm_feature(env, ARM_FEATURE_V7));
5039 define_arm_cp_regs(cpu, vmsa_pmsa_cp_reginfo);
5040 define_arm_cp_regs(cpu, pmsav7_cp_reginfo);
5041 } else {
5042 define_arm_cp_regs(cpu, pmsav5_cp_reginfo);
5043 }
5044 } else {
5045 define_arm_cp_regs(cpu, vmsa_pmsa_cp_reginfo);
5046 define_arm_cp_regs(cpu, vmsa_cp_reginfo);
5047 }
5048 if (arm_feature(env, ARM_FEATURE_THUMB2EE)) {
5049 define_arm_cp_regs(cpu, t2ee_cp_reginfo);
5050 }
5051 if (arm_feature(env, ARM_FEATURE_GENERIC_TIMER)) {
5052 define_arm_cp_regs(cpu, generic_timer_cp_reginfo);
5053 }
5054 if (arm_feature(env, ARM_FEATURE_VAPA)) {
5055 define_arm_cp_regs(cpu, vapa_cp_reginfo);
5056 }
5057 if (arm_feature(env, ARM_FEATURE_CACHE_TEST_CLEAN)) {
5058 define_arm_cp_regs(cpu, cache_test_clean_cp_reginfo);
5059 }
5060 if (arm_feature(env, ARM_FEATURE_CACHE_DIRTY_REG)) {
5061 define_arm_cp_regs(cpu, cache_dirty_status_cp_reginfo);
5062 }
5063 if (arm_feature(env, ARM_FEATURE_CACHE_BLOCK_OPS)) {
5064 define_arm_cp_regs(cpu, cache_block_ops_cp_reginfo);
5065 }
5066 if (arm_feature(env, ARM_FEATURE_OMAPCP)) {
5067 define_arm_cp_regs(cpu, omap_cp_reginfo);
5068 }
5069 if (arm_feature(env, ARM_FEATURE_STRONGARM)) {
5070 define_arm_cp_regs(cpu, strongarm_cp_reginfo);
5071 }
5072 if (arm_feature(env, ARM_FEATURE_XSCALE)) {
5073 define_arm_cp_regs(cpu, xscale_cp_reginfo);
5074 }
5075 if (arm_feature(env, ARM_FEATURE_DUMMY_C15_REGS)) {
5076 define_arm_cp_regs(cpu, dummy_c15_cp_reginfo);
5077 }
5078 if (arm_feature(env, ARM_FEATURE_LPAE)) {
5079 define_arm_cp_regs(cpu, lpae_cp_reginfo);
5080 }
5081
5082
5083
5084
5085 {
5086 ARMCPRegInfo id_pre_v8_midr_cp_reginfo[] = {
5087
5088
5089
5090
5091
5092
5093
5094
5095
5096 { .name = "MIDR",
5097 .cp = 15, .crn = 0, .crm = 0, .opc1 = 0, .opc2 = CP_ANY,
5098 .access = PL1_R, .resetvalue = cpu->midr,
5099 .writefn = arm_cp_write_ignore, .raw_writefn = raw_write,
5100 .readfn = midr_read,
5101 .fieldoffset = offsetof(CPUARMState, cp15.c0_cpuid),
5102 .type = ARM_CP_OVERRIDE },
5103
5104 { .name = "DUMMY",
5105 .cp = 15, .crn = 0, .crm = 3, .opc1 = 0, .opc2 = CP_ANY,
5106 .access = PL1_R, .type = ARM_CP_CONST, .resetvalue = 0 },
5107 { .name = "DUMMY",
5108 .cp = 15, .crn = 0, .crm = 4, .opc1 = 0, .opc2 = CP_ANY,
5109 .access = PL1_R, .type = ARM_CP_CONST, .resetvalue = 0 },
5110 { .name = "DUMMY",
5111 .cp = 15, .crn = 0, .crm = 5, .opc1 = 0, .opc2 = CP_ANY,
5112 .access = PL1_R, .type = ARM_CP_CONST, .resetvalue = 0 },
5113 { .name = "DUMMY",
5114 .cp = 15, .crn = 0, .crm = 6, .opc1 = 0, .opc2 = CP_ANY,
5115 .access = PL1_R, .type = ARM_CP_CONST, .resetvalue = 0 },
5116 { .name = "DUMMY",
5117 .cp = 15, .crn = 0, .crm = 7, .opc1 = 0, .opc2 = CP_ANY,
5118 .access = PL1_R, .type = ARM_CP_CONST, .resetvalue = 0 },
5119 REGINFO_SENTINEL
5120 };
5121 ARMCPRegInfo id_v8_midr_cp_reginfo[] = {
5122 { .name = "MIDR_EL1", .state = ARM_CP_STATE_BOTH,
5123 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 0, .opc2 = 0,
5124 .access = PL1_R, .type = ARM_CP_NO_RAW, .resetvalue = cpu->midr,
5125 .fieldoffset = offsetof(CPUARMState, cp15.c0_cpuid),
5126 .readfn = midr_read },
5127
5128 { .name = "MIDR", .type = ARM_CP_ALIAS | ARM_CP_CONST,
5129 .cp = 15, .crn = 0, .crm = 0, .opc1 = 0, .opc2 = 4,
5130 .access = PL1_R, .resetvalue = cpu->midr },
5131 { .name = "MIDR", .type = ARM_CP_ALIAS | ARM_CP_CONST,
5132 .cp = 15, .crn = 0, .crm = 0, .opc1 = 0, .opc2 = 7,
5133 .access = PL1_R, .resetvalue = cpu->midr },
5134 { .name = "REVIDR_EL1", .state = ARM_CP_STATE_BOTH,
5135 .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 0, .opc2 = 6,
5136 .access = PL1_R, .type = ARM_CP_CONST, .resetvalue = cpu->revidr },
5137 REGINFO_SENTINEL
5138 };
5139 ARMCPRegInfo id_cp_reginfo[] = {
5140
5141 { .name = "CTR",
5142 .cp = 15, .crn = 0, .crm = 0, .opc1 = 0, .opc2 = 1,
5143 .access = PL1_R, .type = ARM_CP_CONST, .resetvalue = cpu->ctr },
5144 { .name = "CTR_EL0", .state = ARM_CP_STATE_AA64,
5145 .opc0 = 3, .opc1 = 3, .opc2 = 1, .crn = 0, .crm = 0,
5146 .access = PL0_R, .accessfn = ctr_el0_access,
5147 .type = ARM_CP_CONST, .resetvalue = cpu->ctr },
5148
5149 { .name = "TCMTR",
5150 .cp = 15, .crn = 0, .crm = 0, .opc1 = 0, .opc2 = 2,
5151 .access = PL1_R, .type = ARM_CP_CONST, .resetvalue = 0 },
5152 REGINFO_SENTINEL
5153 };
5154
5155 ARMCPRegInfo id_tlbtr_reginfo = {
5156 .name = "TLBTR",
5157 .cp = 15, .crn = 0, .crm = 0, .opc1 = 0, .opc2 = 3,
5158 .access = PL1_R, .type = ARM_CP_CONST, .resetvalue = 0,
5159 };
5160
5161 ARMCPRegInfo id_mpuir_reginfo = {
5162 .name = "MPUIR",
5163 .cp = 15, .crn = 0, .crm = 0, .opc1 = 0, .opc2 = 4,
5164 .access = PL1_R, .type = ARM_CP_CONST,
5165 .resetvalue = cpu->pmsav7_dregion << 8
5166 };
5167 ARMCPRegInfo crn0_wi_reginfo = {
5168 .name = "CRN0_WI", .cp = 15, .crn = 0, .crm = CP_ANY,
5169 .opc1 = CP_ANY, .opc2 = CP_ANY, .access = PL1_W,
5170 .type = ARM_CP_NOP | ARM_CP_OVERRIDE
5171 };
5172 if (arm_feature(env, ARM_FEATURE_OMAPCP) ||
5173 arm_feature(env, ARM_FEATURE_STRONGARM)) {
5174 ARMCPRegInfo *r;
5175
5176
5177
5178
5179
5180 define_one_arm_cp_reg(cpu, &crn0_wi_reginfo);
5181 for (r = id_pre_v8_midr_cp_reginfo;
5182 r->type != ARM_CP_SENTINEL; r++) {
5183 r->access = PL1_RW;
5184 }
5185 for (r = id_cp_reginfo; r->type != ARM_CP_SENTINEL; r++) {
5186 r->access = PL1_RW;
5187 }
5188 id_tlbtr_reginfo.access = PL1_RW;
5189 id_tlbtr_reginfo.access = PL1_RW;
5190 }
5191 if (arm_feature(env, ARM_FEATURE_V8)) {
5192 define_arm_cp_regs(cpu, id_v8_midr_cp_reginfo);
5193 } else {
5194 define_arm_cp_regs(cpu, id_pre_v8_midr_cp_reginfo);
5195 }
5196 define_arm_cp_regs(cpu, id_cp_reginfo);
5197 if (!arm_feature(env, ARM_FEATURE_MPU)) {
5198 define_one_arm_cp_reg(cpu, &id_tlbtr_reginfo);
5199 } else if (arm_feature(env, ARM_FEATURE_V7)) {
5200 define_one_arm_cp_reg(cpu, &id_mpuir_reginfo);
5201 }
5202 }
5203
5204 if (arm_feature(env, ARM_FEATURE_MPIDR)) {
5205 define_arm_cp_regs(cpu, mpidr_cp_reginfo);
5206 }
5207
5208 if (arm_feature(env, ARM_FEATURE_AUXCR)) {
5209 ARMCPRegInfo auxcr_reginfo[] = {
5210 { .name = "ACTLR_EL1", .state = ARM_CP_STATE_BOTH,
5211 .opc0 = 3, .opc1 = 0, .crn = 1, .crm = 0, .opc2 = 1,
5212 .access = PL1_RW, .type = ARM_CP_CONST,
5213 .resetvalue = cpu->reset_auxcr },
5214 { .name = "ACTLR_EL2", .state = ARM_CP_STATE_BOTH,
5215 .opc0 = 3, .opc1 = 4, .crn = 1, .crm = 0, .opc2 = 1,
5216 .access = PL2_RW, .type = ARM_CP_CONST,
5217 .resetvalue = 0 },
5218 { .name = "ACTLR_EL3", .state = ARM_CP_STATE_AA64,
5219 .opc0 = 3, .opc1 = 6, .crn = 1, .crm = 0, .opc2 = 1,
5220 .access = PL3_RW, .type = ARM_CP_CONST,
5221 .resetvalue = 0 },
5222 REGINFO_SENTINEL
5223 };
5224 define_arm_cp_regs(cpu, auxcr_reginfo);
5225 }
5226
5227 if (arm_feature(env, ARM_FEATURE_CBAR)) {
5228 if (arm_feature(env, ARM_FEATURE_AARCH64)) {
5229
5230 uint32_t cbar32 = (extract64(cpu->reset_cbar, 18, 14) << 18)
5231 | extract64(cpu->reset_cbar, 32, 12);
5232 ARMCPRegInfo cbar_reginfo[] = {
5233 { .name = "CBAR",
5234 .type = ARM_CP_CONST,
5235 .cp = 15, .crn = 15, .crm = 0, .opc1 = 4, .opc2 = 0,
5236 .access = PL1_R, .resetvalue = cpu->reset_cbar },
5237 { .name = "CBAR_EL1", .state = ARM_CP_STATE_AA64,
5238 .type = ARM_CP_CONST,
5239 .opc0 = 3, .opc1 = 1, .crn = 15, .crm = 3, .opc2 = 0,
5240 .access = PL1_R, .resetvalue = cbar32 },
5241 REGINFO_SENTINEL
5242 };
5243
5244 assert(arm_feature(env, ARM_FEATURE_CBAR_RO));
5245 define_arm_cp_regs(cpu, cbar_reginfo);
5246 } else {
5247 ARMCPRegInfo cbar = {
5248 .name = "CBAR",
5249 .cp = 15, .crn = 15, .crm = 0, .opc1 = 4, .opc2 = 0,
5250 .access = PL1_R|PL3_W, .resetvalue = cpu->reset_cbar,
5251 .fieldoffset = offsetof(CPUARMState,
5252 cp15.c15_config_base_address)
5253 };
5254 if (arm_feature(env, ARM_FEATURE_CBAR_RO)) {
5255 cbar.access = PL1_R;
5256 cbar.fieldoffset = 0;
5257 cbar.type = ARM_CP_CONST;
5258 }
5259 define_one_arm_cp_reg(cpu, &cbar);
5260 }
5261 }
5262
5263
5264 {
5265 ARMCPRegInfo sctlr = {
5266 .name = "SCTLR", .state = ARM_CP_STATE_BOTH,
5267 .opc0 = 3, .opc1 = 0, .crn = 1, .crm = 0, .opc2 = 0,
5268 .access = PL1_RW,
5269 .bank_fieldoffsets = { offsetof(CPUARMState, cp15.sctlr_s),
5270 offsetof(CPUARMState, cp15.sctlr_ns) },
5271 .writefn = sctlr_write, .resetvalue = cpu->reset_sctlr,
5272 .raw_writefn = raw_write,
5273 };
5274 if (arm_feature(env, ARM_FEATURE_XSCALE)) {
5275
5276
5277
5278
5279 sctlr.type |= ARM_CP_SUPPRESS_TB_END;
5280 }
5281 define_one_arm_cp_reg(cpu, &sctlr);
5282 }
5283}
5284
5285ARMCPU *cpu_arm_init(const char *cpu_model)
5286{
5287 return ARM_CPU(cpu_generic_init(TYPE_ARM_CPU, cpu_model));
5288}
5289
5290void arm_cpu_register_gdb_regs_for_features(ARMCPU *cpu)
5291{
5292 CPUState *cs = CPU(cpu);
5293 CPUARMState *env = &cpu->env;
5294
5295 if (arm_feature(env, ARM_FEATURE_AARCH64)) {
5296 gdb_register_coprocessor(cs, aarch64_fpu_gdb_get_reg,
5297 aarch64_fpu_gdb_set_reg,
5298 34, "aarch64-fpu.xml", 0);
5299 } else if (arm_feature(env, ARM_FEATURE_NEON)) {
5300 gdb_register_coprocessor(cs, vfp_gdb_get_reg, vfp_gdb_set_reg,
5301 51, "arm-neon.xml", 0);
5302 } else if (arm_feature(env, ARM_FEATURE_VFP3)) {
5303 gdb_register_coprocessor(cs, vfp_gdb_get_reg, vfp_gdb_set_reg,
5304 35, "arm-vfp3.xml", 0);
5305 } else if (arm_feature(env, ARM_FEATURE_VFP)) {
5306 gdb_register_coprocessor(cs, vfp_gdb_get_reg, vfp_gdb_set_reg,
5307 19, "arm-vfp.xml", 0);
5308 }
5309
5310 if (arm_feature(env, ARM_FEATURE_AARCH64)) {
5311 gdb_register_coprocessor(cs, aarch64_el1_gdb_get_reg,
5312 aarch64_el1_gdb_set_reg,
5313 5, "aarch64-el1.xml", 0);
5314 if (arm_feature(env, ARM_FEATURE_EL2)) {
5315 gdb_register_coprocessor(cs, aarch64_el2_gdb_get_reg,
5316 aarch64_el2_gdb_set_reg,
5317 4, "aarch64-el2.xml", 0);
5318 }
5319
5320 if (arm_feature(env, ARM_FEATURE_EL3)) {
5321 gdb_register_coprocessor(cs, aarch64_el3_gdb_get_reg,
5322 aarch64_el3_gdb_set_reg,
5323 4, "aarch64-el3.xml", 0);
5324 }
5325 } else if (arm_feature(env, ARM_FEATURE_EL3)) {
5326 gdb_register_coprocessor(cs, arm_sys_gdb_get_reg,
5327 arm_sys_gdb_set_reg,
5328 3, "arm-sys.xml", 0);
5329 }
5330}
5331
5332
5333static gint arm_cpu_list_compare(gconstpointer a, gconstpointer b)
5334{
5335 ObjectClass *class_a = (ObjectClass *)a;
5336 ObjectClass *class_b = (ObjectClass *)b;
5337 const char *name_a, *name_b;
5338
5339 name_a = object_class_get_name(class_a);
5340 name_b = object_class_get_name(class_b);
5341 if (strcmp(name_a, "any-" TYPE_ARM_CPU) == 0) {
5342 return 1;
5343 } else if (strcmp(name_b, "any-" TYPE_ARM_CPU) == 0) {
5344 return -1;
5345 } else {
5346 return strcmp(name_a, name_b);
5347 }
5348}
5349
5350static void arm_cpu_list_entry(gpointer data, gpointer user_data)
5351{
5352 ObjectClass *oc = data;
5353 CPUListState *s = user_data;
5354 const char *typename;
5355 char *name;
5356
5357 typename = object_class_get_name(oc);
5358 name = g_strndup(typename, strlen(typename) - strlen("-" TYPE_ARM_CPU));
5359 (*s->cpu_fprintf)(s->file, " %s\n",
5360 name);
5361 g_free(name);
5362}
5363
5364void arm_cpu_list(FILE *f, fprintf_function cpu_fprintf)
5365{
5366 CPUListState s = {
5367 .file = f,
5368 .cpu_fprintf = cpu_fprintf,
5369 };
5370 GSList *list;
5371
5372 list = object_class_get_list(TYPE_ARM_CPU, false);
5373 list = g_slist_sort(list, arm_cpu_list_compare);
5374 (*cpu_fprintf)(f, "Available CPUs:\n");
5375 g_slist_foreach(list, arm_cpu_list_entry, &s);
5376 g_slist_free(list);
5377#ifdef CONFIG_KVM
5378
5379
5380
5381 (*cpu_fprintf)(f, " host (only available in KVM mode)\n");
5382#endif
5383}
5384
5385static void arm_cpu_add_definition(gpointer data, gpointer user_data)
5386{
5387 ObjectClass *oc = data;
5388 CpuDefinitionInfoList **cpu_list = user_data;
5389 CpuDefinitionInfoList *entry;
5390 CpuDefinitionInfo *info;
5391 const char *typename;
5392
5393 typename = object_class_get_name(oc);
5394 info = g_malloc0(sizeof(*info));
5395 info->name = g_strndup(typename,
5396 strlen(typename) - strlen("-" TYPE_ARM_CPU));
5397
5398 entry = g_malloc0(sizeof(*entry));
5399 entry->value = info;
5400 entry->next = *cpu_list;
5401 *cpu_list = entry;
5402}
5403
5404CpuDefinitionInfoList *arch_query_cpu_definitions(Error **errp)
5405{
5406 CpuDefinitionInfoList *cpu_list = NULL;
5407 GSList *list;
5408
5409 list = object_class_get_list(TYPE_ARM_CPU, false);
5410 g_slist_foreach(list, arm_cpu_add_definition, &cpu_list);
5411 g_slist_free(list);
5412
5413 return cpu_list;
5414}
5415
5416static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
5417 void *opaque, int state, int secstate,
5418 int crm, int opc1, int opc2)
5419{
5420
5421
5422
5423 uint32_t *key = g_new(uint32_t, 1);
5424 ARMCPRegInfo *r2 = g_memdup(r, sizeof(ARMCPRegInfo));
5425 int is64 = (r->type & ARM_CP_64BIT) ? 1 : 0;
5426 int ns = (secstate & ARM_CP_SECSTATE_NS) ? 1 : 0;
5427
5428
5429
5430
5431 r2->secure = secstate;
5432
5433 if (r->bank_fieldoffsets[0] && r->bank_fieldoffsets[1]) {
5434
5435
5436
5437
5438 r2->fieldoffset = r->bank_fieldoffsets[ns];
5439 }
5440
5441 if (state == ARM_CP_STATE_AA32) {
5442 if (r->bank_fieldoffsets[0] && r->bank_fieldoffsets[1]) {
5443
5444
5445
5446
5447
5448
5449
5450
5451
5452
5453 if ((r->state == ARM_CP_STATE_BOTH && ns) ||
5454 (arm_feature(&cpu->env, ARM_FEATURE_V8) && !ns)) {
5455 r2->type |= ARM_CP_ALIAS;
5456 }
5457 } else if ((secstate != r->secure) && !ns) {
5458
5459
5460
5461 r2->type |= ARM_CP_ALIAS;
5462 }
5463
5464 if (r->state == ARM_CP_STATE_BOTH) {
5465
5466
5467 if (r2->cp == 0) {
5468 r2->cp = 15;
5469 }
5470
5471#ifdef HOST_WORDS_BIGENDIAN
5472 if (r2->fieldoffset) {
5473 r2->fieldoffset += sizeof(uint32_t);
5474 }
5475#endif
5476 }
5477 }
5478 if (state == ARM_CP_STATE_AA64) {
5479
5480
5481
5482
5483
5484
5485
5486 if (r->cp == 0 || r->state == ARM_CP_STATE_BOTH) {
5487 r2->cp = CP_REG_ARM64_SYSREG_CP;
5488 }
5489 *key = ENCODE_AA64_CP_REG(r2->cp, r2->crn, crm,
5490 r2->opc0, opc1, opc2);
5491 } else {
5492 *key = ENCODE_CP_REG(r2->cp, is64, ns, r2->crn, crm, opc1, opc2);
5493 }
5494 if (opaque) {
5495 r2->opaque = opaque;
5496 }
5497
5498
5499
5500 r2->state = state;
5501
5502
5503
5504 r2->crm = crm;
5505 r2->opc1 = opc1;
5506 r2->opc2 = opc2;
5507
5508
5509
5510
5511
5512
5513 if ((r->type & ARM_CP_SPECIAL)) {
5514 r2->type |= ARM_CP_NO_RAW;
5515 }
5516 if (((r->crm == CP_ANY) && crm != 0) ||
5517 ((r->opc1 == CP_ANY) && opc1 != 0) ||
5518 ((r->opc2 == CP_ANY) && opc2 != 0)) {
5519 r2->type |= ARM_CP_ALIAS;
5520 }
5521
5522
5523
5524
5525
5526 if (!(r2->type & ARM_CP_NO_RAW)) {
5527 assert(!raw_accessors_invalid(r2));
5528 }
5529
5530
5531
5532
5533 if (!(r->type & ARM_CP_OVERRIDE)) {
5534 ARMCPRegInfo *oldreg;
5535 oldreg = g_hash_table_lookup(cpu->cp_regs, key);
5536 if (oldreg && !(oldreg->type & ARM_CP_OVERRIDE)) {
5537 fprintf(stderr, "Register redefined: cp=%d %d bit "
5538 "crn=%d crm=%d opc1=%d opc2=%d, "
5539 "was %s, now %s\n", r2->cp, 32 + 32 * is64,
5540 r2->crn, r2->crm, r2->opc1, r2->opc2,
5541 oldreg->name, r2->name);
5542 g_assert_not_reached();
5543 }
5544 }
5545 g_hash_table_insert(cpu->cp_regs, key, r2);
5546}
5547
5548
5549void define_one_arm_cp_reg_with_opaque(ARMCPU *cpu,
5550 const ARMCPRegInfo *r, void *opaque)
5551{
5552
5553
5554
5555
5556
5557
5558
5559
5560
5561
5562
5563
5564
5565
5566
5567
5568
5569
5570
5571
5572
5573
5574
5575 int crm, opc1, opc2, state;
5576 int crmmin = (r->crm == CP_ANY) ? 0 : r->crm;
5577 int crmmax = (r->crm == CP_ANY) ? 15 : r->crm;
5578 int opc1min = (r->opc1 == CP_ANY) ? 0 : r->opc1;
5579 int opc1max = (r->opc1 == CP_ANY) ? 7 : r->opc1;
5580 int opc2min = (r->opc2 == CP_ANY) ? 0 : r->opc2;
5581 int opc2max = (r->opc2 == CP_ANY) ? 7 : r->opc2;
5582
5583 assert(!((r->type & ARM_CP_64BIT) && (r->opc2 || r->crn)));
5584
5585 assert((r->state != ARM_CP_STATE_AA32) || (r->opc0 == 0));
5586
5587 assert((r->state != ARM_CP_STATE_AA64) || !(r->type & ARM_CP_64BIT));
5588
5589
5590
5591
5592
5593
5594 if (r->state != ARM_CP_STATE_AA32) {
5595 int mask = 0;
5596 switch (r->opc1) {
5597 case 0: case 1: case 2:
5598
5599 mask = PL1_RW;
5600 break;
5601 case 3:
5602
5603 mask = PL0_RW;
5604 break;
5605 case 4:
5606
5607 mask = PL2_RW;
5608 break;
5609 case 5:
5610
5611 assert(false);
5612 break;
5613 case 6:
5614
5615 mask = PL3_RW;
5616 break;
5617 case 7:
5618
5619 mask = PL1_RW;
5620 break;
5621 default:
5622
5623 assert(false);
5624 break;
5625 }
5626
5627 assert((r->access & ~mask) == 0);
5628 }
5629
5630
5631
5632
5633 if (!(r->type & (ARM_CP_SPECIAL|ARM_CP_CONST))) {
5634 if (r->access & PL3_R) {
5635 assert((r->fieldoffset ||
5636 (r->bank_fieldoffsets[0] && r->bank_fieldoffsets[1])) ||
5637 r->readfn);
5638 }
5639 if (r->access & PL3_W) {
5640 assert((r->fieldoffset ||
5641 (r->bank_fieldoffsets[0] && r->bank_fieldoffsets[1])) ||
5642 r->writefn);
5643 }
5644 }
5645
5646 assert(cptype_valid(r->type));
5647 for (crm = crmmin; crm <= crmmax; crm++) {
5648 for (opc1 = opc1min; opc1 <= opc1max; opc1++) {
5649 for (opc2 = opc2min; opc2 <= opc2max; opc2++) {
5650 for (state = ARM_CP_STATE_AA32;
5651 state <= ARM_CP_STATE_AA64; state++) {
5652 if (r->state != state && r->state != ARM_CP_STATE_BOTH) {
5653 continue;
5654 }
5655 if (state == ARM_CP_STATE_AA32) {
5656
5657
5658
5659 switch (r->secure) {
5660 case ARM_CP_SECSTATE_S:
5661 case ARM_CP_SECSTATE_NS:
5662 add_cpreg_to_hashtable(cpu, r, opaque, state,
5663 r->secure, crm, opc1, opc2);
5664 break;
5665 default:
5666 add_cpreg_to_hashtable(cpu, r, opaque, state,
5667 ARM_CP_SECSTATE_S,
5668 crm, opc1, opc2);
5669 add_cpreg_to_hashtable(cpu, r, opaque, state,
5670 ARM_CP_SECSTATE_NS,
5671 crm, opc1, opc2);
5672 break;
5673 }
5674 } else {
5675
5676
5677 add_cpreg_to_hashtable(cpu, r, opaque, state,
5678 ARM_CP_SECSTATE_NS,
5679 crm, opc1, opc2);
5680 }
5681 }
5682 }
5683 }
5684 }
5685}
5686
5687void define_arm_cp_regs_with_opaque(ARMCPU *cpu,
5688 const ARMCPRegInfo *regs, void *opaque)
5689{
5690
5691 const ARMCPRegInfo *r;
5692 for (r = regs; r->type != ARM_CP_SENTINEL; r++) {
5693 define_one_arm_cp_reg_with_opaque(cpu, r, opaque);
5694 }
5695}
5696
5697const ARMCPRegInfo *get_arm_cp_reginfo(GHashTable *cpregs, uint32_t encoded_cp)
5698{
5699 return g_hash_table_lookup(cpregs, &encoded_cp);
5700}
5701
5702void arm_cp_write_ignore(CPUARMState *env, const ARMCPRegInfo *ri,
5703 uint64_t value)
5704{
5705
5706}
5707
5708uint64_t arm_cp_read_zero(CPUARMState *env, const ARMCPRegInfo *ri)
5709{
5710
5711 return 0;
5712}
5713
5714void arm_cp_reset_ignore(CPUARMState *env, const ARMCPRegInfo *opaque)
5715{
5716
5717}
5718
5719static int bad_mode_switch(CPUARMState *env, int mode, CPSRWriteType write_type)
5720{
5721
5722
5723
5724
5725
5726
5727 if (write_type == CPSRWriteByInstr &&
5728 ((env->uncached_cpsr & CPSR_M) == ARM_CPU_MODE_HYP ||
5729 mode == ARM_CPU_MODE_HYP)) {
5730 return 1;
5731 }
5732
5733 switch (mode) {
5734 case ARM_CPU_MODE_USR:
5735 return 0;
5736 case ARM_CPU_MODE_SYS:
5737 case ARM_CPU_MODE_SVC:
5738 case ARM_CPU_MODE_ABT:
5739 case ARM_CPU_MODE_UND:
5740 case ARM_CPU_MODE_IRQ:
5741 case ARM_CPU_MODE_FIQ:
5742
5743
5744
5745
5746
5747
5748 if (write_type == CPSRWriteByInstr &&
5749 (env->cp15.hcr_el2 & HCR_TGE) &&
5750 (env->uncached_cpsr & CPSR_M) == ARM_CPU_MODE_MON &&
5751 !arm_is_secure_below_el3(env)) {
5752 return 1;
5753 }
5754 return 0;
5755 case ARM_CPU_MODE_HYP:
5756 return !arm_feature(env, ARM_FEATURE_EL2)
5757 || arm_current_el(env) < 2 || arm_is_secure(env);
5758 case ARM_CPU_MODE_MON:
5759 return arm_current_el(env) < 3;
5760 default:
5761 return 1;
5762 }
5763}
5764
5765uint32_t cpsr_read(CPUARMState *env)
5766{
5767 int ZF;
5768 ZF = (env->ZF == 0);
5769 return env->uncached_cpsr | (env->NF & 0x80000000) | (ZF << 30) |
5770 (env->CF << 29) | ((env->VF & 0x80000000) >> 3) | (env->QF << 27)
5771 | (env->thumb << 5) | ((env->condexec_bits & 3) << 25)
5772 | ((env->condexec_bits & 0xfc) << 8)
5773 | (env->GE << 16) | (env->daif & CPSR_AIF);
5774}
5775
5776void cpsr_write(CPUARMState *env, uint32_t val, uint32_t mask,
5777 CPSRWriteType write_type)
5778{
5779 uint32_t changed_daif;
5780
5781 if (mask & CPSR_NZCV) {
5782 env->ZF = (~val) & CPSR_Z;
5783 env->NF = val;
5784 env->CF = (val >> 29) & 1;
5785 env->VF = (val << 3) & 0x80000000;
5786 }
5787 if (mask & CPSR_Q)
5788 env->QF = ((val & CPSR_Q) != 0);
5789 if (mask & CPSR_T)
5790 env->thumb = ((val & CPSR_T) != 0);
5791 if (mask & CPSR_IT_0_1) {
5792 env->condexec_bits &= ~3;
5793 env->condexec_bits |= (val >> 25) & 3;
5794 }
5795 if (mask & CPSR_IT_2_7) {
5796 env->condexec_bits &= 3;
5797 env->condexec_bits |= (val >> 8) & 0xfc;
5798 }
5799 if (mask & CPSR_GE) {
5800 env->GE = (val >> 16) & 0xf;
5801 }
5802
5803
5804
5805
5806
5807
5808
5809
5810
5811 if (write_type != CPSRWriteRaw && !arm_feature(env, ARM_FEATURE_V8) &&
5812 arm_feature(env, ARM_FEATURE_EL3) &&
5813 !arm_feature(env, ARM_FEATURE_EL2) &&
5814 !arm_is_secure(env)) {
5815
5816 changed_daif = (env->daif ^ val) & mask;
5817
5818 if (changed_daif & CPSR_A) {
5819
5820
5821
5822 if (!(env->cp15.scr_el3 & SCR_AW)) {
5823 qemu_log_mask(LOG_GUEST_ERROR,
5824 "Ignoring attempt to switch CPSR_A flag from "
5825 "non-secure world with SCR.AW bit clear\n");
5826 mask &= ~CPSR_A;
5827 }
5828 }
5829
5830 if (changed_daif & CPSR_F) {
5831
5832
5833
5834 if (!(env->cp15.scr_el3 & SCR_FW)) {
5835 qemu_log_mask(LOG_GUEST_ERROR,
5836 "Ignoring attempt to switch CPSR_F flag from "
5837 "non-secure world with SCR.FW bit clear\n");
5838 mask &= ~CPSR_F;
5839 }
5840
5841
5842
5843
5844
5845 if ((A32_BANKED_CURRENT_REG_GET(env, sctlr) & SCTLR_NMFI) &&
5846 (val & CPSR_F)) {
5847 qemu_log_mask(LOG_GUEST_ERROR,
5848 "Ignoring attempt to enable CPSR_F flag "
5849 "(non-maskable FIQ [NMFI] support enabled)\n");
5850 mask &= ~CPSR_F;
5851 }
5852 }
5853 }
5854
5855 env->daif &= ~(CPSR_AIF & mask);
5856 env->daif |= val & CPSR_AIF & mask;
5857
5858 if (write_type != CPSRWriteRaw &&
5859 ((env->uncached_cpsr ^ val) & mask & CPSR_M)) {
5860 if ((env->uncached_cpsr & CPSR_M) == ARM_CPU_MODE_USR) {
5861
5862
5863
5864
5865
5866
5867 mask &= ~CPSR_M;
5868 } else if (bad_mode_switch(env, val & CPSR_M, write_type)) {
5869
5870
5871
5872
5873
5874
5875
5876
5877 mask &= ~CPSR_M;
5878 if (write_type != CPSRWriteByGDBStub &&
5879 arm_feature(env, ARM_FEATURE_V8)) {
5880 mask |= CPSR_IL;
5881 val |= CPSR_IL;
5882 }
5883 } else {
5884 switch_mode(env, val & CPSR_M);
5885 }
5886 }
5887 mask &= ~CACHED_CPSR_BITS;
5888 env->uncached_cpsr = (env->uncached_cpsr & ~mask) | (val & mask);
5889}
5890
5891
5892uint32_t HELPER(sxtb16)(uint32_t x)
5893{
5894 uint32_t res;
5895 res = (uint16_t)(int8_t)x;
5896 res |= (uint32_t)(int8_t)(x >> 16) << 16;
5897 return res;
5898}
5899
5900uint32_t HELPER(uxtb16)(uint32_t x)
5901{
5902 uint32_t res;
5903 res = (uint16_t)(uint8_t)x;
5904 res |= (uint32_t)(uint8_t)(x >> 16) << 16;
5905 return res;
5906}
5907
5908uint32_t HELPER(clz)(uint32_t x)
5909{
5910 return clz32(x);
5911}
5912
5913int32_t HELPER(sdiv)(int32_t num, int32_t den)
5914{
5915 if (den == 0)
5916 return 0;
5917 if (num == INT_MIN && den == -1)
5918 return INT_MIN;
5919 return num / den;
5920}
5921
5922uint32_t HELPER(udiv)(uint32_t num, uint32_t den)
5923{
5924 if (den == 0)
5925 return 0;
5926 return num / den;
5927}
5928
5929uint32_t HELPER(rbit)(uint32_t x)
5930{
5931 return revbit32(x);
5932}
5933
5934#if defined(CONFIG_USER_ONLY)
5935
5936
5937void HELPER(v7m_msr)(CPUARMState *env, uint32_t reg, uint32_t val)
5938{
5939 ARMCPU *cpu = arm_env_get_cpu(env);
5940
5941 cpu_abort(CPU(cpu), "v7m_msr %d\n", reg);
5942}
5943
5944uint32_t HELPER(v7m_mrs)(CPUARMState *env, uint32_t reg)
5945{
5946 ARMCPU *cpu = arm_env_get_cpu(env);
5947
5948 cpu_abort(CPU(cpu), "v7m_mrs %d\n", reg);
5949 return 0;
5950}
5951
5952void switch_mode(CPUARMState *env, int mode)
5953{
5954 ARMCPU *cpu = arm_env_get_cpu(env);
5955
5956 if (mode != ARM_CPU_MODE_USR) {
5957 cpu_abort(CPU(cpu), "Tried to switch out of user mode\n");
5958 }
5959}
5960
5961uint32_t arm_phys_excp_target_el(CPUState *cs, uint32_t excp_idx,
5962 uint32_t cur_el, bool secure)
5963{
5964 return 1;
5965}
5966
5967void aarch64_sync_64_to_32(CPUARMState *env)
5968{
5969 g_assert_not_reached();
5970}
5971
5972#else
5973
5974void switch_mode(CPUARMState *env, int mode)
5975{
5976 int old_mode;
5977 int i;
5978
5979 old_mode = env->uncached_cpsr & CPSR_M;
5980 if (mode == old_mode)
5981 return;
5982
5983 if (old_mode == ARM_CPU_MODE_FIQ) {
5984 memcpy (env->fiq_regs, env->regs + 8, 5 * sizeof(uint32_t));
5985 memcpy (env->regs + 8, env->usr_regs, 5 * sizeof(uint32_t));
5986 } else if (mode == ARM_CPU_MODE_FIQ) {
5987 memcpy (env->usr_regs, env->regs + 8, 5 * sizeof(uint32_t));
5988 memcpy (env->regs + 8, env->fiq_regs, 5 * sizeof(uint32_t));
5989 }
5990
5991 i = bank_number(old_mode);
5992 env->banked_r13[i] = env->regs[13];
5993 env->banked_r14[i] = env->regs[14];
5994 env->banked_spsr[i] = env->spsr;
5995
5996 i = bank_number(mode);
5997 env->regs[13] = env->banked_r13[i];
5998 env->regs[14] = env->banked_r14[i];
5999 env->spsr = env->banked_spsr[i];
6000}
6001
6002
6003
6004
6005
6006
6007
6008
6009
6010
6011
6012
6013
6014
6015
6016
6017
6018
6019
6020
6021
6022
6023
6024
6025
6026
6027
6028
6029
6030
6031
6032
6033
6034
6035
6036
6037
6038
6039static const int8_t target_el_table[2][2][2][2][2][4] = {
6040 {{{{{ 1, 1, 2, -1 },{ 3, -1, -1, 3 },},
6041 {{ 2, 2, 2, -1 },{ 3, -1, -1, 3 },},},
6042 {{{ 1, 1, 2, -1 },{ 3, -1, -1, 3 },},
6043 {{ 2, 2, 2, -1 },{ 3, -1, -1, 3 },},},},
6044 {{{{ 3, 3, 3, -1 },{ 3, -1, -1, 3 },},
6045 {{ 3, 3, 3, -1 },{ 3, -1, -1, 3 },},},
6046 {{{ 3, 3, 3, -1 },{ 3, -1, -1, 3 },},
6047 {{ 3, 3, 3, -1 },{ 3, -1, -1, 3 },},},},},
6048 {{{{{ 1, 1, 2, -1 },{ 1, 1, -1, 1 },},
6049 {{ 2, 2, 2, -1 },{ 1, 1, -1, 1 },},},
6050 {{{ 1, 1, 1, -1 },{ 1, 1, -1, 1 },},
6051 {{ 2, 2, 2, -1 },{ 1, 1, -1, 1 },},},},
6052 {{{{ 3, 3, 3, -1 },{ 3, 3, -1, 3 },},
6053 {{ 3, 3, 3, -1 },{ 3, 3, -1, 3 },},},
6054 {{{ 3, 3, 3, -1 },{ 3, 3, -1, 3 },},
6055 {{ 3, 3, 3, -1 },{ 3, 3, -1, 3 },},},},},
6056};
6057
6058
6059
6060
6061uint32_t arm_phys_excp_target_el(CPUState *cs, uint32_t excp_idx,
6062 uint32_t cur_el, bool secure)
6063{
6064 CPUARMState *env = cs->env_ptr;
6065 int rw;
6066 int scr;
6067 int hcr;
6068 int target_el;
6069
6070 int is64 = arm_feature(env, ARM_FEATURE_AARCH64);
6071
6072 if (arm_feature(env, ARM_FEATURE_EL3)) {
6073 rw = ((env->cp15.scr_el3 & SCR_RW) == SCR_RW);
6074 } else {
6075
6076
6077
6078
6079 rw = is64;
6080 }
6081
6082 switch (excp_idx) {
6083 case EXCP_IRQ:
6084 scr = ((env->cp15.scr_el3 & SCR_IRQ) == SCR_IRQ);
6085 hcr = ((env->cp15.hcr_el2 & HCR_IMO) == HCR_IMO);
6086 break;
6087 case EXCP_FIQ:
6088 scr = ((env->cp15.scr_el3 & SCR_FIQ) == SCR_FIQ);
6089 hcr = ((env->cp15.hcr_el2 & HCR_FMO) == HCR_FMO);
6090 break;
6091 default:
6092 scr = ((env->cp15.scr_el3 & SCR_EA) == SCR_EA);
6093 hcr = ((env->cp15.hcr_el2 & HCR_AMO) == HCR_AMO);
6094 break;
6095 };
6096
6097
6098 hcr |= ((env->cp15.hcr_el2 & HCR_TGE) == HCR_TGE);
6099
6100
6101 target_el = target_el_table[is64][scr][rw][hcr][secure][cur_el];
6102
6103 assert(target_el > 0);
6104
6105 return target_el;
6106}
6107
6108static void v7m_push(CPUARMState *env, uint32_t val)
6109{
6110 CPUState *cs = CPU(arm_env_get_cpu(env));
6111
6112 env->regs[13] -= 4;
6113 stl_phys(cs->as, env->regs[13], val);
6114}
6115
6116static uint32_t v7m_pop(CPUARMState *env)
6117{
6118 CPUState *cs = CPU(arm_env_get_cpu(env));
6119 uint32_t val;
6120
6121 val = ldl_phys(cs->as, env->regs[13]);
6122 env->regs[13] += 4;
6123 return val;
6124}
6125
6126
6127static void switch_v7m_sp(CPUARMState *env, int process)
6128{
6129 uint32_t tmp;
6130 if (env->v7m.current_sp != process) {
6131 tmp = env->v7m.other_sp;
6132 env->v7m.other_sp = env->regs[13];
6133 env->regs[13] = tmp;
6134 env->v7m.current_sp = process;
6135 }
6136}
6137
6138static void do_v7m_exception_exit(CPUARMState *env)
6139{
6140 uint32_t type;
6141 uint32_t xpsr;
6142
6143 type = env->regs[15];
6144 if (env->v7m.exception != 0)
6145 armv7m_nvic_complete_irq(env->nvic, env->v7m.exception);
6146
6147
6148 switch_v7m_sp(env, (type & 4) != 0);
6149
6150 env->regs[0] = v7m_pop(env);
6151 env->regs[1] = v7m_pop(env);
6152 env->regs[2] = v7m_pop(env);
6153 env->regs[3] = v7m_pop(env);
6154 env->regs[12] = v7m_pop(env);
6155 env->regs[14] = v7m_pop(env);
6156 env->regs[15] = v7m_pop(env);
6157 if (env->regs[15] & 1) {
6158 qemu_log_mask(LOG_GUEST_ERROR,
6159 "M profile return from interrupt with misaligned "
6160 "PC is UNPREDICTABLE\n");
6161
6162
6163
6164
6165 env->regs[15] &= ~1U;
6166 }
6167 xpsr = v7m_pop(env);
6168 xpsr_write(env, xpsr, 0xfffffdff);
6169
6170 if (xpsr & 0x200)
6171 env->regs[13] |= 4;
6172
6173
6174
6175
6176
6177}
6178
6179static void arm_log_exception(int idx)
6180{
6181 if (qemu_loglevel_mask(CPU_LOG_INT)) {
6182 const char *exc = NULL;
6183
6184 if (idx >= 0 && idx < ARRAY_SIZE(excnames)) {
6185 exc = excnames[idx];
6186 }
6187 if (!exc) {
6188 exc = "unknown";
6189 }
6190 qemu_log_mask(CPU_LOG_INT, "Taking exception %d [%s]\n", idx, exc);
6191 }
6192}
6193
6194void arm_v7m_cpu_do_interrupt(CPUState *cs)
6195{
6196 ARMCPU *cpu = ARM_CPU(cs);
6197 CPUARMState *env = &cpu->env;
6198 uint32_t xpsr = xpsr_read(env);
6199 uint32_t lr;
6200 uint32_t addr;
6201
6202 arm_log_exception(cs->exception_index);
6203
6204 lr = 0xfffffff1;
6205 if (env->v7m.current_sp)
6206 lr |= 4;
6207 if (env->v7m.exception == 0)
6208 lr |= 8;
6209
6210
6211
6212
6213
6214 switch (cs->exception_index) {
6215 case EXCP_UDEF:
6216 armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE);
6217 return;
6218 case EXCP_SWI:
6219
6220 armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_SVC);
6221 return;
6222 case EXCP_PREFETCH_ABORT:
6223 case EXCP_DATA_ABORT:
6224
6225
6226
6227 armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_MEM);
6228 return;
6229 case EXCP_BKPT:
6230 if (semihosting_enabled()) {
6231 int nr;
6232 nr = arm_lduw_code(env, env->regs[15], arm_sctlr_b(env)) & 0xff;
6233 if (nr == 0xab) {
6234 env->regs[15] += 2;
6235 qemu_log_mask(CPU_LOG_INT,
6236 "...handling as semihosting call 0x%x\n",
6237 env->regs[0]);
6238 env->regs[0] = do_arm_semihosting(env);
6239 return;
6240 }
6241 }
6242 armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_DEBUG);
6243 return;
6244 case EXCP_IRQ:
6245 env->v7m.exception = armv7m_nvic_acknowledge_irq(env->nvic);
6246 break;
6247 case EXCP_EXCEPTION_EXIT:
6248 do_v7m_exception_exit(env);
6249 return;
6250 default:
6251 cpu_abort(cs, "Unhandled exception 0x%x\n", cs->exception_index);
6252 return;
6253 }
6254
6255
6256
6257
6258 if (env->regs[13] & 4) {
6259 env->regs[13] -= 4;
6260 xpsr |= 0x200;
6261 }
6262
6263 v7m_push(env, xpsr);
6264 v7m_push(env, env->regs[15]);
6265 v7m_push(env, env->regs[14]);
6266 v7m_push(env, env->regs[12]);
6267 v7m_push(env, env->regs[3]);
6268 v7m_push(env, env->regs[2]);
6269 v7m_push(env, env->regs[1]);
6270 v7m_push(env, env->regs[0]);
6271 switch_v7m_sp(env, 0);
6272
6273 env->condexec_bits = 0;
6274 env->regs[14] = lr;
6275 addr = ldl_phys(cs->as, env->v7m.vecbase + env->v7m.exception * 4);
6276 env->regs[15] = addr & 0xfffffffe;
6277 env->thumb = addr & 1;
6278}
6279
6280
6281
6282
6283
6284void aarch64_sync_32_to_64(CPUARMState *env)
6285{
6286 int i;
6287 uint32_t mode = env->uncached_cpsr & CPSR_M;
6288
6289
6290 for (i = 0; i < 8; i++) {
6291 env->xregs[i] = env->regs[i];
6292 }
6293
6294
6295
6296
6297 if (mode == ARM_CPU_MODE_FIQ) {
6298 for (i = 8; i < 13; i++) {
6299 env->xregs[i] = env->usr_regs[i - 8];
6300 }
6301 } else {
6302 for (i = 8; i < 13; i++) {
6303 env->xregs[i] = env->regs[i];
6304 }
6305 }
6306
6307
6308
6309
6310
6311 if (mode == ARM_CPU_MODE_USR || mode == ARM_CPU_MODE_SYS) {
6312 env->xregs[13] = env->regs[13];
6313 env->xregs[14] = env->regs[14];
6314 } else {
6315 env->xregs[13] = env->banked_r13[bank_number(ARM_CPU_MODE_USR)];
6316
6317 if (mode == ARM_CPU_MODE_HYP) {
6318 env->xregs[14] = env->regs[14];
6319 } else {
6320 env->xregs[14] = env->banked_r14[bank_number(ARM_CPU_MODE_USR)];
6321 }
6322 }
6323
6324 if (mode == ARM_CPU_MODE_HYP) {
6325 env->xregs[15] = env->regs[13];
6326 } else {
6327 env->xregs[15] = env->banked_r13[bank_number(ARM_CPU_MODE_HYP)];
6328 }
6329
6330 if (mode == ARM_CPU_MODE_IRQ) {
6331 env->xregs[16] = env->regs[14];
6332 env->xregs[17] = env->regs[13];
6333 } else {
6334 env->xregs[16] = env->banked_r14[bank_number(ARM_CPU_MODE_IRQ)];
6335 env->xregs[17] = env->banked_r13[bank_number(ARM_CPU_MODE_IRQ)];
6336 }
6337
6338 if (mode == ARM_CPU_MODE_SVC) {
6339 env->xregs[18] = env->regs[14];
6340 env->xregs[19] = env->regs[13];
6341 } else {
6342 env->xregs[18] = env->banked_r14[bank_number(ARM_CPU_MODE_SVC)];
6343 env->xregs[19] = env->banked_r13[bank_number(ARM_CPU_MODE_SVC)];
6344 }
6345
6346 if (mode == ARM_CPU_MODE_ABT) {
6347 env->xregs[20] = env->regs[14];
6348 env->xregs[21] = env->regs[13];
6349 } else {
6350 env->xregs[20] = env->banked_r14[bank_number(ARM_CPU_MODE_ABT)];
6351 env->xregs[21] = env->banked_r13[bank_number(ARM_CPU_MODE_ABT)];
6352 }
6353
6354 if (mode == ARM_CPU_MODE_UND) {
6355 env->xregs[22] = env->regs[14];
6356 env->xregs[23] = env->regs[13];
6357 } else {
6358 env->xregs[22] = env->banked_r14[bank_number(ARM_CPU_MODE_UND)];
6359 env->xregs[23] = env->banked_r13[bank_number(ARM_CPU_MODE_UND)];
6360 }
6361
6362
6363
6364
6365
6366 if (mode == ARM_CPU_MODE_FIQ) {
6367 for (i = 24; i < 31; i++) {
6368 env->xregs[i] = env->regs[i - 16];
6369 }
6370 } else {
6371 for (i = 24; i < 29; i++) {
6372 env->xregs[i] = env->fiq_regs[i - 24];
6373 }
6374 env->xregs[29] = env->banked_r13[bank_number(ARM_CPU_MODE_FIQ)];
6375 env->xregs[30] = env->banked_r14[bank_number(ARM_CPU_MODE_FIQ)];
6376 }
6377
6378 env->pc = env->regs[15];
6379}
6380
6381
6382
6383
6384
6385void aarch64_sync_64_to_32(CPUARMState *env)
6386{
6387 int i;
6388 uint32_t mode = env->uncached_cpsr & CPSR_M;
6389
6390
6391 for (i = 0; i < 8; i++) {
6392 env->regs[i] = env->xregs[i];
6393 }
6394
6395
6396
6397
6398 if (mode == ARM_CPU_MODE_FIQ) {
6399 for (i = 8; i < 13; i++) {
6400 env->usr_regs[i - 8] = env->xregs[i];
6401 }
6402 } else {
6403 for (i = 8; i < 13; i++) {
6404 env->regs[i] = env->xregs[i];
6405 }
6406 }
6407
6408
6409
6410
6411
6412
6413 if (mode == ARM_CPU_MODE_USR || mode == ARM_CPU_MODE_SYS) {
6414 env->regs[13] = env->xregs[13];
6415 env->regs[14] = env->xregs[14];
6416 } else {
6417 env->banked_r13[bank_number(ARM_CPU_MODE_USR)] = env->xregs[13];
6418
6419
6420
6421
6422 if (mode == ARM_CPU_MODE_HYP) {
6423 env->regs[14] = env->xregs[14];
6424 } else {
6425 env->banked_r14[bank_number(ARM_CPU_MODE_USR)] = env->xregs[14];
6426 }
6427 }
6428
6429 if (mode == ARM_CPU_MODE_HYP) {
6430 env->regs[13] = env->xregs[15];
6431 } else {
6432 env->banked_r13[bank_number(ARM_CPU_MODE_HYP)] = env->xregs[15];
6433 }
6434
6435 if (mode == ARM_CPU_MODE_IRQ) {
6436 env->regs[14] = env->xregs[16];
6437 env->regs[13] = env->xregs[17];
6438 } else {
6439 env->banked_r14[bank_number(ARM_CPU_MODE_IRQ)] = env->xregs[16];
6440 env->banked_r13[bank_number(ARM_CPU_MODE_IRQ)] = env->xregs[17];
6441 }
6442
6443 if (mode == ARM_CPU_MODE_SVC) {
6444 env->regs[14] = env->xregs[18];
6445 env->regs[13] = env->xregs[19];
6446 } else {
6447 env->banked_r14[bank_number(ARM_CPU_MODE_SVC)] = env->xregs[18];
6448 env->banked_r13[bank_number(ARM_CPU_MODE_SVC)] = env->xregs[19];
6449 }
6450
6451 if (mode == ARM_CPU_MODE_ABT) {
6452 env->regs[14] = env->xregs[20];
6453 env->regs[13] = env->xregs[21];
6454 } else {
6455 env->banked_r14[bank_number(ARM_CPU_MODE_ABT)] = env->xregs[20];
6456 env->banked_r13[bank_number(ARM_CPU_MODE_ABT)] = env->xregs[21];
6457 }
6458
6459 if (mode == ARM_CPU_MODE_UND) {
6460 env->regs[14] = env->xregs[22];
6461 env->regs[13] = env->xregs[23];
6462 } else {
6463 env->banked_r14[bank_number(ARM_CPU_MODE_UND)] = env->xregs[22];
6464 env->banked_r13[bank_number(ARM_CPU_MODE_UND)] = env->xregs[23];
6465 }
6466
6467
6468
6469
6470
6471 if (mode == ARM_CPU_MODE_FIQ) {
6472 for (i = 24; i < 31; i++) {
6473 env->regs[i - 16] = env->xregs[i];
6474 }
6475 } else {
6476 for (i = 24; i < 29; i++) {
6477 env->fiq_regs[i - 24] = env->xregs[i];
6478 }
6479 env->banked_r13[bank_number(ARM_CPU_MODE_FIQ)] = env->xregs[29];
6480 env->banked_r14[bank_number(ARM_CPU_MODE_FIQ)] = env->xregs[30];
6481 }
6482
6483 env->regs[15] = env->pc;
6484}
6485
6486static void arm_cpu_do_interrupt_aarch32(CPUState *cs)
6487{
6488 ARMCPU *cpu = ARM_CPU(cs);
6489 CPUARMState *env = &cpu->env;
6490 uint32_t addr;
6491 uint32_t mask;
6492 int new_mode;
6493 uint32_t offset;
6494 uint32_t moe;
6495
6496
6497 switch (env->exception.syndrome >> ARM_EL_EC_SHIFT) {
6498 case EC_BREAKPOINT:
6499 case EC_BREAKPOINT_SAME_EL:
6500 moe = 1;
6501 break;
6502 case EC_WATCHPOINT:
6503 case EC_WATCHPOINT_SAME_EL:
6504 moe = 10;
6505 break;
6506 case EC_AA32_BKPT:
6507 moe = 3;
6508 break;
6509 case EC_VECTORCATCH:
6510 moe = 5;
6511 break;
6512 default:
6513 moe = 0;
6514 break;
6515 }
6516
6517 if (moe) {
6518 env->cp15.mdscr_el1 = deposit64(env->cp15.mdscr_el1, 2, 4, moe);
6519 }
6520
6521
6522 switch (cs->exception_index) {
6523 case EXCP_UDEF:
6524 new_mode = ARM_CPU_MODE_UND;
6525 addr = 0x04;
6526 mask = CPSR_I;
6527 if (env->thumb)
6528 offset = 2;
6529 else
6530 offset = 4;
6531 break;
6532 case EXCP_SWI:
6533 new_mode = ARM_CPU_MODE_SVC;
6534 addr = 0x08;
6535 mask = CPSR_I;
6536
6537 offset = 0;
6538 break;
6539 case EXCP_BKPT:
6540 env->exception.fsr = 2;
6541
6542 case EXCP_PREFETCH_ABORT:
6543 A32_BANKED_CURRENT_REG_SET(env, ifsr, env->exception.fsr);
6544 A32_BANKED_CURRENT_REG_SET(env, ifar, env->exception.vaddress);
6545 qemu_log_mask(CPU_LOG_INT, "...with IFSR 0x%x IFAR 0x%x\n",
6546 env->exception.fsr, (uint32_t)env->exception.vaddress);
6547 new_mode = ARM_CPU_MODE_ABT;
6548 addr = 0x0c;
6549 mask = CPSR_A | CPSR_I;
6550 offset = 4;
6551 break;
6552 case EXCP_DATA_ABORT:
6553 A32_BANKED_CURRENT_REG_SET(env, dfsr, env->exception.fsr);
6554 A32_BANKED_CURRENT_REG_SET(env, dfar, env->exception.vaddress);
6555 qemu_log_mask(CPU_LOG_INT, "...with DFSR 0x%x DFAR 0x%x\n",
6556 env->exception.fsr,
6557 (uint32_t)env->exception.vaddress);
6558 new_mode = ARM_CPU_MODE_ABT;
6559 addr = 0x10;
6560 mask = CPSR_A | CPSR_I;
6561 offset = 8;
6562 break;
6563 case EXCP_IRQ:
6564 new_mode = ARM_CPU_MODE_IRQ;
6565 addr = 0x18;
6566
6567 mask = CPSR_A | CPSR_I;
6568 offset = 4;
6569 if (env->cp15.scr_el3 & SCR_IRQ) {
6570
6571 new_mode = ARM_CPU_MODE_MON;
6572 mask |= CPSR_F;
6573 }
6574 break;
6575 case EXCP_FIQ:
6576 new_mode = ARM_CPU_MODE_FIQ;
6577 addr = 0x1c;
6578
6579 mask = CPSR_A | CPSR_I | CPSR_F;
6580 if (env->cp15.scr_el3 & SCR_FIQ) {
6581
6582 new_mode = ARM_CPU_MODE_MON;
6583 }
6584 offset = 4;
6585 break;
6586 case EXCP_SMC:
6587 new_mode = ARM_CPU_MODE_MON;
6588 addr = 0x08;
6589 mask = CPSR_A | CPSR_I | CPSR_F;
6590 offset = 0;
6591 break;
6592 default:
6593 cpu_abort(cs, "Unhandled exception 0x%x\n", cs->exception_index);
6594 return;
6595 }
6596
6597 if (new_mode == ARM_CPU_MODE_MON) {
6598 addr += env->cp15.mvbar;
6599 } else if (A32_BANKED_CURRENT_REG_GET(env, sctlr) & SCTLR_V) {
6600
6601 addr += 0xffff0000;
6602 } else {
6603
6604
6605
6606
6607
6608 addr += A32_BANKED_CURRENT_REG_GET(env, vbar);
6609 }
6610
6611 if ((env->uncached_cpsr & CPSR_M) == ARM_CPU_MODE_MON) {
6612 env->cp15.scr_el3 &= ~SCR_NS;
6613 }
6614
6615 switch_mode (env, new_mode);
6616
6617
6618
6619 env->uncached_cpsr &= ~PSTATE_SS;
6620 env->spsr = cpsr_read(env);
6621
6622 env->condexec_bits = 0;
6623
6624 env->uncached_cpsr = (env->uncached_cpsr & ~CPSR_M) | new_mode;
6625
6626 env->uncached_cpsr &= ~CPSR_E;
6627 if (env->cp15.sctlr_el[arm_current_el(env)] & SCTLR_EE) {
6628 env->uncached_cpsr |= CPSR_E;
6629 }
6630 env->daif |= mask;
6631
6632
6633 if (arm_feature(env, ARM_FEATURE_V4T)) {
6634 env->thumb = (A32_BANKED_CURRENT_REG_GET(env, sctlr) & SCTLR_TE) != 0;
6635 }
6636 env->regs[14] = env->regs[15] + offset;
6637 env->regs[15] = addr;
6638}
6639
6640
6641static void arm_cpu_do_interrupt_aarch64(CPUState *cs)
6642{
6643 ARMCPU *cpu = ARM_CPU(cs);
6644 CPUARMState *env = &cpu->env;
6645 unsigned int new_el = env->exception.target_el;
6646 target_ulong addr = env->cp15.vbar_el[new_el];
6647 unsigned int new_mode = aarch64_pstate_mode(new_el, true);
6648
6649 if (arm_current_el(env) < new_el) {
6650
6651
6652
6653 bool is_aa64;
6654
6655 switch (new_el) {
6656 case 3:
6657 is_aa64 = (env->cp15.scr_el3 & SCR_RW) != 0;
6658 break;
6659 case 2:
6660 is_aa64 = (env->cp15.hcr_el2 & HCR_RW) != 0;
6661 break;
6662 case 1:
6663 is_aa64 = is_a64(env);
6664 break;
6665 default:
6666 g_assert_not_reached();
6667 }
6668
6669 if (is_aa64) {
6670 addr += 0x400;
6671 } else {
6672 addr += 0x600;
6673 }
6674 } else if (pstate_read(env) & PSTATE_SP) {
6675 addr += 0x200;
6676 }
6677
6678 switch (cs->exception_index) {
6679 case EXCP_PREFETCH_ABORT:
6680 case EXCP_DATA_ABORT:
6681 env->cp15.far_el[new_el] = env->exception.vaddress;
6682 qemu_log_mask(CPU_LOG_INT, "...with FAR 0x%" PRIx64 "\n",
6683 env->cp15.far_el[new_el]);
6684
6685 case EXCP_BKPT:
6686 case EXCP_UDEF:
6687 case EXCP_SWI:
6688 case EXCP_HVC:
6689 case EXCP_HYP_TRAP:
6690 case EXCP_SMC:
6691 env->cp15.esr_el[new_el] = env->exception.syndrome;
6692 break;
6693 case EXCP_IRQ:
6694 case EXCP_VIRQ:
6695 addr += 0x80;
6696 break;
6697 case EXCP_FIQ:
6698 case EXCP_VFIQ:
6699 addr += 0x100;
6700 break;
6701 case EXCP_SEMIHOST:
6702 qemu_log_mask(CPU_LOG_INT,
6703 "...handling as semihosting call 0x%" PRIx64 "\n",
6704 env->xregs[0]);
6705 env->xregs[0] = do_arm_semihosting(env);
6706 return;
6707 default:
6708 cpu_abort(cs, "Unhandled exception 0x%x\n", cs->exception_index);
6709 }
6710
6711 if (is_a64(env)) {
6712 env->banked_spsr[aarch64_banked_spsr_index(new_el)] = pstate_read(env);
6713 aarch64_save_sp(env, arm_current_el(env));
6714 env->elr_el[new_el] = env->pc;
6715 } else {
6716 env->banked_spsr[aarch64_banked_spsr_index(new_el)] = cpsr_read(env);
6717 env->elr_el[new_el] = env->regs[15];
6718
6719 aarch64_sync_32_to_64(env);
6720
6721 env->condexec_bits = 0;
6722 }
6723 qemu_log_mask(CPU_LOG_INT, "...with ELR 0x%" PRIx64 "\n",
6724 env->elr_el[new_el]);
6725
6726 pstate_write(env, PSTATE_DAIF | new_mode);
6727 env->aarch64 = 1;
6728 aarch64_restore_sp(env, new_el);
6729
6730 env->pc = addr;
6731
6732 qemu_log_mask(CPU_LOG_INT, "...to EL%d PC 0x%" PRIx64 " PSTATE 0x%x\n",
6733 new_el, env->pc, pstate_read(env));
6734}
6735
6736static inline bool check_for_semihosting(CPUState *cs)
6737{
6738
6739
6740
6741 ARMCPU *cpu = ARM_CPU(cs);
6742 CPUARMState *env = &cpu->env;
6743
6744 if (is_a64(env)) {
6745 if (cs->exception_index == EXCP_SEMIHOST) {
6746
6747
6748
6749
6750 qemu_log_mask(CPU_LOG_INT,
6751 "...handling as semihosting call 0x%" PRIx64 "\n",
6752 env->xregs[0]);
6753 env->xregs[0] = do_arm_semihosting(env);
6754 return true;
6755 }
6756 return false;
6757 } else {
6758 uint32_t imm;
6759
6760
6761
6762
6763 if (cs->exception_index != EXCP_SEMIHOST &&
6764 (!semihosting_enabled() ||
6765 ((env->uncached_cpsr & CPSR_M) == ARM_CPU_MODE_USR))) {
6766 return false;
6767 }
6768
6769 switch (cs->exception_index) {
6770 case EXCP_SEMIHOST:
6771
6772
6773
6774
6775 break;
6776 case EXCP_SWI:
6777
6778 if (env->thumb) {
6779 imm = arm_lduw_code(env, env->regs[15] - 2, arm_sctlr_b(env))
6780 & 0xff;
6781 if (imm == 0xab) {
6782 break;
6783 }
6784 } else {
6785 imm = arm_ldl_code(env, env->regs[15] - 4, arm_sctlr_b(env))
6786 & 0xffffff;
6787 if (imm == 0x123456) {
6788 break;
6789 }
6790 }
6791 return false;
6792 case EXCP_BKPT:
6793
6794 if (env->thumb) {
6795 imm = arm_lduw_code(env, env->regs[15], arm_sctlr_b(env))
6796 & 0xff;
6797 if (imm == 0xab) {
6798 env->regs[15] += 2;
6799 break;
6800 }
6801 }
6802 return false;
6803 default:
6804 return false;
6805 }
6806
6807 qemu_log_mask(CPU_LOG_INT,
6808 "...handling as semihosting call 0x%x\n",
6809 env->regs[0]);
6810 env->regs[0] = do_arm_semihosting(env);
6811 return true;
6812 }
6813}
6814
6815
6816
6817
6818
6819
6820void arm_cpu_do_interrupt(CPUState *cs)
6821{
6822 ARMCPU *cpu = ARM_CPU(cs);
6823 CPUARMState *env = &cpu->env;
6824 unsigned int new_el = env->exception.target_el;
6825
6826 assert(!IS_M(env));
6827
6828 arm_log_exception(cs->exception_index);
6829 qemu_log_mask(CPU_LOG_INT, "...from EL%d to EL%d\n", arm_current_el(env),
6830 new_el);
6831 if (qemu_loglevel_mask(CPU_LOG_INT)
6832 && !excp_is_internal(cs->exception_index)) {
6833 qemu_log_mask(CPU_LOG_INT, "...with ESR %x/0x%" PRIx32 "\n",
6834 env->exception.syndrome >> ARM_EL_EC_SHIFT,
6835 env->exception.syndrome);
6836 }
6837
6838 if (arm_is_psci_call(cpu, cs->exception_index)) {
6839 arm_handle_psci_call(cpu);
6840 qemu_log_mask(CPU_LOG_INT, "...handled as PSCI call\n");
6841 return;
6842 }
6843
6844
6845
6846
6847
6848 if (check_for_semihosting(cs)) {
6849 return;
6850 }
6851
6852 assert(!excp_is_internal(cs->exception_index));
6853 if (arm_el_is_aa64(env, new_el)) {
6854 arm_cpu_do_interrupt_aarch64(cs);
6855 } else {
6856 arm_cpu_do_interrupt_aarch32(cs);
6857 }
6858
6859 arm_call_el_change_hook(cpu);
6860
6861 if (!kvm_enabled()) {
6862 cs->interrupt_request |= CPU_INTERRUPT_EXITTB;
6863 }
6864}
6865
6866
6867static inline bool regime_is_secure(CPUARMState *env, ARMMMUIdx mmu_idx)
6868{
6869 switch (mmu_idx) {
6870 case ARMMMUIdx_S12NSE0:
6871 case ARMMMUIdx_S12NSE1:
6872 case ARMMMUIdx_S1NSE0:
6873 case ARMMMUIdx_S1NSE1:
6874 case ARMMMUIdx_S1E2:
6875 case ARMMMUIdx_S2NS:
6876 return false;
6877 case ARMMMUIdx_S1E3:
6878 case ARMMMUIdx_S1SE0:
6879 case ARMMMUIdx_S1SE1:
6880 return true;
6881 default:
6882 g_assert_not_reached();
6883 }
6884}
6885
6886
6887static inline uint32_t regime_sctlr(CPUARMState *env, ARMMMUIdx mmu_idx)
6888{
6889 return env->cp15.sctlr_el[regime_el(env, mmu_idx)];
6890}
6891
6892
6893static inline bool regime_translation_disabled(CPUARMState *env,
6894 ARMMMUIdx mmu_idx)
6895{
6896 if (mmu_idx == ARMMMUIdx_S2NS) {
6897 return (env->cp15.hcr_el2 & HCR_VM) == 0;
6898 }
6899 return (regime_sctlr(env, mmu_idx) & SCTLR_M) == 0;
6900}
6901
6902static inline bool regime_translation_big_endian(CPUARMState *env,
6903 ARMMMUIdx mmu_idx)
6904{
6905 return (regime_sctlr(env, mmu_idx) & SCTLR_EE) != 0;
6906}
6907
6908
6909uint32_t arm_regime_tbi0(CPUARMState *env, ARMMMUIdx mmu_idx)
6910{
6911 TCR *tcr;
6912 uint32_t el;
6913
6914
6915
6916
6917 if (mmu_idx == ARMMMUIdx_S12NSE0 || mmu_idx == ARMMMUIdx_S12NSE1) {
6918 mmu_idx += ARMMMUIdx_S1NSE0;
6919 }
6920
6921 tcr = regime_tcr(env, mmu_idx);
6922 el = regime_el(env, mmu_idx);
6923
6924 if (el > 1) {
6925 return extract64(tcr->raw_tcr, 20, 1);
6926 } else {
6927 return extract64(tcr->raw_tcr, 37, 1);
6928 }
6929}
6930
6931
6932uint32_t arm_regime_tbi1(CPUARMState *env, ARMMMUIdx mmu_idx)
6933{
6934 TCR *tcr;
6935 uint32_t el;
6936
6937
6938
6939
6940 if (mmu_idx == ARMMMUIdx_S12NSE0 || mmu_idx == ARMMMUIdx_S12NSE1) {
6941 mmu_idx += ARMMMUIdx_S1NSE0;
6942 }
6943
6944 tcr = regime_tcr(env, mmu_idx);
6945 el = regime_el(env, mmu_idx);
6946
6947 if (el > 1) {
6948 return 0;
6949 } else {
6950 return extract64(tcr->raw_tcr, 38, 1);
6951 }
6952}
6953
6954
6955static inline uint64_t regime_ttbr(CPUARMState *env, ARMMMUIdx mmu_idx,
6956 int ttbrn)
6957{
6958 if (mmu_idx == ARMMMUIdx_S2NS) {
6959 return env->cp15.vttbr_el2;
6960 }
6961 if (ttbrn == 0) {
6962 return env->cp15.ttbr0_el[regime_el(env, mmu_idx)];
6963 } else {
6964 return env->cp15.ttbr1_el[regime_el(env, mmu_idx)];
6965 }
6966}
6967
6968
6969static inline bool regime_using_lpae_format(CPUARMState *env,
6970 ARMMMUIdx mmu_idx)
6971{
6972 int el = regime_el(env, mmu_idx);
6973 if (el == 2 || arm_el_is_aa64(env, el)) {
6974 return true;
6975 }
6976 if (arm_feature(env, ARM_FEATURE_LPAE)
6977 && (regime_tcr(env, mmu_idx)->raw_tcr & TTBCR_EAE)) {
6978 return true;
6979 }
6980 return false;
6981}
6982
6983
6984
6985
6986bool arm_s1_regime_using_lpae_format(CPUARMState *env, ARMMMUIdx mmu_idx)
6987{
6988 if (mmu_idx == ARMMMUIdx_S12NSE0 || mmu_idx == ARMMMUIdx_S12NSE1) {
6989 mmu_idx += ARMMMUIdx_S1NSE0;
6990 }
6991
6992 return regime_using_lpae_format(env, mmu_idx);
6993}
6994
6995static inline bool regime_is_user(CPUARMState *env, ARMMMUIdx mmu_idx)
6996{
6997 switch (mmu_idx) {
6998 case ARMMMUIdx_S1SE0:
6999 case ARMMMUIdx_S1NSE0:
7000 return true;
7001 default:
7002 return false;
7003 case ARMMMUIdx_S12NSE0:
7004 case ARMMMUIdx_S12NSE1:
7005 g_assert_not_reached();
7006 }
7007}
7008
7009
7010
7011
7012
7013
7014
7015
7016
7017static inline int ap_to_rw_prot(CPUARMState *env, ARMMMUIdx mmu_idx,
7018 int ap, int domain_prot)
7019{
7020 bool is_user = regime_is_user(env, mmu_idx);
7021
7022 if (domain_prot == 3) {
7023 return PAGE_READ | PAGE_WRITE;
7024 }
7025
7026 switch (ap) {
7027 case 0:
7028 if (arm_feature(env, ARM_FEATURE_V7)) {
7029 return 0;
7030 }
7031 switch (regime_sctlr(env, mmu_idx) & (SCTLR_S | SCTLR_R)) {
7032 case SCTLR_S:
7033 return is_user ? 0 : PAGE_READ;
7034 case SCTLR_R:
7035 return PAGE_READ;
7036 default:
7037 return 0;
7038 }
7039 case 1:
7040 return is_user ? 0 : PAGE_READ | PAGE_WRITE;
7041 case 2:
7042 if (is_user) {
7043 return PAGE_READ;
7044 } else {
7045 return PAGE_READ | PAGE_WRITE;
7046 }
7047 case 3:
7048 return PAGE_READ | PAGE_WRITE;
7049 case 4:
7050 return 0;
7051 case 5:
7052 return is_user ? 0 : PAGE_READ;
7053 case 6:
7054 return PAGE_READ;
7055 case 7:
7056 if (!arm_feature(env, ARM_FEATURE_V6K)) {
7057 return 0;
7058 }
7059 return PAGE_READ;
7060 default:
7061 g_assert_not_reached();
7062 }
7063}
7064
7065
7066
7067
7068
7069
7070
7071static inline int simple_ap_to_rw_prot_is_user(int ap, bool is_user)
7072{
7073 switch (ap) {
7074 case 0:
7075 return is_user ? 0 : PAGE_READ | PAGE_WRITE;
7076 case 1:
7077 return PAGE_READ | PAGE_WRITE;
7078 case 2:
7079 return is_user ? 0 : PAGE_READ;
7080 case 3:
7081 return PAGE_READ;
7082 default:
7083 g_assert_not_reached();
7084 }
7085}
7086
7087static inline int
7088simple_ap_to_rw_prot(CPUARMState *env, ARMMMUIdx mmu_idx, int ap)
7089{
7090 return simple_ap_to_rw_prot_is_user(ap, regime_is_user(env, mmu_idx));
7091}
7092
7093
7094
7095
7096
7097
7098
7099static int get_S2prot(CPUARMState *env, int s2ap, int xn)
7100{
7101 int prot = 0;
7102
7103 if (s2ap & 1) {
7104 prot |= PAGE_READ;
7105 }
7106 if (s2ap & 2) {
7107 prot |= PAGE_WRITE;
7108 }
7109 if (!xn) {
7110 if (arm_el_is_aa64(env, 2) || prot & PAGE_READ) {
7111 prot |= PAGE_EXEC;
7112 }
7113 }
7114 return prot;
7115}
7116
7117
7118
7119
7120
7121
7122
7123
7124
7125
7126
7127static int get_S1prot(CPUARMState *env, ARMMMUIdx mmu_idx, bool is_aa64,
7128 int ap, int ns, int xn, int pxn)
7129{
7130 bool is_user = regime_is_user(env, mmu_idx);
7131 int prot_rw, user_rw;
7132 bool have_wxn;
7133 int wxn = 0;
7134
7135 assert(mmu_idx != ARMMMUIdx_S2NS);
7136
7137 user_rw = simple_ap_to_rw_prot_is_user(ap, true);
7138 if (is_user) {
7139 prot_rw = user_rw;
7140 } else {
7141 prot_rw = simple_ap_to_rw_prot_is_user(ap, false);
7142 }
7143
7144 if (ns && arm_is_secure(env) && (env->cp15.scr_el3 & SCR_SIF)) {
7145 return prot_rw;
7146 }
7147
7148
7149
7150
7151
7152
7153 have_wxn = arm_feature(env, ARM_FEATURE_LPAE);
7154
7155 if (have_wxn) {
7156 wxn = regime_sctlr(env, mmu_idx) & SCTLR_WXN;
7157 }
7158
7159 if (is_aa64) {
7160 switch (regime_el(env, mmu_idx)) {
7161 case 1:
7162 if (!is_user) {
7163 xn = pxn || (user_rw & PAGE_WRITE);
7164 }
7165 break;
7166 case 2:
7167 case 3:
7168 break;
7169 }
7170 } else if (arm_feature(env, ARM_FEATURE_V7)) {
7171 switch (regime_el(env, mmu_idx)) {
7172 case 1:
7173 case 3:
7174 if (is_user) {
7175 xn = xn || !(user_rw & PAGE_READ);
7176 } else {
7177 int uwxn = 0;
7178 if (have_wxn) {
7179 uwxn = regime_sctlr(env, mmu_idx) & SCTLR_UWXN;
7180 }
7181 xn = xn || !(prot_rw & PAGE_READ) || pxn ||
7182 (uwxn && (user_rw & PAGE_WRITE));
7183 }
7184 break;
7185 case 2:
7186 break;
7187 }
7188 } else {
7189 xn = wxn = 0;
7190 }
7191
7192 if (xn || (wxn && (prot_rw & PAGE_WRITE))) {
7193 return prot_rw;
7194 }
7195 return prot_rw | PAGE_EXEC;
7196}
7197
7198static bool get_level1_table_address(CPUARMState *env, ARMMMUIdx mmu_idx,
7199 uint32_t *table, uint32_t address)
7200{
7201
7202 TCR *tcr = regime_tcr(env, mmu_idx);
7203
7204 if (address & tcr->mask) {
7205 if (tcr->raw_tcr & TTBCR_PD1) {
7206
7207 return false;
7208 }
7209 *table = regime_ttbr(env, mmu_idx, 1) & 0xffffc000;
7210 } else {
7211 if (tcr->raw_tcr & TTBCR_PD0) {
7212
7213 return false;
7214 }
7215 *table = regime_ttbr(env, mmu_idx, 0) & tcr->base_mask;
7216 }
7217 *table |= (address >> 18) & 0x3ffc;
7218 return true;
7219}
7220
7221
7222static hwaddr S1_ptw_translate(CPUARMState *env, ARMMMUIdx mmu_idx,
7223 hwaddr addr, MemTxAttrs txattrs,
7224 uint32_t *fsr,
7225 ARMMMUFaultInfo *fi)
7226{
7227 if ((mmu_idx == ARMMMUIdx_S1NSE0 || mmu_idx == ARMMMUIdx_S1NSE1) &&
7228 !regime_translation_disabled(env, ARMMMUIdx_S2NS)) {
7229 target_ulong s2size;
7230 hwaddr s2pa;
7231 int s2prot;
7232 int ret;
7233
7234 ret = get_phys_addr_lpae(env, addr, 0, ARMMMUIdx_S2NS, &s2pa,
7235 &txattrs, &s2prot, &s2size, fsr, fi);
7236 if (ret) {
7237 fi->s2addr = addr;
7238 fi->stage2 = true;
7239 fi->s1ptw = true;
7240 return ~0;
7241 }
7242 addr = s2pa;
7243 }
7244 return addr;
7245}
7246
7247
7248
7249
7250
7251
7252
7253
7254static uint32_t arm_ldl_ptw(CPUState *cs, hwaddr addr, bool is_secure,
7255 ARMMMUIdx mmu_idx, uint32_t *fsr,
7256 ARMMMUFaultInfo *fi)
7257{
7258 ARMCPU *cpu = ARM_CPU(cs);
7259 CPUARMState *env = &cpu->env;
7260 MemTxAttrs attrs = {};
7261 AddressSpace *as;
7262
7263 attrs.secure = is_secure;
7264 as = arm_addressspace(cs, attrs);
7265 addr = S1_ptw_translate(env, mmu_idx, addr, attrs, fsr, fi);
7266 if (fi->s1ptw) {
7267 return 0;
7268 }
7269 if (regime_translation_big_endian(env, mmu_idx)) {
7270 return address_space_ldl_be(as, addr, attrs, NULL);
7271 } else {
7272 return address_space_ldl_le(as, addr, attrs, NULL);
7273 }
7274}
7275
7276static uint64_t arm_ldq_ptw(CPUState *cs, hwaddr addr, bool is_secure,
7277 ARMMMUIdx mmu_idx, uint32_t *fsr,
7278 ARMMMUFaultInfo *fi)
7279{
7280 ARMCPU *cpu = ARM_CPU(cs);
7281 CPUARMState *env = &cpu->env;
7282 MemTxAttrs attrs = {};
7283 AddressSpace *as;
7284
7285 attrs.secure = is_secure;
7286 attrs = env->memattr[attrs.secure].attrs;
7287 as = arm_addressspace(cs, attrs);
7288 addr = S1_ptw_translate(env, mmu_idx, addr, attrs, fsr, fi);
7289 if (fi->s1ptw) {
7290 return 0;
7291 }
7292 if (regime_translation_big_endian(env, mmu_idx)) {
7293 return address_space_ldq_be(as, addr, attrs, NULL);
7294 } else {
7295 return address_space_ldq_le(as, addr, attrs, NULL);
7296 }
7297}
7298
7299static bool get_phys_addr_v5(CPUARMState *env, uint32_t address,
7300 int access_type, ARMMMUIdx mmu_idx,
7301 hwaddr *phys_ptr, int *prot,
7302 target_ulong *page_size, uint32_t *fsr,
7303 ARMMMUFaultInfo *fi)
7304{
7305 CPUState *cs = CPU(arm_env_get_cpu(env));
7306 int code;
7307 uint32_t table;
7308 uint32_t desc;
7309 int type;
7310 int ap;
7311 int domain = 0;
7312 int domain_prot;
7313 hwaddr phys_addr;
7314 uint32_t dacr;
7315
7316
7317
7318 if (!get_level1_table_address(env, mmu_idx, &table, address)) {
7319
7320 code = 5;
7321 goto do_fault;
7322 }
7323 desc = arm_ldl_ptw(cs, table, regime_is_secure(env, mmu_idx),
7324 mmu_idx, fsr, fi);
7325 type = (desc & 3);
7326 domain = (desc >> 5) & 0x0f;
7327 if (regime_el(env, mmu_idx) == 1) {
7328 dacr = env->cp15.dacr_ns;
7329 } else {
7330 dacr = env->cp15.dacr_s;
7331 }
7332 domain_prot = (dacr >> (domain * 2)) & 3;
7333 if (type == 0) {
7334
7335 code = 5;
7336 goto do_fault;
7337 }
7338 if (domain_prot == 0 || domain_prot == 2) {
7339 if (type == 2)
7340 code = 9;
7341 else
7342 code = 11;
7343 goto do_fault;
7344 }
7345 if (type == 2) {
7346
7347 phys_addr = (desc & 0xfff00000) | (address & 0x000fffff);
7348 ap = (desc >> 10) & 3;
7349 code = 13;
7350 *page_size = 1024 * 1024;
7351 } else {
7352
7353 if (type == 1) {
7354
7355 table = (desc & 0xfffffc00) | ((address >> 10) & 0x3fc);
7356 } else {
7357
7358 table = (desc & 0xfffff000) | ((address >> 8) & 0xffc);
7359 }
7360 desc = arm_ldl_ptw(cs, table, regime_is_secure(env, mmu_idx),
7361 mmu_idx, fsr, fi);
7362 switch (desc & 3) {
7363 case 0:
7364 code = 7;
7365 goto do_fault;
7366 case 1:
7367 phys_addr = (desc & 0xffff0000) | (address & 0xffff);
7368 ap = (desc >> (4 + ((address >> 13) & 6))) & 3;
7369 *page_size = 0x10000;
7370 break;
7371 case 2:
7372 phys_addr = (desc & 0xfffff000) | (address & 0xfff);
7373 ap = (desc >> (4 + ((address >> 9) & 6))) & 3;
7374 *page_size = 0x1000;
7375 break;
7376 case 3:
7377 if (type == 1) {
7378
7379 if (arm_feature(env, ARM_FEATURE_XSCALE)
7380 || arm_feature(env, ARM_FEATURE_V6)) {
7381 phys_addr = (desc & 0xfffff000) | (address & 0xfff);
7382 *page_size = 0x1000;
7383 } else {
7384
7385
7386
7387 code = 7;
7388 goto do_fault;
7389 }
7390 } else {
7391 phys_addr = (desc & 0xfffffc00) | (address & 0x3ff);
7392 *page_size = 0x400;
7393 }
7394 ap = (desc >> 4) & 3;
7395 break;
7396 default:
7397
7398 abort();
7399 }
7400 code = 15;
7401 }
7402 *prot = ap_to_rw_prot(env, mmu_idx, ap, domain_prot);
7403 *prot |= *prot ? PAGE_EXEC : 0;
7404 if (!(*prot & (1 << access_type))) {
7405
7406 goto do_fault;
7407 }
7408 *phys_ptr = phys_addr;
7409 return false;
7410do_fault:
7411 *fsr = code | (domain << 4);
7412 return true;
7413}
7414
7415static bool get_phys_addr_v6(CPUARMState *env, uint32_t address,
7416 int access_type, ARMMMUIdx mmu_idx,
7417 hwaddr *phys_ptr, MemTxAttrs *attrs, int *prot,
7418 target_ulong *page_size, uint32_t *fsr,
7419 ARMMMUFaultInfo *fi)
7420{
7421 CPUState *cs = CPU(arm_env_get_cpu(env));
7422 int code;
7423 uint32_t table;
7424 uint32_t desc;
7425 uint32_t xn;
7426 uint32_t pxn = 0;
7427 int type;
7428 int ap;
7429 int domain = 0;
7430 int domain_prot;
7431 hwaddr phys_addr;
7432 uint32_t dacr;
7433 bool ns;
7434
7435
7436
7437 if (!get_level1_table_address(env, mmu_idx, &table, address)) {
7438
7439 code = 5;
7440 goto do_fault;
7441 }
7442 desc = arm_ldl_ptw(cs, table, regime_is_secure(env, mmu_idx),
7443 mmu_idx, fsr, fi);
7444 type = (desc & 3);
7445 if (type == 0 || (type == 3 && !arm_feature(env, ARM_FEATURE_PXN))) {
7446
7447
7448
7449 code = 5;
7450 goto do_fault;
7451 }
7452 if ((type == 1) || !(desc & (1 << 18))) {
7453
7454 domain = (desc >> 5) & 0x0f;
7455 }
7456 if (regime_el(env, mmu_idx) == 1) {
7457 dacr = env->cp15.dacr_ns;
7458 } else {
7459 dacr = env->cp15.dacr_s;
7460 }
7461 domain_prot = (dacr >> (domain * 2)) & 3;
7462 if (domain_prot == 0 || domain_prot == 2) {
7463 if (type != 1) {
7464 code = 9;
7465 } else {
7466 code = 11;
7467 }
7468 goto do_fault;
7469 }
7470 if (type != 1) {
7471 if (desc & (1 << 18)) {
7472
7473 phys_addr = (desc & 0xff000000) | (address & 0x00ffffff);
7474 phys_addr |= (uint64_t)extract32(desc, 20, 4) << 32;
7475 phys_addr |= (uint64_t)extract32(desc, 5, 4) << 36;
7476 *page_size = 0x1000000;
7477 } else {
7478
7479 phys_addr = (desc & 0xfff00000) | (address & 0x000fffff);
7480 *page_size = 0x100000;
7481 }
7482 ap = ((desc >> 10) & 3) | ((desc >> 13) & 4);
7483 xn = desc & (1 << 4);
7484 pxn = desc & 1;
7485 code = 13;
7486 ns = extract32(desc, 19, 1);
7487 } else {
7488 if (arm_feature(env, ARM_FEATURE_PXN)) {
7489 pxn = (desc >> 2) & 1;
7490 }
7491 ns = extract32(desc, 3, 1);
7492
7493 table = (desc & 0xfffffc00) | ((address >> 10) & 0x3fc);
7494 desc = arm_ldl_ptw(cs, table, regime_is_secure(env, mmu_idx),
7495 mmu_idx, fsr, fi);
7496 ap = ((desc >> 4) & 3) | ((desc >> 7) & 4);
7497 switch (desc & 3) {
7498 case 0:
7499 code = 7;
7500 goto do_fault;
7501 case 1:
7502 phys_addr = (desc & 0xffff0000) | (address & 0xffff);
7503 xn = desc & (1 << 15);
7504 *page_size = 0x10000;
7505 break;
7506 case 2: case 3:
7507 phys_addr = (desc & 0xfffff000) | (address & 0xfff);
7508 xn = desc & 1;
7509 *page_size = 0x1000;
7510 break;
7511 default:
7512
7513 abort();
7514 }
7515 code = 15;
7516 }
7517 if (domain_prot == 3) {
7518 *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
7519 } else {
7520 if (pxn && !regime_is_user(env, mmu_idx)) {
7521 xn = 1;
7522 }
7523 if (xn && access_type == 2)
7524 goto do_fault;
7525
7526 if (arm_feature(env, ARM_FEATURE_V6K) &&
7527 (regime_sctlr(env, mmu_idx) & SCTLR_AFE)) {
7528
7529 if ((ap & 1) == 0) {
7530
7531 code = (code == 15) ? 6 : 3;
7532 goto do_fault;
7533 }
7534 *prot = simple_ap_to_rw_prot(env, mmu_idx, ap >> 1);
7535 } else {
7536 *prot = ap_to_rw_prot(env, mmu_idx, ap, domain_prot);
7537 }
7538 if (*prot && !xn) {
7539 *prot |= PAGE_EXEC;
7540 }
7541 if (!(*prot & (1 << access_type))) {
7542
7543 goto do_fault;
7544 }
7545 }
7546 if (ns) {
7547
7548
7549
7550
7551 attrs->secure = false;
7552 }
7553 *phys_ptr = phys_addr;
7554 return false;
7555do_fault:
7556 *fsr = code | (domain << 4);
7557 return true;
7558}
7559
7560
7561
7562
7563typedef enum {
7564 translation_fault = 1,
7565 access_fault = 2,
7566 permission_fault = 3,
7567} MMUFaultType;
7568
7569
7570
7571
7572
7573
7574
7575
7576
7577
7578
7579
7580static bool check_s2_mmu_setup(ARMCPU *cpu, bool is_aa64, int level,
7581 int inputsize, int stride)
7582{
7583 const int grainsize = stride + 3;
7584 int startsizecheck;
7585
7586
7587 if (level < 0) {
7588 return false;
7589 }
7590
7591 startsizecheck = inputsize - ((3 - level) * stride + grainsize);
7592 if (startsizecheck < 1 || startsizecheck > stride + 4) {
7593 return false;
7594 }
7595
7596 if (is_aa64) {
7597 CPUARMState *env = &cpu->env;
7598 unsigned int pamax = arm_pamax(cpu);
7599
7600 switch (stride) {
7601 case 13:
7602 if (level == 0 || (level == 1 && pamax <= 42)) {
7603 return false;
7604 }
7605 break;
7606 case 11:
7607 if (level == 0 || (level == 1 && pamax <= 40)) {
7608 return false;
7609 }
7610 break;
7611 case 9:
7612 if (level == 0 && pamax <= 42) {
7613 return false;
7614 }
7615 break;
7616 default:
7617 g_assert_not_reached();
7618 }
7619
7620
7621 if (inputsize > pamax &&
7622 (arm_el_is_aa64(env, 1) || inputsize > 40)) {
7623
7624 return false;
7625 }
7626 } else {
7627
7628 assert(stride == 9);
7629
7630 if (level == 0) {
7631 return false;
7632 }
7633 }
7634 return true;
7635}
7636
7637static bool get_phys_addr_lpae(CPUARMState *env, target_ulong address,
7638 int access_type, ARMMMUIdx mmu_idx,
7639 hwaddr *phys_ptr, MemTxAttrs *txattrs, int *prot,
7640 target_ulong *page_size_ptr, uint32_t *fsr,
7641 ARMMMUFaultInfo *fi)
7642{
7643 ARMCPU *cpu = arm_env_get_cpu(env);
7644 CPUState *cs = CPU(cpu);
7645
7646 MMUFaultType fault_type = translation_fault;
7647 uint32_t level;
7648 uint32_t epd = 0;
7649 int32_t t0sz, t1sz;
7650 uint32_t tg;
7651 uint64_t ttbr;
7652 int ttbr_select;
7653 hwaddr descaddr, indexmask, indexmask_grainsize;
7654 uint32_t tableattrs;
7655 target_ulong page_size;
7656 uint32_t attrs;
7657 int32_t stride = 9;
7658 int32_t addrsize;
7659 int inputsize;
7660 int32_t tbi = 0;
7661 TCR *tcr = regime_tcr(env, mmu_idx);
7662 int ap, ns, xn, pxn;
7663 uint32_t el = regime_el(env, mmu_idx);
7664 bool ttbr1_valid = true;
7665 uint64_t descaddrmask;
7666 bool aarch64 = arm_el_is_aa64(env, el);
7667
7668
7669
7670
7671
7672
7673
7674 if (aarch64) {
7675 level = 0;
7676 addrsize = 64;
7677 if (el > 1) {
7678 if (mmu_idx != ARMMMUIdx_S2NS) {
7679 tbi = extract64(tcr->raw_tcr, 20, 1);
7680 }
7681 } else {
7682 if (extract64(address, 55, 1)) {
7683 tbi = extract64(tcr->raw_tcr, 38, 1);
7684 } else {
7685 tbi = extract64(tcr->raw_tcr, 37, 1);
7686 }
7687 }
7688 tbi *= 8;
7689
7690
7691
7692
7693 if (el > 1) {
7694 ttbr1_valid = false;
7695 }
7696 } else {
7697 level = 1;
7698 addrsize = 32;
7699
7700 if (el == 2) {
7701 ttbr1_valid = false;
7702 }
7703 }
7704
7705
7706
7707
7708
7709
7710 if (aarch64) {
7711
7712 t0sz = extract32(tcr->raw_tcr, 0, 6);
7713 t0sz = MIN(t0sz, 39);
7714 t0sz = MAX(t0sz, 16);
7715 } else if (mmu_idx != ARMMMUIdx_S2NS) {
7716
7717 t0sz = extract32(tcr->raw_tcr, 0, 3);
7718 } else {
7719
7720 bool sext = extract32(tcr->raw_tcr, 4, 1);
7721 bool sign = extract32(tcr->raw_tcr, 3, 1);
7722
7723
7724
7725
7726 addrsize = 40;
7727 t0sz = sextract32(tcr->raw_tcr, 0, 4) + 8;
7728
7729
7730
7731 if (sign != sext) {
7732 qemu_log_mask(LOG_GUEST_ERROR,
7733 "AArch32: VTCR.S / VTCR.T0SZ[3] mismatch\n");
7734 }
7735 }
7736 t1sz = extract32(tcr->raw_tcr, 16, 6);
7737 if (aarch64) {
7738 t1sz = MIN(t1sz, 39);
7739 t1sz = MAX(t1sz, 16);
7740 }
7741 if (t0sz && !extract64(address, addrsize - t0sz, t0sz - tbi)) {
7742
7743 ttbr_select = 0;
7744 } else if (ttbr1_valid && t1sz &&
7745 !extract64(~address, addrsize - t1sz, t1sz - tbi)) {
7746
7747 ttbr_select = 1;
7748 } else if (!t0sz) {
7749
7750 ttbr_select = 0;
7751 } else if (!t1sz && ttbr1_valid) {
7752
7753 ttbr_select = 1;
7754 } else {
7755
7756 fault_type = translation_fault;
7757 goto do_fault;
7758 }
7759
7760
7761
7762
7763
7764
7765
7766
7767 if (ttbr_select == 0) {
7768 ttbr = regime_ttbr(env, mmu_idx, 0);
7769 if (el < 2) {
7770 epd = extract32(tcr->raw_tcr, 7, 1);
7771 }
7772 inputsize = addrsize - t0sz;
7773
7774 tg = extract32(tcr->raw_tcr, 14, 2);
7775 if (tg == 1) {
7776 stride = 13;
7777 }
7778 if (tg == 2) {
7779 stride = 11;
7780 }
7781 } else {
7782
7783 assert(ttbr1_valid);
7784
7785 ttbr = regime_ttbr(env, mmu_idx, 1);
7786 epd = extract32(tcr->raw_tcr, 23, 1);
7787 inputsize = addrsize - t1sz;
7788
7789 tg = extract32(tcr->raw_tcr, 30, 2);
7790 if (tg == 3) {
7791 stride = 13;
7792 }
7793 if (tg == 1) {
7794 stride = 11;
7795 }
7796 }
7797
7798
7799
7800
7801
7802 if (epd) {
7803
7804
7805
7806 goto do_fault;
7807 }
7808
7809 if (mmu_idx != ARMMMUIdx_S2NS) {
7810
7811
7812
7813
7814
7815
7816
7817
7818
7819
7820
7821 level = 4 - (inputsize - 4) / stride;
7822 } else {
7823
7824
7825
7826 uint32_t sl0 = extract32(tcr->raw_tcr, 6, 2);
7827 uint32_t startlevel;
7828 bool ok;
7829
7830 if (!aarch64 || stride == 9) {
7831
7832 startlevel = 2 - sl0;
7833 } else {
7834
7835 startlevel = 3 - sl0;
7836 }
7837
7838
7839 ok = check_s2_mmu_setup(cpu, aarch64, startlevel,
7840 inputsize, stride);
7841 if (!ok) {
7842 fault_type = translation_fault;
7843 goto do_fault;
7844 }
7845 level = startlevel;
7846 }
7847
7848 indexmask_grainsize = (1ULL << (stride + 3)) - 1;
7849 indexmask = (1ULL << (inputsize - (stride * (4 - level)))) - 1;
7850
7851
7852 descaddr = extract64(ttbr, 0, 48);
7853 descaddr &= ~indexmask;
7854
7855
7856
7857
7858
7859
7860 descaddrmask = ((1ull << (aarch64 ? 48 : 40)) - 1) &
7861 ~indexmask_grainsize;
7862
7863
7864
7865
7866
7867
7868 tableattrs = regime_is_secure(env, mmu_idx) ? 0 : (1 << 4);
7869 for (;;) {
7870 uint64_t descriptor;
7871 bool nstable;
7872
7873 descaddr |= (address >> (stride * (4 - level))) & indexmask;
7874 descaddr &= ~7ULL;
7875 nstable = extract32(tableattrs, 4, 1);
7876 descriptor = arm_ldq_ptw(cs, descaddr, !nstable, mmu_idx, fsr, fi);
7877 if (fi->s1ptw) {
7878 goto do_fault;
7879 }
7880
7881 if (!(descriptor & 1) ||
7882 (!(descriptor & 2) && (level == 3))) {
7883
7884 goto do_fault;
7885 }
7886 descaddr = descriptor & descaddrmask;
7887
7888 if ((descriptor & 2) && (level < 3)) {
7889
7890
7891
7892
7893
7894 tableattrs |= extract64(descriptor, 59, 5);
7895 level++;
7896 indexmask = indexmask_grainsize;
7897 continue;
7898 }
7899
7900
7901
7902
7903 page_size = (1ULL << ((stride * (4 - level)) + 3));
7904 descaddr |= (address & (page_size - 1));
7905
7906 attrs = extract64(descriptor, 2, 10)
7907 | (extract64(descriptor, 52, 12) << 10);
7908
7909 if (mmu_idx == ARMMMUIdx_S2NS) {
7910
7911 break;
7912 }
7913
7914 attrs |= extract32(tableattrs, 0, 2) << 11;
7915 attrs |= extract32(tableattrs, 3, 1) << 5;
7916
7917
7918
7919 if (extract32(tableattrs, 2, 1)) {
7920 attrs &= ~(1 << 4);
7921 }
7922 attrs |= nstable << 3;
7923 break;
7924 }
7925
7926
7927
7928 fault_type = access_fault;
7929 if ((attrs & (1 << 8)) == 0) {
7930
7931 goto do_fault;
7932 }
7933
7934 ap = extract32(attrs, 4, 2);
7935 xn = extract32(attrs, 12, 1);
7936
7937 if (mmu_idx == ARMMMUIdx_S2NS) {
7938 ns = true;
7939 *prot = get_S2prot(env, ap, xn);
7940 } else {
7941 ns = extract32(attrs, 3, 1);
7942 pxn = extract32(attrs, 11, 1);
7943 *prot = get_S1prot(env, mmu_idx, aarch64, ap, ns, xn, pxn);
7944 }
7945
7946 fault_type = permission_fault;
7947 if (!(*prot & (1 << access_type))) {
7948 goto do_fault;
7949 }
7950
7951 if (ns) {
7952
7953
7954
7955
7956 txattrs->secure = false;
7957 }
7958 *phys_ptr = descaddr;
7959 *page_size_ptr = page_size;
7960 return false;
7961
7962do_fault:
7963
7964 *fsr = (1 << 9) | (fault_type << 2) | level;
7965
7966 fi->stage2 = fi->s1ptw || (mmu_idx == ARMMMUIdx_S2NS);
7967 return true;
7968}
7969
7970static inline void get_phys_addr_pmsav7_default(CPUARMState *env,
7971 ARMMMUIdx mmu_idx,
7972 int32_t address, int *prot)
7973{
7974 *prot = PAGE_READ | PAGE_WRITE;
7975 switch (address) {
7976 case 0xF0000000 ... 0xFFFFFFFF:
7977 if (regime_sctlr(env, mmu_idx) & SCTLR_V) {
7978 *prot |= PAGE_EXEC;
7979 }
7980 break;
7981 case 0x00000000 ... 0x7FFFFFFF:
7982 *prot |= PAGE_EXEC;
7983 break;
7984 }
7985
7986}
7987
7988static bool get_phys_addr_pmsav7(CPUARMState *env, uint32_t address,
7989 int access_type, ARMMMUIdx mmu_idx,
7990 hwaddr *phys_ptr, int *prot, uint32_t *fsr)
7991{
7992 ARMCPU *cpu = arm_env_get_cpu(env);
7993 int n;
7994 bool is_user = regime_is_user(env, mmu_idx);
7995
7996 *phys_ptr = address;
7997 *prot = 0;
7998
7999 if (regime_translation_disabled(env, mmu_idx)) {
8000 get_phys_addr_pmsav7_default(env, mmu_idx, address, prot);
8001 } else {
8002 for (n = (int)cpu->pmsav7_dregion - 1; n >= 0; n--) {
8003
8004 uint32_t base = env->pmsav7.drbar[n];
8005 uint32_t rsize = extract32(env->pmsav7.drsr[n], 1, 5);
8006 uint32_t rmask;
8007 bool srdis = false;
8008
8009 if (!(env->pmsav7.drsr[n] & 0x1)) {
8010 continue;
8011 }
8012
8013 if (!rsize) {
8014 qemu_log_mask(LOG_GUEST_ERROR, "DRSR.Rsize field can not be 0");
8015 continue;
8016 }
8017 rsize++;
8018 rmask = (1ull << rsize) - 1;
8019
8020 if (base & rmask) {
8021 qemu_log_mask(LOG_GUEST_ERROR, "DRBAR %" PRIx32 " misaligned "
8022 "to DRSR region size, mask = %" PRIx32,
8023 base, rmask);
8024 continue;
8025 }
8026
8027 if (address < base || address > base + rmask) {
8028 continue;
8029 }
8030
8031
8032
8033 if (rsize >= 8) {
8034 int i, snd;
8035 uint32_t srdis_mask;
8036
8037 rsize -= 3;
8038 snd = ((address - base) >> rsize) & 0x7;
8039 srdis = extract32(env->pmsav7.drsr[n], snd + 8, 1);
8040
8041 srdis_mask = srdis ? 0x3 : 0x0;
8042 for (i = 2; i <= 8 && rsize < TARGET_PAGE_BITS; i *= 2) {
8043
8044
8045
8046
8047
8048
8049 int snd_rounded = snd & ~(i - 1);
8050 uint32_t srdis_multi = extract32(env->pmsav7.drsr[n],
8051 snd_rounded + 8, i);
8052 if (srdis_mask ^ srdis_multi) {
8053 break;
8054 }
8055 srdis_mask = (srdis_mask << i) | srdis_mask;
8056 rsize++;
8057 }
8058 }
8059 if (rsize < TARGET_PAGE_BITS) {
8060 qemu_log_mask(LOG_UNIMP, "No support for MPU (sub)region"
8061 "alignment of %" PRIu32 " bits. Minimum is %d\n",
8062 rsize, TARGET_PAGE_BITS);
8063 continue;
8064 }
8065 if (srdis) {
8066 continue;
8067 }
8068 break;
8069 }
8070
8071 if (n == -1) {
8072 if (cpu->pmsav7_dregion &&
8073 (is_user || !(regime_sctlr(env, mmu_idx) & SCTLR_BR))) {
8074
8075 *fsr = 0;
8076 return true;
8077 }
8078 get_phys_addr_pmsav7_default(env, mmu_idx, address, prot);
8079 } else {
8080 uint32_t ap = extract32(env->pmsav7.dracr[n], 8, 3);
8081
8082 if (is_user) {
8083 switch (ap) {
8084 case 0:
8085 case 1:
8086 case 5:
8087 break;
8088 case 3:
8089 *prot |= PAGE_WRITE;
8090
8091 case 2:
8092 case 6:
8093 *prot |= PAGE_READ | PAGE_EXEC;
8094 break;
8095 default:
8096 qemu_log_mask(LOG_GUEST_ERROR,
8097 "Bad value for AP bits in DRACR %"
8098 PRIx32 "\n", ap);
8099 }
8100 } else {
8101 switch (ap) {
8102 case 0:
8103 break;
8104 case 1:
8105 case 2:
8106 case 3:
8107 *prot |= PAGE_WRITE;
8108
8109 case 5:
8110 case 6:
8111 *prot |= PAGE_READ | PAGE_EXEC;
8112 break;
8113 default:
8114 qemu_log_mask(LOG_GUEST_ERROR,
8115 "Bad value for AP bits in DRACR %"
8116 PRIx32 "\n", ap);
8117 }
8118 }
8119
8120
8121 if (env->pmsav7.dracr[n] & (1 << 12)) {
8122 *prot &= ~PAGE_EXEC;
8123 }
8124 }
8125 }
8126
8127 *fsr = 0x00d;
8128 return !(*prot & (1 << access_type));
8129}
8130
8131static bool get_phys_addr_pmsav5(CPUARMState *env, uint32_t address,
8132 int access_type, ARMMMUIdx mmu_idx,
8133 hwaddr *phys_ptr, int *prot, uint32_t *fsr)
8134{
8135 int n;
8136 uint32_t mask;
8137 uint32_t base;
8138 bool is_user = regime_is_user(env, mmu_idx);
8139
8140 *phys_ptr = address;
8141 for (n = 7; n >= 0; n--) {
8142 base = env->cp15.c6_region[n];
8143 if ((base & 1) == 0) {
8144 continue;
8145 }
8146 mask = 1 << ((base >> 1) & 0x1f);
8147
8148
8149 mask = (mask << 1) - 1;
8150 if (((base ^ address) & ~mask) == 0) {
8151 break;
8152 }
8153 }
8154 if (n < 0) {
8155 *fsr = 2;
8156 return true;
8157 }
8158
8159 if (access_type == 2) {
8160 mask = env->cp15.pmsav5_insn_ap;
8161 } else {
8162 mask = env->cp15.pmsav5_data_ap;
8163 }
8164 mask = (mask >> (n * 4)) & 0xf;
8165 switch (mask) {
8166 case 0:
8167 *fsr = 1;
8168 return true;
8169 case 1:
8170 if (is_user) {
8171 *fsr = 1;
8172 return true;
8173 }
8174 *prot = PAGE_READ | PAGE_WRITE;
8175 break;
8176 case 2:
8177 *prot = PAGE_READ;
8178 if (!is_user) {
8179 *prot |= PAGE_WRITE;
8180 }
8181 break;
8182 case 3:
8183 *prot = PAGE_READ | PAGE_WRITE;
8184 break;
8185 case 5:
8186 if (is_user) {
8187 *fsr = 1;
8188 return true;
8189 }
8190 *prot = PAGE_READ;
8191 break;
8192 case 6:
8193 *prot = PAGE_READ;
8194 break;
8195 default:
8196
8197 *fsr = 1;
8198 return true;
8199 }
8200 *prot |= PAGE_EXEC;
8201 return false;
8202}
8203
8204
8205
8206
8207
8208
8209
8210
8211
8212
8213
8214
8215
8216
8217
8218
8219
8220
8221
8222
8223
8224
8225
8226
8227
8228
8229static bool get_phys_addr(CPUARMState *env, target_ulong address,
8230 int access_type, ARMMMUIdx mmu_idx,
8231 hwaddr *phys_ptr, MemTxAttrs *attrs, int *prot,
8232 target_ulong *page_size, uint32_t *fsr,
8233 ARMMMUFaultInfo *fi)
8234{
8235 if (mmu_idx == ARMMMUIdx_S12NSE0 || mmu_idx == ARMMMUIdx_S12NSE1) {
8236
8237
8238
8239 if (arm_feature(env, ARM_FEATURE_EL2)) {
8240 hwaddr ipa;
8241 int s2_prot;
8242 int ret;
8243
8244 ret = get_phys_addr(env, address, access_type,
8245 mmu_idx + ARMMMUIdx_S1NSE0, &ipa, attrs,
8246 prot, page_size, fsr, fi);
8247
8248
8249 if (ret || regime_translation_disabled(env, ARMMMUIdx_S2NS)) {
8250 *phys_ptr = ipa;
8251 return ret;
8252 }
8253
8254
8255 ret = get_phys_addr_lpae(env, ipa, access_type, ARMMMUIdx_S2NS,
8256 phys_ptr, attrs, &s2_prot,
8257 page_size, fsr, fi);
8258 fi->s2addr = ipa;
8259
8260 *prot &= s2_prot;
8261 return ret;
8262 } else {
8263
8264
8265
8266 mmu_idx += ARMMMUIdx_S1NSE0;
8267 }
8268 }
8269
8270
8271
8272
8273
8274 attrs->secure = regime_is_secure(env, mmu_idx);
8275 attrs->user = regime_is_user(env, mmu_idx);
8276
8277
8278
8279
8280 if (address < 0x02000000 && mmu_idx != ARMMMUIdx_S2NS
8281 && !arm_feature(env, ARM_FEATURE_V8)) {
8282 if (regime_el(env, mmu_idx) == 3) {
8283 address += env->cp15.fcseidr_s;
8284 } else {
8285 address += env->cp15.fcseidr_ns;
8286 }
8287 }
8288
8289
8290
8291
8292 if (arm_feature(env, ARM_FEATURE_MPU) &&
8293 arm_feature(env, ARM_FEATURE_V7)) {
8294 *page_size = TARGET_PAGE_SIZE;
8295 return get_phys_addr_pmsav7(env, address, access_type, mmu_idx,
8296 phys_ptr, prot, fsr);
8297 }
8298
8299 if (regime_translation_disabled(env, mmu_idx)) {
8300
8301 *phys_ptr = address;
8302 *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
8303 *page_size = TARGET_PAGE_SIZE;
8304 return 0;
8305 }
8306
8307 if (arm_feature(env, ARM_FEATURE_MPU)) {
8308
8309 *page_size = TARGET_PAGE_SIZE;
8310 return get_phys_addr_pmsav5(env, address, access_type, mmu_idx,
8311 phys_ptr, prot, fsr);
8312 }
8313
8314 if (regime_using_lpae_format(env, mmu_idx)) {
8315 return get_phys_addr_lpae(env, address, access_type, mmu_idx, phys_ptr,
8316 attrs, prot, page_size, fsr, fi);
8317 } else if (regime_sctlr(env, mmu_idx) & SCTLR_XP) {
8318 return get_phys_addr_v6(env, address, access_type, mmu_idx, phys_ptr,
8319 attrs, prot, page_size, fsr, fi);
8320 } else {
8321 return get_phys_addr_v5(env, address, access_type, mmu_idx, phys_ptr,
8322 prot, page_size, fsr, fi);
8323 }
8324}
8325
8326
8327
8328
8329
8330bool arm_tlb_fill(CPUState *cs, vaddr address,
8331 int access_type, int mmu_idx, uint32_t *fsr,
8332 ARMMMUFaultInfo *fi)
8333{
8334 ARMCPU *cpu = ARM_CPU(cs);
8335 CPUARMState *env = &cpu->env;
8336 hwaddr phys_addr;
8337 target_ulong page_size;
8338 int prot;
8339 int ret;
8340 MemTxAttrs attrs = {};
8341
8342 ret = get_phys_addr(env, address, access_type, mmu_idx, &phys_addr,
8343 &attrs, &prot, &page_size, fsr, fi);
8344 if (!ret) {
8345
8346 phys_addr &= TARGET_PAGE_MASK;
8347 address &= TARGET_PAGE_MASK;
8348 tlb_set_page_with_attrs(cs, address, phys_addr, attrs,
8349 prot, mmu_idx, page_size);
8350 return 0;
8351 }
8352
8353 return ret;
8354}
8355
8356hwaddr arm_cpu_get_phys_page_attrs_debug(CPUState *cs, vaddr addr,
8357 MemTxAttrs *attrs)
8358{
8359 ARMCPU *cpu = ARM_CPU(cs);
8360 CPUARMState *env = &cpu->env;
8361 hwaddr phys_addr;
8362 target_ulong page_size;
8363 int prot;
8364 bool ret;
8365 uint32_t fsr;
8366 ARMMMUFaultInfo fi = {};
8367
8368 *attrs = (MemTxAttrs) {};
8369
8370 ret = get_phys_addr(env, addr, 0, cpu_mmu_index(env, false), &phys_addr,
8371 attrs, &prot, &page_size, &fsr, &fi);
8372
8373 if (ret) {
8374 return -1;
8375 }
8376 return phys_addr;
8377}
8378
8379uint32_t HELPER(v7m_mrs)(CPUARMState *env, uint32_t reg)
8380{
8381 ARMCPU *cpu = arm_env_get_cpu(env);
8382
8383 switch (reg) {
8384 case 0:
8385 return xpsr_read(env) & 0xf8000000;
8386 case 1:
8387 return xpsr_read(env) & 0xf80001ff;
8388 case 2:
8389 return xpsr_read(env) & 0xff00fc00;
8390 case 3:
8391 return xpsr_read(env) & 0xff00fdff;
8392 case 5:
8393 return xpsr_read(env) & 0x000001ff;
8394 case 6:
8395 return xpsr_read(env) & 0x0700fc00;
8396 case 7:
8397 return xpsr_read(env) & 0x0700edff;
8398 case 8:
8399 return env->v7m.current_sp ? env->v7m.other_sp : env->regs[13];
8400 case 9:
8401 return env->v7m.current_sp ? env->regs[13] : env->v7m.other_sp;
8402 case 16:
8403 return (env->daif & PSTATE_I) != 0;
8404 case 17:
8405 case 18:
8406 return env->v7m.basepri;
8407 case 19:
8408 return (env->daif & PSTATE_F) != 0;
8409 case 20:
8410 return env->v7m.control;
8411 default:
8412
8413 cpu_abort(CPU(cpu), "Unimplemented system register read (%d)\n", reg);
8414 return 0;
8415 }
8416}
8417
8418void HELPER(v7m_msr)(CPUARMState *env, uint32_t reg, uint32_t val)
8419{
8420 ARMCPU *cpu = arm_env_get_cpu(env);
8421
8422 switch (reg) {
8423 case 0:
8424 xpsr_write(env, val, 0xf8000000);
8425 break;
8426 case 1:
8427 xpsr_write(env, val, 0xf8000000);
8428 break;
8429 case 2:
8430 xpsr_write(env, val, 0xfe00fc00);
8431 break;
8432 case 3:
8433 xpsr_write(env, val, 0xfe00fc00);
8434 break;
8435 case 5:
8436
8437 break;
8438 case 6:
8439 xpsr_write(env, val, 0x0600fc00);
8440 break;
8441 case 7:
8442 xpsr_write(env, val, 0x0600fc00);
8443 break;
8444 case 8:
8445 if (env->v7m.current_sp)
8446 env->v7m.other_sp = val;
8447 else
8448 env->regs[13] = val;
8449 break;
8450 case 9:
8451 if (env->v7m.current_sp)
8452 env->regs[13] = val;
8453 else
8454 env->v7m.other_sp = val;
8455 break;
8456 case 16:
8457 if (val & 1) {
8458 env->daif |= PSTATE_I;
8459 } else {
8460 env->daif &= ~PSTATE_I;
8461 }
8462 break;
8463 case 17:
8464 env->v7m.basepri = val & 0xff;
8465 break;
8466 case 18:
8467 val &= 0xff;
8468 if (val != 0 && (val < env->v7m.basepri || env->v7m.basepri == 0))
8469 env->v7m.basepri = val;
8470 break;
8471 case 19:
8472 if (val & 1) {
8473 env->daif |= PSTATE_F;
8474 } else {
8475 env->daif &= ~PSTATE_F;
8476 }
8477 break;
8478 case 20:
8479 env->v7m.control = val & 3;
8480 switch_v7m_sp(env, (val & 2) != 0);
8481 break;
8482 default:
8483
8484 cpu_abort(CPU(cpu), "Unimplemented system register write (%d)\n", reg);
8485 return;
8486 }
8487}
8488
8489#endif
8490
8491void HELPER(dc_zva)(CPUARMState *env, uint64_t vaddr_in)
8492{
8493
8494
8495
8496
8497
8498
8499
8500 ARMCPU *cpu = arm_env_get_cpu(env);
8501 uint64_t blocklen = 4 << cpu->dcz_blocksize;
8502 uint64_t vaddr = vaddr_in & ~(blocklen - 1);
8503
8504#ifndef CONFIG_USER_ONLY
8505 {
8506
8507
8508
8509
8510
8511
8512
8513 int maxidx = DIV_ROUND_UP(blocklen, TARGET_PAGE_SIZE);
8514 void *hostaddr[maxidx];
8515 int try, i;
8516 unsigned mmu_idx = cpu_mmu_index(env, false);
8517 TCGMemOpIdx oi = make_memop_idx(MO_UB, mmu_idx);
8518
8519 for (try = 0; try < 2; try++) {
8520
8521 for (i = 0; i < maxidx; i++) {
8522 hostaddr[i] = tlb_vaddr_to_host(env,
8523 vaddr + TARGET_PAGE_SIZE * i,
8524 1, mmu_idx);
8525 if (!hostaddr[i]) {
8526 break;
8527 }
8528 }
8529 if (i == maxidx) {
8530
8531
8532
8533 for (i = 0; i < maxidx - 1; i++) {
8534 memset(hostaddr[i], 0, TARGET_PAGE_SIZE);
8535 }
8536 memset(hostaddr[i], 0, blocklen - (i * TARGET_PAGE_SIZE));
8537 return;
8538 }
8539
8540
8541
8542
8543
8544
8545 helper_ret_stb_mmu(env, vaddr_in, 0, oi, GETPC());
8546
8547 for (i = 0; i < maxidx; i++) {
8548 uint64_t va = vaddr + TARGET_PAGE_SIZE * i;
8549 if (va != (vaddr_in & TARGET_PAGE_MASK)) {
8550 helper_ret_stb_mmu(env, va, 0, oi, GETPC());
8551 }
8552 }
8553 }
8554
8555
8556
8557
8558
8559
8560
8561
8562
8563
8564
8565
8566 for (i = 0; i < blocklen; i++) {
8567 helper_ret_stb_mmu(env, vaddr + i, 0, oi, GETPC());
8568 }
8569 }
8570#else
8571 memset(g2h(vaddr), 0, blocklen);
8572#endif
8573}
8574
8575
8576
8577
8578
8579
8580
8581
8582static inline uint16_t add16_sat(uint16_t a, uint16_t b)
8583{
8584 uint16_t res;
8585
8586 res = a + b;
8587 if (((res ^ a) & 0x8000) && !((a ^ b) & 0x8000)) {
8588 if (a & 0x8000)
8589 res = 0x8000;
8590 else
8591 res = 0x7fff;
8592 }
8593 return res;
8594}
8595
8596
8597static inline uint8_t add8_sat(uint8_t a, uint8_t b)
8598{
8599 uint8_t res;
8600
8601 res = a + b;
8602 if (((res ^ a) & 0x80) && !((a ^ b) & 0x80)) {
8603 if (a & 0x80)
8604 res = 0x80;
8605 else
8606 res = 0x7f;
8607 }
8608 return res;
8609}
8610
8611
8612static inline uint16_t sub16_sat(uint16_t a, uint16_t b)
8613{
8614 uint16_t res;
8615
8616 res = a - b;
8617 if (((res ^ a) & 0x8000) && ((a ^ b) & 0x8000)) {
8618 if (a & 0x8000)
8619 res = 0x8000;
8620 else
8621 res = 0x7fff;
8622 }
8623 return res;
8624}
8625
8626
8627static inline uint8_t sub8_sat(uint8_t a, uint8_t b)
8628{
8629 uint8_t res;
8630
8631 res = a - b;
8632 if (((res ^ a) & 0x80) && ((a ^ b) & 0x80)) {
8633 if (a & 0x80)
8634 res = 0x80;
8635 else
8636 res = 0x7f;
8637 }
8638 return res;
8639}
8640
8641#define ADD16(a, b, n) RESULT(add16_sat(a, b), n, 16);
8642#define SUB16(a, b, n) RESULT(sub16_sat(a, b), n, 16);
8643#define ADD8(a, b, n) RESULT(add8_sat(a, b), n, 8);
8644#define SUB8(a, b, n) RESULT(sub8_sat(a, b), n, 8);
8645#define PFX q
8646
8647#include "op_addsub.h"
8648
8649
8650static inline uint16_t add16_usat(uint16_t a, uint16_t b)
8651{
8652 uint16_t res;
8653 res = a + b;
8654 if (res < a)
8655 res = 0xffff;
8656 return res;
8657}
8658
8659static inline uint16_t sub16_usat(uint16_t a, uint16_t b)
8660{
8661 if (a > b)
8662 return a - b;
8663 else
8664 return 0;
8665}
8666
8667static inline uint8_t add8_usat(uint8_t a, uint8_t b)
8668{
8669 uint8_t res;
8670 res = a + b;
8671 if (res < a)
8672 res = 0xff;
8673 return res;
8674}
8675
8676static inline uint8_t sub8_usat(uint8_t a, uint8_t b)
8677{
8678 if (a > b)
8679 return a - b;
8680 else
8681 return 0;
8682}
8683
8684#define ADD16(a, b, n) RESULT(add16_usat(a, b), n, 16);
8685#define SUB16(a, b, n) RESULT(sub16_usat(a, b), n, 16);
8686#define ADD8(a, b, n) RESULT(add8_usat(a, b), n, 8);
8687#define SUB8(a, b, n) RESULT(sub8_usat(a, b), n, 8);
8688#define PFX uq
8689
8690#include "op_addsub.h"
8691
8692
8693#define SARITH16(a, b, n, op) do { \
8694 int32_t sum; \
8695 sum = (int32_t)(int16_t)(a) op (int32_t)(int16_t)(b); \
8696 RESULT(sum, n, 16); \
8697 if (sum >= 0) \
8698 ge |= 3 << (n * 2); \
8699 } while(0)
8700
8701#define SARITH8(a, b, n, op) do { \
8702 int32_t sum; \
8703 sum = (int32_t)(int8_t)(a) op (int32_t)(int8_t)(b); \
8704 RESULT(sum, n, 8); \
8705 if (sum >= 0) \
8706 ge |= 1 << n; \
8707 } while(0)
8708
8709
8710#define ADD16(a, b, n) SARITH16(a, b, n, +)
8711#define SUB16(a, b, n) SARITH16(a, b, n, -)
8712#define ADD8(a, b, n) SARITH8(a, b, n, +)
8713#define SUB8(a, b, n) SARITH8(a, b, n, -)
8714#define PFX s
8715#define ARITH_GE
8716
8717#include "op_addsub.h"
8718
8719
8720#define ADD16(a, b, n) do { \
8721 uint32_t sum; \
8722 sum = (uint32_t)(uint16_t)(a) + (uint32_t)(uint16_t)(b); \
8723 RESULT(sum, n, 16); \
8724 if ((sum >> 16) == 1) \
8725 ge |= 3 << (n * 2); \
8726 } while(0)
8727
8728#define ADD8(a, b, n) do { \
8729 uint32_t sum; \
8730 sum = (uint32_t)(uint8_t)(a) + (uint32_t)(uint8_t)(b); \
8731 RESULT(sum, n, 8); \
8732 if ((sum >> 8) == 1) \
8733 ge |= 1 << n; \
8734 } while(0)
8735
8736#define SUB16(a, b, n) do { \
8737 uint32_t sum; \
8738 sum = (uint32_t)(uint16_t)(a) - (uint32_t)(uint16_t)(b); \
8739 RESULT(sum, n, 16); \
8740 if ((sum >> 16) == 0) \
8741 ge |= 3 << (n * 2); \
8742 } while(0)
8743
8744#define SUB8(a, b, n) do { \
8745 uint32_t sum; \
8746 sum = (uint32_t)(uint8_t)(a) - (uint32_t)(uint8_t)(b); \
8747 RESULT(sum, n, 8); \
8748 if ((sum >> 8) == 0) \
8749 ge |= 1 << n; \
8750 } while(0)
8751
8752#define PFX u
8753#define ARITH_GE
8754
8755#include "op_addsub.h"
8756
8757
8758#define ADD16(a, b, n) \
8759 RESULT(((int32_t)(int16_t)(a) + (int32_t)(int16_t)(b)) >> 1, n, 16)
8760#define SUB16(a, b, n) \
8761 RESULT(((int32_t)(int16_t)(a) - (int32_t)(int16_t)(b)) >> 1, n, 16)
8762#define ADD8(a, b, n) \
8763 RESULT(((int32_t)(int8_t)(a) + (int32_t)(int8_t)(b)) >> 1, n, 8)
8764#define SUB8(a, b, n) \
8765 RESULT(((int32_t)(int8_t)(a) - (int32_t)(int8_t)(b)) >> 1, n, 8)
8766#define PFX sh
8767
8768#include "op_addsub.h"
8769
8770
8771#define ADD16(a, b, n) \
8772 RESULT(((uint32_t)(uint16_t)(a) + (uint32_t)(uint16_t)(b)) >> 1, n, 16)
8773#define SUB16(a, b, n) \
8774 RESULT(((uint32_t)(uint16_t)(a) - (uint32_t)(uint16_t)(b)) >> 1, n, 16)
8775#define ADD8(a, b, n) \
8776 RESULT(((uint32_t)(uint8_t)(a) + (uint32_t)(uint8_t)(b)) >> 1, n, 8)
8777#define SUB8(a, b, n) \
8778 RESULT(((uint32_t)(uint8_t)(a) - (uint32_t)(uint8_t)(b)) >> 1, n, 8)
8779#define PFX uh
8780
8781#include "op_addsub.h"
8782
8783static inline uint8_t do_usad(uint8_t a, uint8_t b)
8784{
8785 if (a > b)
8786 return a - b;
8787 else
8788 return b - a;
8789}
8790
8791
8792uint32_t HELPER(usad8)(uint32_t a, uint32_t b)
8793{
8794 uint32_t sum;
8795 sum = do_usad(a, b);
8796 sum += do_usad(a >> 8, b >> 8);
8797 sum += do_usad(a >> 16, b >>16);
8798 sum += do_usad(a >> 24, b >> 24);
8799 return sum;
8800}
8801
8802
8803uint32_t HELPER(sel_flags)(uint32_t flags, uint32_t a, uint32_t b)
8804{
8805 uint32_t mask;
8806
8807 mask = 0;
8808 if (flags & 1)
8809 mask |= 0xff;
8810 if (flags & 2)
8811 mask |= 0xff00;
8812 if (flags & 4)
8813 mask |= 0xff0000;
8814 if (flags & 8)
8815 mask |= 0xff000000;
8816 return (a & mask) | (b & ~mask);
8817}
8818
8819
8820
8821
8822
8823
8824static inline int vfp_exceptbits_from_host(int host_bits)
8825{
8826 int target_bits = 0;
8827
8828 if (host_bits & float_flag_invalid)
8829 target_bits |= 1;
8830 if (host_bits & float_flag_divbyzero)
8831 target_bits |= 2;
8832 if (host_bits & float_flag_overflow)
8833 target_bits |= 4;
8834 if (host_bits & (float_flag_underflow | float_flag_output_denormal))
8835 target_bits |= 8;
8836 if (host_bits & float_flag_inexact)
8837 target_bits |= 0x10;
8838 if (host_bits & float_flag_input_denormal)
8839 target_bits |= 0x80;
8840 return target_bits;
8841}
8842
8843uint32_t HELPER(vfp_get_fpscr)(CPUARMState *env)
8844{
8845 int i;
8846 uint32_t fpscr;
8847
8848 fpscr = (env->vfp.xregs[ARM_VFP_FPSCR] & 0xffc8ffff)
8849 | (env->vfp.vec_len << 16)
8850 | (env->vfp.vec_stride << 20);
8851 i = get_float_exception_flags(&env->vfp.fp_status);
8852 i |= get_float_exception_flags(&env->vfp.standard_fp_status);
8853 fpscr |= vfp_exceptbits_from_host(i);
8854 return fpscr;
8855}
8856
8857uint32_t vfp_get_fpscr(CPUARMState *env)
8858{
8859 return HELPER(vfp_get_fpscr)(env);
8860}
8861
8862
8863static inline int vfp_exceptbits_to_host(int target_bits)
8864{
8865 int host_bits = 0;
8866
8867 if (target_bits & 1)
8868 host_bits |= float_flag_invalid;
8869 if (target_bits & 2)
8870 host_bits |= float_flag_divbyzero;
8871 if (target_bits & 4)
8872 host_bits |= float_flag_overflow;
8873 if (target_bits & 8)
8874 host_bits |= float_flag_underflow;
8875 if (target_bits & 0x10)
8876 host_bits |= float_flag_inexact;
8877 if (target_bits & 0x80)
8878 host_bits |= float_flag_input_denormal;
8879 return host_bits;
8880}
8881
8882void HELPER(vfp_set_fpscr)(CPUARMState *env, uint32_t val)
8883{
8884 int i;
8885 uint32_t changed;
8886
8887 changed = env->vfp.xregs[ARM_VFP_FPSCR];
8888 env->vfp.xregs[ARM_VFP_FPSCR] = (val & 0xffc8ffff);
8889 env->vfp.vec_len = (val >> 16) & 7;
8890 env->vfp.vec_stride = (val >> 20) & 3;
8891
8892 changed ^= val;
8893 if (changed & (3 << 22)) {
8894 i = (val >> 22) & 3;
8895 switch (i) {
8896 case FPROUNDING_TIEEVEN:
8897 i = float_round_nearest_even;
8898 break;
8899 case FPROUNDING_POSINF:
8900 i = float_round_up;
8901 break;
8902 case FPROUNDING_NEGINF:
8903 i = float_round_down;
8904 break;
8905 case FPROUNDING_ZERO:
8906 i = float_round_to_zero;
8907 break;
8908 }
8909 set_float_rounding_mode(i, &env->vfp.fp_status);
8910 }
8911 if (changed & (1 << 24)) {
8912 set_flush_to_zero((val & (1 << 24)) != 0, &env->vfp.fp_status);
8913 set_flush_inputs_to_zero((val & (1 << 24)) != 0, &env->vfp.fp_status);
8914 }
8915 if (changed & (1 << 25))
8916 set_default_nan_mode((val & (1 << 25)) != 0, &env->vfp.fp_status);
8917
8918 i = vfp_exceptbits_to_host(val);
8919 set_float_exception_flags(i, &env->vfp.fp_status);
8920 set_float_exception_flags(0, &env->vfp.standard_fp_status);
8921}
8922
8923void vfp_set_fpscr(CPUARMState *env, uint32_t val)
8924{
8925 HELPER(vfp_set_fpscr)(env, val);
8926}
8927
8928#define VFP_HELPER(name, p) HELPER(glue(glue(vfp_,name),p))
8929
8930#define VFP_BINOP(name) \
8931float32 VFP_HELPER(name, s)(float32 a, float32 b, void *fpstp) \
8932{ \
8933 float_status *fpst = fpstp; \
8934 return float32_ ## name(a, b, fpst); \
8935} \
8936float64 VFP_HELPER(name, d)(float64 a, float64 b, void *fpstp) \
8937{ \
8938 float_status *fpst = fpstp; \
8939 return float64_ ## name(a, b, fpst); \
8940}
8941VFP_BINOP(add)
8942VFP_BINOP(sub)
8943VFP_BINOP(mul)
8944VFP_BINOP(div)
8945VFP_BINOP(min)
8946VFP_BINOP(max)
8947VFP_BINOP(minnum)
8948VFP_BINOP(maxnum)
8949#undef VFP_BINOP
8950
8951float32 VFP_HELPER(neg, s)(float32 a)
8952{
8953 return float32_chs(a);
8954}
8955
8956float64 VFP_HELPER(neg, d)(float64 a)
8957{
8958 return float64_chs(a);
8959}
8960
8961float32 VFP_HELPER(abs, s)(float32 a)
8962{
8963 return float32_abs(a);
8964}
8965
8966float64 VFP_HELPER(abs, d)(float64 a)
8967{
8968 return float64_abs(a);
8969}
8970
8971float32 VFP_HELPER(sqrt, s)(float32 a, CPUARMState *env)
8972{
8973 return float32_sqrt(a, &env->vfp.fp_status);
8974}
8975
8976float64 VFP_HELPER(sqrt, d)(float64 a, CPUARMState *env)
8977{
8978 return float64_sqrt(a, &env->vfp.fp_status);
8979}
8980
8981
8982#define DO_VFP_cmp(p, type) \
8983void VFP_HELPER(cmp, p)(type a, type b, CPUARMState *env) \
8984{ \
8985 uint32_t flags; \
8986 switch(type ## _compare_quiet(a, b, &env->vfp.fp_status)) { \
8987 case 0: flags = 0x6; break; \
8988 case -1: flags = 0x8; break; \
8989 case 1: flags = 0x2; break; \
8990 default: case 2: flags = 0x3; break; \
8991 } \
8992 env->vfp.xregs[ARM_VFP_FPSCR] = (flags << 28) \
8993 | (env->vfp.xregs[ARM_VFP_FPSCR] & 0x0fffffff); \
8994} \
8995void VFP_HELPER(cmpe, p)(type a, type b, CPUARMState *env) \
8996{ \
8997 uint32_t flags; \
8998 switch(type ## _compare(a, b, &env->vfp.fp_status)) { \
8999 case 0: flags = 0x6; break; \
9000 case -1: flags = 0x8; break; \
9001 case 1: flags = 0x2; break; \
9002 default: case 2: flags = 0x3; break; \
9003 } \
9004 env->vfp.xregs[ARM_VFP_FPSCR] = (flags << 28) \
9005 | (env->vfp.xregs[ARM_VFP_FPSCR] & 0x0fffffff); \
9006}
9007DO_VFP_cmp(s, float32)
9008DO_VFP_cmp(d, float64)
9009#undef DO_VFP_cmp
9010
9011
9012
9013#define CONV_ITOF(name, fsz, sign) \
9014 float##fsz HELPER(name)(uint32_t x, void *fpstp) \
9015{ \
9016 float_status *fpst = fpstp; \
9017 return sign##int32_to_##float##fsz((sign##int32_t)x, fpst); \
9018}
9019
9020#define CONV_FTOI(name, fsz, sign, round) \
9021uint32_t HELPER(name)(float##fsz x, void *fpstp) \
9022{ \
9023 float_status *fpst = fpstp; \
9024 if (float##fsz##_is_any_nan(x)) { \
9025 float_raise(float_flag_invalid, fpst); \
9026 return 0; \
9027 } \
9028 return float##fsz##_to_##sign##int32##round(x, fpst); \
9029}
9030
9031#define FLOAT_CONVS(name, p, fsz, sign) \
9032CONV_ITOF(vfp_##name##to##p, fsz, sign) \
9033CONV_FTOI(vfp_to##name##p, fsz, sign, ) \
9034CONV_FTOI(vfp_to##name##z##p, fsz, sign, _round_to_zero)
9035
9036FLOAT_CONVS(si, s, 32, )
9037FLOAT_CONVS(si, d, 64, )
9038FLOAT_CONVS(ui, s, 32, u)
9039FLOAT_CONVS(ui, d, 64, u)
9040
9041#undef CONV_ITOF
9042#undef CONV_FTOI
9043#undef FLOAT_CONVS
9044
9045
9046float64 VFP_HELPER(fcvtd, s)(float32 x, CPUARMState *env)
9047{
9048 float64 r = float32_to_float64(x, &env->vfp.fp_status);
9049
9050
9051
9052 return float64_maybe_silence_nan(r, &env->vfp.fp_status);
9053}
9054
9055float32 VFP_HELPER(fcvts, d)(float64 x, CPUARMState *env)
9056{
9057 float32 r = float64_to_float32(x, &env->vfp.fp_status);
9058
9059
9060
9061 return float32_maybe_silence_nan(r, &env->vfp.fp_status);
9062}
9063
9064
9065#define VFP_CONV_FIX_FLOAT(name, p, fsz, isz, itype) \
9066float##fsz HELPER(vfp_##name##to##p)(uint##isz##_t x, uint32_t shift, \
9067 void *fpstp) \
9068{ \
9069 float_status *fpst = fpstp; \
9070 float##fsz tmp; \
9071 tmp = itype##_to_##float##fsz(x, fpst); \
9072 return float##fsz##_scalbn(tmp, -(int)shift, fpst); \
9073}
9074
9075
9076
9077
9078
9079
9080#define VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, isz, itype, round) \
9081uint##isz##_t HELPER(vfp_to##name##p##round)(float##fsz x, \
9082 uint32_t shift, \
9083 void *fpstp) \
9084{ \
9085 float_status *fpst = fpstp; \
9086 int old_exc_flags = get_float_exception_flags(fpst); \
9087 float##fsz tmp; \
9088 if (float##fsz##_is_any_nan(x)) { \
9089 float_raise(float_flag_invalid, fpst); \
9090 return 0; \
9091 } \
9092 tmp = float##fsz##_scalbn(x, shift, fpst); \
9093 old_exc_flags |= get_float_exception_flags(fpst) \
9094 & float_flag_input_denormal; \
9095 set_float_exception_flags(old_exc_flags, fpst); \
9096 return float##fsz##_to_##itype##round(tmp, fpst); \
9097}
9098
9099#define VFP_CONV_FIX(name, p, fsz, isz, itype) \
9100VFP_CONV_FIX_FLOAT(name, p, fsz, isz, itype) \
9101VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, isz, itype, _round_to_zero) \
9102VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, isz, itype, )
9103
9104#define VFP_CONV_FIX_A64(name, p, fsz, isz, itype) \
9105VFP_CONV_FIX_FLOAT(name, p, fsz, isz, itype) \
9106VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, isz, itype, )
9107
9108VFP_CONV_FIX(sh, d, 64, 64, int16)
9109VFP_CONV_FIX(sl, d, 64, 64, int32)
9110VFP_CONV_FIX_A64(sq, d, 64, 64, int64)
9111VFP_CONV_FIX(uh, d, 64, 64, uint16)
9112VFP_CONV_FIX(ul, d, 64, 64, uint32)
9113VFP_CONV_FIX_A64(uq, d, 64, 64, uint64)
9114VFP_CONV_FIX(sh, s, 32, 32, int16)
9115VFP_CONV_FIX(sl, s, 32, 32, int32)
9116VFP_CONV_FIX_A64(sq, s, 32, 64, int64)
9117VFP_CONV_FIX(uh, s, 32, 32, uint16)
9118VFP_CONV_FIX(ul, s, 32, 32, uint32)
9119VFP_CONV_FIX_A64(uq, s, 32, 64, uint64)
9120#undef VFP_CONV_FIX
9121#undef VFP_CONV_FIX_FLOAT
9122#undef VFP_CONV_FLOAT_FIX_ROUND
9123
9124
9125
9126
9127uint32_t HELPER(set_rmode)(uint32_t rmode, CPUARMState *env)
9128{
9129 float_status *fp_status = &env->vfp.fp_status;
9130
9131 uint32_t prev_rmode = get_float_rounding_mode(fp_status);
9132 set_float_rounding_mode(rmode, fp_status);
9133
9134 return prev_rmode;
9135}
9136
9137
9138
9139
9140
9141
9142
9143
9144uint32_t HELPER(set_neon_rmode)(uint32_t rmode, CPUARMState *env)
9145{
9146 float_status *fp_status = &env->vfp.standard_fp_status;
9147
9148 uint32_t prev_rmode = get_float_rounding_mode(fp_status);
9149 set_float_rounding_mode(rmode, fp_status);
9150
9151 return prev_rmode;
9152}
9153
9154
9155static float32 do_fcvt_f16_to_f32(uint32_t a, CPUARMState *env, float_status *s)
9156{
9157 int ieee = (env->vfp.xregs[ARM_VFP_FPSCR] & (1 << 26)) == 0;
9158 float32 r = float16_to_float32(make_float16(a), ieee, s);
9159 if (ieee) {
9160 return float32_maybe_silence_nan(r, s);
9161 }
9162 return r;
9163}
9164
9165static uint32_t do_fcvt_f32_to_f16(float32 a, CPUARMState *env, float_status *s)
9166{
9167 int ieee = (env->vfp.xregs[ARM_VFP_FPSCR] & (1 << 26)) == 0;
9168 float16 r = float32_to_float16(a, ieee, s);
9169 if (ieee) {
9170 r = float16_maybe_silence_nan(r, s);
9171 }
9172 return float16_val(r);
9173}
9174
9175float32 HELPER(neon_fcvt_f16_to_f32)(uint32_t a, CPUARMState *env)
9176{
9177 return do_fcvt_f16_to_f32(a, env, &env->vfp.standard_fp_status);
9178}
9179
9180uint32_t HELPER(neon_fcvt_f32_to_f16)(float32 a, CPUARMState *env)
9181{
9182 return do_fcvt_f32_to_f16(a, env, &env->vfp.standard_fp_status);
9183}
9184
9185float32 HELPER(vfp_fcvt_f16_to_f32)(uint32_t a, CPUARMState *env)
9186{
9187 return do_fcvt_f16_to_f32(a, env, &env->vfp.fp_status);
9188}
9189
9190uint32_t HELPER(vfp_fcvt_f32_to_f16)(float32 a, CPUARMState *env)
9191{
9192 return do_fcvt_f32_to_f16(a, env, &env->vfp.fp_status);
9193}
9194
9195float64 HELPER(vfp_fcvt_f16_to_f64)(uint32_t a, CPUARMState *env)
9196{
9197 int ieee = (env->vfp.xregs[ARM_VFP_FPSCR] & (1 << 26)) == 0;
9198 float64 r = float16_to_float64(make_float16(a), ieee, &env->vfp.fp_status);
9199 if (ieee) {
9200 return float64_maybe_silence_nan(r, &env->vfp.fp_status);
9201 }
9202 return r;
9203}
9204
9205uint32_t HELPER(vfp_fcvt_f64_to_f16)(float64 a, CPUARMState *env)
9206{
9207 int ieee = (env->vfp.xregs[ARM_VFP_FPSCR] & (1 << 26)) == 0;
9208 float16 r = float64_to_float16(a, ieee, &env->vfp.fp_status);
9209 if (ieee) {
9210 r = float16_maybe_silence_nan(r, &env->vfp.fp_status);
9211 }
9212 return float16_val(r);
9213}
9214
9215#define float32_two make_float32(0x40000000)
9216#define float32_three make_float32(0x40400000)
9217#define float32_one_point_five make_float32(0x3fc00000)
9218
9219float32 HELPER(recps_f32)(float32 a, float32 b, CPUARMState *env)
9220{
9221 float_status *s = &env->vfp.standard_fp_status;
9222 if ((float32_is_infinity(a) && float32_is_zero_or_denormal(b)) ||
9223 (float32_is_infinity(b) && float32_is_zero_or_denormal(a))) {
9224 if (!(float32_is_zero(a) || float32_is_zero(b))) {
9225 float_raise(float_flag_input_denormal, s);
9226 }
9227 return float32_two;
9228 }
9229 return float32_sub(float32_two, float32_mul(a, b, s), s);
9230}
9231
9232float32 HELPER(rsqrts_f32)(float32 a, float32 b, CPUARMState *env)
9233{
9234 float_status *s = &env->vfp.standard_fp_status;
9235 float32 product;
9236 if ((float32_is_infinity(a) && float32_is_zero_or_denormal(b)) ||
9237 (float32_is_infinity(b) && float32_is_zero_or_denormal(a))) {
9238 if (!(float32_is_zero(a) || float32_is_zero(b))) {
9239 float_raise(float_flag_input_denormal, s);
9240 }
9241 return float32_one_point_five;
9242 }
9243 product = float32_mul(a, b, s);
9244 return float32_div(float32_sub(float32_three, product, s), float32_two, s);
9245}
9246
9247
9248
9249
9250
9251#define float64_256 make_float64(0x4070000000000000LL)
9252#define float64_512 make_float64(0x4080000000000000LL)
9253#define float32_maxnorm make_float32(0x7f7fffff)
9254#define float64_maxnorm make_float64(0x7fefffffffffffffLL)
9255
9256
9257
9258
9259
9260
9261
9262static float64 recip_estimate(float64 a, float_status *real_fp_status)
9263{
9264
9265
9266
9267 float_status dummy_status = *real_fp_status;
9268 float_status *s = &dummy_status;
9269
9270 float64 q = float64_mul(float64_512, a, s);
9271 int64_t q_int = float64_to_int64_round_to_zero(q, s);
9272
9273
9274 q = int64_to_float64(q_int, s);
9275 q = float64_add(q, float64_half, s);
9276 q = float64_div(q, float64_512, s);
9277 q = float64_div(float64_one, q, s);
9278
9279
9280 q = float64_mul(q, float64_256, s);
9281 q = float64_add(q, float64_half, s);
9282 q_int = float64_to_int64_round_to_zero(q, s);
9283
9284
9285 return float64_div(int64_to_float64(q_int, s), float64_256, s);
9286}
9287
9288
9289static float64 call_recip_estimate(float64 num, int off, float_status *fpst)
9290{
9291 uint64_t val64 = float64_val(num);
9292 uint64_t frac = extract64(val64, 0, 52);
9293 int64_t exp = extract64(val64, 52, 11);
9294 uint64_t sbit;
9295 float64 scaled, estimate;
9296
9297
9298 if (exp == 0) {
9299 if (extract64(frac, 51, 1) == 0) {
9300 exp = -1;
9301 frac = extract64(frac, 0, 50) << 2;
9302 } else {
9303 frac = extract64(frac, 0, 51) << 1;
9304 }
9305 }
9306
9307
9308 scaled = make_float64((0x3feULL << 52)
9309 | extract64(frac, 44, 8) << 44);
9310
9311 estimate = recip_estimate(scaled, fpst);
9312
9313
9314 val64 = float64_val(estimate);
9315 sbit = 0x8000000000000000ULL & val64;
9316 exp = off - exp;
9317 frac = extract64(val64, 0, 52);
9318
9319 if (exp == 0) {
9320 frac = 1ULL << 51 | extract64(frac, 1, 51);
9321 } else if (exp == -1) {
9322 frac = 1ULL << 50 | extract64(frac, 2, 50);
9323 exp = 0;
9324 }
9325
9326 return make_float64(sbit | (exp << 52) | frac);
9327}
9328
9329static bool round_to_inf(float_status *fpst, bool sign_bit)
9330{
9331 switch (fpst->float_rounding_mode) {
9332 case float_round_nearest_even:
9333 return true;
9334 case float_round_up:
9335 return !sign_bit;
9336 case float_round_down:
9337 return sign_bit;
9338 case float_round_to_zero:
9339 return false;
9340 }
9341
9342 g_assert_not_reached();
9343}
9344
9345float32 HELPER(recpe_f32)(float32 input, void *fpstp)
9346{
9347 float_status *fpst = fpstp;
9348 float32 f32 = float32_squash_input_denormal(input, fpst);
9349 uint32_t f32_val = float32_val(f32);
9350 uint32_t f32_sbit = 0x80000000ULL & f32_val;
9351 int32_t f32_exp = extract32(f32_val, 23, 8);
9352 uint32_t f32_frac = extract32(f32_val, 0, 23);
9353 float64 f64, r64;
9354 uint64_t r64_val;
9355 int64_t r64_exp;
9356 uint64_t r64_frac;
9357
9358 if (float32_is_any_nan(f32)) {
9359 float32 nan = f32;
9360 if (float32_is_signaling_nan(f32, fpst)) {
9361 float_raise(float_flag_invalid, fpst);
9362 nan = float32_maybe_silence_nan(f32, fpst);
9363 }
9364 if (fpst->default_nan_mode) {
9365 nan = float32_default_nan(fpst);
9366 }
9367 return nan;
9368 } else if (float32_is_infinity(f32)) {
9369 return float32_set_sign(float32_zero, float32_is_neg(f32));
9370 } else if (float32_is_zero(f32)) {
9371 float_raise(float_flag_divbyzero, fpst);
9372 return float32_set_sign(float32_infinity, float32_is_neg(f32));
9373 } else if ((f32_val & ~(1ULL << 31)) < (1ULL << 21)) {
9374
9375 float_raise(float_flag_overflow | float_flag_inexact, fpst);
9376 if (round_to_inf(fpst, f32_sbit)) {
9377 return float32_set_sign(float32_infinity, float32_is_neg(f32));
9378 } else {
9379 return float32_set_sign(float32_maxnorm, float32_is_neg(f32));
9380 }
9381 } else if (f32_exp >= 253 && fpst->flush_to_zero) {
9382 float_raise(float_flag_underflow, fpst);
9383 return float32_set_sign(float32_zero, float32_is_neg(f32));
9384 }
9385
9386
9387 f64 = make_float64(((int64_t)(f32_exp) << 52) | (int64_t)(f32_frac) << 29);
9388 r64 = call_recip_estimate(f64, 253, fpst);
9389 r64_val = float64_val(r64);
9390 r64_exp = extract64(r64_val, 52, 11);
9391 r64_frac = extract64(r64_val, 0, 52);
9392
9393
9394 return make_float32(f32_sbit |
9395 (r64_exp & 0xff) << 23 |
9396 extract64(r64_frac, 29, 24));
9397}
9398
9399float64 HELPER(recpe_f64)(float64 input, void *fpstp)
9400{
9401 float_status *fpst = fpstp;
9402 float64 f64 = float64_squash_input_denormal(input, fpst);
9403 uint64_t f64_val = float64_val(f64);
9404 uint64_t f64_sbit = 0x8000000000000000ULL & f64_val;
9405 int64_t f64_exp = extract64(f64_val, 52, 11);
9406 float64 r64;
9407 uint64_t r64_val;
9408 int64_t r64_exp;
9409 uint64_t r64_frac;
9410
9411
9412 if (float64_is_any_nan(f64)) {
9413 float64 nan = f64;
9414 if (float64_is_signaling_nan(f64, fpst)) {
9415 float_raise(float_flag_invalid, fpst);
9416 nan = float64_maybe_silence_nan(f64, fpst);
9417 }
9418 if (fpst->default_nan_mode) {
9419 nan = float64_default_nan(fpst);
9420 }
9421 return nan;
9422 } else if (float64_is_infinity(f64)) {
9423 return float64_set_sign(float64_zero, float64_is_neg(f64));
9424 } else if (float64_is_zero(f64)) {
9425 float_raise(float_flag_divbyzero, fpst);
9426 return float64_set_sign(float64_infinity, float64_is_neg(f64));
9427 } else if ((f64_val & ~(1ULL << 63)) < (1ULL << 50)) {
9428
9429 float_raise(float_flag_overflow | float_flag_inexact, fpst);
9430 if (round_to_inf(fpst, f64_sbit)) {
9431 return float64_set_sign(float64_infinity, float64_is_neg(f64));
9432 } else {
9433 return float64_set_sign(float64_maxnorm, float64_is_neg(f64));
9434 }
9435 } else if (f64_exp >= 2045 && fpst->flush_to_zero) {
9436 float_raise(float_flag_underflow, fpst);
9437 return float64_set_sign(float64_zero, float64_is_neg(f64));
9438 }
9439
9440 r64 = call_recip_estimate(f64, 2045, fpst);
9441 r64_val = float64_val(r64);
9442 r64_exp = extract64(r64_val, 52, 11);
9443 r64_frac = extract64(r64_val, 0, 52);
9444
9445
9446 return make_float64(f64_sbit |
9447 ((r64_exp & 0x7ff) << 52) |
9448 r64_frac);
9449}
9450
9451
9452
9453
9454static float64 recip_sqrt_estimate(float64 a, float_status *real_fp_status)
9455{
9456
9457
9458
9459 float_status dummy_status = *real_fp_status;
9460 float_status *s = &dummy_status;
9461 float64 q;
9462 int64_t q_int;
9463
9464 if (float64_lt(a, float64_half, s)) {
9465
9466
9467
9468
9469 q = float64_mul(float64_512, a, s);
9470 q_int = float64_to_int64_round_to_zero(q, s);
9471
9472
9473
9474 q = int64_to_float64(q_int, s);
9475 q = float64_add(q, float64_half, s);
9476 q = float64_div(q, float64_512, s);
9477 q = float64_sqrt(q, s);
9478 q = float64_div(float64_one, q, s);
9479 } else {
9480
9481
9482
9483
9484 q = float64_mul(float64_256, a, s);
9485 int64_t q_int = float64_to_int64_round_to_zero(q, s);
9486
9487
9488
9489 q = int64_to_float64(q_int, s);
9490 q = float64_add(q, float64_half, s);
9491 q = float64_div(q, float64_256, s);
9492 q = float64_sqrt(q, s);
9493 q = float64_div(float64_one, q, s);
9494 }
9495
9496
9497
9498 q = float64_mul(q, float64_256,s );
9499 q = float64_add(q, float64_half, s);
9500 q_int = float64_to_int64_round_to_zero(q, s);
9501
9502
9503 return float64_div(int64_to_float64(q_int, s), float64_256, s);
9504}
9505
9506float32 HELPER(rsqrte_f32)(float32 input, void *fpstp)
9507{
9508 float_status *s = fpstp;
9509 float32 f32 = float32_squash_input_denormal(input, s);
9510 uint32_t val = float32_val(f32);
9511 uint32_t f32_sbit = 0x80000000 & val;
9512 int32_t f32_exp = extract32(val, 23, 8);
9513 uint32_t f32_frac = extract32(val, 0, 23);
9514 uint64_t f64_frac;
9515 uint64_t val64;
9516 int result_exp;
9517 float64 f64;
9518
9519 if (float32_is_any_nan(f32)) {
9520 float32 nan = f32;
9521 if (float32_is_signaling_nan(f32, s)) {
9522 float_raise(float_flag_invalid, s);
9523 nan = float32_maybe_silence_nan(f32, s);
9524 }
9525 if (s->default_nan_mode) {
9526 nan = float32_default_nan(s);
9527 }
9528 return nan;
9529 } else if (float32_is_zero(f32)) {
9530 float_raise(float_flag_divbyzero, s);
9531 return float32_set_sign(float32_infinity, float32_is_neg(f32));
9532 } else if (float32_is_neg(f32)) {
9533 float_raise(float_flag_invalid, s);
9534 return float32_default_nan(s);
9535 } else if (float32_is_infinity(f32)) {
9536 return float32_zero;
9537 }
9538
9539
9540
9541
9542 f64_frac = ((uint64_t) f32_frac) << 29;
9543 if (f32_exp == 0) {
9544 while (extract64(f64_frac, 51, 1) == 0) {
9545 f64_frac = f64_frac << 1;
9546 f32_exp = f32_exp-1;
9547 }
9548 f64_frac = extract64(f64_frac, 0, 51) << 1;
9549 }
9550
9551 if (extract64(f32_exp, 0, 1) == 0) {
9552 f64 = make_float64(((uint64_t) f32_sbit) << 32
9553 | (0x3feULL << 52)
9554 | f64_frac);
9555 } else {
9556 f64 = make_float64(((uint64_t) f32_sbit) << 32
9557 | (0x3fdULL << 52)
9558 | f64_frac);
9559 }
9560
9561 result_exp = (380 - f32_exp) / 2;
9562
9563 f64 = recip_sqrt_estimate(f64, s);
9564
9565 val64 = float64_val(f64);
9566
9567 val = ((result_exp & 0xff) << 23)
9568 | ((val64 >> 29) & 0x7fffff);
9569 return make_float32(val);
9570}
9571
9572float64 HELPER(rsqrte_f64)(float64 input, void *fpstp)
9573{
9574 float_status *s = fpstp;
9575 float64 f64 = float64_squash_input_denormal(input, s);
9576 uint64_t val = float64_val(f64);
9577 uint64_t f64_sbit = 0x8000000000000000ULL & val;
9578 int64_t f64_exp = extract64(val, 52, 11);
9579 uint64_t f64_frac = extract64(val, 0, 52);
9580 int64_t result_exp;
9581 uint64_t result_frac;
9582
9583 if (float64_is_any_nan(f64)) {
9584 float64 nan = f64;
9585 if (float64_is_signaling_nan(f64, s)) {
9586 float_raise(float_flag_invalid, s);
9587 nan = float64_maybe_silence_nan(f64, s);
9588 }
9589 if (s->default_nan_mode) {
9590 nan = float64_default_nan(s);
9591 }
9592 return nan;
9593 } else if (float64_is_zero(f64)) {
9594 float_raise(float_flag_divbyzero, s);
9595 return float64_set_sign(float64_infinity, float64_is_neg(f64));
9596 } else if (float64_is_neg(f64)) {
9597 float_raise(float_flag_invalid, s);
9598 return float64_default_nan(s);
9599 } else if (float64_is_infinity(f64)) {
9600 return float64_zero;
9601 }
9602
9603
9604
9605
9606 if (f64_exp == 0) {
9607 while (extract64(f64_frac, 51, 1) == 0) {
9608 f64_frac = f64_frac << 1;
9609 f64_exp = f64_exp - 1;
9610 }
9611 f64_frac = extract64(f64_frac, 0, 51) << 1;
9612 }
9613
9614 if (extract64(f64_exp, 0, 1) == 0) {
9615 f64 = make_float64(f64_sbit
9616 | (0x3feULL << 52)
9617 | f64_frac);
9618 } else {
9619 f64 = make_float64(f64_sbit
9620 | (0x3fdULL << 52)
9621 | f64_frac);
9622 }
9623
9624 result_exp = (3068 - f64_exp) / 2;
9625
9626 f64 = recip_sqrt_estimate(f64, s);
9627
9628 result_frac = extract64(float64_val(f64), 0, 52);
9629
9630 return make_float64(f64_sbit |
9631 ((result_exp & 0x7ff) << 52) |
9632 result_frac);
9633}
9634
9635uint32_t HELPER(recpe_u32)(uint32_t a, void *fpstp)
9636{
9637 float_status *s = fpstp;
9638 float64 f64;
9639
9640 if ((a & 0x80000000) == 0) {
9641 return 0xffffffff;
9642 }
9643
9644 f64 = make_float64((0x3feULL << 52)
9645 | ((int64_t)(a & 0x7fffffff) << 21));
9646
9647 f64 = recip_estimate(f64, s);
9648
9649 return 0x80000000 | ((float64_val(f64) >> 21) & 0x7fffffff);
9650}
9651
9652uint32_t HELPER(rsqrte_u32)(uint32_t a, void *fpstp)
9653{
9654 float_status *fpst = fpstp;
9655 float64 f64;
9656
9657 if ((a & 0xc0000000) == 0) {
9658 return 0xffffffff;
9659 }
9660
9661 if (a & 0x80000000) {
9662 f64 = make_float64((0x3feULL << 52)
9663 | ((uint64_t)(a & 0x7fffffff) << 21));
9664 } else {
9665 f64 = make_float64((0x3fdULL << 52)
9666 | ((uint64_t)(a & 0x3fffffff) << 22));
9667 }
9668
9669 f64 = recip_sqrt_estimate(f64, fpst);
9670
9671 return 0x80000000 | ((float64_val(f64) >> 21) & 0x7fffffff);
9672}
9673
9674
9675float32 VFP_HELPER(muladd, s)(float32 a, float32 b, float32 c, void *fpstp)
9676{
9677 float_status *fpst = fpstp;
9678 return float32_muladd(a, b, c, 0, fpst);
9679}
9680
9681float64 VFP_HELPER(muladd, d)(float64 a, float64 b, float64 c, void *fpstp)
9682{
9683 float_status *fpst = fpstp;
9684 return float64_muladd(a, b, c, 0, fpst);
9685}
9686
9687
9688float32 HELPER(rints_exact)(float32 x, void *fp_status)
9689{
9690 return float32_round_to_int(x, fp_status);
9691}
9692
9693float64 HELPER(rintd_exact)(float64 x, void *fp_status)
9694{
9695 return float64_round_to_int(x, fp_status);
9696}
9697
9698float32 HELPER(rints)(float32 x, void *fp_status)
9699{
9700 int old_flags = get_float_exception_flags(fp_status), new_flags;
9701 float32 ret;
9702
9703 ret = float32_round_to_int(x, fp_status);
9704
9705
9706 if (!(old_flags & float_flag_inexact)) {
9707 new_flags = get_float_exception_flags(fp_status);
9708 set_float_exception_flags(new_flags & ~float_flag_inexact, fp_status);
9709 }
9710
9711 return ret;
9712}
9713
9714float64 HELPER(rintd)(float64 x, void *fp_status)
9715{
9716 int old_flags = get_float_exception_flags(fp_status), new_flags;
9717 float64 ret;
9718
9719 ret = float64_round_to_int(x, fp_status);
9720
9721 new_flags = get_float_exception_flags(fp_status);
9722
9723
9724 if (!(old_flags & float_flag_inexact)) {
9725 new_flags = get_float_exception_flags(fp_status);
9726 set_float_exception_flags(new_flags & ~float_flag_inexact, fp_status);
9727 }
9728
9729 return ret;
9730}
9731
9732
9733int arm_rmode_to_sf(int rmode)
9734{
9735 switch (rmode) {
9736 case FPROUNDING_TIEAWAY:
9737 rmode = float_round_ties_away;
9738 break;
9739 case FPROUNDING_ODD:
9740
9741 qemu_log_mask(LOG_UNIMP, "arm: unimplemented rounding mode: %d\n",
9742 rmode);
9743 case FPROUNDING_TIEEVEN:
9744 default:
9745 rmode = float_round_nearest_even;
9746 break;
9747 case FPROUNDING_POSINF:
9748 rmode = float_round_up;
9749 break;
9750 case FPROUNDING_NEGINF:
9751 rmode = float_round_down;
9752 break;
9753 case FPROUNDING_ZERO:
9754 rmode = float_round_to_zero;
9755 break;
9756 }
9757 return rmode;
9758}
9759
9760
9761
9762
9763
9764uint32_t HELPER(crc32)(uint32_t acc, uint32_t val, uint32_t bytes)
9765{
9766 uint8_t buf[4];
9767
9768 stl_le_p(buf, val);
9769
9770
9771 return crc32(acc ^ 0xffffffff, buf, bytes) ^ 0xffffffff;
9772}
9773
9774uint32_t HELPER(crc32c)(uint32_t acc, uint32_t val, uint32_t bytes)
9775{
9776 uint8_t buf[4];
9777
9778 stl_le_p(buf, val);
9779
9780
9781 return crc32c(acc, buf, bytes) ^ 0xffffffff;
9782}
9783