target/arm: Move OMAP CP15 register definitions to cpregs-omap.c
The OMAP CP15 registers are only relevant to system-mode emulation of OMAP SoCs. Move them out of the monolithic helper.c into a dedicated file, following the pattern of cpregs-pmu.c and cpregs-gcs.c. This reduces the size of helper.c and compiles the OMAP-specific code out of CONFIG_USER_ONLY builds. Suggested-by: Paolo Bonzini <pbonzini@redhat.com> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Signed-off-by: Alessandro Ratti <alessandro@0x65c.net> Message-id: 20260405180826.729652-1-alessandro@0x65c.net Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Alessandro Ratti committed
Apr 23, 2026 at 10:24 UTC
9672cd7770176297817ef753001ed27c07500253
5 files changed
+103
-78
target/arm/cpregs-omap-stub.c
new
+10
@@ -0,0 +1,10 @@
1
+/* SPDX-License-Identifier: GPL-2.0-or-later */
2
+
3
+#include "qemu/osdep.h"
4
+#include "target/arm/cpu-qom.h"
5
+#include "internals.h"
6
+
7
+void define_omap_cp_regs(ARMCPU *cpu)
8
+{
9
+ g_assert_not_reached();
10
+}
target/arm/cpregs-omap.c
new
+88
@@ -0,0 +1,88 @@
1
+/*
2
+ * QEMU ARM OMAP CP15 register definitions
3
+ *
4
+ * SPDX-License-Identifier: GPL-2.0-or-later
5
+ */
6
+
7
+#include "qemu/osdep.h"
8
+#include "target/arm/cpu.h"
9
+#include "target/arm/cpregs.h"
10
+#include "target/arm/internals.h"
11
+
12
+static void omap_ticonfig_write(CPUARMState *env, const ARMCPRegInfo *ri,
13
+ uint64_t value)
14
+{
15
+ env->cp15.c15_ticonfig = value & 0xe7;
16
+ /* The OS_TYPE bit in this register changes the reported CPUID! */
17
+ env->cp15.c0_cpuid = (value & (1 << 5)) ?
18
+ ARM_CPUID_TI915T : ARM_CPUID_TI925T;
19
+}
20
+
21
+static void omap_threadid_write(CPUARMState *env, const ARMCPRegInfo *ri,
22
+ uint64_t value)
23
+{
24
+ env->cp15.c15_threadid = value & 0xffff;
25
+}
26
+
27
+static void omap_wfi_write(CPUARMState *env, const ARMCPRegInfo *ri,
28
+ uint64_t value)
29
+{
30
+ /* Wait-for-interrupt (deprecated) */
31
+ cpu_interrupt(env_cpu(env), CPU_INTERRUPT_HALT);
32
+}
33
+
34
+static void omap_cachemaint_write(CPUARMState *env, const ARMCPRegInfo *ri,
35
+ uint64_t value)
36
+{
37
+ /*
38
+ * On OMAP there are registers indicating the max/min index of dcache lines
39
+ * containing a dirty line; cache flush operations have to reset these.
40
+ */
41
+ env->cp15.c15_i_max = 0x000;
42
+ env->cp15.c15_i_min = 0xff0;
43
+}
44
+
45
+static const ARMCPRegInfo omap_cp_reginfo[] = {
46
+ { .name = "DFSR", .cp = 15, .crn = 5, .crm = CP_ANY,
47
+ .opc1 = CP_ANY, .opc2 = CP_ANY, .access = PL1_RW, .type = ARM_CP_OVERRIDE,
48
+ .fieldoffset = offsetoflow32(CPUARMState, cp15.esr_el[1]),
49
+ .resetvalue = 0, },
50
+ { .name = "", .cp = 15, .crn = 15, .crm = 0, .opc1 = 0, .opc2 = 0,
51
+ .access = PL1_RW, .type = ARM_CP_NOP },
52
+ { .name = "TICONFIG", .cp = 15, .crn = 15, .crm = 1, .opc1 = 0, .opc2 = 0,
53
+ .access = PL1_RW,
54
+ .fieldoffset = offsetof(CPUARMState, cp15.c15_ticonfig), .resetvalue = 0,
55
+ .writefn = omap_ticonfig_write },
56
+ { .name = "IMAX", .cp = 15, .crn = 15, .crm = 2, .opc1 = 0, .opc2 = 0,
57
+ .access = PL1_RW,
58
+ .fieldoffset = offsetof(CPUARMState, cp15.c15_i_max), .resetvalue = 0, },
59
+ { .name = "IMIN", .cp = 15, .crn = 15, .crm = 3, .opc1 = 0, .opc2 = 0,
60
+ .access = PL1_RW, .resetvalue = 0xff0,
61
+ .fieldoffset = offsetof(CPUARMState, cp15.c15_i_min) },
62
+ { .name = "THREADID", .cp = 15, .crn = 15, .crm = 4, .opc1 = 0, .opc2 = 0,
63
+ .access = PL1_RW,
64
+ .fieldoffset = offsetof(CPUARMState, cp15.c15_threadid), .resetvalue = 0,
65
+ .writefn = omap_threadid_write },
66
+ { .name = "TI925T_STATUS", .cp = 15, .crn = 15,
67
+ .crm = 8, .opc1 = 0, .opc2 = 0, .access = PL1_RW,
68
+ .type = ARM_CP_NO_RAW,
69
+ .readfn = arm_cp_read_zero, .writefn = omap_wfi_write, },
70
+ /*
71
+ * TODO: Peripheral port remap register:
72
+ * On OMAP2 mcr p15, 0, rn, c15, c2, 4 sets up the interrupt controller
73
+ * base address at $rn & ~0xfff and map size of 0x200 << ($rn & 0xfff),
74
+ * when MMU is off.
75
+ */
76
+ { .name = "OMAP_CACHEMAINT", .cp = 15, .crn = 7, .crm = CP_ANY,
77
+ .opc1 = 0, .opc2 = CP_ANY, .access = PL1_W,
78
+ .type = ARM_CP_OVERRIDE | ARM_CP_NO_RAW,
79
+ .writefn = omap_cachemaint_write },
80
+ { .name = "C9", .cp = 15, .crn = 9,
81
+ .crm = CP_ANY, .opc1 = CP_ANY, .opc2 = CP_ANY, .access = PL1_RW,
82
+ .type = ARM_CP_CONST | ARM_CP_OVERRIDE, .resetvalue = 0 },
83
+};
84
+
85
+void define_omap_cp_regs(ARMCPU *cpu)
86
+{
87
+ define_arm_cp_regs(cpu, omap_cp_reginfo);
88
+}
target/arm/helper.c
+1
-78
@@ -2900,83 +2900,6 @@ static const ARMCPRegInfo ttbcr2_reginfo = {
2900
},
2901
};
2902
2903
-static void omap_ticonfig_write(CPUARMState *env, const ARMCPRegInfo *ri,
2904
- uint64_t value)
2905
-{
2906
- env->cp15.c15_ticonfig = value & 0xe7;
2907
- /* The OS_TYPE bit in this register changes the reported CPUID! */
2908
- env->cp15.c0_cpuid = (value & (1 << 5)) ?
2909
- ARM_CPUID_TI915T : ARM_CPUID_TI925T;
2910
-}
2911
-
2912
-static void omap_threadid_write(CPUARMState *env, const ARMCPRegInfo *ri,
2913
- uint64_t value)
2914
-{
2915
- env->cp15.c15_threadid = value & 0xffff;
2916
-}
2917
-
2918
-static void omap_wfi_write(CPUARMState *env, const ARMCPRegInfo *ri,
2919
- uint64_t value)
2920
-{
2921
-#ifdef CONFIG_USER_ONLY
2922
- g_assert_not_reached();
2923
-#else
2924
- /* Wait-for-interrupt (deprecated) */
2925
- cpu_interrupt(env_cpu(env), CPU_INTERRUPT_HALT);
2926
-#endif
2927
-}
2928
-
2929
-static void omap_cachemaint_write(CPUARMState *env, const ARMCPRegInfo *ri,
2930
- uint64_t value)
2931
-{
2932
- /*
2933
- * On OMAP there are registers indicating the max/min index of dcache lines
2934
- * containing a dirty line; cache flush operations have to reset these.
2935
- */
2936
- env->cp15.c15_i_max = 0x000;
2937
- env->cp15.c15_i_min = 0xff0;
2938
-}
2939
-
2940
-static const ARMCPRegInfo omap_cp_reginfo[] = {
2941
- { .name = "DFSR", .cp = 15, .crn = 5, .crm = CP_ANY,
2942
- .opc1 = CP_ANY, .opc2 = CP_ANY, .access = PL1_RW, .type = ARM_CP_OVERRIDE,
2943
- .fieldoffset = offsetoflow32(CPUARMState, cp15.esr_el[1]),
2944
- .resetvalue = 0, },
2945
- { .name = "", .cp = 15, .crn = 15, .crm = 0, .opc1 = 0, .opc2 = 0,
2946
- .access = PL1_RW, .type = ARM_CP_NOP },
2947
- { .name = "TICONFIG", .cp = 15, .crn = 15, .crm = 1, .opc1 = 0, .opc2 = 0,
2948
- .access = PL1_RW,
2949
- .fieldoffset = offsetof(CPUARMState, cp15.c15_ticonfig), .resetvalue = 0,
2950
- .writefn = omap_ticonfig_write },
2951
- { .name = "IMAX", .cp = 15, .crn = 15, .crm = 2, .opc1 = 0, .opc2 = 0,
2952
- .access = PL1_RW,
2953
- .fieldoffset = offsetof(CPUARMState, cp15.c15_i_max), .resetvalue = 0, },
2954
- { .name = "IMIN", .cp = 15, .crn = 15, .crm = 3, .opc1 = 0, .opc2 = 0,
2955
- .access = PL1_RW, .resetvalue = 0xff0,
2956
- .fieldoffset = offsetof(CPUARMState, cp15.c15_i_min) },
2957
- { .name = "THREADID", .cp = 15, .crn = 15, .crm = 4, .opc1 = 0, .opc2 = 0,
2958
- .access = PL1_RW,
2959
- .fieldoffset = offsetof(CPUARMState, cp15.c15_threadid), .resetvalue = 0,
2960
- .writefn = omap_threadid_write },
2961
- { .name = "TI925T_STATUS", .cp = 15, .crn = 15,
2962
- .crm = 8, .opc1 = 0, .opc2 = 0, .access = PL1_RW,
2963
- .type = ARM_CP_NO_RAW,
2964
- .readfn = arm_cp_read_zero, .writefn = omap_wfi_write, },
2965
- /*
2966
- * TODO: Peripheral port remap register:
2967
- * On OMAP2 mcr p15, 0, rn, c15, c2, 4 sets up the interrupt controller
2968
- * base address at $rn & ~0xfff and map size of 0x200 << ($rn & 0xfff),
2969
- * when MMU is off.
2970
- */
2971
- { .name = "OMAP_CACHEMAINT", .cp = 15, .crn = 7, .crm = CP_ANY,
2972
- .opc1 = 0, .opc2 = CP_ANY, .access = PL1_W,
2973
- .type = ARM_CP_OVERRIDE | ARM_CP_NO_RAW,
2974
- .writefn = omap_cachemaint_write },
2975
- { .name = "C9", .cp = 15, .crn = 9,
2976
- .crm = CP_ANY, .opc1 = CP_ANY, .opc2 = CP_ANY, .access = PL1_RW,
2977
- .type = ARM_CP_CONST | ARM_CP_OVERRIDE, .resetvalue = 0 },
2978
-};
2979
-
2903
static const ARMCPRegInfo dummy_c15_cp_reginfo[] = {
2904
/*
2905
* RAZ/WI the whole crn=15 space, when we don't have a more specific
@@ -7043,7 +6966,7 @@ void register_cp_regs_for_features(ARMCPU *cpu)
6966
define_arm_cp_regs(cpu, cache_block_ops_cp_reginfo);
6967
}
6968
if (arm_feature(env, ARM_FEATURE_OMAPCP)) {
7046
- define_arm_cp_regs(cpu, omap_cp_reginfo);
6969
+ define_omap_cp_regs(cpu);
6970
}
6971
if (arm_feature(env, ARM_FEATURE_STRONGARM)) {
6972
define_arm_cp_regs(cpu, strongarm_cp_reginfo);
target/arm/internals.h
+2
@@ -1799,6 +1799,8 @@ void define_at_insn_regs(ARMCPU *cpu);
1799
void define_pm_cpregs(ARMCPU *cpu);
1800
/* Add the cpreg definitions for GCS cpregs */
1801
void define_gcs_cpregs(ARMCPU *cpu);
1802
+/* Add the cpreg definitions for OMAP CP15 regs */
1803
+void define_omap_cp_regs(ARMCPU *cpu);
1804
1805
/* Effective value of MDCR_EL2 */
1806
static inline uint64_t arm_mdcr_el2_eff(CPUARMState *env)
target/arm/meson.build
+2
@@ -33,6 +33,7 @@ arm_user_ss.add(files(
33
'helper.c',
34
'vfp_fpscr.c',
35
'el2-stubs.c',
36
+ 'cpregs-omap-stub.c',
37
))
38
arm_user_ss.add(when: 'CONFIG_ARM_COMPATIBLE_SEMIHOSTING',
39
if_true: files('common-semi-target.c'))
@@ -48,6 +49,7 @@ arm_common_system_ss.add(files(
49
'arm-powerctl.c',
50
'cortex-regs.c',
51
'cpregs-gcs.c',
52
+ 'cpregs-omap.c',
53
'cpregs-pmu.c',
54
'cpu-irq.c',
55
'debug_helper.c',