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