1
Two small bugfixes, plus most of RTH's refactoring of cpregs
1
Hi; here's a target-arm pullreq to go in before softfreeze.
2
handling.
2
This is actually pretty much entirely bugfixes (since the
3
SEL2 timers we implement here are a missing part of a feature
4
we claim to already implement).
3
5
6
thanks
4
-- PMM
7
-- PMM
5
8
6
The following changes since commit 1fba9dc71a170b3a05b9d3272dd8ecfe7f26e215:
9
The following changes since commit 98c7362b1efe651327385a25874a73e008c6549e:
7
10
8
Merge tag 'pull-request-2022-05-04' of https://gitlab.com/thuth/qemu into staging (2022-05-04 08:07:02 -0700)
11
Merge tag 'accel-cpus-20250306' of https://github.com/philmd/qemu into staging (2025-03-07 07:39:49 +0800)
9
12
10
are available in the Git repository at:
13
are available in the Git repository at:
11
14
12
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20220505
15
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20250307
13
16
14
for you to fetch changes up to 99a50d1a67c602126fc2b3a4812d3000eba9bf34:
17
for you to fetch changes up to 0ce0739d46983e5e88fa9c149cb305689c9d8c6f:
15
18
16
target/arm: read access to performance counters from EL0 (2022-05-05 09:36:22 +0100)
19
target/rx: Remove TCG_CALL_NO_WG from helpers which write env (2025-03-07 15:03:20 +0000)
17
20
18
----------------------------------------------------------------
21
----------------------------------------------------------------
19
target-arm queue:
22
target-arm queue:
20
* Enable read access to performance counters from EL0
23
* hw/arm/smmu-common: Remove the repeated ttb field
21
* Enable SCTLR_EL1.BT0 for aarch64-linux-user
24
* hw/gpio: npcm7xx: fixup out-of-bounds access
22
* Refactoring of cpreg handling
25
* tests/functional/test_arm_sx1: Check whether the serial console is working
26
* target/arm: Fix minor bugs in generic timer register handling
27
* target/arm: Implement SEL2 physical and virtual timers
28
* target/arm: Correct STRD, LDRD atomicity and fault behaviour
29
* target/arm: Make dummy debug registers RAZ, not NOP
30
* util/qemu-timer.c: Don't warp timer from timerlist_rearm()
31
* include/exec/memop.h: Expand comment for MO_ATOM_SUBALIGN
32
* hw/arm/smmu: Introduce smmu_configs_inv_sid_range() helper
33
* target/rx: Set exception vector base to 0xffffff80
34
* target/rx: Remove TCG_CALL_NO_WG from helpers which write env
23
35
24
----------------------------------------------------------------
36
----------------------------------------------------------------
25
Alex Zuepke (1):
37
Alex Bennée (4):
26
target/arm: read access to performance counters from EL0
38
target/arm: Implement SEL2 physical and virtual timers
39
target/arm: Document the architectural names of our GTIMERs
40
hw/arm: enable secure EL2 timers for virt machine
41
hw/arm: enable secure EL2 timers for sbsa machine
27
42
28
Richard Henderson (22):
43
JianChunfu (2):
29
target/arm: Enable SCTLR_EL1.BT0 for aarch64-linux-user
44
hw/arm/smmu-common: Remove the repeated ttb field
30
target/arm: Split out cpregs.h
45
hw/arm/smmu: Introduce smmu_configs_inv_sid_range() helper
31
target/arm: Reorg CPAccessResult and access_check_cp_reg
32
target/arm: Replace sentinels with ARRAY_SIZE in cpregs.h
33
target/arm: Make some more cpreg data static const
34
target/arm: Reorg ARMCPRegInfo type field bits
35
target/arm: Avoid bare abort() or assert(0)
36
target/arm: Change cpreg access permissions to enum
37
target/arm: Name CPState type
38
target/arm: Name CPSecureState type
39
target/arm: Drop always-true test in define_arm_vh_e2h_redirects_aliases
40
target/arm: Store cpregs key in the hash table directly
41
target/arm: Merge allocation of the cpreg and its name
42
target/arm: Hoist computation of key in add_cpreg_to_hashtable
43
target/arm: Consolidate cpreg updates in add_cpreg_to_hashtable
44
target/arm: Use bool for is64 and ns in add_cpreg_to_hashtable
45
target/arm: Hoist isbanked computation in add_cpreg_to_hashtable
46
target/arm: Perform override check early in add_cpreg_to_hashtable
47
target/arm: Reformat comments in add_cpreg_to_hashtable
48
target/arm: Remove HOST_BIG_ENDIAN ifdef in add_cpreg_to_hashtable
49
target/arm: Add isar predicates for FEAT_Debugv8p2
50
target/arm: Add isar_feature_{aa64,any}_ras
51
46
52
target/arm/cpregs.h | 453 ++++++++++++++++++++++++++++++++++++++
47
Keith Packard (2):
53
target/arm/cpu.h | 393 +++------------------------------
48
target/rx: Set exception vector base to 0xffffff80
54
hw/arm/pxa2xx.c | 2 +-
49
target/rx: Remove TCG_CALL_NO_WG from helpers which write env
55
hw/arm/pxa2xx_pic.c | 2 +-
50
56
hw/intc/arm_gicv3_cpuif.c | 6 +-
51
Patrick Venture (1):
57
hw/intc/arm_gicv3_kvm.c | 3 +-
52
hw/gpio: npcm7xx: fixup out-of-bounds access
58
target/arm/cpu.c | 25 +--
53
59
target/arm/cpu64.c | 2 +-
54
Peter Maydell (11):
60
target/arm/cpu_tcg.c | 5 +-
55
target/arm: Apply correct timer offset when calculating deadlines
61
target/arm/gdbstub.c | 5 +-
56
target/arm: Don't apply CNTVOFF_EL2 for EL2_VIRT timer
62
target/arm/helper.c | 358 +++++++++++++-----------------
57
target/arm: Make CNTPS_* UNDEF from Secure EL1 when Secure EL2 is enabled
63
target/arm/hvf/hvf.c | 2 +-
58
target/arm: Always apply CNTVOFF_EL2 for CNTV_TVAL_EL02 accesses
64
target/arm/kvm-stub.c | 4 +-
59
target/arm: Refactor handling of timer offset for direct register accesses
65
target/arm/kvm.c | 4 +-
60
target/arm: Correct LDRD atomicity and fault behaviour
66
target/arm/machine.c | 4 +-
61
target/arm: Correct STRD atomicity
67
target/arm/op_helper.c | 57 ++---
62
target/arm: Drop unused address_offset from op_addr_{rr, ri}_post()
68
target/arm/translate-a64.c | 14 +-
63
target/arm: Make dummy debug registers RAZ, not NOP
69
target/arm/translate-neon.c | 2 +-
64
util/qemu-timer.c: Don't warp timer from timerlist_rearm()
70
target/arm/translate.c | 13 +-
65
include/exec/memop.h: Expand comment for MO_ATOM_SUBALIGN
71
tests/tcg/aarch64/bti-3.c | 42 ++++
66
72
tests/tcg/aarch64/Makefile.target | 6 +-
67
Thomas Huth (1):
73
21 files changed, 738 insertions(+), 664 deletions(-)
68
tests/functional/test_arm_sx1: Check whether the serial console is working
74
create mode 100644 target/arm/cpregs.h
69
75
create mode 100644 tests/tcg/aarch64/bti-3.c
70
MAINTAINERS | 1 +
71
hw/arm/smmu-internal.h | 5 -
72
include/exec/memop.h | 8 +-
73
include/hw/arm/bsa.h | 2 +
74
include/hw/arm/smmu-common.h | 7 +-
75
target/arm/cpu.h | 2 +
76
target/arm/gtimer.h | 14 +-
77
target/arm/internals.h | 5 +-
78
target/rx/helper.h | 34 ++--
79
hw/arm/sbsa-ref.c | 2 +
80
hw/arm/smmu-common.c | 21 +++
81
hw/arm/smmuv3.c | 19 +--
82
hw/arm/virt.c | 2 +
83
hw/gpio/npcm7xx_gpio.c | 3 +-
84
target/arm/cpu.c | 4 +
85
target/arm/debug_helper.c | 7 +-
86
target/arm/helper.c | 324 ++++++++++++++++++++++++++++++++-------
87
target/arm/tcg/op_helper.c | 8 +-
88
target/arm/tcg/translate.c | 147 +++++++++++-------
89
target/rx/helper.c | 2 +-
90
util/qemu-timer.c | 4 -
91
hw/arm/trace-events | 3 +-
92
tests/functional/test_arm_sx1.py | 7 +-
93
23 files changed, 455 insertions(+), 176 deletions(-)
94
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
This controls whether the PACI{A,B}SP instructions trap with BTYPE=3
4
(indirect branch from register other than x16/x17). The linux kernel
5
sets this in bti_enable().
6
7
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/998
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Message-id: 20220427042312.294300-1-richard.henderson@linaro.org
11
[PMM: remove stray change to makefile comment]
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
14
target/arm/cpu.c | 2 ++
15
tests/tcg/aarch64/bti-3.c | 42 +++++++++++++++++++++++++++++++
16
tests/tcg/aarch64/Makefile.target | 6 ++---
17
3 files changed, 47 insertions(+), 3 deletions(-)
18
create mode 100644 tests/tcg/aarch64/bti-3.c
19
20
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
21
index XXXXXXX..XXXXXXX 100644
22
--- a/target/arm/cpu.c
23
+++ b/target/arm/cpu.c
24
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_reset(DeviceState *dev)
25
/* Enable all PAC keys. */
26
env->cp15.sctlr_el[1] |= (SCTLR_EnIA | SCTLR_EnIB |
27
SCTLR_EnDA | SCTLR_EnDB);
28
+ /* Trap on btype=3 for PACIxSP. */
29
+ env->cp15.sctlr_el[1] |= SCTLR_BT0;
30
/* and to the FP/Neon instructions */
31
env->cp15.cpacr_el1 = deposit64(env->cp15.cpacr_el1, 20, 2, 3);
32
/* and to the SVE instructions */
33
diff --git a/tests/tcg/aarch64/bti-3.c b/tests/tcg/aarch64/bti-3.c
34
new file mode 100644
35
index XXXXXXX..XXXXXXX
36
--- /dev/null
37
+++ b/tests/tcg/aarch64/bti-3.c
38
@@ -XXX,XX +XXX,XX @@
39
+/*
40
+ * BTI vs PACIASP
41
+ */
42
+
43
+#include "bti-crt.inc.c"
44
+
45
+static void skip2_sigill(int sig, siginfo_t *info, ucontext_t *uc)
46
+{
47
+ uc->uc_mcontext.pc += 8;
48
+ uc->uc_mcontext.pstate = 1;
49
+}
50
+
51
+#define BTYPE_1() \
52
+ asm("mov %0,#1; adr x16, 1f; br x16; 1: hint #25; mov %0,#0" \
53
+ : "=r"(skipped) : : "x16", "x30")
54
+
55
+#define BTYPE_2() \
56
+ asm("mov %0,#1; adr x16, 1f; blr x16; 1: hint #25; mov %0,#0" \
57
+ : "=r"(skipped) : : "x16", "x30")
58
+
59
+#define BTYPE_3() \
60
+ asm("mov %0,#1; adr x15, 1f; br x15; 1: hint #25; mov %0,#0" \
61
+ : "=r"(skipped) : : "x15", "x30")
62
+
63
+#define TEST(WHICH, EXPECT) \
64
+ do { WHICH(); fail += skipped ^ EXPECT; } while (0)
65
+
66
+int main()
67
+{
68
+ int fail = 0;
69
+ int skipped;
70
+
71
+ /* Signal-like with SA_SIGINFO. */
72
+ signal_info(SIGILL, skip2_sigill);
73
+
74
+ /* With SCTLR_EL1.BT0 set, PACIASP is not compatible with type=3. */
75
+ TEST(BTYPE_1, 0);
76
+ TEST(BTYPE_2, 0);
77
+ TEST(BTYPE_3, 1);
78
+
79
+ return fail;
80
+}
81
diff --git a/tests/tcg/aarch64/Makefile.target b/tests/tcg/aarch64/Makefile.target
82
index XXXXXXX..XXXXXXX 100644
83
--- a/tests/tcg/aarch64/Makefile.target
84
+++ b/tests/tcg/aarch64/Makefile.target
85
@@ -XXX,XX +XXX,XX @@ endif
86
# BTI Tests
87
# bti-1 tests the elf notes, so we require special compiler support.
88
ifneq ($(CROSS_CC_HAS_ARMV8_BTI),)
89
-AARCH64_TESTS += bti-1
90
-bti-1: CFLAGS += -mbranch-protection=standard
91
-bti-1: LDFLAGS += -nostdlib
92
+AARCH64_TESTS += bti-1 bti-3
93
+bti-1 bti-3: CFLAGS += -mbranch-protection=standard
94
+bti-1 bti-3: LDFLAGS += -nostdlib
95
endif
96
# bti-2 tests PROT_BTI, so no special compiler support required.
97
AARCH64_TESTS += bti-2
98
--
99
2.25.1
diff view generated by jsdifflib
1
From: Alex Zuepke <alex.zuepke@tum.de>
1
From: JianChunfu <jansef.jian@hj-micro.com>
2
2
3
The ARMv8 manual defines that PMUSERENR_EL0.ER enables read-access
3
SMMUTransCfg->ttb is never used in QEMU, TT base address
4
to both PMXEVCNTR_EL0 and PMEVCNTR<n>_EL0 registers, however,
4
can be accessed by SMMUTransCfg->tt[i]->ttb.
5
we only use it for PMXEVCNTR_EL0. Extend to PMEVCNTR<n>_EL0 as well.
6
5
7
Signed-off-by: Alex Zuepke <alex.zuepke@tum.de>
6
Signed-off-by: JianChunfu <jansef.jian@hj-micro.com>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Eric Auger <eric.auger@redhat.com>
9
Message-id: 20220428132717.84190-1-alex.zuepke@tum.de
8
Message-id: 20250221031034.69822-1-jansef.jian@hj-micro.com
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
10
---
12
target/arm/helper.c | 4 ++--
11
include/hw/arm/smmu-common.h | 1 -
13
1 file changed, 2 insertions(+), 2 deletions(-)
12
1 file changed, 1 deletion(-)
14
13
15
diff --git a/target/arm/helper.c b/target/arm/helper.c
14
diff --git a/include/hw/arm/smmu-common.h b/include/hw/arm/smmu-common.h
16
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/helper.c
16
--- a/include/hw/arm/smmu-common.h
18
+++ b/target/arm/helper.c
17
+++ b/include/hw/arm/smmu-common.h
19
@@ -XXX,XX +XXX,XX @@ static void define_pmu_regs(ARMCPU *cpu)
18
@@ -XXX,XX +XXX,XX @@ typedef struct SMMUTransCfg {
20
.crm = 8 | (3 & (i >> 3)), .opc1 = 0, .opc2 = i & 7,
19
/* Used by stage-1 only. */
21
.access = PL0_RW, .type = ARM_CP_IO | ARM_CP_ALIAS,
20
bool aa64; /* arch64 or aarch32 translation table */
22
.readfn = pmevcntr_readfn, .writefn = pmevcntr_writefn,
21
bool record_faults; /* record fault events */
23
- .accessfn = pmreg_access },
22
- uint64_t ttb; /* TT base address */
24
+ .accessfn = pmreg_access_xevcntr },
23
uint8_t oas; /* output address width */
25
{ .name = pmevcntr_el0_name, .state = ARM_CP_STATE_AA64,
24
uint8_t tbi; /* Top Byte Ignore */
26
.opc0 = 3, .opc1 = 3, .crn = 14, .crm = 8 | (3 & (i >> 3)),
25
int asid;
27
- .opc2 = i & 7, .access = PL0_RW, .accessfn = pmreg_access,
28
+ .opc2 = i & 7, .access = PL0_RW, .accessfn = pmreg_access_xevcntr,
29
.type = ARM_CP_IO,
30
.readfn = pmevcntr_readfn, .writefn = pmevcntr_writefn,
31
.raw_readfn = pmevcntr_rawread,
32
--
26
--
33
2.25.1
27
2.43.0
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Patrick Venture <venture@google.com>
2
2
3
Instead of defining ARM_CP_FLAG_MASK to remove flags,
3
The reg isn't validated to be a possible register before
4
define ARM_CP_SPECIAL_MASK to isolate special cases.
4
it's dereferenced for one case. The mmio space registered
5
Sort the specials to the low bits. Use an enum.
5
for the gpio device is 4KiB but there aren't that many
6
registers in the struct.
6
7
7
Split the large comment block so as to document each
8
Cc: qemu-stable@nongnu.org
8
value separately.
9
Fixes: 526dbbe0874 ("hw/gpio: Add GPIO model for Nuvoton NPCM7xx")
9
10
Signed-off-by: Patrick Venture <venture@google.com>
10
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
Message-id: 20250226024603.493148-1-venture@google.com
12
Message-id: 20220501055028.646596-6-richard.henderson@linaro.org
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
14
---
15
target/arm/cpregs.h | 130 +++++++++++++++++++++++--------------
15
hw/gpio/npcm7xx_gpio.c | 3 +--
16
target/arm/cpu.c | 4 +-
16
1 file changed, 1 insertion(+), 2 deletions(-)
17
target/arm/helper.c | 4 +-
18
target/arm/translate-a64.c | 6 +-
19
target/arm/translate.c | 6 +-
20
5 files changed, 92 insertions(+), 58 deletions(-)
21
17
22
diff --git a/target/arm/cpregs.h b/target/arm/cpregs.h
18
diff --git a/hw/gpio/npcm7xx_gpio.c b/hw/gpio/npcm7xx_gpio.c
23
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
24
--- a/target/arm/cpregs.h
20
--- a/hw/gpio/npcm7xx_gpio.c
25
+++ b/target/arm/cpregs.h
21
+++ b/hw/gpio/npcm7xx_gpio.c
26
@@ -XXX,XX +XXX,XX @@
22
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_gpio_regs_write(void *opaque, hwaddr addr, uint64_t v,
27
#define TARGET_ARM_CPREGS_H
28
29
/*
30
- * ARMCPRegInfo type field bits. If the SPECIAL bit is set this is a
31
- * special-behaviour cp reg and bits [11..8] indicate what behaviour
32
- * it has. Otherwise it is a simple cp reg, where CONST indicates that
33
- * TCG can assume the value to be constant (ie load at translate time)
34
- * and 64BIT indicates a 64 bit wide coprocessor register. SUPPRESS_TB_END
35
- * indicates that the TB should not be ended after a write to this register
36
- * (the default is that the TB ends after cp writes). OVERRIDE permits
37
- * a register definition to override a previous definition for the
38
- * same (cp, is64, crn, crm, opc1, opc2) tuple: either the new or the
39
- * old must have the OVERRIDE bit set.
40
- * ALIAS indicates that this register is an alias view of some underlying
41
- * state which is also visible via another register, and that the other
42
- * register is handling migration and reset; registers marked ALIAS will not be
43
- * migrated but may have their state set by syncing of register state from KVM.
44
- * NO_RAW indicates that this register has no underlying state and does not
45
- * support raw access for state saving/loading; it will not be used for either
46
- * migration or KVM state synchronization. (Typically this is for "registers"
47
- * which are actually used as instructions for cache maintenance and so on.)
48
- * IO indicates that this register does I/O and therefore its accesses
49
- * need to be marked with gen_io_start() and also end the TB. In particular,
50
- * registers which implement clocks or timers require this.
51
- * RAISES_EXC is for when the read or write hook might raise an exception;
52
- * the generated code will synchronize the CPU state before calling the hook
53
- * so that it is safe for the hook to call raise_exception().
54
- * NEWEL is for writes to registers that might change the exception
55
- * level - typically on older ARM chips. For those cases we need to
56
- * re-read the new el when recomputing the translation flags.
57
+ * ARMCPRegInfo type field bits:
58
*/
59
-#define ARM_CP_SPECIAL 0x0001
60
-#define ARM_CP_CONST 0x0002
61
-#define ARM_CP_64BIT 0x0004
62
-#define ARM_CP_SUPPRESS_TB_END 0x0008
63
-#define ARM_CP_OVERRIDE 0x0010
64
-#define ARM_CP_ALIAS 0x0020
65
-#define ARM_CP_IO 0x0040
66
-#define ARM_CP_NO_RAW 0x0080
67
-#define ARM_CP_NOP (ARM_CP_SPECIAL | 0x0100)
68
-#define ARM_CP_WFI (ARM_CP_SPECIAL | 0x0200)
69
-#define ARM_CP_NZCV (ARM_CP_SPECIAL | 0x0300)
70
-#define ARM_CP_CURRENTEL (ARM_CP_SPECIAL | 0x0400)
71
-#define ARM_CP_DC_ZVA (ARM_CP_SPECIAL | 0x0500)
72
-#define ARM_CP_DC_GVA (ARM_CP_SPECIAL | 0x0600)
73
-#define ARM_CP_DC_GZVA (ARM_CP_SPECIAL | 0x0700)
74
-#define ARM_LAST_SPECIAL ARM_CP_DC_GZVA
75
-#define ARM_CP_FPU 0x1000
76
-#define ARM_CP_SVE 0x2000
77
-#define ARM_CP_NO_GDB 0x4000
78
-#define ARM_CP_RAISES_EXC 0x8000
79
-#define ARM_CP_NEWEL 0x10000
80
-/* Mask of only the flag bits in a type field */
81
-#define ARM_CP_FLAG_MASK 0x1f0ff
82
+enum {
83
+ /*
84
+ * Register must be handled specially during translation.
85
+ * The method is one of the values below:
86
+ */
87
+ ARM_CP_SPECIAL_MASK = 0x000f,
88
+ /* Special: no change to PE state: writes ignored, reads ignored. */
89
+ ARM_CP_NOP = 0x0001,
90
+ /* Special: sysreg is WFI, for v5 and v6. */
91
+ ARM_CP_WFI = 0x0002,
92
+ /* Special: sysreg is NZCV. */
93
+ ARM_CP_NZCV = 0x0003,
94
+ /* Special: sysreg is CURRENTEL. */
95
+ ARM_CP_CURRENTEL = 0x0004,
96
+ /* Special: sysreg is DC ZVA or similar. */
97
+ ARM_CP_DC_ZVA = 0x0005,
98
+ ARM_CP_DC_GVA = 0x0006,
99
+ ARM_CP_DC_GZVA = 0x0007,
100
+
101
+ /* Flag: reads produce resetvalue; writes ignored. */
102
+ ARM_CP_CONST = 1 << 4,
103
+ /* Flag: For ARM_CP_STATE_AA32, sysreg is 64-bit. */
104
+ ARM_CP_64BIT = 1 << 5,
105
+ /*
106
+ * Flag: TB should not be ended after a write to this register
107
+ * (the default is that the TB ends after cp writes).
108
+ */
109
+ ARM_CP_SUPPRESS_TB_END = 1 << 6,
110
+ /*
111
+ * Flag: Permit a register definition to override a previous definition
112
+ * for the same (cp, is64, crn, crm, opc1, opc2) tuple: either the new
113
+ * or the old must have the ARM_CP_OVERRIDE bit set.
114
+ */
115
+ ARM_CP_OVERRIDE = 1 << 7,
116
+ /*
117
+ * Flag: Register is an alias view of some underlying state which is also
118
+ * visible via another register, and that the other register is handling
119
+ * migration and reset; registers marked ARM_CP_ALIAS will not be migrated
120
+ * but may have their state set by syncing of register state from KVM.
121
+ */
122
+ ARM_CP_ALIAS = 1 << 8,
123
+ /*
124
+ * Flag: Register does I/O and therefore its accesses need to be marked
125
+ * with gen_io_start() and also end the TB. In particular, registers which
126
+ * implement clocks or timers require this.
127
+ */
128
+ ARM_CP_IO = 1 << 9,
129
+ /*
130
+ * Flag: Register has no underlying state and does not support raw access
131
+ * for state saving/loading; it will not be used for either migration or
132
+ * KVM state synchronization. Typically this is for "registers" which are
133
+ * actually used as instructions for cache maintenance and so on.
134
+ */
135
+ ARM_CP_NO_RAW = 1 << 10,
136
+ /*
137
+ * Flag: The read or write hook might raise an exception; the generated
138
+ * code will synchronize the CPU state before calling the hook so that it
139
+ * is safe for the hook to call raise_exception().
140
+ */
141
+ ARM_CP_RAISES_EXC = 1 << 11,
142
+ /*
143
+ * Flag: Writes to the sysreg might change the exception level - typically
144
+ * on older ARM chips. For those cases we need to re-read the new el when
145
+ * recomputing the translation flags.
146
+ */
147
+ ARM_CP_NEWEL = 1 << 12,
148
+ /*
149
+ * Flag: Access check for this sysreg is identical to accessing FPU state
150
+ * from an instruction: use translation fp_access_check().
151
+ */
152
+ ARM_CP_FPU = 1 << 13,
153
+ /*
154
+ * Flag: Access check for this sysreg is identical to accessing SVE state
155
+ * from an instruction: use translation sve_access_check().
156
+ */
157
+ ARM_CP_SVE = 1 << 14,
158
+ /* Flag: Do not expose in gdb sysreg xml. */
159
+ ARM_CP_NO_GDB = 1 << 15,
160
+};
161
162
/*
163
* Valid values for ARMCPRegInfo state field, indicating which of
164
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
165
index XXXXXXX..XXXXXXX 100644
166
--- a/target/arm/cpu.c
167
+++ b/target/arm/cpu.c
168
@@ -XXX,XX +XXX,XX @@ static void cp_reg_reset(gpointer key, gpointer value, gpointer opaque)
169
ARMCPRegInfo *ri = value;
170
ARMCPU *cpu = opaque;
171
172
- if (ri->type & (ARM_CP_SPECIAL | ARM_CP_ALIAS)) {
173
+ if (ri->type & (ARM_CP_SPECIAL_MASK | ARM_CP_ALIAS)) {
174
return;
23
return;
175
}
24
}
176
25
177
@@ -XXX,XX +XXX,XX @@ static void cp_reg_check_reset(gpointer key, gpointer value, gpointer opaque)
26
- diff = s->regs[reg] ^ value;
178
ARMCPU *cpu = opaque;
27
-
179
uint64_t oldvalue, newvalue;
28
switch (reg) {
180
29
case NPCM7XX_GPIO_TLOCK1:
181
- if (ri->type & (ARM_CP_SPECIAL | ARM_CP_ALIAS | ARM_CP_NO_RAW)) {
30
case NPCM7XX_GPIO_TLOCK2:
182
+ if (ri->type & (ARM_CP_SPECIAL_MASK | ARM_CP_ALIAS | ARM_CP_NO_RAW)) {
31
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_gpio_regs_write(void *opaque, hwaddr addr, uint64_t v,
183
return;
32
case NPCM7XX_GPIO_PU:
184
}
33
case NPCM7XX_GPIO_PD:
185
34
case NPCM7XX_GPIO_IEM:
186
diff --git a/target/arm/helper.c b/target/arm/helper.c
35
+ diff = s->regs[reg] ^ value;
187
index XXXXXXX..XXXXXXX 100644
36
s->regs[reg] = value;
188
--- a/target/arm/helper.c
37
npcm7xx_gpio_update_pins(s, diff);
189
+++ b/target/arm/helper.c
38
break;
190
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
191
* multiple times. Special registers (ie NOP/WFI) are
192
* never migratable and not even raw-accessible.
193
*/
194
- if ((r->type & ARM_CP_SPECIAL)) {
195
+ if (r->type & ARM_CP_SPECIAL_MASK) {
196
r2->type |= ARM_CP_NO_RAW;
197
}
198
if (((r->crm == CP_ANY) && crm != 0) ||
199
@@ -XXX,XX +XXX,XX @@ void define_one_arm_cp_reg_with_opaque(ARMCPU *cpu,
200
/* Check that the register definition has enough info to handle
201
* reads and writes if they are permitted.
202
*/
203
- if (!(r->type & (ARM_CP_SPECIAL|ARM_CP_CONST))) {
204
+ if (!(r->type & (ARM_CP_SPECIAL_MASK | ARM_CP_CONST))) {
205
if (r->access & PL3_R) {
206
assert((r->fieldoffset ||
207
(r->bank_fieldoffsets[0] && r->bank_fieldoffsets[1])) ||
208
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
209
index XXXXXXX..XXXXXXX 100644
210
--- a/target/arm/translate-a64.c
211
+++ b/target/arm/translate-a64.c
212
@@ -XXX,XX +XXX,XX @@ static void handle_sys(DisasContext *s, uint32_t insn, bool isread,
213
}
214
215
/* Handle special cases first */
216
- switch (ri->type & ~(ARM_CP_FLAG_MASK & ~ARM_CP_SPECIAL)) {
217
+ switch (ri->type & ARM_CP_SPECIAL_MASK) {
218
+ case 0:
219
+ break;
220
case ARM_CP_NOP:
221
return;
222
case ARM_CP_NZCV:
223
@@ -XXX,XX +XXX,XX @@ static void handle_sys(DisasContext *s, uint32_t insn, bool isread,
224
}
225
return;
226
default:
227
- break;
228
+ g_assert_not_reached();
229
}
230
if ((ri->type & ARM_CP_FPU) && !fp_access_check(s)) {
231
return;
232
diff --git a/target/arm/translate.c b/target/arm/translate.c
233
index XXXXXXX..XXXXXXX 100644
234
--- a/target/arm/translate.c
235
+++ b/target/arm/translate.c
236
@@ -XXX,XX +XXX,XX @@ static void do_coproc_insn(DisasContext *s, int cpnum, int is64,
237
}
238
239
/* Handle special cases first */
240
- switch (ri->type & ~(ARM_CP_FLAG_MASK & ~ARM_CP_SPECIAL)) {
241
+ switch (ri->type & ARM_CP_SPECIAL_MASK) {
242
+ case 0:
243
+ break;
244
case ARM_CP_NOP:
245
return;
246
case ARM_CP_WFI:
247
@@ -XXX,XX +XXX,XX @@ static void do_coproc_insn(DisasContext *s, int cpnum, int is64,
248
s->base.is_jmp = DISAS_WFI;
249
return;
250
default:
251
- break;
252
+ g_assert_not_reached();
253
}
254
255
if ((tb_cflags(s->base.tb) & CF_USE_ICOUNT) && (ri->type & ARM_CP_IO)) {
256
--
39
--
257
2.25.1
40
2.43.0
41
42
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Thomas Huth <thuth@redhat.com>
2
2
3
Since e03b56863d2bc, our host endian indicator is unconditionally
3
The kernel that is used in the sx1 test prints the usual Linux log
4
set, which means that we can use a normal C condition.
4
onto the serial console, but this test currently ignores it. To
5
make sure that the serial device is working properly, let's check
6
for some strings in the output here.
5
7
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
While we're at it, also add the test to the corresponding section
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
in the MAINTAINERS file.
8
Message-id: 20220501055028.646596-20-richard.henderson@linaro.org
10
9
[PMM: quote correct git hash in commit message]
11
Signed-off-by: Thomas Huth <thuth@redhat.com>
12
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
13
Message-id: 20250226104833.1176253-1-thuth@redhat.com
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
15
---
12
target/arm/helper.c | 9 +++------
16
MAINTAINERS | 1 +
13
1 file changed, 3 insertions(+), 6 deletions(-)
17
tests/functional/test_arm_sx1.py | 7 ++++---
18
2 files changed, 5 insertions(+), 3 deletions(-)
14
19
15
diff --git a/target/arm/helper.c b/target/arm/helper.c
20
diff --git a/MAINTAINERS b/MAINTAINERS
16
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/helper.c
22
--- a/MAINTAINERS
18
+++ b/target/arm/helper.c
23
+++ b/MAINTAINERS
19
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
24
@@ -XXX,XX +XXX,XX @@ S: Maintained
20
r2->type |= ARM_CP_ALIAS;
25
F: hw/*/omap*
21
}
26
F: include/hw/arm/omap.h
22
27
F: docs/system/arm/sx1.rst
23
- if (r->state == ARM_CP_STATE_BOTH) {
28
+F: tests/functional/test_arm_sx1.py
24
-#if HOST_BIG_ENDIAN
29
25
- if (r2->fieldoffset) {
30
IPack
26
- r2->fieldoffset += sizeof(uint32_t);
31
M: Alberto Garcia <berto@igalia.com>
27
- }
32
diff --git a/tests/functional/test_arm_sx1.py b/tests/functional/test_arm_sx1.py
28
-#endif
33
index XXXXXXX..XXXXXXX 100755
29
+ if (HOST_BIG_ENDIAN &&
34
--- a/tests/functional/test_arm_sx1.py
30
+ r->state == ARM_CP_STATE_BOTH && r2->fieldoffset) {
35
+++ b/tests/functional/test_arm_sx1.py
31
+ r2->fieldoffset += sizeof(uint32_t);
36
@@ -XXX,XX +XXX,XX @@ def test_arm_sx1_initrd(self):
32
}
37
self.vm.add_args('-append', f'kunit.enable=0 rdinit=/sbin/init {self.CONSOLE_ARGS}')
33
}
38
self.vm.add_args('-no-reboot')
34
39
self.launch_kernel(zimage_path,
40
- initrd=initrd_path)
41
+ initrd=initrd_path,
42
+ wait_for='Boot successful')
43
self.vm.wait(timeout=120)
44
45
def test_arm_sx1_sd(self):
46
@@ -XXX,XX +XXX,XX @@ def test_arm_sx1_sd(self):
47
self.vm.add_args('-no-reboot')
48
self.vm.add_args('-snapshot')
49
self.vm.add_args('-drive', f'format=raw,if=sd,file={sd_fs_path}')
50
- self.launch_kernel(zimage_path)
51
+ self.launch_kernel(zimage_path, wait_for='Boot successful')
52
self.vm.wait(timeout=120)
53
54
def test_arm_sx1_flash(self):
55
@@ -XXX,XX +XXX,XX @@ def test_arm_sx1_flash(self):
56
self.vm.add_args('-no-reboot')
57
self.vm.add_args('-snapshot')
58
self.vm.add_args('-drive', f'format=raw,if=pflash,file={flash_path}')
59
- self.launch_kernel(zimage_path)
60
+ self.launch_kernel(zimage_path, wait_for='Boot successful')
61
self.vm.wait(timeout=120)
62
63
if __name__ == '__main__':
35
--
64
--
36
2.25.1
65
2.43.0
66
67
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
When we are calculating timer deadlines, the correct definition of
2
whether or not to apply an offset to the physical count is described
3
in the Arm ARM DDI4087 rev L.a section D12.2.4.1. This is different
4
from when the offset should be applied for a direct read of the
5
counter sysreg.
2
6
3
Put the block comments into the current coding style.
7
We got this right for the EL1 physical timer and for the EL1 virtual
8
timer, but got all the rest wrong: they should be using a zero offset
9
always.
4
10
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
Factor the offset calculation out into a function that has a comment
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
documenting exactly which offset it is calculating and which gets the
7
Message-id: 20220501055028.646596-19-richard.henderson@linaro.org
13
HYP, SEC, and HYPVIRT cases right.
14
15
Cc: qemu-stable@nongnu.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
18
Message-id: 20250204125009.2281315-2-peter.maydell@linaro.org
9
---
19
---
10
target/arm/helper.c | 24 +++++++++++++++---------
20
target/arm/helper.c | 29 +++++++++++++++++++++++++++--
11
1 file changed, 15 insertions(+), 9 deletions(-)
21
1 file changed, 27 insertions(+), 2 deletions(-)
12
22
13
diff --git a/target/arm/helper.c b/target/arm/helper.c
23
diff --git a/target/arm/helper.c b/target/arm/helper.c
14
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/helper.c
25
--- a/target/arm/helper.c
16
+++ b/target/arm/helper.c
26
+++ b/target/arm/helper.c
17
@@ -XXX,XX +XXX,XX @@ CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp)
27
@@ -XXX,XX +XXX,XX @@ static uint64_t gt_phys_cnt_offset(CPUARMState *env)
18
return cpu_list;
28
return gt_phys_raw_cnt_offset(env);
19
}
29
}
20
30
21
+/*
31
+static uint64_t gt_indirect_access_timer_offset(CPUARMState *env, int timeridx)
22
+ * Private utility function for define_one_arm_cp_reg_with_opaque():
32
+{
23
+ * add a single reginfo struct to the hash table.
33
+ /*
24
+ */
34
+ * Return the timer offset to use for indirect accesses to the timer.
25
static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
35
+ * This is the Offset value as defined in D12.2.4.1 "Operation of the
26
void *opaque, CPState state,
36
+ * CompareValue views of the timers".
27
CPSecureState secstate,
37
+ *
28
int crm, int opc1, int opc2,
38
+ * The condition here is not always the same as the condition for
29
const char *name)
39
+ * whether to apply an offset register when doing a direct read of
40
+ * the counter sysreg; those conditions are described in the
41
+ * access pseudocode for each counter register.
42
+ */
43
+ switch (timeridx) {
44
+ case GTIMER_PHYS:
45
+ return gt_phys_raw_cnt_offset(env);
46
+ case GTIMER_VIRT:
47
+ return env->cp15.cntvoff_el2;
48
+ case GTIMER_HYP:
49
+ case GTIMER_SEC:
50
+ case GTIMER_HYPVIRT:
51
+ return 0;
52
+ default:
53
+ g_assert_not_reached();
54
+ }
55
+}
56
+
57
static void gt_recalc_timer(ARMCPU *cpu, int timeridx)
30
{
58
{
31
- /* Private utility function for define_one_arm_cp_reg_with_opaque():
59
ARMGenericTimer *gt = &cpu->env.cp15.c14_timer[timeridx];
32
- * add a single reginfo struct to the hash table.
60
@@ -XXX,XX +XXX,XX @@ static void gt_recalc_timer(ARMCPU *cpu, int timeridx)
33
- */
61
* Timer enabled: calculate and set current ISTATUS, irq, and
34
uint32_t key;
62
* reset timer to when ISTATUS next has to change
35
ARMCPRegInfo *r2;
36
bool is64 = r->type & ARM_CP_64BIT;
37
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
38
39
isbanked = r->bank_fieldoffsets[0] && r->bank_fieldoffsets[1];
40
if (isbanked) {
41
- /* Register is banked (using both entries in array).
42
+ /*
43
+ * Register is banked (using both entries in array).
44
* Overwriting fieldoffset as the array is only used to define
45
* banked registers but later only fieldoffset is used.
46
*/
63
*/
47
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
64
- uint64_t offset = timeridx == GTIMER_VIRT ?
48
65
- cpu->env.cp15.cntvoff_el2 : gt_phys_raw_cnt_offset(&cpu->env);
49
if (state == ARM_CP_STATE_AA32) {
66
+ uint64_t offset = gt_indirect_access_timer_offset(&cpu->env, timeridx);
50
if (isbanked) {
67
uint64_t count = gt_get_countervalue(&cpu->env);
51
- /* If the register is banked then we don't need to migrate or
68
/* Note that this must be unsigned 64 bit arithmetic: */
52
+ /*
69
int istatus = count - offset >= gt->cval;
53
+ * If the register is banked then we don't need to migrate or
54
* reset the 32-bit instance in certain cases:
55
*
56
* 1) If the register has both 32-bit and 64-bit instances then we
57
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
58
r2->type |= ARM_CP_ALIAS;
59
}
60
} else if ((secstate != r->secure) && !ns) {
61
- /* The register is not banked so we only want to allow migration of
62
- * the non-secure instance.
63
+ /*
64
+ * The register is not banked so we only want to allow migration
65
+ * of the non-secure instance.
66
*/
67
r2->type |= ARM_CP_ALIAS;
68
}
69
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
70
}
71
}
72
73
- /* By convention, for wildcarded registers only the first
74
+ /*
75
+ * By convention, for wildcarded registers only the first
76
* entry is used for migration; the others are marked as
77
* ALIAS so we don't try to transfer the register
78
* multiple times. Special registers (ie NOP/WFI) are
79
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
80
r2->type |= ARM_CP_ALIAS | ARM_CP_NO_GDB;
81
}
82
83
- /* Check that raw accesses are either forbidden or handled. Note that
84
+ /*
85
+ * Check that raw accesses are either forbidden or handled. Note that
86
* we can't assert this earlier because the setup of fieldoffset for
87
* banked registers has to be done first.
88
*/
89
--
70
--
90
2.25.1
71
2.43.0
72
73
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
The CNTVOFF_EL2 offset register should only be applied for accessses
2
to CNTVCT_EL0 and for the EL1 virtual timer (CNTV_*). We were
3
incorrectly applying it for the EL2 virtual timer (CNTHV_*).
2
4
3
Computing isbanked only once makes the code
5
Cc: qemu-stable@nongnu.org
4
a bit easier to read.
5
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Message-id: 20220501055028.646596-17-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
8
Message-id: 20250204125009.2281315-3-peter.maydell@linaro.org
10
---
9
---
11
target/arm/helper.c | 6 ++++--
10
target/arm/helper.c | 2 --
12
1 file changed, 4 insertions(+), 2 deletions(-)
11
1 file changed, 2 deletions(-)
13
12
14
diff --git a/target/arm/helper.c b/target/arm/helper.c
13
diff --git a/target/arm/helper.c b/target/arm/helper.c
15
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/helper.c
15
--- a/target/arm/helper.c
17
+++ b/target/arm/helper.c
16
+++ b/target/arm/helper.c
18
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
17
@@ -XXX,XX +XXX,XX @@ static uint64_t gt_tval_read(CPUARMState *env, const ARMCPRegInfo *ri,
19
bool is64 = r->type & ARM_CP_64BIT;
18
20
bool ns = secstate & ARM_CP_SECSTATE_NS;
19
switch (timeridx) {
21
int cp = r->cp;
20
case GTIMER_VIRT:
22
+ bool isbanked;
21
- case GTIMER_HYPVIRT:
23
size_t name_len;
22
offset = gt_virt_cnt_offset(env);
24
23
break;
25
switch (state) {
24
case GTIMER_PHYS:
26
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
25
@@ -XXX,XX +XXX,XX @@ static void gt_tval_write(CPUARMState *env, const ARMCPRegInfo *ri,
27
r2->opaque = opaque;
26
28
}
27
switch (timeridx) {
29
28
case GTIMER_VIRT:
30
- if (r->bank_fieldoffsets[0] && r->bank_fieldoffsets[1]) {
29
- case GTIMER_HYPVIRT:
31
+ isbanked = r->bank_fieldoffsets[0] && r->bank_fieldoffsets[1];
30
offset = gt_virt_cnt_offset(env);
32
+ if (isbanked) {
31
break;
33
/* Register is banked (using both entries in array).
32
case GTIMER_PHYS:
34
* Overwriting fieldoffset as the array is only used to define
35
* banked registers but later only fieldoffset is used.
36
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
37
}
38
39
if (state == ARM_CP_STATE_AA32) {
40
- if (r->bank_fieldoffsets[0] && r->bank_fieldoffsets[1]) {
41
+ if (isbanked) {
42
/* If the register is banked then we don't need to migrate or
43
* reset the 32-bit instance in certain cases:
44
*
45
--
33
--
46
2.25.1
34
2.43.0
35
36
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
When we added Secure EL2 support, we missed that this needs an update
2
to the access code for the EL3 physical timer registers. These are
3
supposed to UNDEF from Secure EL1 when Secure EL2 is enabled.
2
4
3
Bool is a more appropriate type for these variables.
5
(Note for stable backporting: for backports to branches where
6
CP_ACCESS_UNDEFINED is not defined, the old name to use instead
7
is CP_ACCESS_TRAP_UNCATEGORIZED.)
4
8
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Cc: qemu-stable@nongnu.org
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Message-id: 20220501055028.646596-16-richard.henderson@linaro.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
12
Message-id: 20250204125009.2281315-4-peter.maydell@linaro.org
9
---
13
---
10
target/arm/helper.c | 4 ++--
14
target/arm/helper.c | 3 +++
11
1 file changed, 2 insertions(+), 2 deletions(-)
15
1 file changed, 3 insertions(+)
12
16
13
diff --git a/target/arm/helper.c b/target/arm/helper.c
17
diff --git a/target/arm/helper.c b/target/arm/helper.c
14
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/helper.c
19
--- a/target/arm/helper.c
16
+++ b/target/arm/helper.c
20
+++ b/target/arm/helper.c
17
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
21
@@ -XXX,XX +XXX,XX @@ static CPAccessResult gt_stimer_access(CPUARMState *env,
18
*/
22
if (!arm_is_secure(env)) {
19
uint32_t key;
23
return CP_ACCESS_UNDEFINED;
20
ARMCPRegInfo *r2;
24
}
21
- int is64 = (r->type & ARM_CP_64BIT) ? 1 : 0;
25
+ if (arm_is_el2_enabled(env)) {
22
- int ns = (secstate & ARM_CP_SECSTATE_NS) ? 1 : 0;
26
+ return CP_ACCESS_UNDEFINED;
23
+ bool is64 = r->type & ARM_CP_64BIT;
27
+ }
24
+ bool ns = secstate & ARM_CP_SECSTATE_NS;
28
if (!(env->cp15.scr_el3 & SCR_ST)) {
25
int cp = r->cp;
29
return CP_ACCESS_TRAP_EL3;
26
size_t name_len;
30
}
27
28
--
31
--
29
2.25.1
32
2.43.0
33
34
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
Currently we handle CNTV_TVAL_EL02 by calling gt_tval_read() for the
2
EL1 virt timer. This is almost correct, but the underlying
3
CNTV_TVAL_EL0 register behaves slightly differently. CNTV_TVAL_EL02
4
always applies the CNTVOFF_EL2 offset; CNTV_TVAL_EL0 doesn't do so if
5
we're at EL2 and HCR_EL2.E2H is 1.
2
6
3
Perform the override check early, so that it is still done
7
We were getting this wrong, because we ended up in
4
even when we decide to discard an unreachable cpreg.
8
gt_virt_cnt_offset() and did the E2H check.
5
9
6
Use assert not printf+abort.
10
Factor out the tval read/write calculation from the selection of the
11
offset, so that we can special case gt_virt_tval_read() and
12
gt_virt_tval_write() to unconditionally pass CNTVOFF_EL2.
7
13
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
14
Cc: qemu-stable@nongnu.org
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Message-id: 20220501055028.646596-18-richard.henderson@linaro.org
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
17
Message-id: 20250204125009.2281315-5-peter.maydell@linaro.org
12
---
18
---
13
target/arm/helper.c | 22 ++++++++--------------
19
target/arm/helper.c | 36 +++++++++++++++++++++++++++---------
14
1 file changed, 8 insertions(+), 14 deletions(-)
20
1 file changed, 27 insertions(+), 9 deletions(-)
15
21
16
diff --git a/target/arm/helper.c b/target/arm/helper.c
22
diff --git a/target/arm/helper.c b/target/arm/helper.c
17
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/helper.c
24
--- a/target/arm/helper.c
19
+++ b/target/arm/helper.c
25
+++ b/target/arm/helper.c
20
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
26
@@ -XXX,XX +XXX,XX @@ static void gt_cval_write(CPUARMState *env, const ARMCPRegInfo *ri,
21
g_assert_not_reached();
27
gt_recalc_timer(env_archcpu(env), timeridx);
28
}
29
30
+static uint64_t do_tval_read(CPUARMState *env, int timeridx, uint64_t offset)
31
+{
32
+ return (uint32_t)(env->cp15.c14_timer[timeridx].cval -
33
+ (gt_get_countervalue(env) - offset));
34
+}
35
+
36
static uint64_t gt_tval_read(CPUARMState *env, const ARMCPRegInfo *ri,
37
int timeridx)
38
{
39
@@ -XXX,XX +XXX,XX @@ static uint64_t gt_tval_read(CPUARMState *env, const ARMCPRegInfo *ri,
40
break;
22
}
41
}
23
42
24
+ /* Overriding of an existing definition must be explicitly requested. */
43
- return (uint32_t)(env->cp15.c14_timer[timeridx].cval -
25
+ if (!(r->type & ARM_CP_OVERRIDE)) {
44
- (gt_get_countervalue(env) - offset));
26
+ const ARMCPRegInfo *oldreg = get_arm_cp_reginfo(cpu->cp_regs, key);
45
+ return do_tval_read(env, timeridx, offset);
27
+ if (oldreg) {
46
+}
28
+ assert(oldreg->type & ARM_CP_OVERRIDE);
29
+ }
30
+ }
31
+
47
+
32
/* Combine cpreg and name into one allocation. */
48
+static void do_tval_write(CPUARMState *env, int timeridx, uint64_t value,
33
name_len = strlen(name) + 1;
49
+ uint64_t offset)
34
r2 = g_malloc(sizeof(*r2) + name_len);
50
+{
35
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
51
+ trace_arm_gt_tval_write(timeridx, value);
36
assert(!raw_accessors_invalid(r2));
52
+ env->cp15.c14_timer[timeridx].cval = gt_get_countervalue(env) - offset +
53
+ sextract64(value, 0, 32);
54
+ gt_recalc_timer(env_archcpu(env), timeridx);
55
}
56
57
static void gt_tval_write(CPUARMState *env, const ARMCPRegInfo *ri,
58
@@ -XXX,XX +XXX,XX @@ static void gt_tval_write(CPUARMState *env, const ARMCPRegInfo *ri,
59
offset = gt_phys_cnt_offset(env);
60
break;
37
}
61
}
38
62
-
39
- /* Overriding of an existing definition must be explicitly
63
- trace_arm_gt_tval_write(timeridx, value);
40
- * requested.
64
- env->cp15.c14_timer[timeridx].cval = gt_get_countervalue(env) - offset +
41
- */
65
- sextract64(value, 0, 32);
42
- if (!(r->type & ARM_CP_OVERRIDE)) {
66
- gt_recalc_timer(env_archcpu(env), timeridx);
43
- const ARMCPRegInfo *oldreg = get_arm_cp_reginfo(cpu->cp_regs, key);
67
+ do_tval_write(env, timeridx, value, offset);
44
- if (oldreg && !(oldreg->type & ARM_CP_OVERRIDE)) {
45
- fprintf(stderr, "Register redefined: cp=%d %d bit "
46
- "crn=%d crm=%d opc1=%d opc2=%d, "
47
- "was %s, now %s\n", r2->cp, 32 + 32 * is64,
48
- r2->crn, r2->crm, r2->opc1, r2->opc2,
49
- oldreg->name, r2->name);
50
- g_assert_not_reached();
51
- }
52
- }
53
g_hash_table_insert(cpu->cp_regs, (gpointer)(uintptr_t)key, r2);
54
}
68
}
55
69
70
static void gt_ctl_write(CPUARMState *env, const ARMCPRegInfo *ri,
71
@@ -XXX,XX +XXX,XX @@ static void gt_virt_cval_write(CPUARMState *env, const ARMCPRegInfo *ri,
72
73
static uint64_t gt_virt_tval_read(CPUARMState *env, const ARMCPRegInfo *ri)
74
{
75
- return gt_tval_read(env, ri, GTIMER_VIRT);
76
+ /*
77
+ * This is CNTV_TVAL_EL02; unlike the underlying CNTV_TVAL_EL0
78
+ * we always apply CNTVOFF_EL2. Special case that here rather
79
+ * than going into the generic gt_tval_read() and then having
80
+ * to re-detect that it's this register.
81
+ * Note that the accessfn/perms mean we know we're at EL2 or EL3 here.
82
+ */
83
+ return do_tval_read(env, GTIMER_VIRT, env->cp15.cntvoff_el2);
84
}
85
86
static void gt_virt_tval_write(CPUARMState *env, const ARMCPRegInfo *ri,
87
uint64_t value)
88
{
89
- gt_tval_write(env, ri, GTIMER_VIRT, value);
90
+ /* Similarly for writes to CNTV_TVAL_EL02 */
91
+ do_tval_write(env, GTIMER_VIRT, value, env->cp15.cntvoff_el2);
92
}
93
94
static void gt_virt_ctl_write(CPUARMState *env, const ARMCPRegInfo *ri,
56
--
95
--
57
2.25.1
96
2.43.0
97
98
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
When reading or writing the timer registers, sometimes we need to
2
2
apply one of the timer offsets. Specifically, this happens for
3
Move the computation of key to the top of the function.
3
direct reads of the counter registers CNTPCT_EL0 and CNTVCT_EL0 (and
4
Hoist the resolution of cp as well, as an input to the
4
their self-synchronized variants CNTVCTSS_EL0 and CNTPCTSS_EL0). It
5
computation of key.
5
also applies for direct reads and writes of the CNT*_TVAL_EL*
6
6
registers that provide the 32-bit downcounting view of each timer.
7
This will be required by a subsequent patch.
7
8
8
We currently do this with duplicated code in gt_tval_read() and
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
gt_tval_write() and a special-case in gt_virt_cnt_read() and
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
gt_cnt_read(). Refactor this so that we handle it all in a single
11
Message-id: 20220501055028.646596-14-richard.henderson@linaro.org
11
function gt_direct_access_timer_offset(), to parallel how we handle
12
the offset for indirect accesses.
13
14
The call in the WFIT helper previously to gt_virt_cnt_offset() is
15
now to gt_direct_access_timer_offset(); this is the correct
16
behaviour, but it's not immediately obvious that it shouldn't be
17
considered an indirect access, so we add an explanatory comment.
18
19
This commit should make no behavioural changes.
20
21
(Cc to stable because the following bugfix commit will
22
depend on this one.)
23
24
Cc: qemu-stable@nongnu.org
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
25
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
26
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
27
Message-id: 20250204125009.2281315-6-peter.maydell@linaro.org
13
---
28
---
14
target/arm/helper.c | 49 +++++++++++++++++++++++++--------------------
29
target/arm/internals.h | 5 +-
15
1 file changed, 27 insertions(+), 22 deletions(-)
30
target/arm/helper.c | 103 +++++++++++++++++++------------------
16
31
target/arm/tcg/op_helper.c | 8 ++-
32
3 files changed, 62 insertions(+), 54 deletions(-)
33
34
diff --git a/target/arm/internals.h b/target/arm/internals.h
35
index XXXXXXX..XXXXXXX 100644
36
--- a/target/arm/internals.h
37
+++ b/target/arm/internals.h
38
@@ -XXX,XX +XXX,XX @@ int delete_hw_watchpoint(target_ulong addr, target_ulong len, int type);
39
uint64_t gt_get_countervalue(CPUARMState *env);
40
/*
41
* Return the currently applicable offset between the system counter
42
- * and CNTVCT_EL0 (this will be either 0 or the value of CNTVOFF_EL2).
43
+ * and the counter for the specified timer, as used for direct register
44
+ * accesses.
45
*/
46
-uint64_t gt_virt_cnt_offset(CPUARMState *env);
47
+uint64_t gt_direct_access_timer_offset(CPUARMState *env, int timeridx);
48
49
/*
50
* Return mask of ARMMMUIdxBit values corresponding to an "invalidate
17
diff --git a/target/arm/helper.c b/target/arm/helper.c
51
diff --git a/target/arm/helper.c b/target/arm/helper.c
18
index XXXXXXX..XXXXXXX 100644
52
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/helper.c
53
--- a/target/arm/helper.c
20
+++ b/target/arm/helper.c
54
+++ b/target/arm/helper.c
21
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
55
@@ -XXX,XX +XXX,XX @@ static uint64_t gt_phys_raw_cnt_offset(CPUARMState *env)
22
ARMCPRegInfo *r2;
56
return 0;
23
int is64 = (r->type & ARM_CP_64BIT) ? 1 : 0;
57
}
24
int ns = (secstate & ARM_CP_SECSTATE_NS) ? 1 : 0;
58
25
+ int cp = r->cp;
59
-static uint64_t gt_phys_cnt_offset(CPUARMState *env)
26
size_t name_len;
60
-{
27
61
- if (arm_current_el(env) >= 2) {
28
+ switch (state) {
62
- return 0;
29
+ case ARM_CP_STATE_AA32:
63
- }
30
+ /* We assume it is a cp15 register if the .cp field is left unset. */
64
- return gt_phys_raw_cnt_offset(env);
31
+ if (cp == 0 && r->state == ARM_CP_STATE_BOTH) {
65
-}
32
+ cp = 15;
66
-
67
static uint64_t gt_indirect_access_timer_offset(CPUARMState *env, int timeridx)
68
{
69
/*
70
@@ -XXX,XX +XXX,XX @@ static uint64_t gt_indirect_access_timer_offset(CPUARMState *env, int timeridx)
71
}
72
}
73
74
+uint64_t gt_direct_access_timer_offset(CPUARMState *env, int timeridx)
75
+{
76
+ /*
77
+ * Return the timer offset to use for direct accesses to the
78
+ * counter registers CNTPCT and CNTVCT, and for direct accesses
79
+ * to the CNT*_TVAL registers.
80
+ *
81
+ * This isn't exactly the same as the indirect-access offset,
82
+ * because here we also care about what EL the register access
83
+ * is being made from.
84
+ *
85
+ * This corresponds to the access pseudocode for the registers.
86
+ */
87
+ uint64_t hcr;
88
+
89
+ switch (timeridx) {
90
+ case GTIMER_PHYS:
91
+ if (arm_current_el(env) >= 2) {
92
+ return 0;
33
+ }
93
+ }
34
+ key = ENCODE_CP_REG(cp, is64, ns, r->crn, crm, opc1, opc2);
94
+ return gt_phys_raw_cnt_offset(env);
35
+ break;
95
+ case GTIMER_VIRT:
36
+ case ARM_CP_STATE_AA64:
96
+ switch (arm_current_el(env)) {
37
+ /*
97
+ case 2:
38
+ * To allow abbreviation of ARMCPRegInfo definitions, we treat
98
+ hcr = arm_hcr_el2_eff(env);
39
+ * cp == 0 as equivalent to the value for "standard guest-visible
99
+ if (hcr & HCR_E2H) {
40
+ * sysreg". STATE_BOTH definitions are also always "standard sysreg"
100
+ return 0;
41
+ * in their AArch64 view (the .cp value may be non-zero for the
101
+ }
42
+ * benefit of the AArch32 view).
102
+ break;
43
+ */
103
+ case 0:
44
+ if (cp == 0 || r->state == ARM_CP_STATE_BOTH) {
104
+ hcr = arm_hcr_el2_eff(env);
45
+ cp = CP_REG_ARM64_SYSREG_CP;
105
+ if ((hcr & (HCR_E2H | HCR_TGE)) == (HCR_E2H | HCR_TGE)) {
106
+ return 0;
107
+ }
108
+ break;
46
+ }
109
+ }
47
+ key = ENCODE_AA64_CP_REG(cp, r->crn, crm, r->opc0, opc1, opc2);
110
+ return env->cp15.cntvoff_el2;
48
+ break;
111
+ case GTIMER_HYP:
112
+ case GTIMER_SEC:
113
+ case GTIMER_HYPVIRT:
114
+ return 0;
49
+ default:
115
+ default:
50
+ g_assert_not_reached();
116
+ g_assert_not_reached();
51
+ }
117
+ }
118
+}
52
+
119
+
53
/* Combine cpreg and name into one allocation. */
120
static void gt_recalc_timer(ARMCPU *cpu, int timeridx)
54
name_len = strlen(name) + 1;
121
{
55
r2 = g_malloc(sizeof(*r2) + name_len);
122
ARMGenericTimer *gt = &cpu->env.cp15.c14_timer[timeridx];
56
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
123
@@ -XXX,XX +XXX,XX @@ static void gt_timer_reset(CPUARMState *env, const ARMCPRegInfo *ri,
57
}
124
58
125
static uint64_t gt_cnt_read(CPUARMState *env, const ARMCPRegInfo *ri)
59
if (r->state == ARM_CP_STATE_BOTH) {
126
{
60
- /* We assume it is a cp15 register if the .cp field is left unset.
127
- return gt_get_countervalue(env) - gt_phys_cnt_offset(env);
61
- */
128
-}
62
- if (r2->cp == 0) {
129
-
63
- r2->cp = 15;
130
-uint64_t gt_virt_cnt_offset(CPUARMState *env)
64
- }
131
-{
65
-
132
- uint64_t hcr;
66
#if HOST_BIG_ENDIAN
133
-
67
if (r2->fieldoffset) {
134
- switch (arm_current_el(env)) {
68
r2->fieldoffset += sizeof(uint32_t);
135
- case 2:
69
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
136
- hcr = arm_hcr_el2_eff(env);
70
#endif
137
- if (hcr & HCR_E2H) {
71
}
138
- return 0;
72
}
73
- if (state == ARM_CP_STATE_AA64) {
74
- /* To allow abbreviation of ARMCPRegInfo
75
- * definitions, we treat cp == 0 as equivalent to
76
- * the value for "standard guest-visible sysreg".
77
- * STATE_BOTH definitions are also always "standard
78
- * sysreg" in their AArch64 view (the .cp value may
79
- * be non-zero for the benefit of the AArch32 view).
80
- */
81
- if (r->cp == 0 || r->state == ARM_CP_STATE_BOTH) {
82
- r2->cp = CP_REG_ARM64_SYSREG_CP;
83
- }
139
- }
84
- key = ENCODE_AA64_CP_REG(r2->cp, r2->crn, crm,
140
- break;
85
- r2->opc0, opc1, opc2);
141
- case 0:
86
- } else {
142
- hcr = arm_hcr_el2_eff(env);
87
- key = ENCODE_CP_REG(r2->cp, is64, ns, r2->crn, crm, opc1, opc2);
143
- if ((hcr & (HCR_E2H | HCR_TGE)) == (HCR_E2H | HCR_TGE)) {
88
- }
144
- return 0;
89
if (opaque) {
145
- }
90
r2->opaque = opaque;
146
- break;
91
}
147
- }
92
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
148
-
93
/* Make sure reginfo passed to helpers for wildcarded regs
149
- return env->cp15.cntvoff_el2;
94
* has the correct crm/opc1/opc2 for this reg, not CP_ANY:
150
+ uint64_t offset = gt_direct_access_timer_offset(env, GTIMER_PHYS);
95
*/
151
+ return gt_get_countervalue(env) - offset;
96
+ r2->cp = cp;
152
}
97
r2->crm = crm;
153
98
r2->opc1 = opc1;
154
static uint64_t gt_virt_cnt_read(CPUARMState *env, const ARMCPRegInfo *ri)
99
r2->opc2 = opc2;
155
{
156
- return gt_get_countervalue(env) - gt_virt_cnt_offset(env);
157
+ uint64_t offset = gt_direct_access_timer_offset(env, GTIMER_VIRT);
158
+ return gt_get_countervalue(env) - offset;
159
}
160
161
static void gt_cval_write(CPUARMState *env, const ARMCPRegInfo *ri,
162
@@ -XXX,XX +XXX,XX @@ static uint64_t do_tval_read(CPUARMState *env, int timeridx, uint64_t offset)
163
static uint64_t gt_tval_read(CPUARMState *env, const ARMCPRegInfo *ri,
164
int timeridx)
165
{
166
- uint64_t offset = 0;
167
-
168
- switch (timeridx) {
169
- case GTIMER_VIRT:
170
- offset = gt_virt_cnt_offset(env);
171
- break;
172
- case GTIMER_PHYS:
173
- offset = gt_phys_cnt_offset(env);
174
- break;
175
- }
176
+ uint64_t offset = gt_direct_access_timer_offset(env, timeridx);
177
178
return do_tval_read(env, timeridx, offset);
179
}
180
@@ -XXX,XX +XXX,XX @@ static void gt_tval_write(CPUARMState *env, const ARMCPRegInfo *ri,
181
int timeridx,
182
uint64_t value)
183
{
184
- uint64_t offset = 0;
185
+ uint64_t offset = gt_direct_access_timer_offset(env, timeridx);
186
187
- switch (timeridx) {
188
- case GTIMER_VIRT:
189
- offset = gt_virt_cnt_offset(env);
190
- break;
191
- case GTIMER_PHYS:
192
- offset = gt_phys_cnt_offset(env);
193
- break;
194
- }
195
do_tval_write(env, timeridx, value, offset);
196
}
197
198
diff --git a/target/arm/tcg/op_helper.c b/target/arm/tcg/op_helper.c
199
index XXXXXXX..XXXXXXX 100644
200
--- a/target/arm/tcg/op_helper.c
201
+++ b/target/arm/tcg/op_helper.c
202
@@ -XXX,XX +XXX,XX @@ void HELPER(wfit)(CPUARMState *env, uint64_t timeout)
203
int target_el = check_wfx_trap(env, false, &excp);
204
/* The WFIT should time out when CNTVCT_EL0 >= the specified value. */
205
uint64_t cntval = gt_get_countervalue(env);
206
- uint64_t offset = gt_virt_cnt_offset(env);
207
+ /*
208
+ * We want the value that we would get if we read CNTVCT_EL0 from
209
+ * the current exception level, so the direct_access offset, not
210
+ * the indirect_access one. Compare the pseudocode LocalTimeoutEvent(),
211
+ * which calls VirtualCounterTimer().
212
+ */
213
+ uint64_t offset = gt_direct_access_timer_offset(env, GTIMER_VIRT);
214
uint64_t cntvct = cntval - offset;
215
uint64_t nexttick;
216
100
--
217
--
101
2.25.1
218
2.43.0
219
220
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Alex Bennée <alex.bennee@linaro.org>
2
2
3
Cast the uint32_t key into a gpointer directly, which
3
When FEAT_SEL2 was implemented the SEL2 timers were missed. This
4
allows us to avoid allocating storage for each key.
4
shows up when building the latest Hafnium with SPMC_AT_EL=2. The
5
5
actual implementation utilises the same logic as the rest of the
6
Use g_hash_table_lookup when we already have a gpointer
6
timers so all we need to do is:
7
(e.g. for callbacks like count_cpreg), or when using
7
8
get_arm_cp_reginfo would require casting away const.
8
- define the timers and their access functions
9
9
- conditionally add the correct system registers
10
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
- create a new accessfn as the rules are subtly different to the
11
existing secure timer
12
13
Fixes: e9152ee91c (target/arm: add ARMv8.4-SEL2 system registers)
14
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
16
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
Message-id: 20220501055028.646596-12-richard.henderson@linaro.org
17
Message-id: 20250204125009.2281315-7-peter.maydell@linaro.org
18
Cc: qemu-stable@nongnu.org
19
Cc: Andrei Homescu <ahomescu@google.com>
20
Cc: Arve Hjønnevåg <arve@google.com>
21
Cc: Rémi Denis-Courmont <remi.denis.courmont@huawei.com>
22
[PMM: CP_ACCESS_TRAP_UNCATEGORIZED -> CP_ACCESS_UNDEFINED;
23
offset logic now in gt_{indirect,direct}_access_timer_offset() ]
24
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
25
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
26
---
15
target/arm/cpu.c | 4 ++--
27
include/hw/arm/bsa.h | 2 +
16
target/arm/gdbstub.c | 2 +-
28
target/arm/cpu.h | 2 +
17
target/arm/helper.c | 41 ++++++++++++++++++-----------------------
29
target/arm/gtimer.h | 4 +-
18
3 files changed, 21 insertions(+), 26 deletions(-)
30
target/arm/cpu.c | 4 ++
19
31
target/arm/helper.c | 163 +++++++++++++++++++++++++++++++++++++++++++
32
5 files changed, 174 insertions(+), 1 deletion(-)
33
34
diff --git a/include/hw/arm/bsa.h b/include/hw/arm/bsa.h
35
index XXXXXXX..XXXXXXX 100644
36
--- a/include/hw/arm/bsa.h
37
+++ b/include/hw/arm/bsa.h
38
@@ -XXX,XX +XXX,XX @@
39
#define QEMU_ARM_BSA_H
40
41
/* These are architectural INTID values */
42
+#define ARCH_TIMER_S_EL2_VIRT_IRQ 19
43
+#define ARCH_TIMER_S_EL2_IRQ 20
44
#define VIRTUAL_PMU_IRQ 23
45
#define ARCH_GIC_MAINT_IRQ 25
46
#define ARCH_TIMER_NS_EL2_IRQ 26
47
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
48
index XXXXXXX..XXXXXXX 100644
49
--- a/target/arm/cpu.h
50
+++ b/target/arm/cpu.h
51
@@ -XXX,XX +XXX,XX @@ void arm_gt_vtimer_cb(void *opaque);
52
void arm_gt_htimer_cb(void *opaque);
53
void arm_gt_stimer_cb(void *opaque);
54
void arm_gt_hvtimer_cb(void *opaque);
55
+void arm_gt_sel2timer_cb(void *opaque);
56
+void arm_gt_sel2vtimer_cb(void *opaque);
57
58
unsigned int gt_cntfrq_period_ns(ARMCPU *cpu);
59
void gt_rme_post_el_change(ARMCPU *cpu, void *opaque);
60
diff --git a/target/arm/gtimer.h b/target/arm/gtimer.h
61
index XXXXXXX..XXXXXXX 100644
62
--- a/target/arm/gtimer.h
63
+++ b/target/arm/gtimer.h
64
@@ -XXX,XX +XXX,XX @@ enum {
65
GTIMER_HYP = 2,
66
GTIMER_SEC = 3,
67
GTIMER_HYPVIRT = 4,
68
-#define NUM_GTIMERS 5
69
+ GTIMER_S_EL2_PHYS = 5, /* CNTHPS_* ; only if FEAT_SEL2 */
70
+ GTIMER_S_EL2_VIRT = 6, /* CNTHVS_* ; only if FEAT_SEL2 */
71
+#define NUM_GTIMERS 7
72
};
73
74
#endif
20
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
75
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
21
index XXXXXXX..XXXXXXX 100644
76
index XXXXXXX..XXXXXXX 100644
22
--- a/target/arm/cpu.c
77
--- a/target/arm/cpu.c
23
+++ b/target/arm/cpu.c
78
+++ b/target/arm/cpu.c
24
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_initfn(Object *obj)
79
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
25
ARMCPU *cpu = ARM_CPU(obj);
80
arm_gt_stimer_cb, cpu);
26
81
cpu->gt_timer[GTIMER_HYPVIRT] = timer_new(QEMU_CLOCK_VIRTUAL, scale,
27
cpu_set_cpustate_pointers(cpu);
82
arm_gt_hvtimer_cb, cpu);
28
- cpu->cp_regs = g_hash_table_new_full(g_int_hash, g_int_equal,
83
+ cpu->gt_timer[GTIMER_S_EL2_PHYS] = timer_new(QEMU_CLOCK_VIRTUAL, scale,
29
- g_free, cpreg_hashtable_data_destroy);
84
+ arm_gt_sel2timer_cb, cpu);
30
+ cpu->cp_regs = g_hash_table_new_full(g_direct_hash, g_direct_equal,
85
+ cpu->gt_timer[GTIMER_S_EL2_VIRT] = timer_new(QEMU_CLOCK_VIRTUAL, scale,
31
+ NULL, cpreg_hashtable_data_destroy);
86
+ arm_gt_sel2vtimer_cb, cpu);
32
87
}
33
QLIST_INIT(&cpu->pre_el_change_hooks);
88
#endif
34
QLIST_INIT(&cpu->el_change_hooks);
89
35
diff --git a/target/arm/gdbstub.c b/target/arm/gdbstub.c
36
index XXXXXXX..XXXXXXX 100644
37
--- a/target/arm/gdbstub.c
38
+++ b/target/arm/gdbstub.c
39
@@ -XXX,XX +XXX,XX @@ static void arm_gen_one_xml_sysreg_tag(GString *s, DynamicGDBXMLInfo *dyn_xml,
40
static void arm_register_sysreg_for_xml(gpointer key, gpointer value,
41
gpointer p)
42
{
43
- uint32_t ri_key = *(uint32_t *)key;
44
+ uint32_t ri_key = (uintptr_t)key;
45
ARMCPRegInfo *ri = value;
46
RegisterSysregXmlParam *param = (RegisterSysregXmlParam *)p;
47
GString *s = param->s;
48
diff --git a/target/arm/helper.c b/target/arm/helper.c
90
diff --git a/target/arm/helper.c b/target/arm/helper.c
49
index XXXXXXX..XXXXXXX 100644
91
index XXXXXXX..XXXXXXX 100644
50
--- a/target/arm/helper.c
92
--- a/target/arm/helper.c
51
+++ b/target/arm/helper.c
93
+++ b/target/arm/helper.c
52
@@ -XXX,XX +XXX,XX @@ bool write_list_to_cpustate(ARMCPU *cpu)
94
@@ -XXX,XX +XXX,XX @@ static CPAccessResult gt_stimer_access(CPUARMState *env,
53
static void add_cpreg_to_list(gpointer key, gpointer opaque)
95
}
96
}
97
98
+static CPAccessResult gt_sel2timer_access(CPUARMState *env,
99
+ const ARMCPRegInfo *ri,
100
+ bool isread)
101
+{
102
+ /*
103
+ * The AArch64 register view of the secure EL2 timers are mostly
104
+ * accessible from EL3 and EL2 although can also be trapped to EL2
105
+ * from EL1 depending on nested virt config.
106
+ */
107
+ switch (arm_current_el(env)) {
108
+ case 0: /* UNDEFINED */
109
+ return CP_ACCESS_UNDEFINED;
110
+ case 1:
111
+ if (!arm_is_secure(env)) {
112
+ /* UNDEFINED */
113
+ return CP_ACCESS_UNDEFINED;
114
+ } else if (arm_hcr_el2_eff(env) & HCR_NV) {
115
+ /* Aarch64.SystemAccessTrap(EL2, 0x18) */
116
+ return CP_ACCESS_TRAP_EL2;
117
+ }
118
+ /* UNDEFINED */
119
+ return CP_ACCESS_UNDEFINED;
120
+ case 2:
121
+ if (!arm_is_secure(env)) {
122
+ /* UNDEFINED */
123
+ return CP_ACCESS_UNDEFINED;
124
+ }
125
+ return CP_ACCESS_OK;
126
+ case 3:
127
+ if (env->cp15.scr_el3 & SCR_EEL2) {
128
+ return CP_ACCESS_OK;
129
+ } else {
130
+ return CP_ACCESS_UNDEFINED;
131
+ }
132
+ default:
133
+ g_assert_not_reached();
134
+ }
135
+}
136
+
137
uint64_t gt_get_countervalue(CPUARMState *env)
138
{
139
ARMCPU *cpu = env_archcpu(env);
140
@@ -XXX,XX +XXX,XX @@ static uint64_t gt_indirect_access_timer_offset(CPUARMState *env, int timeridx)
141
case GTIMER_HYP:
142
case GTIMER_SEC:
143
case GTIMER_HYPVIRT:
144
+ case GTIMER_S_EL2_PHYS:
145
+ case GTIMER_S_EL2_VIRT:
146
return 0;
147
default:
148
g_assert_not_reached();
149
@@ -XXX,XX +XXX,XX @@ uint64_t gt_direct_access_timer_offset(CPUARMState *env, int timeridx)
150
case GTIMER_HYP:
151
case GTIMER_SEC:
152
case GTIMER_HYPVIRT:
153
+ case GTIMER_S_EL2_PHYS:
154
+ case GTIMER_S_EL2_VIRT:
155
return 0;
156
default:
157
g_assert_not_reached();
158
@@ -XXX,XX +XXX,XX @@ static void gt_sec_ctl_write(CPUARMState *env, const ARMCPRegInfo *ri,
159
gt_ctl_write(env, ri, GTIMER_SEC, value);
160
}
161
162
+static void gt_sec_pel2_timer_reset(CPUARMState *env, const ARMCPRegInfo *ri)
163
+{
164
+ gt_timer_reset(env, ri, GTIMER_S_EL2_PHYS);
165
+}
166
+
167
+static void gt_sec_pel2_cval_write(CPUARMState *env, const ARMCPRegInfo *ri,
168
+ uint64_t value)
169
+{
170
+ gt_cval_write(env, ri, GTIMER_S_EL2_PHYS, value);
171
+}
172
+
173
+static uint64_t gt_sec_pel2_tval_read(CPUARMState *env, const ARMCPRegInfo *ri)
174
+{
175
+ return gt_tval_read(env, ri, GTIMER_S_EL2_PHYS);
176
+}
177
+
178
+static void gt_sec_pel2_tval_write(CPUARMState *env, const ARMCPRegInfo *ri,
179
+ uint64_t value)
180
+{
181
+ gt_tval_write(env, ri, GTIMER_S_EL2_PHYS, value);
182
+}
183
+
184
+static void gt_sec_pel2_ctl_write(CPUARMState *env, const ARMCPRegInfo *ri,
185
+ uint64_t value)
186
+{
187
+ gt_ctl_write(env, ri, GTIMER_S_EL2_PHYS, value);
188
+}
189
+
190
+static void gt_sec_vel2_timer_reset(CPUARMState *env, const ARMCPRegInfo *ri)
191
+{
192
+ gt_timer_reset(env, ri, GTIMER_S_EL2_VIRT);
193
+}
194
+
195
+static void gt_sec_vel2_cval_write(CPUARMState *env, const ARMCPRegInfo *ri,
196
+ uint64_t value)
197
+{
198
+ gt_cval_write(env, ri, GTIMER_S_EL2_VIRT, value);
199
+}
200
+
201
+static uint64_t gt_sec_vel2_tval_read(CPUARMState *env, const ARMCPRegInfo *ri)
202
+{
203
+ return gt_tval_read(env, ri, GTIMER_S_EL2_VIRT);
204
+}
205
+
206
+static void gt_sec_vel2_tval_write(CPUARMState *env, const ARMCPRegInfo *ri,
207
+ uint64_t value)
208
+{
209
+ gt_tval_write(env, ri, GTIMER_S_EL2_VIRT, value);
210
+}
211
+
212
+static void gt_sec_vel2_ctl_write(CPUARMState *env, const ARMCPRegInfo *ri,
213
+ uint64_t value)
214
+{
215
+ gt_ctl_write(env, ri, GTIMER_S_EL2_VIRT, value);
216
+}
217
+
218
static void gt_hv_timer_reset(CPUARMState *env, const ARMCPRegInfo *ri)
219
{
220
gt_timer_reset(env, ri, GTIMER_HYPVIRT);
221
@@ -XXX,XX +XXX,XX @@ void arm_gt_stimer_cb(void *opaque)
222
gt_recalc_timer(cpu, GTIMER_SEC);
223
}
224
225
+void arm_gt_sel2timer_cb(void *opaque)
226
+{
227
+ ARMCPU *cpu = opaque;
228
+
229
+ gt_recalc_timer(cpu, GTIMER_S_EL2_PHYS);
230
+}
231
+
232
+void arm_gt_sel2vtimer_cb(void *opaque)
233
+{
234
+ ARMCPU *cpu = opaque;
235
+
236
+ gt_recalc_timer(cpu, GTIMER_S_EL2_VIRT);
237
+}
238
+
239
void arm_gt_hvtimer_cb(void *opaque)
54
{
240
{
55
ARMCPU *cpu = opaque;
241
ARMCPU *cpu = opaque;
56
- uint64_t regidx;
242
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo el2_sec_cp_reginfo[] = {
57
- const ARMCPRegInfo *ri;
243
.access = PL2_RW, .accessfn = sel2_access,
58
-
244
.nv2_redirect_offset = 0x48,
59
- regidx = *(uint32_t *)key;
245
.fieldoffset = offsetof(CPUARMState, cp15.vstcr_el2) },
60
- ri = get_arm_cp_reginfo(cpu->cp_regs, regidx);
246
+#ifndef CONFIG_USER_ONLY
61
+ uint32_t regidx = (uintptr_t)key;
247
+ /* Secure EL2 Physical Timer */
62
+ const ARMCPRegInfo *ri = get_arm_cp_reginfo(cpu->cp_regs, regidx);
248
+ { .name = "CNTHPS_TVAL_EL2", .state = ARM_CP_STATE_AA64,
63
249
+ .opc0 = 3, .opc1 = 4, .crn = 14, .crm = 5, .opc2 = 0,
64
if (!(ri->type & (ARM_CP_NO_RAW|ARM_CP_ALIAS))) {
250
+ .type = ARM_CP_NO_RAW | ARM_CP_IO, .access = PL2_RW,
65
cpu->cpreg_indexes[cpu->cpreg_array_len] = cpreg_to_kvm_id(regidx);
251
+ .accessfn = gt_sel2timer_access,
66
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_list(gpointer key, gpointer opaque)
252
+ .readfn = gt_sec_pel2_tval_read,
67
static void count_cpreg(gpointer key, gpointer opaque)
253
+ .writefn = gt_sec_pel2_tval_write,
68
{
254
+ .resetfn = gt_sec_pel2_timer_reset,
69
ARMCPU *cpu = opaque;
255
+ },
70
- uint64_t regidx;
256
+ { .name = "CNTHPS_CTL_EL2", .state = ARM_CP_STATE_AA64,
71
const ARMCPRegInfo *ri;
257
+ .opc0 = 3, .opc1 = 4, .crn = 14, .crm = 5, .opc2 = 1,
72
258
+ .type = ARM_CP_IO, .access = PL2_RW,
73
- regidx = *(uint32_t *)key;
259
+ .accessfn = gt_sel2timer_access,
74
- ri = get_arm_cp_reginfo(cpu->cp_regs, regidx);
260
+ .fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_S_EL2_PHYS].ctl),
75
+ ri = g_hash_table_lookup(cpu->cp_regs, key);
261
+ .resetvalue = 0,
76
262
+ .writefn = gt_sec_pel2_ctl_write, .raw_writefn = raw_write,
77
if (!(ri->type & (ARM_CP_NO_RAW|ARM_CP_ALIAS))) {
263
+ },
78
cpu->cpreg_array_len++;
264
+ { .name = "CNTHPS_CVAL_EL2", .state = ARM_CP_STATE_AA64,
79
@@ -XXX,XX +XXX,XX @@ static void count_cpreg(gpointer key, gpointer opaque)
265
+ .opc0 = 3, .opc1 = 4, .crn = 14, .crm = 5, .opc2 = 2,
80
266
+ .type = ARM_CP_IO, .access = PL2_RW,
81
static gint cpreg_key_compare(gconstpointer a, gconstpointer b)
267
+ .accessfn = gt_sel2timer_access,
82
{
268
+ .fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_S_EL2_PHYS].cval),
83
- uint64_t aidx = cpreg_to_kvm_id(*(uint32_t *)a);
269
+ .writefn = gt_sec_pel2_cval_write, .raw_writefn = raw_write,
84
- uint64_t bidx = cpreg_to_kvm_id(*(uint32_t *)b);
270
+ },
85
+ uint64_t aidx = cpreg_to_kvm_id((uintptr_t)a);
271
+ /* Secure EL2 Virtual Timer */
86
+ uint64_t bidx = cpreg_to_kvm_id((uintptr_t)b);
272
+ { .name = "CNTHVS_TVAL_EL2", .state = ARM_CP_STATE_AA64,
87
273
+ .opc0 = 3, .opc1 = 4, .crn = 14, .crm = 4, .opc2 = 0,
88
if (aidx > bidx) {
274
+ .type = ARM_CP_NO_RAW | ARM_CP_IO, .access = PL2_RW,
89
return 1;
275
+ .accessfn = gt_sel2timer_access,
90
@@ -XXX,XX +XXX,XX @@ static void define_arm_vh_e2h_redirects_aliases(ARMCPU *cpu)
276
+ .readfn = gt_sec_vel2_tval_read,
91
for (i = 0; i < ARRAY_SIZE(aliases); i++) {
277
+ .writefn = gt_sec_vel2_tval_write,
92
const struct E2HAlias *a = &aliases[i];
278
+ .resetfn = gt_sec_vel2_timer_reset,
93
ARMCPRegInfo *src_reg, *dst_reg, *new_reg;
279
+ },
94
- uint32_t *new_key;
280
+ { .name = "CNTHVS_CTL_EL2", .state = ARM_CP_STATE_AA64,
95
bool ok;
281
+ .opc0 = 3, .opc1 = 4, .crn = 14, .crm = 4, .opc2 = 1,
96
282
+ .type = ARM_CP_IO, .access = PL2_RW,
97
if (a->feature && !a->feature(&cpu->isar)) {
283
+ .accessfn = gt_sel2timer_access,
98
continue;
284
+ .fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_S_EL2_VIRT].ctl),
99
}
285
+ .resetvalue = 0,
100
286
+ .writefn = gt_sec_vel2_ctl_write, .raw_writefn = raw_write,
101
- src_reg = g_hash_table_lookup(cpu->cp_regs, &a->src_key);
287
+ },
102
- dst_reg = g_hash_table_lookup(cpu->cp_regs, &a->dst_key);
288
+ { .name = "CNTHVS_CVAL_EL2", .state = ARM_CP_STATE_AA64,
103
+ src_reg = g_hash_table_lookup(cpu->cp_regs,
289
+ .opc0 = 3, .opc1 = 4, .crn = 14, .crm = 4, .opc2 = 2,
104
+ (gpointer)(uintptr_t)a->src_key);
290
+ .type = ARM_CP_IO, .access = PL2_RW,
105
+ dst_reg = g_hash_table_lookup(cpu->cp_regs,
291
+ .accessfn = gt_sel2timer_access,
106
+ (gpointer)(uintptr_t)a->dst_key);
292
+ .fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_S_EL2_VIRT].cval),
107
g_assert(src_reg != NULL);
293
+ .writefn = gt_sec_vel2_cval_write, .raw_writefn = raw_write,
108
g_assert(dst_reg != NULL);
294
+ },
109
295
+#endif
110
@@ -XXX,XX +XXX,XX @@ static void define_arm_vh_e2h_redirects_aliases(ARMCPU *cpu)
296
};
111
297
112
/* Create alias before redirection so we dup the right data. */
298
static CPAccessResult nsacr_access(CPUARMState *env, const ARMCPRegInfo *ri,
113
new_reg = g_memdup(src_reg, sizeof(ARMCPRegInfo));
114
- new_key = g_memdup(&a->new_key, sizeof(uint32_t));
115
116
new_reg->name = a->new_name;
117
new_reg->type |= ARM_CP_ALIAS;
118
/* Remove PL1/PL0 access, leaving PL2/PL3 R/W in place. */
119
new_reg->access &= PL2_RW | PL3_RW;
120
121
- ok = g_hash_table_insert(cpu->cp_regs, new_key, new_reg);
122
+ ok = g_hash_table_insert(cpu->cp_regs,
123
+ (gpointer)(uintptr_t)a->new_key, new_reg);
124
g_assert(ok);
125
126
src_reg->opaque = dst_reg;
127
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
128
/* Private utility function for define_one_arm_cp_reg_with_opaque():
129
* add a single reginfo struct to the hash table.
130
*/
131
- uint32_t *key = g_new(uint32_t, 1);
132
+ uint32_t key;
133
ARMCPRegInfo *r2 = g_memdup(r, sizeof(ARMCPRegInfo));
134
int is64 = (r->type & ARM_CP_64BIT) ? 1 : 0;
135
int ns = (secstate & ARM_CP_SECSTATE_NS) ? 1 : 0;
136
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
137
if (r->cp == 0 || r->state == ARM_CP_STATE_BOTH) {
138
r2->cp = CP_REG_ARM64_SYSREG_CP;
139
}
140
- *key = ENCODE_AA64_CP_REG(r2->cp, r2->crn, crm,
141
- r2->opc0, opc1, opc2);
142
+ key = ENCODE_AA64_CP_REG(r2->cp, r2->crn, crm,
143
+ r2->opc0, opc1, opc2);
144
} else {
145
- *key = ENCODE_CP_REG(r2->cp, is64, ns, r2->crn, crm, opc1, opc2);
146
+ key = ENCODE_CP_REG(r2->cp, is64, ns, r2->crn, crm, opc1, opc2);
147
}
148
if (opaque) {
149
r2->opaque = opaque;
150
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
151
* requested.
152
*/
153
if (!(r->type & ARM_CP_OVERRIDE)) {
154
- ARMCPRegInfo *oldreg;
155
- oldreg = g_hash_table_lookup(cpu->cp_regs, key);
156
+ const ARMCPRegInfo *oldreg = get_arm_cp_reginfo(cpu->cp_regs, key);
157
if (oldreg && !(oldreg->type & ARM_CP_OVERRIDE)) {
158
fprintf(stderr, "Register redefined: cp=%d %d bit "
159
"crn=%d crm=%d opc1=%d opc2=%d, "
160
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
161
g_assert_not_reached();
162
}
163
}
164
- g_hash_table_insert(cpu->cp_regs, key, r2);
165
+ g_hash_table_insert(cpu->cp_regs, (gpointer)(uintptr_t)key, r2);
166
}
167
168
169
@@ -XXX,XX +XXX,XX @@ void modify_arm_cp_regs_with_len(ARMCPRegInfo *regs, size_t regs_len,
170
171
const ARMCPRegInfo *get_arm_cp_reginfo(GHashTable *cpregs, uint32_t encoded_cp)
172
{
173
- return g_hash_table_lookup(cpregs, &encoded_cp);
174
+ return g_hash_table_lookup(cpregs, (gpointer)(uintptr_t)encoded_cp);
175
}
176
177
void arm_cp_write_ignore(CPUARMState *env, const ARMCPRegInfo *ri,
178
--
299
--
179
2.25.1
300
2.43.0
301
302
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Alex Bennée <alex.bennee@linaro.org>
2
2
3
Give this enum a name and use in ARMCPRegInfo,
3
As we are about to add more physical and virtual timers let's make it
4
add_cpreg_to_hashtable and define_one_arm_cp_reg_with_opaque.
4
clear what each timer does.
5
5
6
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
6
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20250204125009.2281315-8-peter.maydell@linaro.org
9
Message-id: 20220501055028.646596-9-richard.henderson@linaro.org
10
[PMM: Add timer register name prefix to each comment]
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
13
---
12
target/arm/cpregs.h | 6 +++---
14
target/arm/gtimer.h | 10 +++++-----
13
target/arm/helper.c | 6 ++++--
15
1 file changed, 5 insertions(+), 5 deletions(-)
14
2 files changed, 7 insertions(+), 5 deletions(-)
15
16
16
diff --git a/target/arm/cpregs.h b/target/arm/cpregs.h
17
diff --git a/target/arm/gtimer.h b/target/arm/gtimer.h
17
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/cpregs.h
19
--- a/target/arm/gtimer.h
19
+++ b/target/arm/cpregs.h
20
+++ b/target/arm/gtimer.h
20
@@ -XXX,XX +XXX,XX @@ enum {
21
@@ -XXX,XX +XXX,XX @@
21
* Note that we rely on the values of these enums as we iterate through
22
#define TARGET_ARM_GTIMER_H
22
* the various states in some places.
23
23
*/
24
enum {
24
-enum {
25
- GTIMER_PHYS = 0,
25
+typedef enum {
26
- GTIMER_VIRT = 1,
26
ARM_CP_STATE_AA32 = 0,
27
- GTIMER_HYP = 2,
27
ARM_CP_STATE_AA64 = 1,
28
- GTIMER_SEC = 3,
28
ARM_CP_STATE_BOTH = 2,
29
- GTIMER_HYPVIRT = 4,
29
-};
30
+ GTIMER_PHYS = 0, /* CNTP_* ; EL1 physical timer */
30
+} CPState;
31
+ GTIMER_VIRT = 1, /* CNTV_* ; EL1 virtual timer */
31
32
+ GTIMER_HYP = 2, /* CNTHP_* ; EL2 physical timer */
32
/*
33
+ GTIMER_SEC = 3, /* CNTPS_* ; EL3 physical timer */
33
* ARM CP register secure state flags. These flags identify security state
34
+ GTIMER_HYPVIRT = 4, /* CNTHV_* ; EL2 virtual timer ; only if FEAT_VHE */
34
@@ -XXX,XX +XXX,XX @@ struct ARMCPRegInfo {
35
GTIMER_S_EL2_PHYS = 5, /* CNTHPS_* ; only if FEAT_SEL2 */
35
uint8_t opc1;
36
GTIMER_S_EL2_VIRT = 6, /* CNTHVS_* ; only if FEAT_SEL2 */
36
uint8_t opc2;
37
#define NUM_GTIMERS 7
37
/* Execution state in which this register is visible: ARM_CP_STATE_* */
38
- int state;
39
+ CPState state;
40
/* Register type: ARM_CP_* bits/values */
41
int type;
42
/* Access rights: PL*_[RW] */
43
diff --git a/target/arm/helper.c b/target/arm/helper.c
44
index XXXXXXX..XXXXXXX 100644
45
--- a/target/arm/helper.c
46
+++ b/target/arm/helper.c
47
@@ -XXX,XX +XXX,XX @@ CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp)
48
}
49
50
static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
51
- void *opaque, int state, int secstate,
52
+ void *opaque, CPState state, int secstate,
53
int crm, int opc1, int opc2,
54
const char *name)
55
{
56
@@ -XXX,XX +XXX,XX @@ void define_one_arm_cp_reg_with_opaque(ARMCPU *cpu,
57
* bits; the ARM_CP_64BIT* flag applies only to the AArch32 view of
58
* the register, if any.
59
*/
60
- int crm, opc1, opc2, state;
61
+ int crm, opc1, opc2;
62
int crmmin = (r->crm == CP_ANY) ? 0 : r->crm;
63
int crmmax = (r->crm == CP_ANY) ? 15 : r->crm;
64
int opc1min = (r->opc1 == CP_ANY) ? 0 : r->opc1;
65
int opc1max = (r->opc1 == CP_ANY) ? 7 : r->opc1;
66
int opc2min = (r->opc2 == CP_ANY) ? 0 : r->opc2;
67
int opc2max = (r->opc2 == CP_ANY) ? 7 : r->opc2;
68
+ CPState state;
69
+
70
/* 64 bit registers have only CRm and Opc1 fields */
71
assert(!((r->type & ARM_CP_64BIT) && (r->opc2 || r->crn)));
72
/* op0 only exists in the AArch64 encodings */
73
--
38
--
74
2.25.1
39
2.43.0
75
40
76
41
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Alex Bennée <alex.bennee@linaro.org>
2
2
3
These particular data structures are not modified at runtime.
3
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
4
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20250204125009.2281315-9-peter.maydell@linaro.org
8
Message-id: 20220501055028.646596-5-richard.henderson@linaro.org
7
Cc: qemu-stable@nongnu.org
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
10
---
11
target/arm/helper.c | 16 ++++++++--------
11
hw/arm/virt.c | 2 ++
12
1 file changed, 8 insertions(+), 8 deletions(-)
12
1 file changed, 2 insertions(+)
13
13
14
diff --git a/target/arm/helper.c b/target/arm/helper.c
14
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
15
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/helper.c
16
--- a/hw/arm/virt.c
17
+++ b/target/arm/helper.c
17
+++ b/hw/arm/virt.c
18
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
18
@@ -XXX,XX +XXX,XX @@ static void create_gic(VirtMachineState *vms, MemoryRegion *mem)
19
.resetvalue = cpu->pmceid1 },
19
[GTIMER_HYP] = ARCH_TIMER_NS_EL2_IRQ,
20
[GTIMER_SEC] = ARCH_TIMER_S_EL1_IRQ,
21
[GTIMER_HYPVIRT] = ARCH_TIMER_NS_EL2_VIRT_IRQ,
22
+ [GTIMER_S_EL2_PHYS] = ARCH_TIMER_S_EL2_IRQ,
23
+ [GTIMER_S_EL2_VIRT] = ARCH_TIMER_S_EL2_VIRT_IRQ,
20
};
24
};
21
#ifdef CONFIG_USER_ONLY
25
22
- ARMCPRegUserSpaceInfo v8_user_idregs[] = {
26
for (unsigned irq = 0; irq < ARRAY_SIZE(timer_irq); irq++) {
23
+ static const ARMCPRegUserSpaceInfo v8_user_idregs[] = {
24
{ .name = "ID_AA64PFR0_EL1",
25
.exported_bits = 0x000f000f00ff0000,
26
.fixed_bits = 0x0000000000000011 },
27
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
28
*/
29
if (arm_feature(env, ARM_FEATURE_EL3)) {
30
if (arm_feature(env, ARM_FEATURE_AARCH64)) {
31
- ARMCPRegInfo nsacr = {
32
+ static const ARMCPRegInfo nsacr = {
33
.name = "NSACR", .type = ARM_CP_CONST,
34
.cp = 15, .opc1 = 0, .crn = 1, .crm = 1, .opc2 = 2,
35
.access = PL1_RW, .accessfn = nsacr_access,
36
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
37
};
38
define_one_arm_cp_reg(cpu, &nsacr);
39
} else {
40
- ARMCPRegInfo nsacr = {
41
+ static const ARMCPRegInfo nsacr = {
42
.name = "NSACR",
43
.cp = 15, .opc1 = 0, .crn = 1, .crm = 1, .opc2 = 2,
44
.access = PL3_RW | PL1_R,
45
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
46
}
47
} else {
48
if (arm_feature(env, ARM_FEATURE_V8)) {
49
- ARMCPRegInfo nsacr = {
50
+ static const ARMCPRegInfo nsacr = {
51
.name = "NSACR", .type = ARM_CP_CONST,
52
.cp = 15, .opc1 = 0, .crn = 1, .crm = 1, .opc2 = 2,
53
.access = PL1_R,
54
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
55
.access = PL1_R, .type = ARM_CP_CONST,
56
.resetvalue = cpu->pmsav7_dregion << 8
57
};
58
- ARMCPRegInfo crn0_wi_reginfo = {
59
+ static const ARMCPRegInfo crn0_wi_reginfo = {
60
.name = "CRN0_WI", .cp = 15, .crn = 0, .crm = CP_ANY,
61
.opc1 = CP_ANY, .opc2 = CP_ANY, .access = PL1_W,
62
.type = ARM_CP_NOP | ARM_CP_OVERRIDE
63
};
64
#ifdef CONFIG_USER_ONLY
65
- ARMCPRegUserSpaceInfo id_v8_user_midr_cp_reginfo[] = {
66
+ static const ARMCPRegUserSpaceInfo id_v8_user_midr_cp_reginfo[] = {
67
{ .name = "MIDR_EL1",
68
.exported_bits = 0x00000000ffffffff },
69
{ .name = "REVIDR_EL1" },
70
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
71
.access = PL1_R, .readfn = mpidr_read, .type = ARM_CP_NO_RAW },
72
};
73
#ifdef CONFIG_USER_ONLY
74
- ARMCPRegUserSpaceInfo mpidr_user_cp_reginfo[] = {
75
+ static const ARMCPRegUserSpaceInfo mpidr_user_cp_reginfo[] = {
76
{ .name = "MPIDR_EL1",
77
.fixed_bits = 0x0000000080000000 },
78
};
79
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
80
}
81
82
if (arm_feature(env, ARM_FEATURE_VBAR)) {
83
- ARMCPRegInfo vbar_cp_reginfo[] = {
84
+ static const ARMCPRegInfo vbar_cp_reginfo[] = {
85
{ .name = "VBAR", .state = ARM_CP_STATE_BOTH,
86
.opc0 = 3, .crn = 12, .crm = 0, .opc1 = 0, .opc2 = 0,
87
.access = PL1_RW, .writefn = vbar_write,
88
--
27
--
89
2.25.1
28
2.43.0
90
29
91
30
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Alex Bennée <alex.bennee@linaro.org>
2
2
3
Remove a possible source of error by removing REGINFO_SENTINEL
3
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
4
and using ARRAY_SIZE (convinently hidden inside a macro) to
5
find the end of the set of regs being registered or modified.
6
7
The space saved by not having the extra array element reduces
8
the executable's .data.rel.ro section by about 9k.
9
10
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Message-id: 20220501055028.646596-4-richard.henderson@linaro.org
6
Message-id: 20250204125009.2281315-10-peter.maydell@linaro.org
7
Cc: qemu-stable@nongnu.org
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
---
9
---
16
target/arm/cpregs.h | 53 +++++++++---------
10
hw/arm/sbsa-ref.c | 2 ++
17
hw/arm/pxa2xx.c | 1 -
11
1 file changed, 2 insertions(+)
18
hw/arm/pxa2xx_pic.c | 1 -
19
hw/intc/arm_gicv3_cpuif.c | 5 --
20
hw/intc/arm_gicv3_kvm.c | 1 -
21
target/arm/cpu64.c | 1 -
22
target/arm/cpu_tcg.c | 4 --
23
target/arm/helper.c | 111 ++++++++------------------------------
24
8 files changed, 48 insertions(+), 129 deletions(-)
25
12
26
diff --git a/target/arm/cpregs.h b/target/arm/cpregs.h
13
diff --git a/hw/arm/sbsa-ref.c b/hw/arm/sbsa-ref.c
27
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
28
--- a/target/arm/cpregs.h
15
--- a/hw/arm/sbsa-ref.c
29
+++ b/target/arm/cpregs.h
16
+++ b/hw/arm/sbsa-ref.c
30
@@ -XXX,XX +XXX,XX @@
17
@@ -XXX,XX +XXX,XX @@ static void create_gic(SBSAMachineState *sms, MemoryRegion *mem)
31
#define ARM_CP_NO_GDB 0x4000
18
[GTIMER_HYP] = ARCH_TIMER_NS_EL2_IRQ,
32
#define ARM_CP_RAISES_EXC 0x8000
19
[GTIMER_SEC] = ARCH_TIMER_S_EL1_IRQ,
33
#define ARM_CP_NEWEL 0x10000
20
[GTIMER_HYPVIRT] = ARCH_TIMER_NS_EL2_VIRT_IRQ,
34
-/* Used only as a terminator for ARMCPRegInfo lists */
21
+ [GTIMER_S_EL2_PHYS] = ARCH_TIMER_S_EL2_IRQ,
35
-#define ARM_CP_SENTINEL 0xfffff
22
+ [GTIMER_S_EL2_VIRT] = ARCH_TIMER_S_EL2_VIRT_IRQ,
36
/* Mask of only the flag bits in a type field */
37
#define ARM_CP_FLAG_MASK 0x1f0ff
38
39
@@ -XXX,XX +XXX,XX @@ enum {
40
ARM_CP_SECSTATE_NS = (1 << 1), /* bit[1]: Non-secure state register */
41
};
42
43
-/*
44
- * Return true if cptype is a valid type field. This is used to try to
45
- * catch errors where the sentinel has been accidentally left off the end
46
- * of a list of registers.
47
- */
48
-static inline bool cptype_valid(int cptype)
49
-{
50
- return ((cptype & ~ARM_CP_FLAG_MASK) == 0)
51
- || ((cptype & ARM_CP_SPECIAL) &&
52
- ((cptype & ~ARM_CP_FLAG_MASK) <= ARM_LAST_SPECIAL));
53
-}
54
-
55
/*
56
* Access rights:
57
* We define bits for Read and Write access for what rev C of the v7-AR ARM ARM
58
@@ -XXX,XX +XXX,XX @@ struct ARMCPRegInfo {
59
#define CPREG_FIELD64(env, ri) \
60
(*(uint64_t *)((char *)(env) + (ri)->fieldoffset))
61
62
-#define REGINFO_SENTINEL { .type = ARM_CP_SENTINEL }
63
+void define_one_arm_cp_reg_with_opaque(ARMCPU *cpu, const ARMCPRegInfo *reg,
64
+ void *opaque);
65
66
-void define_arm_cp_regs_with_opaque(ARMCPU *cpu,
67
- const ARMCPRegInfo *regs, void *opaque);
68
-void define_one_arm_cp_reg_with_opaque(ARMCPU *cpu,
69
- const ARMCPRegInfo *regs, void *opaque);
70
-static inline void define_arm_cp_regs(ARMCPU *cpu, const ARMCPRegInfo *regs)
71
-{
72
- define_arm_cp_regs_with_opaque(cpu, regs, 0);
73
-}
74
static inline void define_one_arm_cp_reg(ARMCPU *cpu, const ARMCPRegInfo *regs)
75
{
76
- define_one_arm_cp_reg_with_opaque(cpu, regs, 0);
77
+ define_one_arm_cp_reg_with_opaque(cpu, regs, NULL);
78
}
79
+
80
+void define_arm_cp_regs_with_opaque_len(ARMCPU *cpu, const ARMCPRegInfo *regs,
81
+ void *opaque, size_t len);
82
+
83
+#define define_arm_cp_regs_with_opaque(CPU, REGS, OPAQUE) \
84
+ do { \
85
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(REGS) == 0); \
86
+ define_arm_cp_regs_with_opaque_len(CPU, REGS, OPAQUE, \
87
+ ARRAY_SIZE(REGS)); \
88
+ } while (0)
89
+
90
+#define define_arm_cp_regs(CPU, REGS) \
91
+ define_arm_cp_regs_with_opaque(CPU, REGS, NULL)
92
+
93
const ARMCPRegInfo *get_arm_cp_reginfo(GHashTable *cpregs, uint32_t encoded_cp);
94
95
/*
96
@@ -XXX,XX +XXX,XX @@ typedef struct ARMCPRegUserSpaceInfo {
97
uint64_t fixed_bits;
98
} ARMCPRegUserSpaceInfo;
99
100
-#define REGUSERINFO_SENTINEL { .name = NULL }
101
+void modify_arm_cp_regs_with_len(ARMCPRegInfo *regs, size_t regs_len,
102
+ const ARMCPRegUserSpaceInfo *mods,
103
+ size_t mods_len);
104
105
-void modify_arm_cp_regs(ARMCPRegInfo *regs, const ARMCPRegUserSpaceInfo *mods);
106
+#define modify_arm_cp_regs(REGS, MODS) \
107
+ do { \
108
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(REGS) == 0); \
109
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(MODS) == 0); \
110
+ modify_arm_cp_regs_with_len(REGS, ARRAY_SIZE(REGS), \
111
+ MODS, ARRAY_SIZE(MODS)); \
112
+ } while (0)
113
114
/* CPWriteFn that can be used to implement writes-ignored behaviour */
115
void arm_cp_write_ignore(CPUARMState *env, const ARMCPRegInfo *ri,
116
diff --git a/hw/arm/pxa2xx.c b/hw/arm/pxa2xx.c
117
index XXXXXXX..XXXXXXX 100644
118
--- a/hw/arm/pxa2xx.c
119
+++ b/hw/arm/pxa2xx.c
120
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo pxa_cp_reginfo[] = {
121
{ .name = "PWRMODE", .cp = 14, .crn = 7, .crm = 0, .opc1 = 0, .opc2 = 0,
122
.access = PL1_RW, .type = ARM_CP_IO,
123
.readfn = arm_cp_read_zero, .writefn = pxa2xx_pwrmode_write },
124
- REGINFO_SENTINEL
125
};
126
127
static void pxa2xx_setup_cp14(PXA2xxState *s)
128
diff --git a/hw/arm/pxa2xx_pic.c b/hw/arm/pxa2xx_pic.c
129
index XXXXXXX..XXXXXXX 100644
130
--- a/hw/arm/pxa2xx_pic.c
131
+++ b/hw/arm/pxa2xx_pic.c
132
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo pxa_pic_cp_reginfo[] = {
133
REGINFO_FOR_PIC_CP("ICLR2", 8),
134
REGINFO_FOR_PIC_CP("ICFP2", 9),
135
REGINFO_FOR_PIC_CP("ICPR2", 0xa),
136
- REGINFO_SENTINEL
137
};
138
139
static const MemoryRegionOps pxa2xx_pic_ops = {
140
diff --git a/hw/intc/arm_gicv3_cpuif.c b/hw/intc/arm_gicv3_cpuif.c
141
index XXXXXXX..XXXXXXX 100644
142
--- a/hw/intc/arm_gicv3_cpuif.c
143
+++ b/hw/intc/arm_gicv3_cpuif.c
144
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo gicv3_cpuif_reginfo[] = {
145
.readfn = icc_igrpen1_el3_read,
146
.writefn = icc_igrpen1_el3_write,
147
},
148
- REGINFO_SENTINEL
149
};
150
151
static uint64_t ich_ap_read(CPUARMState *env, const ARMCPRegInfo *ri)
152
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo gicv3_cpuif_hcr_reginfo[] = {
153
.readfn = ich_vmcr_read,
154
.writefn = ich_vmcr_write,
155
},
156
- REGINFO_SENTINEL
157
};
158
159
static const ARMCPRegInfo gicv3_cpuif_ich_apxr1_reginfo[] = {
160
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo gicv3_cpuif_ich_apxr1_reginfo[] = {
161
.readfn = ich_ap_read,
162
.writefn = ich_ap_write,
163
},
164
- REGINFO_SENTINEL
165
};
166
167
static const ARMCPRegInfo gicv3_cpuif_ich_apxr23_reginfo[] = {
168
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo gicv3_cpuif_ich_apxr23_reginfo[] = {
169
.readfn = ich_ap_read,
170
.writefn = ich_ap_write,
171
},
172
- REGINFO_SENTINEL
173
};
174
175
static void gicv3_cpuif_el_change_hook(ARMCPU *cpu, void *opaque)
176
@@ -XXX,XX +XXX,XX @@ void gicv3_init_cpuif(GICv3State *s)
177
.readfn = ich_lr_read,
178
.writefn = ich_lr_write,
179
},
180
- REGINFO_SENTINEL
181
};
182
define_arm_cp_regs(cpu, lr_regset);
183
}
184
diff --git a/hw/intc/arm_gicv3_kvm.c b/hw/intc/arm_gicv3_kvm.c
185
index XXXXXXX..XXXXXXX 100644
186
--- a/hw/intc/arm_gicv3_kvm.c
187
+++ b/hw/intc/arm_gicv3_kvm.c
188
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo gicv3_cpuif_reginfo[] = {
189
*/
190
.resetfn = arm_gicv3_icc_reset,
191
},
192
- REGINFO_SENTINEL
193
};
194
195
/**
196
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
197
index XXXXXXX..XXXXXXX 100644
198
--- a/target/arm/cpu64.c
199
+++ b/target/arm/cpu64.c
200
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo cortex_a72_a57_a53_cp_reginfo[] = {
201
{ .name = "L2MERRSR",
202
.cp = 15, .opc1 = 3, .crm = 15,
203
.access = PL1_RW, .type = ARM_CP_CONST | ARM_CP_64BIT, .resetvalue = 0 },
204
- REGINFO_SENTINEL
205
};
206
207
static void aarch64_a57_initfn(Object *obj)
208
diff --git a/target/arm/cpu_tcg.c b/target/arm/cpu_tcg.c
209
index XXXXXXX..XXXXXXX 100644
210
--- a/target/arm/cpu_tcg.c
211
+++ b/target/arm/cpu_tcg.c
212
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo cortexa8_cp_reginfo[] = {
213
.access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
214
{ .name = "L2AUXCR", .cp = 15, .crn = 9, .crm = 0, .opc1 = 1, .opc2 = 2,
215
.access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
216
- REGINFO_SENTINEL
217
};
218
219
static void cortex_a8_initfn(Object *obj)
220
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo cortexa9_cp_reginfo[] = {
221
.access = PL1_RW, .resetvalue = 0, .type = ARM_CP_CONST },
222
{ .name = "TLB_ATTR", .cp = 15, .crn = 15, .crm = 7, .opc1 = 5, .opc2 = 2,
223
.access = PL1_RW, .resetvalue = 0, .type = ARM_CP_CONST },
224
- REGINFO_SENTINEL
225
};
226
227
static void cortex_a9_initfn(Object *obj)
228
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo cortexa15_cp_reginfo[] = {
229
#endif
230
{ .name = "L2ECTLR", .cp = 15, .crn = 9, .crm = 0, .opc1 = 1, .opc2 = 3,
231
.access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
232
- REGINFO_SENTINEL
233
};
234
235
static void cortex_a7_initfn(Object *obj)
236
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo cortexr5_cp_reginfo[] = {
237
.access = PL1_RW, .type = ARM_CP_CONST },
238
{ .name = "DCACHE_INVAL", .cp = 15, .opc1 = 0, .crn = 15, .crm = 5,
239
.opc2 = 0, .access = PL1_W, .type = ARM_CP_NOP },
240
- REGINFO_SENTINEL
241
};
242
243
static void cortex_r5_initfn(Object *obj)
244
diff --git a/target/arm/helper.c b/target/arm/helper.c
245
index XXXXXXX..XXXXXXX 100644
246
--- a/target/arm/helper.c
247
+++ b/target/arm/helper.c
248
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo cp_reginfo[] = {
249
.secure = ARM_CP_SECSTATE_S,
250
.fieldoffset = offsetof(CPUARMState, cp15.contextidr_s),
251
.resetvalue = 0, .writefn = contextidr_write, .raw_writefn = raw_write, },
252
- REGINFO_SENTINEL
253
};
254
255
static const ARMCPRegInfo not_v8_cp_reginfo[] = {
256
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo not_v8_cp_reginfo[] = {
257
{ .name = "CACHEMAINT", .cp = 15, .crn = 7, .crm = CP_ANY,
258
.opc1 = 0, .opc2 = CP_ANY, .access = PL1_W,
259
.type = ARM_CP_NOP | ARM_CP_OVERRIDE },
260
- REGINFO_SENTINEL
261
};
262
263
static const ARMCPRegInfo not_v6_cp_reginfo[] = {
264
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo not_v6_cp_reginfo[] = {
265
*/
266
{ .name = "WFI_v5", .cp = 15, .crn = 7, .crm = 8, .opc1 = 0, .opc2 = 2,
267
.access = PL1_W, .type = ARM_CP_WFI },
268
- REGINFO_SENTINEL
269
};
270
271
static const ARMCPRegInfo not_v7_cp_reginfo[] = {
272
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo not_v7_cp_reginfo[] = {
273
.opc1 = 0, .opc2 = 0, .access = PL1_RW, .type = ARM_CP_NOP },
274
{ .name = "NMRR", .cp = 15, .crn = 10, .crm = 2,
275
.opc1 = 0, .opc2 = 1, .access = PL1_RW, .type = ARM_CP_NOP },
276
- REGINFO_SENTINEL
277
};
278
279
static void cpacr_write(CPUARMState *env, const ARMCPRegInfo *ri,
280
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo v6_cp_reginfo[] = {
281
.crn = 1, .crm = 0, .opc1 = 0, .opc2 = 2, .accessfn = cpacr_access,
282
.access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.cpacr_el1),
283
.resetfn = cpacr_reset, .writefn = cpacr_write, .readfn = cpacr_read },
284
- REGINFO_SENTINEL
285
};
286
287
typedef struct pm_event {
288
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo v7_cp_reginfo[] = {
289
{ .name = "TLBIMVAA", .cp = 15, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 3,
290
.type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlb,
291
.writefn = tlbimvaa_write },
292
- REGINFO_SENTINEL
293
};
294
295
static const ARMCPRegInfo v7mp_cp_reginfo[] = {
296
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo v7mp_cp_reginfo[] = {
297
{ .name = "TLBIMVAAIS", .cp = 15, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 3,
298
.type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlb,
299
.writefn = tlbimvaa_is_write },
300
- REGINFO_SENTINEL
301
};
302
303
static const ARMCPRegInfo pmovsset_cp_reginfo[] = {
304
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo pmovsset_cp_reginfo[] = {
305
.fieldoffset = offsetof(CPUARMState, cp15.c9_pmovsr),
306
.writefn = pmovsset_write,
307
.raw_writefn = raw_write },
308
- REGINFO_SENTINEL
309
};
310
311
static void teecr_write(CPUARMState *env, const ARMCPRegInfo *ri,
312
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo t2ee_cp_reginfo[] = {
313
{ .name = "TEEHBR", .cp = 14, .crn = 1, .crm = 0, .opc1 = 6, .opc2 = 0,
314
.access = PL0_RW, .fieldoffset = offsetof(CPUARMState, teehbr),
315
.accessfn = teehbr_access, .resetvalue = 0 },
316
- REGINFO_SENTINEL
317
};
318
319
static const ARMCPRegInfo v6k_cp_reginfo[] = {
320
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo v6k_cp_reginfo[] = {
321
.bank_fieldoffsets = { offsetoflow32(CPUARMState, cp15.tpidrprw_s),
322
offsetoflow32(CPUARMState, cp15.tpidrprw_ns) },
323
.resetvalue = 0 },
324
- REGINFO_SENTINEL
325
};
326
327
#ifndef CONFIG_USER_ONLY
328
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo generic_timer_cp_reginfo[] = {
329
.fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_SEC].cval),
330
.writefn = gt_sec_cval_write, .raw_writefn = raw_write,
331
},
332
- REGINFO_SENTINEL
333
};
334
335
static CPAccessResult e2h_access(CPUARMState *env, const ARMCPRegInfo *ri,
336
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo generic_timer_cp_reginfo[] = {
337
.access = PL0_R, .type = ARM_CP_NO_RAW | ARM_CP_IO,
338
.readfn = gt_virt_cnt_read,
339
},
340
- REGINFO_SENTINEL
341
};
342
343
#endif
344
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo vapa_cp_reginfo[] = {
345
.access = PL1_W, .accessfn = ats_access,
346
.writefn = ats_write, .type = ARM_CP_NO_RAW | ARM_CP_RAISES_EXC },
347
#endif
348
- REGINFO_SENTINEL
349
};
350
351
/* Return basic MPU access permission bits. */
352
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo pmsav7_cp_reginfo[] = {
353
.fieldoffset = offsetof(CPUARMState, pmsav7.rnr[M_REG_NS]),
354
.writefn = pmsav7_rgnr_write,
355
.resetfn = arm_cp_reset_ignore },
356
- REGINFO_SENTINEL
357
};
358
359
static const ARMCPRegInfo pmsav5_cp_reginfo[] = {
360
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo pmsav5_cp_reginfo[] = {
361
{ .name = "946_PRBS7", .cp = 15, .crn = 6, .crm = 7, .opc1 = 0,
362
.opc2 = CP_ANY, .access = PL1_RW, .resetvalue = 0,
363
.fieldoffset = offsetof(CPUARMState, cp15.c6_region[7]) },
364
- REGINFO_SENTINEL
365
};
366
367
static void vmsa_ttbcr_raw_write(CPUARMState *env, const ARMCPRegInfo *ri,
368
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo vmsa_pmsa_cp_reginfo[] = {
369
.access = PL1_RW, .accessfn = access_tvm_trvm,
370
.fieldoffset = offsetof(CPUARMState, cp15.far_el[1]),
371
.resetvalue = 0, },
372
- REGINFO_SENTINEL
373
};
374
375
static const ARMCPRegInfo vmsa_cp_reginfo[] = {
376
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo vmsa_cp_reginfo[] = {
377
/* No offsetoflow32 -- pass the entire TCR to writefn/raw_writefn. */
378
.bank_fieldoffsets = { offsetof(CPUARMState, cp15.tcr_el[3]),
379
offsetof(CPUARMState, cp15.tcr_el[1])} },
380
- REGINFO_SENTINEL
381
};
382
383
/* Note that unlike TTBCR, writing to TTBCR2 does not require flushing
384
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo omap_cp_reginfo[] = {
385
{ .name = "C9", .cp = 15, .crn = 9,
386
.crm = CP_ANY, .opc1 = CP_ANY, .opc2 = CP_ANY, .access = PL1_RW,
387
.type = ARM_CP_CONST | ARM_CP_OVERRIDE, .resetvalue = 0 },
388
- REGINFO_SENTINEL
389
};
390
391
static void xscale_cpar_write(CPUARMState *env, const ARMCPRegInfo *ri,
392
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo xscale_cp_reginfo[] = {
393
{ .name = "XSCALE_UNLOCK_DCACHE",
394
.cp = 15, .opc1 = 0, .crn = 9, .crm = 2, .opc2 = 1,
395
.access = PL1_W, .type = ARM_CP_NOP },
396
- REGINFO_SENTINEL
397
};
398
399
static const ARMCPRegInfo dummy_c15_cp_reginfo[] = {
400
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo dummy_c15_cp_reginfo[] = {
401
.access = PL1_RW,
402
.type = ARM_CP_CONST | ARM_CP_NO_RAW | ARM_CP_OVERRIDE,
403
.resetvalue = 0 },
404
- REGINFO_SENTINEL
405
};
406
407
static const ARMCPRegInfo cache_dirty_status_cp_reginfo[] = {
408
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo cache_dirty_status_cp_reginfo[] = {
409
{ .name = "CDSR", .cp = 15, .crn = 7, .crm = 10, .opc1 = 0, .opc2 = 6,
410
.access = PL1_R, .type = ARM_CP_CONST | ARM_CP_NO_RAW,
411
.resetvalue = 0 },
412
- REGINFO_SENTINEL
413
};
414
415
static const ARMCPRegInfo cache_block_ops_cp_reginfo[] = {
416
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo cache_block_ops_cp_reginfo[] = {
417
.access = PL0_W, .type = ARM_CP_NOP|ARM_CP_64BIT },
418
{ .name = "CIDCR", .cp = 15, .crm = 14, .opc1 = 0,
419
.access = PL1_W, .type = ARM_CP_NOP|ARM_CP_64BIT },
420
- REGINFO_SENTINEL
421
};
422
423
static const ARMCPRegInfo cache_test_clean_cp_reginfo[] = {
424
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo cache_test_clean_cp_reginfo[] = {
425
{ .name = "TCI_DCACHE", .cp = 15, .crn = 7, .crm = 14, .opc1 = 0, .opc2 = 3,
426
.access = PL0_R, .type = ARM_CP_CONST | ARM_CP_NO_RAW,
427
.resetvalue = (1 << 30) },
428
- REGINFO_SENTINEL
429
};
430
431
static const ARMCPRegInfo strongarm_cp_reginfo[] = {
432
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo strongarm_cp_reginfo[] = {
433
.crm = CP_ANY, .opc1 = CP_ANY, .opc2 = CP_ANY,
434
.access = PL1_RW, .resetvalue = 0,
435
.type = ARM_CP_CONST | ARM_CP_OVERRIDE | ARM_CP_NO_RAW },
436
- REGINFO_SENTINEL
437
};
438
439
static uint64_t midr_read(CPUARMState *env, const ARMCPRegInfo *ri)
440
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo lpae_cp_reginfo[] = {
441
.bank_fieldoffsets = { offsetof(CPUARMState, cp15.ttbr1_s),
442
offsetof(CPUARMState, cp15.ttbr1_ns) },
443
.writefn = vmsa_ttbr_write, },
444
- REGINFO_SENTINEL
445
};
446
447
static uint64_t aa64_fpcr_read(CPUARMState *env, const ARMCPRegInfo *ri)
448
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo v8_cp_reginfo[] = {
449
.access = PL1_RW, .accessfn = access_trap_aa32s_el1,
450
.writefn = sdcr_write,
451
.fieldoffset = offsetoflow32(CPUARMState, cp15.mdcr_el3) },
452
- REGINFO_SENTINEL
453
};
454
455
/* Used to describe the behaviour of EL2 regs when EL2 does not exist. */
456
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo el3_no_el2_cp_reginfo[] = {
457
.type = ARM_CP_CONST,
458
.cp = 15, .opc1 = 4, .crn = 6, .crm = 0, .opc2 = 2,
459
.access = PL2_RW, .resetvalue = 0 },
460
- REGINFO_SENTINEL
461
};
462
463
/* Ditto, but for registers which exist in ARMv8 but not v7 */
464
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo el3_no_el2_v8_cp_reginfo[] = {
465
.cp = 15, .opc1 = 4, .crn = 1, .crm = 1, .opc2 = 4,
466
.access = PL2_RW,
467
.type = ARM_CP_CONST, .resetvalue = 0 },
468
- REGINFO_SENTINEL
469
};
470
471
static void do_hcr_write(CPUARMState *env, uint64_t value, uint64_t valid_mask)
472
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo el2_cp_reginfo[] = {
473
.cp = 15, .opc0 = 3, .opc1 = 4, .crn = 1, .crm = 1, .opc2 = 3,
474
.access = PL2_RW,
475
.fieldoffset = offsetof(CPUARMState, cp15.hstr_el2) },
476
- REGINFO_SENTINEL
477
};
478
479
static const ARMCPRegInfo el2_v8_cp_reginfo[] = {
480
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo el2_v8_cp_reginfo[] = {
481
.access = PL2_RW,
482
.fieldoffset = offsetofhigh32(CPUARMState, cp15.hcr_el2),
483
.writefn = hcr_writehigh },
484
- REGINFO_SENTINEL
485
};
486
487
static CPAccessResult sel2_access(CPUARMState *env, const ARMCPRegInfo *ri,
488
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo el2_sec_cp_reginfo[] = {
489
.opc0 = 3, .opc1 = 4, .crn = 2, .crm = 6, .opc2 = 2,
490
.access = PL2_RW, .accessfn = sel2_access,
491
.fieldoffset = offsetof(CPUARMState, cp15.vstcr_el2) },
492
- REGINFO_SENTINEL
493
};
494
495
static CPAccessResult nsacr_access(CPUARMState *env, const ARMCPRegInfo *ri,
496
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo el3_cp_reginfo[] = {
497
.opc0 = 1, .opc1 = 6, .crn = 8, .crm = 7, .opc2 = 5,
498
.access = PL3_W, .type = ARM_CP_NO_RAW,
499
.writefn = tlbi_aa64_vae3_write },
500
- REGINFO_SENTINEL
501
};
502
503
#ifndef CONFIG_USER_ONLY
504
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo debug_cp_reginfo[] = {
505
.cp = 14, .opc0 = 2, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 0,
506
.access = PL1_RW, .accessfn = access_tda,
507
.type = ARM_CP_NOP },
508
- REGINFO_SENTINEL
509
};
510
511
static const ARMCPRegInfo debug_lpae_cp_reginfo[] = {
512
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo debug_lpae_cp_reginfo[] = {
513
.access = PL0_R, .type = ARM_CP_CONST|ARM_CP_64BIT, .resetvalue = 0 },
514
{ .name = "DBGDSAR", .cp = 14, .crm = 2, .opc1 = 0,
515
.access = PL0_R, .type = ARM_CP_CONST|ARM_CP_64BIT, .resetvalue = 0 },
516
- REGINFO_SENTINEL
517
};
518
519
/* Return the exception level to which exceptions should be taken
520
@@ -XXX,XX +XXX,XX @@ static void define_debug_regs(ARMCPU *cpu)
521
.fieldoffset = offsetof(CPUARMState, cp15.dbgbcr[i]),
522
.writefn = dbgbcr_write, .raw_writefn = raw_write
523
},
524
- REGINFO_SENTINEL
525
};
23
};
526
define_arm_cp_regs(cpu, dbgregs);
24
527
}
25
for (irq = 0; irq < ARRAY_SIZE(timer_irq); irq++) {
528
@@ -XXX,XX +XXX,XX @@ static void define_debug_regs(ARMCPU *cpu)
529
.fieldoffset = offsetof(CPUARMState, cp15.dbgwcr[i]),
530
.writefn = dbgwcr_write, .raw_writefn = raw_write
531
},
532
- REGINFO_SENTINEL
533
};
534
define_arm_cp_regs(cpu, dbgregs);
535
}
536
@@ -XXX,XX +XXX,XX @@ static void define_pmu_regs(ARMCPU *cpu)
537
.type = ARM_CP_IO,
538
.readfn = pmevtyper_readfn, .writefn = pmevtyper_writefn,
539
.raw_writefn = pmevtyper_rawwrite },
540
- REGINFO_SENTINEL
541
};
542
define_arm_cp_regs(cpu, pmev_regs);
543
g_free(pmevcntr_name);
544
@@ -XXX,XX +XXX,XX @@ static void define_pmu_regs(ARMCPU *cpu)
545
.cp = 15, .opc1 = 0, .crn = 9, .crm = 14, .opc2 = 5,
546
.access = PL0_R, .accessfn = pmreg_access, .type = ARM_CP_CONST,
547
.resetvalue = extract64(cpu->pmceid1, 32, 32) },
548
- REGINFO_SENTINEL
549
};
550
define_arm_cp_regs(cpu, v81_pmu_regs);
551
}
552
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo lor_reginfo[] = {
553
.opc0 = 3, .opc1 = 0, .crn = 10, .crm = 4, .opc2 = 7,
554
.access = PL1_R, .accessfn = access_lor_ns,
555
.type = ARM_CP_CONST, .resetvalue = 0 },
556
- REGINFO_SENTINEL
557
};
558
559
#ifdef TARGET_AARCH64
560
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo pauth_reginfo[] = {
561
.opc0 = 3, .opc1 = 0, .crn = 2, .crm = 1, .opc2 = 3,
562
.access = PL1_RW, .accessfn = access_pauth,
563
.fieldoffset = offsetof(CPUARMState, keys.apib.hi) },
564
- REGINFO_SENTINEL
565
};
566
567
static const ARMCPRegInfo tlbirange_reginfo[] = {
568
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo tlbirange_reginfo[] = {
569
.opc0 = 1, .opc1 = 6, .crn = 8, .crm = 6, .opc2 = 5,
570
.access = PL3_W, .type = ARM_CP_NO_RAW,
571
.writefn = tlbi_aa64_rvae3_write },
572
- REGINFO_SENTINEL
573
};
574
575
static const ARMCPRegInfo tlbios_reginfo[] = {
576
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo tlbios_reginfo[] = {
577
.opc0 = 1, .opc1 = 6, .crn = 8, .crm = 1, .opc2 = 5,
578
.access = PL3_W, .type = ARM_CP_NO_RAW,
579
.writefn = tlbi_aa64_vae3is_write },
580
- REGINFO_SENTINEL
581
};
582
583
static uint64_t rndr_readfn(CPUARMState *env, const ARMCPRegInfo *ri)
584
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo rndr_reginfo[] = {
585
.type = ARM_CP_NO_RAW | ARM_CP_SUPPRESS_TB_END | ARM_CP_IO,
586
.opc0 = 3, .opc1 = 3, .crn = 2, .crm = 4, .opc2 = 1,
587
.access = PL0_R, .readfn = rndr_readfn },
588
- REGINFO_SENTINEL
589
};
590
591
#ifndef CONFIG_USER_ONLY
592
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo dcpop_reg[] = {
593
.opc0 = 1, .opc1 = 3, .crn = 7, .crm = 12, .opc2 = 1,
594
.access = PL0_W, .type = ARM_CP_NO_RAW | ARM_CP_SUPPRESS_TB_END,
595
.accessfn = aa64_cacheop_poc_access, .writefn = dccvap_writefn },
596
- REGINFO_SENTINEL
597
};
598
599
static const ARMCPRegInfo dcpodp_reg[] = {
600
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo dcpodp_reg[] = {
601
.opc0 = 1, .opc1 = 3, .crn = 7, .crm = 13, .opc2 = 1,
602
.access = PL0_W, .type = ARM_CP_NO_RAW | ARM_CP_SUPPRESS_TB_END,
603
.accessfn = aa64_cacheop_poc_access, .writefn = dccvap_writefn },
604
- REGINFO_SENTINEL
605
};
606
#endif /*CONFIG_USER_ONLY*/
607
608
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo mte_reginfo[] = {
609
{ .name = "DC_CIGDSW", .state = ARM_CP_STATE_AA64,
610
.opc0 = 1, .opc1 = 0, .crn = 7, .crm = 14, .opc2 = 6,
611
.type = ARM_CP_NOP, .access = PL1_W, .accessfn = access_tsw },
612
- REGINFO_SENTINEL
613
};
614
615
static const ARMCPRegInfo mte_tco_ro_reginfo[] = {
616
{ .name = "TCO", .state = ARM_CP_STATE_AA64,
617
.opc0 = 3, .opc1 = 3, .crn = 4, .crm = 2, .opc2 = 7,
618
.type = ARM_CP_CONST, .access = PL0_RW, },
619
- REGINFO_SENTINEL
620
};
621
622
static const ARMCPRegInfo mte_el0_cacheop_reginfo[] = {
623
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo mte_el0_cacheop_reginfo[] = {
624
.accessfn = aa64_zva_access,
625
#endif
626
},
627
- REGINFO_SENTINEL
628
};
629
630
#endif
631
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo predinv_reginfo[] = {
632
{ .name = "CPPRCTX", .state = ARM_CP_STATE_AA32,
633
.cp = 15, .opc1 = 0, .crn = 7, .crm = 3, .opc2 = 7,
634
.type = ARM_CP_NOP, .access = PL0_W, .accessfn = access_predinv },
635
- REGINFO_SENTINEL
636
};
637
638
static uint64_t ccsidr2_read(CPUARMState *env, const ARMCPRegInfo *ri)
639
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo ccsidr2_reginfo[] = {
640
.access = PL1_R,
641
.accessfn = access_aa64_tid2,
642
.readfn = ccsidr2_read, .type = ARM_CP_NO_RAW },
643
- REGINFO_SENTINEL
644
};
645
646
static CPAccessResult access_aa64_tid3(CPUARMState *env, const ARMCPRegInfo *ri,
647
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo jazelle_regs[] = {
648
.cp = 14, .crn = 2, .crm = 0, .opc1 = 7, .opc2 = 0,
649
.accessfn = access_joscr_jmcr,
650
.access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
651
- REGINFO_SENTINEL
652
};
653
654
static const ARMCPRegInfo vhe_reginfo[] = {
655
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo vhe_reginfo[] = {
656
.access = PL2_RW, .accessfn = e2h_access,
657
.writefn = gt_virt_cval_write, .raw_writefn = raw_write },
658
#endif
659
- REGINFO_SENTINEL
660
};
661
662
#ifndef CONFIG_USER_ONLY
663
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo ats1e1_reginfo[] = {
664
.opc0 = 1, .opc1 = 0, .crn = 7, .crm = 9, .opc2 = 1,
665
.access = PL1_W, .type = ARM_CP_NO_RAW | ARM_CP_RAISES_EXC,
666
.writefn = ats_write64 },
667
- REGINFO_SENTINEL
668
};
669
670
static const ARMCPRegInfo ats1cp_reginfo[] = {
671
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo ats1cp_reginfo[] = {
672
.cp = 15, .opc1 = 0, .crn = 7, .crm = 9, .opc2 = 1,
673
.access = PL1_W, .type = ARM_CP_NO_RAW | ARM_CP_RAISES_EXC,
674
.writefn = ats_write },
675
- REGINFO_SENTINEL
676
};
677
#endif
678
679
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo actlr2_hactlr2_reginfo[] = {
680
.cp = 15, .opc1 = 4, .crn = 1, .crm = 0, .opc2 = 3,
681
.access = PL2_RW, .type = ARM_CP_CONST,
682
.resetvalue = 0 },
683
- REGINFO_SENTINEL
684
};
685
686
void register_cp_regs_for_features(ARMCPU *cpu)
687
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
688
.access = PL1_R, .type = ARM_CP_CONST,
689
.accessfn = access_aa32_tid3,
690
.resetvalue = cpu->isar.id_isar6 },
691
- REGINFO_SENTINEL
692
};
693
define_arm_cp_regs(cpu, v6_idregs);
694
define_arm_cp_regs(cpu, v6_cp_reginfo);
695
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
696
.opc0 = 3, .opc1 = 3, .crn = 9, .crm = 12, .opc2 = 7,
697
.access = PL0_R, .accessfn = pmreg_access, .type = ARM_CP_CONST,
698
.resetvalue = cpu->pmceid1 },
699
- REGINFO_SENTINEL
700
};
701
#ifdef CONFIG_USER_ONLY
702
ARMCPRegUserSpaceInfo v8_user_idregs[] = {
703
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
704
.exported_bits = 0x000000f0ffffffff },
705
{ .name = "ID_AA64ISAR*_EL1_RESERVED",
706
.is_glob = true },
707
- REGUSERINFO_SENTINEL
708
};
709
modify_arm_cp_regs(v8_idregs, v8_user_idregs);
710
#endif
711
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
712
.access = PL2_RW,
713
.resetvalue = vmpidr_def,
714
.fieldoffset = offsetof(CPUARMState, cp15.vmpidr_el2) },
715
- REGINFO_SENTINEL
716
};
717
define_arm_cp_regs(cpu, vpidr_regs);
718
define_arm_cp_regs(cpu, el2_cp_reginfo);
719
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
720
.access = PL2_RW, .accessfn = access_el3_aa32ns,
721
.type = ARM_CP_NO_RAW,
722
.writefn = arm_cp_write_ignore, .readfn = mpidr_read },
723
- REGINFO_SENTINEL
724
};
725
define_arm_cp_regs(cpu, vpidr_regs);
726
define_arm_cp_regs(cpu, el3_no_el2_cp_reginfo);
727
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
728
.raw_writefn = raw_write, .writefn = sctlr_write,
729
.fieldoffset = offsetof(CPUARMState, cp15.sctlr_el[3]),
730
.resetvalue = cpu->reset_sctlr },
731
- REGINFO_SENTINEL
732
};
733
734
define_arm_cp_regs(cpu, el3_regs);
735
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
736
{ .name = "DUMMY",
737
.cp = 15, .crn = 0, .crm = 7, .opc1 = 0, .opc2 = CP_ANY,
738
.access = PL1_R, .type = ARM_CP_CONST, .resetvalue = 0 },
739
- REGINFO_SENTINEL
740
};
741
ARMCPRegInfo id_v8_midr_cp_reginfo[] = {
742
{ .name = "MIDR_EL1", .state = ARM_CP_STATE_BOTH,
743
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
744
.access = PL1_R,
745
.accessfn = access_aa64_tid1,
746
.type = ARM_CP_CONST, .resetvalue = cpu->revidr },
747
- REGINFO_SENTINEL
748
};
749
ARMCPRegInfo id_cp_reginfo[] = {
750
/* These are common to v8 and pre-v8 */
751
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
752
.access = PL1_R,
753
.accessfn = access_aa32_tid1,
754
.type = ARM_CP_CONST, .resetvalue = 0 },
755
- REGINFO_SENTINEL
756
};
757
/* TLBTR is specific to VMSA */
758
ARMCPRegInfo id_tlbtr_reginfo = {
759
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
760
{ .name = "MIDR_EL1",
761
.exported_bits = 0x00000000ffffffff },
762
{ .name = "REVIDR_EL1" },
763
- REGUSERINFO_SENTINEL
764
};
765
modify_arm_cp_regs(id_v8_midr_cp_reginfo, id_v8_user_midr_cp_reginfo);
766
#endif
767
if (arm_feature(env, ARM_FEATURE_OMAPCP) ||
768
arm_feature(env, ARM_FEATURE_STRONGARM)) {
769
- ARMCPRegInfo *r;
770
+ size_t i;
771
/* Register the blanket "writes ignored" value first to cover the
772
* whole space. Then update the specific ID registers to allow write
773
* access, so that they ignore writes rather than causing them to
774
* UNDEF.
775
*/
776
define_one_arm_cp_reg(cpu, &crn0_wi_reginfo);
777
- for (r = id_pre_v8_midr_cp_reginfo;
778
- r->type != ARM_CP_SENTINEL; r++) {
779
- r->access = PL1_RW;
780
+ for (i = 0; i < ARRAY_SIZE(id_pre_v8_midr_cp_reginfo); ++i) {
781
+ id_pre_v8_midr_cp_reginfo[i].access = PL1_RW;
782
}
783
- for (r = id_cp_reginfo; r->type != ARM_CP_SENTINEL; r++) {
784
- r->access = PL1_RW;
785
+ for (i = 0; i < ARRAY_SIZE(id_cp_reginfo); ++i) {
786
+ id_cp_reginfo[i].access = PL1_RW;
787
}
788
id_mpuir_reginfo.access = PL1_RW;
789
id_tlbtr_reginfo.access = PL1_RW;
790
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
791
{ .name = "MPIDR_EL1", .state = ARM_CP_STATE_BOTH,
792
.opc0 = 3, .crn = 0, .crm = 0, .opc1 = 0, .opc2 = 5,
793
.access = PL1_R, .readfn = mpidr_read, .type = ARM_CP_NO_RAW },
794
- REGINFO_SENTINEL
795
};
796
#ifdef CONFIG_USER_ONLY
797
ARMCPRegUserSpaceInfo mpidr_user_cp_reginfo[] = {
798
{ .name = "MPIDR_EL1",
799
.fixed_bits = 0x0000000080000000 },
800
- REGUSERINFO_SENTINEL
801
};
802
modify_arm_cp_regs(mpidr_cp_reginfo, mpidr_user_cp_reginfo);
803
#endif
804
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
805
.opc0 = 3, .opc1 = 6, .crn = 1, .crm = 0, .opc2 = 1,
806
.access = PL3_RW, .type = ARM_CP_CONST,
807
.resetvalue = 0 },
808
- REGINFO_SENTINEL
809
};
810
define_arm_cp_regs(cpu, auxcr_reginfo);
811
if (cpu_isar_feature(aa32_ac2, cpu)) {
812
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
813
.type = ARM_CP_CONST,
814
.opc0 = 3, .opc1 = 1, .crn = 15, .crm = 3, .opc2 = 0,
815
.access = PL1_R, .resetvalue = cpu->reset_cbar },
816
- REGINFO_SENTINEL
817
};
818
/* We don't implement a r/w 64 bit CBAR currently */
819
assert(arm_feature(env, ARM_FEATURE_CBAR_RO));
820
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
821
.bank_fieldoffsets = { offsetof(CPUARMState, cp15.vbar_s),
822
offsetof(CPUARMState, cp15.vbar_ns) },
823
.resetvalue = 0 },
824
- REGINFO_SENTINEL
825
};
826
define_arm_cp_regs(cpu, vbar_cp_reginfo);
827
}
828
@@ -XXX,XX +XXX,XX @@ void define_one_arm_cp_reg_with_opaque(ARMCPU *cpu,
829
r->writefn);
830
}
831
}
832
- /* Bad type field probably means missing sentinel at end of reg list */
833
- assert(cptype_valid(r->type));
834
+
835
for (crm = crmmin; crm <= crmmax; crm++) {
836
for (opc1 = opc1min; opc1 <= opc1max; opc1++) {
837
for (opc2 = opc2min; opc2 <= opc2max; opc2++) {
838
@@ -XXX,XX +XXX,XX @@ void define_one_arm_cp_reg_with_opaque(ARMCPU *cpu,
839
}
840
}
841
842
-void define_arm_cp_regs_with_opaque(ARMCPU *cpu,
843
- const ARMCPRegInfo *regs, void *opaque)
844
+/* Define a whole list of registers */
845
+void define_arm_cp_regs_with_opaque_len(ARMCPU *cpu, const ARMCPRegInfo *regs,
846
+ void *opaque, size_t len)
847
{
848
- /* Define a whole list of registers */
849
- const ARMCPRegInfo *r;
850
- for (r = regs; r->type != ARM_CP_SENTINEL; r++) {
851
- define_one_arm_cp_reg_with_opaque(cpu, r, opaque);
852
+ size_t i;
853
+ for (i = 0; i < len; ++i) {
854
+ define_one_arm_cp_reg_with_opaque(cpu, regs + i, opaque);
855
}
856
}
857
858
@@ -XXX,XX +XXX,XX @@ void define_arm_cp_regs_with_opaque(ARMCPU *cpu,
859
* user-space cannot alter any values and dynamic values pertaining to
860
* execution state are hidden from user space view anyway.
861
*/
862
-void modify_arm_cp_regs(ARMCPRegInfo *regs, const ARMCPRegUserSpaceInfo *mods)
863
+void modify_arm_cp_regs_with_len(ARMCPRegInfo *regs, size_t regs_len,
864
+ const ARMCPRegUserSpaceInfo *mods,
865
+ size_t mods_len)
866
{
867
- const ARMCPRegUserSpaceInfo *m;
868
- ARMCPRegInfo *r;
869
-
870
- for (m = mods; m->name; m++) {
871
+ for (size_t mi = 0; mi < mods_len; ++mi) {
872
+ const ARMCPRegUserSpaceInfo *m = mods + mi;
873
GPatternSpec *pat = NULL;
874
+
875
if (m->is_glob) {
876
pat = g_pattern_spec_new(m->name);
877
}
878
- for (r = regs; r->type != ARM_CP_SENTINEL; r++) {
879
+ for (size_t ri = 0; ri < regs_len; ++ri) {
880
+ ARMCPRegInfo *r = regs + ri;
881
+
882
if (pat && g_pattern_match_string(pat, r->name)) {
883
r->type = ARM_CP_CONST;
884
r->access = PL0U_R;
885
--
26
--
886
2.25.1
27
2.43.0
887
28
888
29
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
Our LDRD implementation is wrong in two respects:
2
2
3
Add the aa64 predicate for detecting RAS support from id registers.
3
* if the address is 4-aligned and the load crosses a page boundary
4
We already have the aa32 version from the M-profile work.
4
and the second load faults and the first load was to the
5
Add the 'any' predicate for testing both aa64 and aa32.
5
base register (as in cases like "ldrd r2, r3, [r2]", then we
6
must not update the base register before taking the fault
7
* if the address is 8-aligned the access must be a 64-bit
8
single-copy atomic access, not two 32-bit accesses
6
9
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Rewrite the handling of the loads in LDRD to use a single
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
tcg_gen_qemu_ld_i64() and split the result into the destination
9
Message-id: 20220501055028.646596-34-richard.henderson@linaro.org
12
registers. This allows us to get the atomicity requirements
13
right, and also implicitly means that we won't update the
14
base register too early for the page-crossing case.
15
16
Note that because we no longer increment 'addr' by 4 in the course of
17
performing the LDRD we must change the adjustment value we pass to
18
op_addr_ri_post() and op_addr_rr_post(): it no longer needs to
19
subtract 4 to get the correct value to use if doing base register
20
writeback.
21
22
STRD has the same problem with not getting the atomicity right;
23
we will deal with that in the following commit.
24
25
Cc: qemu-stable@nongnu.org
26
Reported-by: Stu Grossman <stu.grossman@gmail.com>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
27
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
28
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
29
Message-id: 20250227142746.1698904-2-peter.maydell@linaro.org
11
---
30
---
12
target/arm/cpu.h | 10 ++++++++++
31
target/arm/tcg/translate.c | 70 +++++++++++++++++++++++++-------------
13
1 file changed, 10 insertions(+)
32
1 file changed, 46 insertions(+), 24 deletions(-)
14
33
15
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
34
diff --git a/target/arm/tcg/translate.c b/target/arm/tcg/translate.c
16
index XXXXXXX..XXXXXXX 100644
35
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/cpu.h
36
--- a/target/arm/tcg/translate.c
18
+++ b/target/arm/cpu.h
37
+++ b/target/arm/tcg/translate.c
19
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa64_aa32_el1(const ARMISARegisters *id)
38
@@ -XXX,XX +XXX,XX @@ static bool op_store_rr(DisasContext *s, arg_ldst_rr *a,
20
return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, EL1) >= 2;
39
return true;
21
}
40
}
22
41
23
+static inline bool isar_feature_aa64_ras(const ARMISARegisters *id)
42
+static void do_ldrd_load(DisasContext *s, TCGv_i32 addr, int rt, int rt2)
24
+{
43
+{
25
+ return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, RAS) != 0;
44
+ /*
45
+ * LDRD is required to be an atomic 64-bit access if the
46
+ * address is 8-aligned, two atomic 32-bit accesses if
47
+ * it's only 4-aligned, and to give an alignment fault
48
+ * if it's not 4-aligned. This is MO_ALIGN_4 | MO_ATOM_SUBALIGN.
49
+ * Rt is always the word from the lower address, and Rt2 the
50
+ * data from the higher address, regardless of endianness.
51
+ * So (like gen_load_exclusive) we avoid gen_aa32_ld_i64()
52
+ * so we don't get its SCTLR_B check, and instead do a 64-bit access
53
+ * using MO_BE if appropriate and then split the two halves.
54
+ *
55
+ * For M-profile, and for A-profile before LPAE, the 64-bit
56
+ * atomicity is not required. We could model that using
57
+ * the looser MO_ATOM_IFALIGN_PAIR, but providing a higher
58
+ * level of atomicity than required is harmless (we would not
59
+ * currently generate better code for IFALIGN_PAIR here).
60
+ *
61
+ * This also gives us the correct behaviour of not updating
62
+ * rt if the load of rt2 faults; this is required for cases
63
+ * like "ldrd r2, r3, [r2]" where rt is also the base register.
64
+ */
65
+ int mem_idx = get_mem_index(s);
66
+ MemOp opc = MO_64 | MO_ALIGN_4 | MO_ATOM_SUBALIGN | s->be_data;
67
+ TCGv taddr = gen_aa32_addr(s, addr, opc);
68
+ TCGv_i64 t64 = tcg_temp_new_i64();
69
+ TCGv_i32 tmp = tcg_temp_new_i32();
70
+ TCGv_i32 tmp2 = tcg_temp_new_i32();
71
+
72
+ tcg_gen_qemu_ld_i64(t64, taddr, mem_idx, opc);
73
+ if (s->be_data == MO_BE) {
74
+ tcg_gen_extr_i64_i32(tmp2, tmp, t64);
75
+ } else {
76
+ tcg_gen_extr_i64_i32(tmp, tmp2, t64);
77
+ }
78
+ store_reg(s, rt, tmp);
79
+ store_reg(s, rt2, tmp2);
26
+}
80
+}
27
+
81
+
28
static inline bool isar_feature_aa64_sve(const ARMISARegisters *id)
82
static bool trans_LDRD_rr(DisasContext *s, arg_ldst_rr *a)
29
{
83
{
30
return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, SVE) != 0;
84
- int mem_idx = get_mem_index(s);
31
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_any_debugv8p2(const ARMISARegisters *id)
85
- TCGv_i32 addr, tmp;
32
return isar_feature_aa64_debugv8p2(id) || isar_feature_aa32_debugv8p2(id);
86
+ TCGv_i32 addr;
87
88
if (!ENABLE_ARCH_5TE) {
89
return false;
90
@@ -XXX,XX +XXX,XX @@ static bool trans_LDRD_rr(DisasContext *s, arg_ldst_rr *a)
91
}
92
addr = op_addr_rr_pre(s, a);
93
94
- tmp = tcg_temp_new_i32();
95
- gen_aa32_ld_i32(s, tmp, addr, mem_idx, MO_UL | MO_ALIGN);
96
- store_reg(s, a->rt, tmp);
97
-
98
- tcg_gen_addi_i32(addr, addr, 4);
99
-
100
- tmp = tcg_temp_new_i32();
101
- gen_aa32_ld_i32(s, tmp, addr, mem_idx, MO_UL | MO_ALIGN);
102
- store_reg(s, a->rt + 1, tmp);
103
+ do_ldrd_load(s, addr, a->rt, a->rt + 1);
104
105
/* LDRD w/ base writeback is undefined if the registers overlap. */
106
- op_addr_rr_post(s, a, addr, -4);
107
+ op_addr_rr_post(s, a, addr, 0);
108
return true;
33
}
109
}
34
110
35
+static inline bool isar_feature_any_ras(const ARMISARegisters *id)
111
@@ -XXX,XX +XXX,XX @@ static bool op_store_ri(DisasContext *s, arg_ldst_ri *a,
36
+{
112
37
+ return isar_feature_aa64_ras(id) || isar_feature_aa32_ras(id);
113
static bool op_ldrd_ri(DisasContext *s, arg_ldst_ri *a, int rt2)
38
+}
114
{
39
+
115
- int mem_idx = get_mem_index(s);
40
/*
116
- TCGv_i32 addr, tmp;
41
* Forward to the above feature tests given an ARMCPU pointer.
117
+ TCGv_i32 addr;
42
*/
118
119
addr = op_addr_ri_pre(s, a);
120
121
- tmp = tcg_temp_new_i32();
122
- gen_aa32_ld_i32(s, tmp, addr, mem_idx, MO_UL | MO_ALIGN);
123
- store_reg(s, a->rt, tmp);
124
-
125
- tcg_gen_addi_i32(addr, addr, 4);
126
-
127
- tmp = tcg_temp_new_i32();
128
- gen_aa32_ld_i32(s, tmp, addr, mem_idx, MO_UL | MO_ALIGN);
129
- store_reg(s, rt2, tmp);
130
+ do_ldrd_load(s, addr, a->rt, rt2);
131
132
/* LDRD w/ base writeback is undefined if the registers overlap. */
133
- op_addr_ri_post(s, a, addr, -4);
134
+ op_addr_ri_post(s, a, addr, 0);
135
return true;
136
}
137
43
--
138
--
44
2.25.1
139
2.43.0
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
Our STRD implementation doesn't correctly implement the requirement:
2
* if the address is 8-aligned the access must be a 64-bit
3
single-copy atomic access, not two 32-bit accesses
2
4
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
5
Rewrite the handling of STRD to use a single tcg_gen_qemu_st_i64()
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
of a value produced by concatenating the two 32 bit source registers.
5
Message-id: 20220501055028.646596-24-richard.henderson@linaro.org
7
This allows us to get the atomicity right.
8
9
As with the LDRD change, now that we don't update 'addr' in the
10
course of performing the store we need to adjust the offset
11
we pass to op_addr_ri_post() and op_addr_rr_post().
12
13
Cc: qemu-stable@nongnu.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
16
Message-id: 20250227142746.1698904-3-peter.maydell@linaro.org
7
---
17
---
8
target/arm/cpu.h | 15 +++++++++++++++
18
target/arm/tcg/translate.c | 59 +++++++++++++++++++++++++-------------
9
1 file changed, 15 insertions(+)
19
1 file changed, 39 insertions(+), 20 deletions(-)
10
20
11
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
21
diff --git a/target/arm/tcg/translate.c b/target/arm/tcg/translate.c
12
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
13
--- a/target/arm/cpu.h
23
--- a/target/arm/tcg/translate.c
14
+++ b/target/arm/cpu.h
24
+++ b/target/arm/tcg/translate.c
15
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa32_ssbs(const ARMISARegisters *id)
25
@@ -XXX,XX +XXX,XX @@ static bool trans_LDRD_rr(DisasContext *s, arg_ldst_rr *a)
16
return FIELD_EX32(id->id_pfr2, ID_PFR2, SSBS) != 0;
26
return true;
17
}
27
}
18
28
19
+static inline bool isar_feature_aa32_debugv8p2(const ARMISARegisters *id)
29
+static void do_strd_store(DisasContext *s, TCGv_i32 addr, int rt, int rt2)
20
+{
30
+{
21
+ return FIELD_EX32(id->id_dfr0, ID_DFR0, COPDBG) >= 8;
31
+ /*
32
+ * STRD is required to be an atomic 64-bit access if the
33
+ * address is 8-aligned, two atomic 32-bit accesses if
34
+ * it's only 4-aligned, and to give an alignment fault
35
+ * if it's not 4-aligned.
36
+ * Rt is always the word from the lower address, and Rt2 the
37
+ * data from the higher address, regardless of endianness.
38
+ * So (like gen_store_exclusive) we avoid gen_aa32_ld_i64()
39
+ * so we don't get its SCTLR_B check, and instead do a 64-bit access
40
+ * using MO_BE if appropriate, using a value constructed
41
+ * by putting the two halves together in the right order.
42
+ *
43
+ * As with LDRD, the 64-bit atomicity is not required for
44
+ * M-profile, or for A-profile before LPAE, and we provide
45
+ * the higher guarantee always for simplicity.
46
+ */
47
+ int mem_idx = get_mem_index(s);
48
+ MemOp opc = MO_64 | MO_ALIGN_4 | MO_ATOM_SUBALIGN | s->be_data;
49
+ TCGv taddr = gen_aa32_addr(s, addr, opc);
50
+ TCGv_i32 t1 = load_reg(s, rt);
51
+ TCGv_i32 t2 = load_reg(s, rt2);
52
+ TCGv_i64 t64 = tcg_temp_new_i64();
53
+
54
+ if (s->be_data == MO_BE) {
55
+ tcg_gen_concat_i32_i64(t64, t2, t1);
56
+ } else {
57
+ tcg_gen_concat_i32_i64(t64, t1, t2);
58
+ }
59
+ tcg_gen_qemu_st_i64(t64, taddr, mem_idx, opc);
22
+}
60
+}
23
+
61
+
24
/*
62
static bool trans_STRD_rr(DisasContext *s, arg_ldst_rr *a)
25
* 64-bit feature tests via id registers.
63
{
26
*/
64
- int mem_idx = get_mem_index(s);
27
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa64_ssbs(const ARMISARegisters *id)
65
- TCGv_i32 addr, tmp;
28
return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, SSBS) != 0;
66
+ TCGv_i32 addr;
67
68
if (!ENABLE_ARCH_5TE) {
69
return false;
70
@@ -XXX,XX +XXX,XX @@ static bool trans_STRD_rr(DisasContext *s, arg_ldst_rr *a)
71
}
72
addr = op_addr_rr_pre(s, a);
73
74
- tmp = load_reg(s, a->rt);
75
- gen_aa32_st_i32(s, tmp, addr, mem_idx, MO_UL | MO_ALIGN);
76
+ do_strd_store(s, addr, a->rt, a->rt + 1);
77
78
- tcg_gen_addi_i32(addr, addr, 4);
79
-
80
- tmp = load_reg(s, a->rt + 1);
81
- gen_aa32_st_i32(s, tmp, addr, mem_idx, MO_UL | MO_ALIGN);
82
-
83
- op_addr_rr_post(s, a, addr, -4);
84
+ op_addr_rr_post(s, a, addr, 0);
85
return true;
29
}
86
}
30
87
31
+static inline bool isar_feature_aa64_debugv8p2(const ARMISARegisters *id)
88
@@ -XXX,XX +XXX,XX @@ static bool trans_LDRD_ri_t32(DisasContext *s, arg_ldst_ri2 *a)
32
+{
89
33
+ return FIELD_EX64(id->id_aa64dfr0, ID_AA64DFR0, DEBUGVER) >= 8;
90
static bool op_strd_ri(DisasContext *s, arg_ldst_ri *a, int rt2)
34
+}
35
+
36
static inline bool isar_feature_aa64_sve2(const ARMISARegisters *id)
37
{
91
{
38
return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, SVEVER) != 0;
92
- int mem_idx = get_mem_index(s);
39
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_any_tts2uxn(const ARMISARegisters *id)
93
- TCGv_i32 addr, tmp;
40
return isar_feature_aa64_tts2uxn(id) || isar_feature_aa32_tts2uxn(id);
94
+ TCGv_i32 addr;
95
96
addr = op_addr_ri_pre(s, a);
97
98
- tmp = load_reg(s, a->rt);
99
- gen_aa32_st_i32(s, tmp, addr, mem_idx, MO_UL | MO_ALIGN);
100
+ do_strd_store(s, addr, a->rt, rt2);
101
102
- tcg_gen_addi_i32(addr, addr, 4);
103
-
104
- tmp = load_reg(s, rt2);
105
- gen_aa32_st_i32(s, tmp, addr, mem_idx, MO_UL | MO_ALIGN);
106
-
107
- op_addr_ri_post(s, a, addr, -4);
108
+ op_addr_ri_post(s, a, addr, 0);
109
return true;
41
}
110
}
42
111
43
+static inline bool isar_feature_any_debugv8p2(const ARMISARegisters *id)
44
+{
45
+ return isar_feature_aa64_debugv8p2(id) || isar_feature_aa32_debugv8p2(id);
46
+}
47
+
48
/*
49
* Forward to the above feature tests given an ARMCPU pointer.
50
*/
51
--
112
--
52
2.25.1
113
2.43.0
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
All the callers of op_addr_rr_post() and op_addr_ri_post() now pass in
2
zero for the address_offset, so we can remove that argument.
2
3
3
Move ARMCPRegInfo and all related declarations to a new
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
internal header, out of the public cpu.h.
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
7
Message-id: 20250227142746.1698904-4-peter.maydell@linaro.org
8
---
9
target/arm/tcg/translate.c | 26 +++++++++++++-------------
10
1 file changed, 13 insertions(+), 13 deletions(-)
5
11
6
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
12
diff --git a/target/arm/tcg/translate.c b/target/arm/tcg/translate.c
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20220501055028.646596-2-richard.henderson@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
target/arm/cpregs.h | 413 +++++++++++++++++++++++++++++++++++++
13
target/arm/cpu.h | 368 ---------------------------------
14
hw/arm/pxa2xx.c | 1 +
15
hw/arm/pxa2xx_pic.c | 1 +
16
hw/intc/arm_gicv3_cpuif.c | 1 +
17
hw/intc/arm_gicv3_kvm.c | 2 +
18
target/arm/cpu.c | 1 +
19
target/arm/cpu64.c | 1 +
20
target/arm/cpu_tcg.c | 1 +
21
target/arm/gdbstub.c | 3 +-
22
target/arm/helper.c | 1 +
23
target/arm/op_helper.c | 1 +
24
target/arm/translate-a64.c | 4 +-
25
target/arm/translate.c | 3 +-
26
14 files changed, 427 insertions(+), 374 deletions(-)
27
create mode 100644 target/arm/cpregs.h
28
29
diff --git a/target/arm/cpregs.h b/target/arm/cpregs.h
30
new file mode 100644
31
index XXXXXXX..XXXXXXX
32
--- /dev/null
33
+++ b/target/arm/cpregs.h
34
@@ -XXX,XX +XXX,XX @@
35
+/*
36
+ * QEMU ARM CP Register access and descriptions
37
+ *
38
+ * Copyright (c) 2022 Linaro Ltd
39
+ *
40
+ * This program is free software; you can redistribute it and/or
41
+ * modify it under the terms of the GNU General Public License
42
+ * as published by the Free Software Foundation; either version 2
43
+ * of the License, or (at your option) any later version.
44
+ *
45
+ * This program is distributed in the hope that it will be useful,
46
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
47
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
48
+ * GNU General Public License for more details.
49
+ *
50
+ * You should have received a copy of the GNU General Public License
51
+ * along with this program; if not, see
52
+ * <http://www.gnu.org/licenses/gpl-2.0.html>
53
+ */
54
+
55
+#ifndef TARGET_ARM_CPREGS_H
56
+#define TARGET_ARM_CPREGS_H
57
+
58
+/*
59
+ * ARMCPRegInfo type field bits. If the SPECIAL bit is set this is a
60
+ * special-behaviour cp reg and bits [11..8] indicate what behaviour
61
+ * it has. Otherwise it is a simple cp reg, where CONST indicates that
62
+ * TCG can assume the value to be constant (ie load at translate time)
63
+ * and 64BIT indicates a 64 bit wide coprocessor register. SUPPRESS_TB_END
64
+ * indicates that the TB should not be ended after a write to this register
65
+ * (the default is that the TB ends after cp writes). OVERRIDE permits
66
+ * a register definition to override a previous definition for the
67
+ * same (cp, is64, crn, crm, opc1, opc2) tuple: either the new or the
68
+ * old must have the OVERRIDE bit set.
69
+ * ALIAS indicates that this register is an alias view of some underlying
70
+ * state which is also visible via another register, and that the other
71
+ * register is handling migration and reset; registers marked ALIAS will not be
72
+ * migrated but may have their state set by syncing of register state from KVM.
73
+ * NO_RAW indicates that this register has no underlying state and does not
74
+ * support raw access for state saving/loading; it will not be used for either
75
+ * migration or KVM state synchronization. (Typically this is for "registers"
76
+ * which are actually used as instructions for cache maintenance and so on.)
77
+ * IO indicates that this register does I/O and therefore its accesses
78
+ * need to be marked with gen_io_start() and also end the TB. In particular,
79
+ * registers which implement clocks or timers require this.
80
+ * RAISES_EXC is for when the read or write hook might raise an exception;
81
+ * the generated code will synchronize the CPU state before calling the hook
82
+ * so that it is safe for the hook to call raise_exception().
83
+ * NEWEL is for writes to registers that might change the exception
84
+ * level - typically on older ARM chips. For those cases we need to
85
+ * re-read the new el when recomputing the translation flags.
86
+ */
87
+#define ARM_CP_SPECIAL 0x0001
88
+#define ARM_CP_CONST 0x0002
89
+#define ARM_CP_64BIT 0x0004
90
+#define ARM_CP_SUPPRESS_TB_END 0x0008
91
+#define ARM_CP_OVERRIDE 0x0010
92
+#define ARM_CP_ALIAS 0x0020
93
+#define ARM_CP_IO 0x0040
94
+#define ARM_CP_NO_RAW 0x0080
95
+#define ARM_CP_NOP (ARM_CP_SPECIAL | 0x0100)
96
+#define ARM_CP_WFI (ARM_CP_SPECIAL | 0x0200)
97
+#define ARM_CP_NZCV (ARM_CP_SPECIAL | 0x0300)
98
+#define ARM_CP_CURRENTEL (ARM_CP_SPECIAL | 0x0400)
99
+#define ARM_CP_DC_ZVA (ARM_CP_SPECIAL | 0x0500)
100
+#define ARM_CP_DC_GVA (ARM_CP_SPECIAL | 0x0600)
101
+#define ARM_CP_DC_GZVA (ARM_CP_SPECIAL | 0x0700)
102
+#define ARM_LAST_SPECIAL ARM_CP_DC_GZVA
103
+#define ARM_CP_FPU 0x1000
104
+#define ARM_CP_SVE 0x2000
105
+#define ARM_CP_NO_GDB 0x4000
106
+#define ARM_CP_RAISES_EXC 0x8000
107
+#define ARM_CP_NEWEL 0x10000
108
+/* Used only as a terminator for ARMCPRegInfo lists */
109
+#define ARM_CP_SENTINEL 0xfffff
110
+/* Mask of only the flag bits in a type field */
111
+#define ARM_CP_FLAG_MASK 0x1f0ff
112
+
113
+/*
114
+ * Valid values for ARMCPRegInfo state field, indicating which of
115
+ * the AArch32 and AArch64 execution states this register is visible in.
116
+ * If the reginfo doesn't explicitly specify then it is AArch32 only.
117
+ * If the reginfo is declared to be visible in both states then a second
118
+ * reginfo is synthesised for the AArch32 view of the AArch64 register,
119
+ * such that the AArch32 view is the lower 32 bits of the AArch64 one.
120
+ * Note that we rely on the values of these enums as we iterate through
121
+ * the various states in some places.
122
+ */
123
+enum {
124
+ ARM_CP_STATE_AA32 = 0,
125
+ ARM_CP_STATE_AA64 = 1,
126
+ ARM_CP_STATE_BOTH = 2,
127
+};
128
+
129
+/*
130
+ * ARM CP register secure state flags. These flags identify security state
131
+ * attributes for a given CP register entry.
132
+ * The existence of both or neither secure and non-secure flags indicates that
133
+ * the register has both a secure and non-secure hash entry. A single one of
134
+ * these flags causes the register to only be hashed for the specified
135
+ * security state.
136
+ * Although definitions may have any combination of the S/NS bits, each
137
+ * registered entry will only have one to identify whether the entry is secure
138
+ * or non-secure.
139
+ */
140
+enum {
141
+ ARM_CP_SECSTATE_S = (1 << 0), /* bit[0]: Secure state register */
142
+ ARM_CP_SECSTATE_NS = (1 << 1), /* bit[1]: Non-secure state register */
143
+};
144
+
145
+/*
146
+ * Return true if cptype is a valid type field. This is used to try to
147
+ * catch errors where the sentinel has been accidentally left off the end
148
+ * of a list of registers.
149
+ */
150
+static inline bool cptype_valid(int cptype)
151
+{
152
+ return ((cptype & ~ARM_CP_FLAG_MASK) == 0)
153
+ || ((cptype & ARM_CP_SPECIAL) &&
154
+ ((cptype & ~ARM_CP_FLAG_MASK) <= ARM_LAST_SPECIAL));
155
+}
156
+
157
+/*
158
+ * Access rights:
159
+ * We define bits for Read and Write access for what rev C of the v7-AR ARM ARM
160
+ * defines as PL0 (user), PL1 (fiq/irq/svc/abt/und/sys, ie privileged), and
161
+ * PL2 (hyp). The other level which has Read and Write bits is Secure PL1
162
+ * (ie any of the privileged modes in Secure state, or Monitor mode).
163
+ * If a register is accessible in one privilege level it's always accessible
164
+ * in higher privilege levels too. Since "Secure PL1" also follows this rule
165
+ * (ie anything visible in PL2 is visible in S-PL1, some things are only
166
+ * visible in S-PL1) but "Secure PL1" is a bit of a mouthful, we bend the
167
+ * terminology a little and call this PL3.
168
+ * In AArch64 things are somewhat simpler as the PLx bits line up exactly
169
+ * with the ELx exception levels.
170
+ *
171
+ * If access permissions for a register are more complex than can be
172
+ * described with these bits, then use a laxer set of restrictions, and
173
+ * do the more restrictive/complex check inside a helper function.
174
+ */
175
+#define PL3_R 0x80
176
+#define PL3_W 0x40
177
+#define PL2_R (0x20 | PL3_R)
178
+#define PL2_W (0x10 | PL3_W)
179
+#define PL1_R (0x08 | PL2_R)
180
+#define PL1_W (0x04 | PL2_W)
181
+#define PL0_R (0x02 | PL1_R)
182
+#define PL0_W (0x01 | PL1_W)
183
+
184
+/*
185
+ * For user-mode some registers are accessible to EL0 via a kernel
186
+ * trap-and-emulate ABI. In this case we define the read permissions
187
+ * as actually being PL0_R. However some bits of any given register
188
+ * may still be masked.
189
+ */
190
+#ifdef CONFIG_USER_ONLY
191
+#define PL0U_R PL0_R
192
+#else
193
+#define PL0U_R PL1_R
194
+#endif
195
+
196
+#define PL3_RW (PL3_R | PL3_W)
197
+#define PL2_RW (PL2_R | PL2_W)
198
+#define PL1_RW (PL1_R | PL1_W)
199
+#define PL0_RW (PL0_R | PL0_W)
200
+
201
+typedef enum CPAccessResult {
202
+ /* Access is permitted */
203
+ CP_ACCESS_OK = 0,
204
+ /*
205
+ * Access fails due to a configurable trap or enable which would
206
+ * result in a categorized exception syndrome giving information about
207
+ * the failing instruction (ie syndrome category 0x3, 0x4, 0x5, 0x6,
208
+ * 0xc or 0x18). The exception is taken to the usual target EL (EL1 or
209
+ * PL1 if in EL0, otherwise to the current EL).
210
+ */
211
+ CP_ACCESS_TRAP = 1,
212
+ /*
213
+ * Access fails and results in an exception syndrome 0x0 ("uncategorized").
214
+ * Note that this is not a catch-all case -- the set of cases which may
215
+ * result in this failure is specifically defined by the architecture.
216
+ */
217
+ CP_ACCESS_TRAP_UNCATEGORIZED = 2,
218
+ /* As CP_ACCESS_TRAP, but for traps directly to EL2 or EL3 */
219
+ CP_ACCESS_TRAP_EL2 = 3,
220
+ CP_ACCESS_TRAP_EL3 = 4,
221
+ /* As CP_ACCESS_UNCATEGORIZED, but for traps directly to EL2 or EL3 */
222
+ CP_ACCESS_TRAP_UNCATEGORIZED_EL2 = 5,
223
+ CP_ACCESS_TRAP_UNCATEGORIZED_EL3 = 6,
224
+} CPAccessResult;
225
+
226
+typedef struct ARMCPRegInfo ARMCPRegInfo;
227
+
228
+/*
229
+ * Access functions for coprocessor registers. These cannot fail and
230
+ * may not raise exceptions.
231
+ */
232
+typedef uint64_t CPReadFn(CPUARMState *env, const ARMCPRegInfo *opaque);
233
+typedef void CPWriteFn(CPUARMState *env, const ARMCPRegInfo *opaque,
234
+ uint64_t value);
235
+/* Access permission check functions for coprocessor registers. */
236
+typedef CPAccessResult CPAccessFn(CPUARMState *env,
237
+ const ARMCPRegInfo *opaque,
238
+ bool isread);
239
+/* Hook function for register reset */
240
+typedef void CPResetFn(CPUARMState *env, const ARMCPRegInfo *opaque);
241
+
242
+#define CP_ANY 0xff
243
+
244
+/* Definition of an ARM coprocessor register */
245
+struct ARMCPRegInfo {
246
+ /* Name of register (useful mainly for debugging, need not be unique) */
247
+ const char *name;
248
+ /*
249
+ * Location of register: coprocessor number and (crn,crm,opc1,opc2)
250
+ * tuple. Any of crm, opc1 and opc2 may be CP_ANY to indicate a
251
+ * 'wildcard' field -- any value of that field in the MRC/MCR insn
252
+ * will be decoded to this register. The register read and write
253
+ * callbacks will be passed an ARMCPRegInfo with the crn/crm/opc1/opc2
254
+ * used by the program, so it is possible to register a wildcard and
255
+ * then behave differently on read/write if necessary.
256
+ * For 64 bit registers, only crm and opc1 are relevant; crn and opc2
257
+ * must both be zero.
258
+ * For AArch64-visible registers, opc0 is also used.
259
+ * Since there are no "coprocessors" in AArch64, cp is purely used as a
260
+ * way to distinguish (for KVM's benefit) guest-visible system registers
261
+ * from demuxed ones provided to preserve the "no side effects on
262
+ * KVM register read/write from QEMU" semantics. cp==0x13 is guest
263
+ * visible (to match KVM's encoding); cp==0 will be converted to
264
+ * cp==0x13 when the ARMCPRegInfo is registered, for convenience.
265
+ */
266
+ uint8_t cp;
267
+ uint8_t crn;
268
+ uint8_t crm;
269
+ uint8_t opc0;
270
+ uint8_t opc1;
271
+ uint8_t opc2;
272
+ /* Execution state in which this register is visible: ARM_CP_STATE_* */
273
+ int state;
274
+ /* Register type: ARM_CP_* bits/values */
275
+ int type;
276
+ /* Access rights: PL*_[RW] */
277
+ int access;
278
+ /* Security state: ARM_CP_SECSTATE_* bits/values */
279
+ int secure;
280
+ /*
281
+ * The opaque pointer passed to define_arm_cp_regs_with_opaque() when
282
+ * this register was defined: can be used to hand data through to the
283
+ * register read/write functions, since they are passed the ARMCPRegInfo*.
284
+ */
285
+ void *opaque;
286
+ /*
287
+ * Value of this register, if it is ARM_CP_CONST. Otherwise, if
288
+ * fieldoffset is non-zero, the reset value of the register.
289
+ */
290
+ uint64_t resetvalue;
291
+ /*
292
+ * Offset of the field in CPUARMState for this register.
293
+ * This is not needed if either:
294
+ * 1. type is ARM_CP_CONST or one of the ARM_CP_SPECIALs
295
+ * 2. both readfn and writefn are specified
296
+ */
297
+ ptrdiff_t fieldoffset; /* offsetof(CPUARMState, field) */
298
+
299
+ /*
300
+ * Offsets of the secure and non-secure fields in CPUARMState for the
301
+ * register if it is banked. These fields are only used during the static
302
+ * registration of a register. During hashing the bank associated
303
+ * with a given security state is copied to fieldoffset which is used from
304
+ * there on out.
305
+ *
306
+ * It is expected that register definitions use either fieldoffset or
307
+ * bank_fieldoffsets in the definition but not both. It is also expected
308
+ * that both bank offsets are set when defining a banked register. This
309
+ * use indicates that a register is banked.
310
+ */
311
+ ptrdiff_t bank_fieldoffsets[2];
312
+
313
+ /*
314
+ * Function for making any access checks for this register in addition to
315
+ * those specified by the 'access' permissions bits. If NULL, no extra
316
+ * checks required. The access check is performed at runtime, not at
317
+ * translate time.
318
+ */
319
+ CPAccessFn *accessfn;
320
+ /*
321
+ * Function for handling reads of this register. If NULL, then reads
322
+ * will be done by loading from the offset into CPUARMState specified
323
+ * by fieldoffset.
324
+ */
325
+ CPReadFn *readfn;
326
+ /*
327
+ * Function for handling writes of this register. If NULL, then writes
328
+ * will be done by writing to the offset into CPUARMState specified
329
+ * by fieldoffset.
330
+ */
331
+ CPWriteFn *writefn;
332
+ /*
333
+ * Function for doing a "raw" read; used when we need to copy
334
+ * coprocessor state to the kernel for KVM or out for
335
+ * migration. This only needs to be provided if there is also a
336
+ * readfn and it has side effects (for instance clear-on-read bits).
337
+ */
338
+ CPReadFn *raw_readfn;
339
+ /*
340
+ * Function for doing a "raw" write; used when we need to copy KVM
341
+ * kernel coprocessor state into userspace, or for inbound
342
+ * migration. This only needs to be provided if there is also a
343
+ * writefn and it masks out "unwritable" bits or has write-one-to-clear
344
+ * or similar behaviour.
345
+ */
346
+ CPWriteFn *raw_writefn;
347
+ /*
348
+ * Function for resetting the register. If NULL, then reset will be done
349
+ * by writing resetvalue to the field specified in fieldoffset. If
350
+ * fieldoffset is 0 then no reset will be done.
351
+ */
352
+ CPResetFn *resetfn;
353
+
354
+ /*
355
+ * "Original" writefn and readfn.
356
+ * For ARMv8.1-VHE register aliases, we overwrite the read/write
357
+ * accessor functions of various EL1/EL0 to perform the runtime
358
+ * check for which sysreg should actually be modified, and then
359
+ * forwards the operation. Before overwriting the accessors,
360
+ * the original function is copied here, so that accesses that
361
+ * really do go to the EL1/EL0 version proceed normally.
362
+ * (The corresponding EL2 register is linked via opaque.)
363
+ */
364
+ CPReadFn *orig_readfn;
365
+ CPWriteFn *orig_writefn;
366
+};
367
+
368
+/*
369
+ * Macros which are lvalues for the field in CPUARMState for the
370
+ * ARMCPRegInfo *ri.
371
+ */
372
+#define CPREG_FIELD32(env, ri) \
373
+ (*(uint32_t *)((char *)(env) + (ri)->fieldoffset))
374
+#define CPREG_FIELD64(env, ri) \
375
+ (*(uint64_t *)((char *)(env) + (ri)->fieldoffset))
376
+
377
+#define REGINFO_SENTINEL { .type = ARM_CP_SENTINEL }
378
+
379
+void define_arm_cp_regs_with_opaque(ARMCPU *cpu,
380
+ const ARMCPRegInfo *regs, void *opaque);
381
+void define_one_arm_cp_reg_with_opaque(ARMCPU *cpu,
382
+ const ARMCPRegInfo *regs, void *opaque);
383
+static inline void define_arm_cp_regs(ARMCPU *cpu, const ARMCPRegInfo *regs)
384
+{
385
+ define_arm_cp_regs_with_opaque(cpu, regs, 0);
386
+}
387
+static inline void define_one_arm_cp_reg(ARMCPU *cpu, const ARMCPRegInfo *regs)
388
+{
389
+ define_one_arm_cp_reg_with_opaque(cpu, regs, 0);
390
+}
391
+const ARMCPRegInfo *get_arm_cp_reginfo(GHashTable *cpregs, uint32_t encoded_cp);
392
+
393
+/*
394
+ * Definition of an ARM co-processor register as viewed from
395
+ * userspace. This is used for presenting sanitised versions of
396
+ * registers to userspace when emulating the Linux AArch64 CPU
397
+ * ID/feature ABI (advertised as HWCAP_CPUID).
398
+ */
399
+typedef struct ARMCPRegUserSpaceInfo {
400
+ /* Name of register */
401
+ const char *name;
402
+
403
+ /* Is the name actually a glob pattern */
404
+ bool is_glob;
405
+
406
+ /* Only some bits are exported to user space */
407
+ uint64_t exported_bits;
408
+
409
+ /* Fixed bits are applied after the mask */
410
+ uint64_t fixed_bits;
411
+} ARMCPRegUserSpaceInfo;
412
+
413
+#define REGUSERINFO_SENTINEL { .name = NULL }
414
+
415
+void modify_arm_cp_regs(ARMCPRegInfo *regs, const ARMCPRegUserSpaceInfo *mods);
416
+
417
+/* CPWriteFn that can be used to implement writes-ignored behaviour */
418
+void arm_cp_write_ignore(CPUARMState *env, const ARMCPRegInfo *ri,
419
+ uint64_t value);
420
+/* CPReadFn that can be used for read-as-zero behaviour */
421
+uint64_t arm_cp_read_zero(CPUARMState *env, const ARMCPRegInfo *ri);
422
+
423
+/*
424
+ * CPResetFn that does nothing, for use if no reset is required even
425
+ * if fieldoffset is non zero.
426
+ */
427
+void arm_cp_reset_ignore(CPUARMState *env, const ARMCPRegInfo *opaque);
428
+
429
+/*
430
+ * Return true if this reginfo struct's field in the cpu state struct
431
+ * is 64 bits wide.
432
+ */
433
+static inline bool cpreg_field_is_64bit(const ARMCPRegInfo *ri)
434
+{
435
+ return (ri->state == ARM_CP_STATE_AA64) || (ri->type & ARM_CP_64BIT);
436
+}
437
+
438
+static inline bool cp_access_ok(int current_el,
439
+ const ARMCPRegInfo *ri, int isread)
440
+{
441
+ return (ri->access >> ((current_el * 2) + isread)) & 1;
442
+}
443
+
444
+/* Raw read of a coprocessor register (as needed for migration, etc) */
445
+uint64_t read_raw_cp_reg(CPUARMState *env, const ARMCPRegInfo *ri);
446
+
447
+#endif /* TARGET_ARM_CPREGS_H */
448
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
449
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
450
--- a/target/arm/cpu.h
14
--- a/target/arm/tcg/translate.c
451
+++ b/target/arm/cpu.h
15
+++ b/target/arm/tcg/translate.c
452
@@ -XXX,XX +XXX,XX @@ static inline uint64_t cpreg_to_kvm_id(uint32_t cpregid)
16
@@ -XXX,XX +XXX,XX @@ static TCGv_i32 op_addr_rr_pre(DisasContext *s, arg_ldst_rr *a)
453
return kvmid;
454
}
17
}
455
18
456
-/* ARMCPRegInfo type field bits. If the SPECIAL bit is set this is a
19
static void op_addr_rr_post(DisasContext *s, arg_ldst_rr *a,
457
- * special-behaviour cp reg and bits [11..8] indicate what behaviour
20
- TCGv_i32 addr, int address_offset)
458
- * it has. Otherwise it is a simple cp reg, where CONST indicates that
21
+ TCGv_i32 addr)
459
- * TCG can assume the value to be constant (ie load at translate time)
460
- * and 64BIT indicates a 64 bit wide coprocessor register. SUPPRESS_TB_END
461
- * indicates that the TB should not be ended after a write to this register
462
- * (the default is that the TB ends after cp writes). OVERRIDE permits
463
- * a register definition to override a previous definition for the
464
- * same (cp, is64, crn, crm, opc1, opc2) tuple: either the new or the
465
- * old must have the OVERRIDE bit set.
466
- * ALIAS indicates that this register is an alias view of some underlying
467
- * state which is also visible via another register, and that the other
468
- * register is handling migration and reset; registers marked ALIAS will not be
469
- * migrated but may have their state set by syncing of register state from KVM.
470
- * NO_RAW indicates that this register has no underlying state and does not
471
- * support raw access for state saving/loading; it will not be used for either
472
- * migration or KVM state synchronization. (Typically this is for "registers"
473
- * which are actually used as instructions for cache maintenance and so on.)
474
- * IO indicates that this register does I/O and therefore its accesses
475
- * need to be marked with gen_io_start() and also end the TB. In particular,
476
- * registers which implement clocks or timers require this.
477
- * RAISES_EXC is for when the read or write hook might raise an exception;
478
- * the generated code will synchronize the CPU state before calling the hook
479
- * so that it is safe for the hook to call raise_exception().
480
- * NEWEL is for writes to registers that might change the exception
481
- * level - typically on older ARM chips. For those cases we need to
482
- * re-read the new el when recomputing the translation flags.
483
- */
484
-#define ARM_CP_SPECIAL 0x0001
485
-#define ARM_CP_CONST 0x0002
486
-#define ARM_CP_64BIT 0x0004
487
-#define ARM_CP_SUPPRESS_TB_END 0x0008
488
-#define ARM_CP_OVERRIDE 0x0010
489
-#define ARM_CP_ALIAS 0x0020
490
-#define ARM_CP_IO 0x0040
491
-#define ARM_CP_NO_RAW 0x0080
492
-#define ARM_CP_NOP (ARM_CP_SPECIAL | 0x0100)
493
-#define ARM_CP_WFI (ARM_CP_SPECIAL | 0x0200)
494
-#define ARM_CP_NZCV (ARM_CP_SPECIAL | 0x0300)
495
-#define ARM_CP_CURRENTEL (ARM_CP_SPECIAL | 0x0400)
496
-#define ARM_CP_DC_ZVA (ARM_CP_SPECIAL | 0x0500)
497
-#define ARM_CP_DC_GVA (ARM_CP_SPECIAL | 0x0600)
498
-#define ARM_CP_DC_GZVA (ARM_CP_SPECIAL | 0x0700)
499
-#define ARM_LAST_SPECIAL ARM_CP_DC_GZVA
500
-#define ARM_CP_FPU 0x1000
501
-#define ARM_CP_SVE 0x2000
502
-#define ARM_CP_NO_GDB 0x4000
503
-#define ARM_CP_RAISES_EXC 0x8000
504
-#define ARM_CP_NEWEL 0x10000
505
-/* Used only as a terminator for ARMCPRegInfo lists */
506
-#define ARM_CP_SENTINEL 0xfffff
507
-/* Mask of only the flag bits in a type field */
508
-#define ARM_CP_FLAG_MASK 0x1f0ff
509
-
510
-/* Valid values for ARMCPRegInfo state field, indicating which of
511
- * the AArch32 and AArch64 execution states this register is visible in.
512
- * If the reginfo doesn't explicitly specify then it is AArch32 only.
513
- * If the reginfo is declared to be visible in both states then a second
514
- * reginfo is synthesised for the AArch32 view of the AArch64 register,
515
- * such that the AArch32 view is the lower 32 bits of the AArch64 one.
516
- * Note that we rely on the values of these enums as we iterate through
517
- * the various states in some places.
518
- */
519
-enum {
520
- ARM_CP_STATE_AA32 = 0,
521
- ARM_CP_STATE_AA64 = 1,
522
- ARM_CP_STATE_BOTH = 2,
523
-};
524
-
525
-/* ARM CP register secure state flags. These flags identify security state
526
- * attributes for a given CP register entry.
527
- * The existence of both or neither secure and non-secure flags indicates that
528
- * the register has both a secure and non-secure hash entry. A single one of
529
- * these flags causes the register to only be hashed for the specified
530
- * security state.
531
- * Although definitions may have any combination of the S/NS bits, each
532
- * registered entry will only have one to identify whether the entry is secure
533
- * or non-secure.
534
- */
535
-enum {
536
- ARM_CP_SECSTATE_S = (1 << 0), /* bit[0]: Secure state register */
537
- ARM_CP_SECSTATE_NS = (1 << 1), /* bit[1]: Non-secure state register */
538
-};
539
-
540
-/* Return true if cptype is a valid type field. This is used to try to
541
- * catch errors where the sentinel has been accidentally left off the end
542
- * of a list of registers.
543
- */
544
-static inline bool cptype_valid(int cptype)
545
-{
546
- return ((cptype & ~ARM_CP_FLAG_MASK) == 0)
547
- || ((cptype & ARM_CP_SPECIAL) &&
548
- ((cptype & ~ARM_CP_FLAG_MASK) <= ARM_LAST_SPECIAL));
549
-}
550
-
551
-/* Access rights:
552
- * We define bits for Read and Write access for what rev C of the v7-AR ARM ARM
553
- * defines as PL0 (user), PL1 (fiq/irq/svc/abt/und/sys, ie privileged), and
554
- * PL2 (hyp). The other level which has Read and Write bits is Secure PL1
555
- * (ie any of the privileged modes in Secure state, or Monitor mode).
556
- * If a register is accessible in one privilege level it's always accessible
557
- * in higher privilege levels too. Since "Secure PL1" also follows this rule
558
- * (ie anything visible in PL2 is visible in S-PL1, some things are only
559
- * visible in S-PL1) but "Secure PL1" is a bit of a mouthful, we bend the
560
- * terminology a little and call this PL3.
561
- * In AArch64 things are somewhat simpler as the PLx bits line up exactly
562
- * with the ELx exception levels.
563
- *
564
- * If access permissions for a register are more complex than can be
565
- * described with these bits, then use a laxer set of restrictions, and
566
- * do the more restrictive/complex check inside a helper function.
567
- */
568
-#define PL3_R 0x80
569
-#define PL3_W 0x40
570
-#define PL2_R (0x20 | PL3_R)
571
-#define PL2_W (0x10 | PL3_W)
572
-#define PL1_R (0x08 | PL2_R)
573
-#define PL1_W (0x04 | PL2_W)
574
-#define PL0_R (0x02 | PL1_R)
575
-#define PL0_W (0x01 | PL1_W)
576
-
577
-/*
578
- * For user-mode some registers are accessible to EL0 via a kernel
579
- * trap-and-emulate ABI. In this case we define the read permissions
580
- * as actually being PL0_R. However some bits of any given register
581
- * may still be masked.
582
- */
583
-#ifdef CONFIG_USER_ONLY
584
-#define PL0U_R PL0_R
585
-#else
586
-#define PL0U_R PL1_R
587
-#endif
588
-
589
-#define PL3_RW (PL3_R | PL3_W)
590
-#define PL2_RW (PL2_R | PL2_W)
591
-#define PL1_RW (PL1_R | PL1_W)
592
-#define PL0_RW (PL0_R | PL0_W)
593
-
594
/* Return the highest implemented Exception Level */
595
static inline int arm_highest_el(CPUARMState *env)
596
{
22
{
597
@@ -XXX,XX +XXX,XX @@ static inline int arm_current_el(CPUARMState *env)
23
if (!a->p) {
24
TCGv_i32 ofs = load_reg(s, a->rm);
25
@@ -XXX,XX +XXX,XX @@ static void op_addr_rr_post(DisasContext *s, arg_ldst_rr *a,
26
} else if (!a->w) {
27
return;
598
}
28
}
29
- tcg_gen_addi_i32(addr, addr, address_offset);
30
store_reg(s, a->rn, addr);
599
}
31
}
600
32
601
-typedef struct ARMCPRegInfo ARMCPRegInfo;
33
@@ -XXX,XX +XXX,XX @@ static bool op_load_rr(DisasContext *s, arg_ldst_rr *a,
602
-
34
* Perform base writeback before the loaded value to
603
-typedef enum CPAccessResult {
35
* ensure correct behavior with overlapping index registers.
604
- /* Access is permitted */
36
*/
605
- CP_ACCESS_OK = 0,
37
- op_addr_rr_post(s, a, addr, 0);
606
- /* Access fails due to a configurable trap or enable which would
38
+ op_addr_rr_post(s, a, addr);
607
- * result in a categorized exception syndrome giving information about
39
store_reg_from_load(s, a->rt, tmp);
608
- * the failing instruction (ie syndrome category 0x3, 0x4, 0x5, 0x6,
40
return true;
609
- * 0xc or 0x18). The exception is taken to the usual target EL (EL1 or
41
}
610
- * PL1 if in EL0, otherwise to the current EL).
42
@@ -XXX,XX +XXX,XX @@ static bool op_store_rr(DisasContext *s, arg_ldst_rr *a,
611
- */
43
gen_aa32_st_i32(s, tmp, addr, mem_idx, mop);
612
- CP_ACCESS_TRAP = 1,
44
disas_set_da_iss(s, mop, issinfo);
613
- /* Access fails and results in an exception syndrome 0x0 ("uncategorized").
45
614
- * Note that this is not a catch-all case -- the set of cases which may
46
- op_addr_rr_post(s, a, addr, 0);
615
- * result in this failure is specifically defined by the architecture.
47
+ op_addr_rr_post(s, a, addr);
616
- */
48
return true;
617
- CP_ACCESS_TRAP_UNCATEGORIZED = 2,
49
}
618
- /* As CP_ACCESS_TRAP, but for traps directly to EL2 or EL3 */
50
619
- CP_ACCESS_TRAP_EL2 = 3,
51
@@ -XXX,XX +XXX,XX @@ static bool trans_LDRD_rr(DisasContext *s, arg_ldst_rr *a)
620
- CP_ACCESS_TRAP_EL3 = 4,
52
do_ldrd_load(s, addr, a->rt, a->rt + 1);
621
- /* As CP_ACCESS_UNCATEGORIZED, but for traps directly to EL2 or EL3 */
53
622
- CP_ACCESS_TRAP_UNCATEGORIZED_EL2 = 5,
54
/* LDRD w/ base writeback is undefined if the registers overlap. */
623
- CP_ACCESS_TRAP_UNCATEGORIZED_EL3 = 6,
55
- op_addr_rr_post(s, a, addr, 0);
624
-} CPAccessResult;
56
+ op_addr_rr_post(s, a, addr);
625
-
57
return true;
626
-/* Access functions for coprocessor registers. These cannot fail and
58
}
627
- * may not raise exceptions.
59
628
- */
60
@@ -XXX,XX +XXX,XX @@ static bool trans_STRD_rr(DisasContext *s, arg_ldst_rr *a)
629
-typedef uint64_t CPReadFn(CPUARMState *env, const ARMCPRegInfo *opaque);
61
630
-typedef void CPWriteFn(CPUARMState *env, const ARMCPRegInfo *opaque,
62
do_strd_store(s, addr, a->rt, a->rt + 1);
631
- uint64_t value);
63
632
-/* Access permission check functions for coprocessor registers. */
64
- op_addr_rr_post(s, a, addr, 0);
633
-typedef CPAccessResult CPAccessFn(CPUARMState *env,
65
+ op_addr_rr_post(s, a, addr);
634
- const ARMCPRegInfo *opaque,
66
return true;
635
- bool isread);
67
}
636
-/* Hook function for register reset */
68
637
-typedef void CPResetFn(CPUARMState *env, const ARMCPRegInfo *opaque);
69
@@ -XXX,XX +XXX,XX @@ static TCGv_i32 op_addr_ri_pre(DisasContext *s, arg_ldst_ri *a)
638
-
70
}
639
-#define CP_ANY 0xff
71
640
-
72
static void op_addr_ri_post(DisasContext *s, arg_ldst_ri *a,
641
-/* Definition of an ARM coprocessor register */
73
- TCGv_i32 addr, int address_offset)
642
-struct ARMCPRegInfo {
74
+ TCGv_i32 addr)
643
- /* Name of register (useful mainly for debugging, need not be unique) */
644
- const char *name;
645
- /* Location of register: coprocessor number and (crn,crm,opc1,opc2)
646
- * tuple. Any of crm, opc1 and opc2 may be CP_ANY to indicate a
647
- * 'wildcard' field -- any value of that field in the MRC/MCR insn
648
- * will be decoded to this register. The register read and write
649
- * callbacks will be passed an ARMCPRegInfo with the crn/crm/opc1/opc2
650
- * used by the program, so it is possible to register a wildcard and
651
- * then behave differently on read/write if necessary.
652
- * For 64 bit registers, only crm and opc1 are relevant; crn and opc2
653
- * must both be zero.
654
- * For AArch64-visible registers, opc0 is also used.
655
- * Since there are no "coprocessors" in AArch64, cp is purely used as a
656
- * way to distinguish (for KVM's benefit) guest-visible system registers
657
- * from demuxed ones provided to preserve the "no side effects on
658
- * KVM register read/write from QEMU" semantics. cp==0x13 is guest
659
- * visible (to match KVM's encoding); cp==0 will be converted to
660
- * cp==0x13 when the ARMCPRegInfo is registered, for convenience.
661
- */
662
- uint8_t cp;
663
- uint8_t crn;
664
- uint8_t crm;
665
- uint8_t opc0;
666
- uint8_t opc1;
667
- uint8_t opc2;
668
- /* Execution state in which this register is visible: ARM_CP_STATE_* */
669
- int state;
670
- /* Register type: ARM_CP_* bits/values */
671
- int type;
672
- /* Access rights: PL*_[RW] */
673
- int access;
674
- /* Security state: ARM_CP_SECSTATE_* bits/values */
675
- int secure;
676
- /* The opaque pointer passed to define_arm_cp_regs_with_opaque() when
677
- * this register was defined: can be used to hand data through to the
678
- * register read/write functions, since they are passed the ARMCPRegInfo*.
679
- */
680
- void *opaque;
681
- /* Value of this register, if it is ARM_CP_CONST. Otherwise, if
682
- * fieldoffset is non-zero, the reset value of the register.
683
- */
684
- uint64_t resetvalue;
685
- /* Offset of the field in CPUARMState for this register.
686
- *
687
- * This is not needed if either:
688
- * 1. type is ARM_CP_CONST or one of the ARM_CP_SPECIALs
689
- * 2. both readfn and writefn are specified
690
- */
691
- ptrdiff_t fieldoffset; /* offsetof(CPUARMState, field) */
692
-
693
- /* Offsets of the secure and non-secure fields in CPUARMState for the
694
- * register if it is banked. These fields are only used during the static
695
- * registration of a register. During hashing the bank associated
696
- * with a given security state is copied to fieldoffset which is used from
697
- * there on out.
698
- *
699
- * It is expected that register definitions use either fieldoffset or
700
- * bank_fieldoffsets in the definition but not both. It is also expected
701
- * that both bank offsets are set when defining a banked register. This
702
- * use indicates that a register is banked.
703
- */
704
- ptrdiff_t bank_fieldoffsets[2];
705
-
706
- /* Function for making any access checks for this register in addition to
707
- * those specified by the 'access' permissions bits. If NULL, no extra
708
- * checks required. The access check is performed at runtime, not at
709
- * translate time.
710
- */
711
- CPAccessFn *accessfn;
712
- /* Function for handling reads of this register. If NULL, then reads
713
- * will be done by loading from the offset into CPUARMState specified
714
- * by fieldoffset.
715
- */
716
- CPReadFn *readfn;
717
- /* Function for handling writes of this register. If NULL, then writes
718
- * will be done by writing to the offset into CPUARMState specified
719
- * by fieldoffset.
720
- */
721
- CPWriteFn *writefn;
722
- /* Function for doing a "raw" read; used when we need to copy
723
- * coprocessor state to the kernel for KVM or out for
724
- * migration. This only needs to be provided if there is also a
725
- * readfn and it has side effects (for instance clear-on-read bits).
726
- */
727
- CPReadFn *raw_readfn;
728
- /* Function for doing a "raw" write; used when we need to copy KVM
729
- * kernel coprocessor state into userspace, or for inbound
730
- * migration. This only needs to be provided if there is also a
731
- * writefn and it masks out "unwritable" bits or has write-one-to-clear
732
- * or similar behaviour.
733
- */
734
- CPWriteFn *raw_writefn;
735
- /* Function for resetting the register. If NULL, then reset will be done
736
- * by writing resetvalue to the field specified in fieldoffset. If
737
- * fieldoffset is 0 then no reset will be done.
738
- */
739
- CPResetFn *resetfn;
740
-
741
- /*
742
- * "Original" writefn and readfn.
743
- * For ARMv8.1-VHE register aliases, we overwrite the read/write
744
- * accessor functions of various EL1/EL0 to perform the runtime
745
- * check for which sysreg should actually be modified, and then
746
- * forwards the operation. Before overwriting the accessors,
747
- * the original function is copied here, so that accesses that
748
- * really do go to the EL1/EL0 version proceed normally.
749
- * (The corresponding EL2 register is linked via opaque.)
750
- */
751
- CPReadFn *orig_readfn;
752
- CPWriteFn *orig_writefn;
753
-};
754
-
755
-/* Macros which are lvalues for the field in CPUARMState for the
756
- * ARMCPRegInfo *ri.
757
- */
758
-#define CPREG_FIELD32(env, ri) \
759
- (*(uint32_t *)((char *)(env) + (ri)->fieldoffset))
760
-#define CPREG_FIELD64(env, ri) \
761
- (*(uint64_t *)((char *)(env) + (ri)->fieldoffset))
762
-
763
-#define REGINFO_SENTINEL { .type = ARM_CP_SENTINEL }
764
-
765
-void define_arm_cp_regs_with_opaque(ARMCPU *cpu,
766
- const ARMCPRegInfo *regs, void *opaque);
767
-void define_one_arm_cp_reg_with_opaque(ARMCPU *cpu,
768
- const ARMCPRegInfo *regs, void *opaque);
769
-static inline void define_arm_cp_regs(ARMCPU *cpu, const ARMCPRegInfo *regs)
770
-{
771
- define_arm_cp_regs_with_opaque(cpu, regs, 0);
772
-}
773
-static inline void define_one_arm_cp_reg(ARMCPU *cpu, const ARMCPRegInfo *regs)
774
-{
775
- define_one_arm_cp_reg_with_opaque(cpu, regs, 0);
776
-}
777
-const ARMCPRegInfo *get_arm_cp_reginfo(GHashTable *cpregs, uint32_t encoded_cp);
778
-
779
-/*
780
- * Definition of an ARM co-processor register as viewed from
781
- * userspace. This is used for presenting sanitised versions of
782
- * registers to userspace when emulating the Linux AArch64 CPU
783
- * ID/feature ABI (advertised as HWCAP_CPUID).
784
- */
785
-typedef struct ARMCPRegUserSpaceInfo {
786
- /* Name of register */
787
- const char *name;
788
-
789
- /* Is the name actually a glob pattern */
790
- bool is_glob;
791
-
792
- /* Only some bits are exported to user space */
793
- uint64_t exported_bits;
794
-
795
- /* Fixed bits are applied after the mask */
796
- uint64_t fixed_bits;
797
-} ARMCPRegUserSpaceInfo;
798
-
799
-#define REGUSERINFO_SENTINEL { .name = NULL }
800
-
801
-void modify_arm_cp_regs(ARMCPRegInfo *regs, const ARMCPRegUserSpaceInfo *mods);
802
-
803
-/* CPWriteFn that can be used to implement writes-ignored behaviour */
804
-void arm_cp_write_ignore(CPUARMState *env, const ARMCPRegInfo *ri,
805
- uint64_t value);
806
-/* CPReadFn that can be used for read-as-zero behaviour */
807
-uint64_t arm_cp_read_zero(CPUARMState *env, const ARMCPRegInfo *ri);
808
-
809
-/* CPResetFn that does nothing, for use if no reset is required even
810
- * if fieldoffset is non zero.
811
- */
812
-void arm_cp_reset_ignore(CPUARMState *env, const ARMCPRegInfo *opaque);
813
-
814
-/* Return true if this reginfo struct's field in the cpu state struct
815
- * is 64 bits wide.
816
- */
817
-static inline bool cpreg_field_is_64bit(const ARMCPRegInfo *ri)
818
-{
819
- return (ri->state == ARM_CP_STATE_AA64) || (ri->type & ARM_CP_64BIT);
820
-}
821
-
822
-static inline bool cp_access_ok(int current_el,
823
- const ARMCPRegInfo *ri, int isread)
824
-{
825
- return (ri->access >> ((current_el * 2) + isread)) & 1;
826
-}
827
-
828
-/* Raw read of a coprocessor register (as needed for migration, etc) */
829
-uint64_t read_raw_cp_reg(CPUARMState *env, const ARMCPRegInfo *ri);
830
-
831
/**
832
* write_list_to_cpustate
833
* @cpu: ARMCPU
834
diff --git a/hw/arm/pxa2xx.c b/hw/arm/pxa2xx.c
835
index XXXXXXX..XXXXXXX 100644
836
--- a/hw/arm/pxa2xx.c
837
+++ b/hw/arm/pxa2xx.c
838
@@ -XXX,XX +XXX,XX @@
839
#include "qemu/cutils.h"
840
#include "qemu/log.h"
841
#include "qom/object.h"
842
+#include "target/arm/cpregs.h"
843
844
static struct {
845
hwaddr io_base;
846
diff --git a/hw/arm/pxa2xx_pic.c b/hw/arm/pxa2xx_pic.c
847
index XXXXXXX..XXXXXXX 100644
848
--- a/hw/arm/pxa2xx_pic.c
849
+++ b/hw/arm/pxa2xx_pic.c
850
@@ -XXX,XX +XXX,XX @@
851
#include "hw/sysbus.h"
852
#include "migration/vmstate.h"
853
#include "qom/object.h"
854
+#include "target/arm/cpregs.h"
855
856
#define ICIP    0x00    /* Interrupt Controller IRQ Pending register */
857
#define ICMR    0x04    /* Interrupt Controller Mask register */
858
diff --git a/hw/intc/arm_gicv3_cpuif.c b/hw/intc/arm_gicv3_cpuif.c
859
index XXXXXXX..XXXXXXX 100644
860
--- a/hw/intc/arm_gicv3_cpuif.c
861
+++ b/hw/intc/arm_gicv3_cpuif.c
862
@@ -XXX,XX +XXX,XX @@
863
#include "gicv3_internal.h"
864
#include "hw/irq.h"
865
#include "cpu.h"
866
+#include "target/arm/cpregs.h"
867
868
/*
869
* Special case return value from hppvi_index(); must be larger than
870
diff --git a/hw/intc/arm_gicv3_kvm.c b/hw/intc/arm_gicv3_kvm.c
871
index XXXXXXX..XXXXXXX 100644
872
--- a/hw/intc/arm_gicv3_kvm.c
873
+++ b/hw/intc/arm_gicv3_kvm.c
874
@@ -XXX,XX +XXX,XX @@
875
#include "vgic_common.h"
876
#include "migration/blocker.h"
877
#include "qom/object.h"
878
+#include "target/arm/cpregs.h"
879
+
880
881
#ifdef DEBUG_GICV3_KVM
882
#define DPRINTF(fmt, ...) \
883
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
884
index XXXXXXX..XXXXXXX 100644
885
--- a/target/arm/cpu.c
886
+++ b/target/arm/cpu.c
887
@@ -XXX,XX +XXX,XX @@
888
#include "kvm_arm.h"
889
#include "disas/capstone.h"
890
#include "fpu/softfloat.h"
891
+#include "cpregs.h"
892
893
static void arm_cpu_set_pc(CPUState *cs, vaddr value)
894
{
75
{
895
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
76
+ int address_offset = 0;
896
index XXXXXXX..XXXXXXX 100644
77
if (!a->p) {
897
--- a/target/arm/cpu64.c
78
if (a->u) {
898
+++ b/target/arm/cpu64.c
79
- address_offset += a->imm;
899
@@ -XXX,XX +XXX,XX @@
80
+ address_offset = a->imm;
900
#include "hvf_arm.h"
81
} else {
901
#include "qapi/visitor.h"
82
- address_offset -= a->imm;
902
#include "hw/qdev-properties.h"
83
+ address_offset = -a->imm;
903
+#include "cpregs.h"
84
}
904
85
} else if (!a->w) {
905
86
return;
906
#ifndef CONFIG_USER_ONLY
87
@@ -XXX,XX +XXX,XX @@ static bool op_load_ri(DisasContext *s, arg_ldst_ri *a,
907
diff --git a/target/arm/cpu_tcg.c b/target/arm/cpu_tcg.c
88
* Perform base writeback before the loaded value to
908
index XXXXXXX..XXXXXXX 100644
89
* ensure correct behavior with overlapping index registers.
909
--- a/target/arm/cpu_tcg.c
90
*/
910
+++ b/target/arm/cpu_tcg.c
91
- op_addr_ri_post(s, a, addr, 0);
911
@@ -XXX,XX +XXX,XX @@
92
+ op_addr_ri_post(s, a, addr);
912
#if !defined(CONFIG_USER_ONLY)
93
store_reg_from_load(s, a->rt, tmp);
913
#include "hw/boards.h"
94
return true;
914
#endif
95
}
915
+#include "cpregs.h"
96
@@ -XXX,XX +XXX,XX @@ static bool op_store_ri(DisasContext *s, arg_ldst_ri *a,
916
97
gen_aa32_st_i32(s, tmp, addr, mem_idx, mop);
917
/* CPU models. These are not needed for the AArch64 linux-user build. */
98
disas_set_da_iss(s, mop, issinfo);
918
#if !defined(CONFIG_USER_ONLY) || !defined(TARGET_AARCH64)
99
919
diff --git a/target/arm/gdbstub.c b/target/arm/gdbstub.c
100
- op_addr_ri_post(s, a, addr, 0);
920
index XXXXXXX..XXXXXXX 100644
101
+ op_addr_ri_post(s, a, addr);
921
--- a/target/arm/gdbstub.c
102
return true;
922
+++ b/target/arm/gdbstub.c
103
}
923
@@ -XXX,XX +XXX,XX @@
104
924
*/
105
@@ -XXX,XX +XXX,XX @@ static bool op_ldrd_ri(DisasContext *s, arg_ldst_ri *a, int rt2)
925
#include "qemu/osdep.h"
106
do_ldrd_load(s, addr, a->rt, rt2);
926
#include "cpu.h"
107
927
-#include "internals.h"
108
/* LDRD w/ base writeback is undefined if the registers overlap. */
928
#include "exec/gdbstub.h"
109
- op_addr_ri_post(s, a, addr, 0);
929
+#include "internals.h"
110
+ op_addr_ri_post(s, a, addr);
930
+#include "cpregs.h"
111
return true;
931
112
}
932
typedef struct RegisterSysregXmlParam {
113
933
CPUState *cs;
114
@@ -XXX,XX +XXX,XX @@ static bool op_strd_ri(DisasContext *s, arg_ldst_ri *a, int rt2)
934
diff --git a/target/arm/helper.c b/target/arm/helper.c
115
935
index XXXXXXX..XXXXXXX 100644
116
do_strd_store(s, addr, a->rt, rt2);
936
--- a/target/arm/helper.c
117
937
+++ b/target/arm/helper.c
118
- op_addr_ri_post(s, a, addr, 0);
938
@@ -XXX,XX +XXX,XX @@
119
+ op_addr_ri_post(s, a, addr);
939
#include "exec/cpu_ldst.h"
120
return true;
940
#include "semihosting/common-semi.h"
121
}
941
#endif
122
942
+#include "cpregs.h"
943
944
#define ARM_CPU_FREQ 1000000000 /* FIXME: 1 GHz, should be configurable */
945
#define PMCR_NUM_COUNTERS 4 /* QEMU IMPDEF choice */
946
diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c
947
index XXXXXXX..XXXXXXX 100644
948
--- a/target/arm/op_helper.c
949
+++ b/target/arm/op_helper.c
950
@@ -XXX,XX +XXX,XX @@
951
#include "internals.h"
952
#include "exec/exec-all.h"
953
#include "exec/cpu_ldst.h"
954
+#include "cpregs.h"
955
956
#define SIGNBIT (uint32_t)0x80000000
957
#define SIGNBIT64 ((uint64_t)1 << 63)
958
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
959
index XXXXXXX..XXXXXXX 100644
960
--- a/target/arm/translate-a64.c
961
+++ b/target/arm/translate-a64.c
962
@@ -XXX,XX +XXX,XX @@
963
#include "translate.h"
964
#include "internals.h"
965
#include "qemu/host-utils.h"
966
-
967
#include "semihosting/semihost.h"
968
#include "exec/gen-icount.h"
969
-
970
#include "exec/helper-proto.h"
971
#include "exec/helper-gen.h"
972
#include "exec/log.h"
973
-
974
+#include "cpregs.h"
975
#include "translate-a64.h"
976
#include "qemu/atomic128.h"
977
978
diff --git a/target/arm/translate.c b/target/arm/translate.c
979
index XXXXXXX..XXXXXXX 100644
980
--- a/target/arm/translate.c
981
+++ b/target/arm/translate.c
982
@@ -XXX,XX +XXX,XX @@
983
#include "qemu/bitops.h"
984
#include "arm_ldst.h"
985
#include "semihosting/semihost.h"
986
-
987
#include "exec/helper-proto.h"
988
#include "exec/helper-gen.h"
989
-
990
#include "exec/log.h"
991
+#include "cpregs.h"
992
993
994
#define ENABLE_ARCH_4T arm_dc_feature(s, ARM_FEATURE_V4T)
995
--
123
--
996
2.25.1
124
2.43.0
997
125
998
126
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
In debug_helper.c we provide a few dummy versions of
2
debug registers:
3
* DBGVCR (AArch32 only): enable bits for vector-catch
4
debug events
5
* MDCCINT_EL1: interrupt enable bits for the DCC
6
debug communications channel
7
* DBGVCR32_EL2: the AArch64 accessor for the state in
8
DBGVCR
2
9
3
Put most of the value writeback to the same place,
10
We implemented these only to stop Linux crashing on startup,
4
and improve the comment that goes with them.
11
but we chose to implement them as ARM_CP_NOP. This worked
12
for Linux where it only cares about trying to write to these
13
registers, but is very confusing behaviour for anything that
14
wants to read the registers (perhaps for context state switches),
15
because the destination register will be left with whatever
16
random value it happened to have before the read.
5
17
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
18
Model these registers instead as RAZ.
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
19
8
Message-id: 20220501055028.646596-15-richard.henderson@linaro.org
20
Fixes: 5e8b12ffbb8c68 ("target-arm: Implement minimal DBGVCR, OSDLR_EL1, MDCCSR_EL0")
21
Fixes: 5dbdc4342f479d ("target-arm: Implement dummy MDCCINT_EL1")
22
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2708
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
23
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
24
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
25
Message-id: 20250228162424.1917269-1-peter.maydell@linaro.org
10
---
26
---
11
target/arm/helper.c | 28 ++++++++++++----------------
27
target/arm/debug_helper.c | 7 ++++---
12
1 file changed, 12 insertions(+), 16 deletions(-)
28
1 file changed, 4 insertions(+), 3 deletions(-)
13
29
14
diff --git a/target/arm/helper.c b/target/arm/helper.c
30
diff --git a/target/arm/debug_helper.c b/target/arm/debug_helper.c
15
index XXXXXXX..XXXXXXX 100644
31
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/helper.c
32
--- a/target/arm/debug_helper.c
17
+++ b/target/arm/helper.c
33
+++ b/target/arm/debug_helper.c
18
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
34
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo debug_cp_reginfo[] = {
19
*r2 = *r;
35
{ .name = "DBGVCR",
20
r2->name = memcpy(r2 + 1, name, name_len);
36
.cp = 14, .opc1 = 0, .crn = 0, .crm = 7, .opc2 = 0,
21
37
.access = PL1_RW, .accessfn = access_tda,
22
- /* Reset the secure state to the specific incoming state. This is
38
- .type = ARM_CP_NOP },
23
- * necessary as the register may have been defined with both states.
39
+ .type = ARM_CP_CONST, .resetvalue = 0 },
24
+ /*
40
/*
25
+ * Update fields to match the instantiation, overwiting wildcards
41
* Dummy MDCCINT_EL1, since we don't implement the Debug Communications
26
+ * such as CP_ANY, ARM_CP_STATE_BOTH, or ARM_CP_SECSTATE_BOTH.
42
* Channel but Linux may try to access this register. The 32-bit
27
*/
43
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo debug_cp_reginfo[] = {
28
+ r2->cp = cp;
44
{ .name = "MDCCINT_EL1", .state = ARM_CP_STATE_BOTH,
29
+ r2->crm = crm;
45
.cp = 14, .opc0 = 2, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 0,
30
+ r2->opc1 = opc1;
46
.access = PL1_RW, .accessfn = access_tdcc,
31
+ r2->opc2 = opc2;
47
- .type = ARM_CP_NOP },
32
+ r2->state = state;
48
+ .type = ARM_CP_CONST, .resetvalue = 0 },
33
r2->secure = secstate;
49
/*
34
+ if (opaque) {
50
* Dummy DBGCLAIM registers.
35
+ r2->opaque = opaque;
51
* "The architecture does not define any functionality for the CLAIM tag bits.",
36
+ }
52
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo debug_aa32_el1_reginfo[] = {
37
53
{ .name = "DBGVCR32_EL2", .state = ARM_CP_STATE_AA64,
38
if (r->bank_fieldoffsets[0] && r->bank_fieldoffsets[1]) {
54
.opc0 = 2, .opc1 = 4, .crn = 0, .crm = 7, .opc2 = 0,
39
/* Register is banked (using both entries in array).
55
.access = PL2_RW, .accessfn = access_dbgvcr32,
40
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
56
- .type = ARM_CP_NOP | ARM_CP_EL3_NO_EL2_KEEP },
41
#endif
57
+ .type = ARM_CP_CONST | ARM_CP_EL3_NO_EL2_KEEP,
42
}
58
+ .resetvalue = 0 },
43
}
59
};
44
- if (opaque) {
60
45
- r2->opaque = opaque;
61
static const ARMCPRegInfo debug_lpae_cp_reginfo[] = {
46
- }
47
- /* reginfo passed to helpers is correct for the actual access,
48
- * and is never ARM_CP_STATE_BOTH:
49
- */
50
- r2->state = state;
51
- /* Make sure reginfo passed to helpers for wildcarded regs
52
- * has the correct crm/opc1/opc2 for this reg, not CP_ANY:
53
- */
54
- r2->cp = cp;
55
- r2->crm = crm;
56
- r2->opc1 = opc1;
57
- r2->opc2 = opc2;
58
+
59
/* By convention, for wildcarded registers only the first
60
* entry is used for migration; the others are marked as
61
* ALIAS so we don't try to transfer the register
62
--
62
--
63
2.25.1
63
2.43.0
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
Currently we call icount_start_warp_timer() from timerlist_rearm().
2
This produces incorrect behaviour, because timerlist_rearm() is
3
called, for instance, when a timer callback modifies its timer. We
4
cannot decide here to warp the timer forwards to the next timer
5
deadline merely because all_cpu_threads_idle() is true, because the
6
timer callback we were called from (or some other callback later in
7
the list of callbacks being invoked) may be about to raise a CPU
8
interrupt and move a CPU from idle to ready.
2
9
3
Rearrange the values of the enumerators of CPAccessResult
10
The only valid place to choose to warp the timer forward is from the
4
so that we may directly extract the target el. For the two
11
main loop, when we know we have no outstanding IO or timer callbacks
5
special cases in access_check_cp_reg, use CPAccessResult.
12
that might be about to wake up a CPU.
6
13
14
For Arm guests, this bug was mostly latent until the refactoring
15
commit f6fc36deef6abc ("target/arm/helper: Implement
16
CNTHCTL_EL2.CNT[VP]MASK"), which exposed it because it refactored a
17
timer callback so that it happened to call timer_mod() first and
18
raise the interrupt second, when it had previously raised the
19
interrupt first and called timer_mod() afterwards.
20
21
This call seems to have originally derived from the
22
pre-record-and-replay icount code, which (as of e.g. commit
23
db1a49726c3c in 2010) in this location did a call to
24
qemu_notify_event(), necessary to get the icount code in the vCPU
25
round-robin thread to stop and recalculate the icount deadline when a
26
timer was reprogrammed from the IO thread. In current QEMU,
27
everything is done on the vCPU thread when we are in icount mode, so
28
there's no need to try to notify another thread here.
29
30
I suspect that the other reason why this call was doing icount timer
31
warping is that it pre-dates commit efab87cf79077a from 2015, which
32
added a call to icount_start_warp_timer() to main_loop_wait(). Once
33
the call in timerlist_rearm() has been removed, if the timer
34
callbacks don't cause any CPU to be woken up then we will end up
35
calling icount_start_warp_timer() from main_loop_wait() when the rr
36
main loop code calls rr_wait_io_event().
37
38
Remove the incorrect call from timerlist_rearm().
39
40
Cc: qemu-stable@nongnu.org
41
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2703
42
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
43
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
44
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
45
Tested-by: Alex Bennée <alex.bennee@linaro.org>
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
46
Message-id: 20250210135804.3526943-1-peter.maydell@linaro.org
10
Message-id: 20220501055028.646596-3-richard.henderson@linaro.org
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
47
---
13
target/arm/cpregs.h | 26 ++++++++++++--------
48
util/qemu-timer.c | 4 ----
14
target/arm/op_helper.c | 56 +++++++++++++++++++++---------------------
49
1 file changed, 4 deletions(-)
15
2 files changed, 44 insertions(+), 38 deletions(-)
16
50
17
diff --git a/target/arm/cpregs.h b/target/arm/cpregs.h
51
diff --git a/util/qemu-timer.c b/util/qemu-timer.c
18
index XXXXXXX..XXXXXXX 100644
52
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/cpregs.h
53
--- a/util/qemu-timer.c
20
+++ b/target/arm/cpregs.h
54
+++ b/util/qemu-timer.c
21
@@ -XXX,XX +XXX,XX @@ static inline bool cptype_valid(int cptype)
55
@@ -XXX,XX +XXX,XX @@ static bool timer_mod_ns_locked(QEMUTimerList *timer_list,
22
typedef enum CPAccessResult {
56
23
/* Access is permitted */
57
static void timerlist_rearm(QEMUTimerList *timer_list)
24
CP_ACCESS_OK = 0,
25
+
26
+ /*
27
+ * Combined with one of the following, the low 2 bits indicate the
28
+ * target exception level. If 0, the exception is taken to the usual
29
+ * target EL (EL1 or PL1 if in EL0, otherwise to the current EL).
30
+ */
31
+ CP_ACCESS_EL_MASK = 3,
32
+
33
/*
34
* Access fails due to a configurable trap or enable which would
35
* result in a categorized exception syndrome giving information about
36
* the failing instruction (ie syndrome category 0x3, 0x4, 0x5, 0x6,
37
- * 0xc or 0x18). The exception is taken to the usual target EL (EL1 or
38
- * PL1 if in EL0, otherwise to the current EL).
39
+ * 0xc or 0x18).
40
*/
41
- CP_ACCESS_TRAP = 1,
42
+ CP_ACCESS_TRAP = (1 << 2),
43
+ CP_ACCESS_TRAP_EL2 = CP_ACCESS_TRAP | 2,
44
+ CP_ACCESS_TRAP_EL3 = CP_ACCESS_TRAP | 3,
45
+
46
/*
47
* Access fails and results in an exception syndrome 0x0 ("uncategorized").
48
* Note that this is not a catch-all case -- the set of cases which may
49
* result in this failure is specifically defined by the architecture.
50
*/
51
- CP_ACCESS_TRAP_UNCATEGORIZED = 2,
52
- /* As CP_ACCESS_TRAP, but for traps directly to EL2 or EL3 */
53
- CP_ACCESS_TRAP_EL2 = 3,
54
- CP_ACCESS_TRAP_EL3 = 4,
55
- /* As CP_ACCESS_UNCATEGORIZED, but for traps directly to EL2 or EL3 */
56
- CP_ACCESS_TRAP_UNCATEGORIZED_EL2 = 5,
57
- CP_ACCESS_TRAP_UNCATEGORIZED_EL3 = 6,
58
+ CP_ACCESS_TRAP_UNCATEGORIZED = (2 << 2),
59
+ CP_ACCESS_TRAP_UNCATEGORIZED_EL2 = CP_ACCESS_TRAP_UNCATEGORIZED | 2,
60
+ CP_ACCESS_TRAP_UNCATEGORIZED_EL3 = CP_ACCESS_TRAP_UNCATEGORIZED | 3,
61
} CPAccessResult;
62
63
typedef struct ARMCPRegInfo ARMCPRegInfo;
64
diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c
65
index XXXXXXX..XXXXXXX 100644
66
--- a/target/arm/op_helper.c
67
+++ b/target/arm/op_helper.c
68
@@ -XXX,XX +XXX,XX @@ void HELPER(access_check_cp_reg)(CPUARMState *env, void *rip, uint32_t syndrome,
69
uint32_t isread)
70
{
58
{
71
const ARMCPRegInfo *ri = rip;
59
- /* Interrupt execution to force deadline recalculation. */
72
+ CPAccessResult res = CP_ACCESS_OK;
60
- if (icount_enabled() && timer_list->clock->type == QEMU_CLOCK_VIRTUAL) {
73
int target_el;
61
- icount_start_warp_timer();
74
62
- }
75
if (arm_feature(env, ARM_FEATURE_XSCALE) && ri->cp < 14
63
timerlist_notify(timer_list);
76
&& extract32(env->cp15.c15_cpar, ri->cp, 1) == 0) {
77
- raise_exception(env, EXCP_UDEF, syndrome, exception_target_el(env));
78
+ res = CP_ACCESS_TRAP;
79
+ goto fail;
80
}
81
82
/*
83
@@ -XXX,XX +XXX,XX @@ void HELPER(access_check_cp_reg)(CPUARMState *env, void *rip, uint32_t syndrome,
84
mask &= ~((1 << 4) | (1 << 14));
85
86
if (env->cp15.hstr_el2 & mask) {
87
- target_el = 2;
88
- goto exept;
89
+ res = CP_ACCESS_TRAP_EL2;
90
+ goto fail;
91
}
92
}
93
94
- if (!ri->accessfn) {
95
+ if (ri->accessfn) {
96
+ res = ri->accessfn(env, ri, isread);
97
+ }
98
+ if (likely(res == CP_ACCESS_OK)) {
99
return;
100
}
101
102
- switch (ri->accessfn(env, ri, isread)) {
103
- case CP_ACCESS_OK:
104
- return;
105
+ fail:
106
+ switch (res & ~CP_ACCESS_EL_MASK) {
107
case CP_ACCESS_TRAP:
108
- target_el = exception_target_el(env);
109
- break;
110
- case CP_ACCESS_TRAP_EL2:
111
- /* Requesting a trap to EL2 when we're in EL3 is
112
- * a bug in the access function.
113
- */
114
- assert(arm_current_el(env) != 3);
115
- target_el = 2;
116
- break;
117
- case CP_ACCESS_TRAP_EL3:
118
- target_el = 3;
119
break;
120
case CP_ACCESS_TRAP_UNCATEGORIZED:
121
- target_el = exception_target_el(env);
122
- syndrome = syn_uncategorized();
123
- break;
124
- case CP_ACCESS_TRAP_UNCATEGORIZED_EL2:
125
- target_el = 2;
126
- syndrome = syn_uncategorized();
127
- break;
128
- case CP_ACCESS_TRAP_UNCATEGORIZED_EL3:
129
- target_el = 3;
130
syndrome = syn_uncategorized();
131
break;
132
default:
133
g_assert_not_reached();
134
}
135
136
-exept:
137
+ target_el = res & CP_ACCESS_EL_MASK;
138
+ switch (target_el) {
139
+ case 0:
140
+ target_el = exception_target_el(env);
141
+ break;
142
+ case 2:
143
+ assert(arm_current_el(env) != 3);
144
+ assert(arm_is_el2_enabled(env));
145
+ break;
146
+ case 3:
147
+ assert(arm_feature(env, ARM_FEATURE_EL3));
148
+ break;
149
+ default:
150
+ /* No "direct" traps to EL1 */
151
+ g_assert_not_reached();
152
+ }
153
+
154
raise_exception(env, EXCP_UDEF, syndrome, target_el);
155
}
64
}
156
65
157
--
66
--
158
2.25.1
67
2.43.0
159
68
160
69
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
Expand the example in the comment documenting MO_ATOM_SUBALIGN,
2
to be clearer about the atomicity guarantees it represents.
2
3
3
Simplify freeing cp_regs hash table entries by using a single
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
allocation for the entire value.
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20250228103222.1838913-1-peter.maydell@linaro.org
7
---
8
include/exec/memop.h | 8 ++++++--
9
1 file changed, 6 insertions(+), 2 deletions(-)
5
10
6
This fixes a theoretical bug if we were to ever free the entire
11
diff --git a/include/exec/memop.h b/include/exec/memop.h
7
hash table, because we've been installing string literal constants
8
into the cpreg structure in define_arm_vh_e2h_redirects_aliases.
9
However, at present we only free entries created for AArch32
10
wildcard cpregs which get overwritten by more specific cpregs,
11
so this bug is never exposed.
12
13
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
14
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
15
Message-id: 20220501055028.646596-13-richard.henderson@linaro.org
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
---
18
target/arm/cpu.c | 16 +---------------
19
target/arm/helper.c | 10 ++++++++--
20
2 files changed, 9 insertions(+), 17 deletions(-)
21
22
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
23
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
24
--- a/target/arm/cpu.c
13
--- a/include/exec/memop.h
25
+++ b/target/arm/cpu.c
14
+++ b/include/exec/memop.h
26
@@ -XXX,XX +XXX,XX @@ uint64_t arm_cpu_mp_affinity(int idx, uint8_t clustersz)
15
@@ -XXX,XX +XXX,XX @@ typedef enum MemOp {
27
return (Aff1 << ARM_AFF1_SHIFT) | Aff0;
16
* Depending on alignment, one or both will be single-copy atomic.
28
}
17
* This is the atomicity e.g. of Arm FEAT_LSE2 LDP.
29
18
* MO_ATOM_SUBALIGN: the operation is single-copy atomic by parts
30
-static void cpreg_hashtable_data_destroy(gpointer data)
19
- * by the alignment. E.g. if the address is 0 mod 4, then each
31
-{
20
- * 4-byte subobject is single-copy atomic.
32
- /*
21
+ * by the alignment. E.g. if an 8-byte value is accessed at an
33
- * Destroy function for cpu->cp_regs hashtable data entries.
22
+ * address which is 0 mod 8, then the whole 8-byte access is
34
- * We must free the name string because it was g_strdup()ed in
23
+ * single-copy atomic; otherwise, if it is accessed at 0 mod 4
35
- * add_cpreg_to_hashtable(). It's OK to cast away the 'const'
24
+ * then each 4-byte subobject is single-copy atomic; otherwise
36
- * from r->name because we know we definitely allocated it.
25
+ * if it is accessed at 0 mod 2 then the four 2-byte subobjects
37
- */
26
+ * are single-copy atomic.
38
- ARMCPRegInfo *r = data;
27
* This is the atomicity e.g. of IBM Power.
39
-
28
* MO_ATOM_NONE: the operation has no atomicity requirements.
40
- g_free((void *)r->name);
29
*
41
- g_free(r);
42
-}
43
-
44
static void arm_cpu_initfn(Object *obj)
45
{
46
ARMCPU *cpu = ARM_CPU(obj);
47
48
cpu_set_cpustate_pointers(cpu);
49
cpu->cp_regs = g_hash_table_new_full(g_direct_hash, g_direct_equal,
50
- NULL, cpreg_hashtable_data_destroy);
51
+ NULL, g_free);
52
53
QLIST_INIT(&cpu->pre_el_change_hooks);
54
QLIST_INIT(&cpu->el_change_hooks);
55
diff --git a/target/arm/helper.c b/target/arm/helper.c
56
index XXXXXXX..XXXXXXX 100644
57
--- a/target/arm/helper.c
58
+++ b/target/arm/helper.c
59
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
60
* add a single reginfo struct to the hash table.
61
*/
62
uint32_t key;
63
- ARMCPRegInfo *r2 = g_memdup(r, sizeof(ARMCPRegInfo));
64
+ ARMCPRegInfo *r2;
65
int is64 = (r->type & ARM_CP_64BIT) ? 1 : 0;
66
int ns = (secstate & ARM_CP_SECSTATE_NS) ? 1 : 0;
67
+ size_t name_len;
68
+
69
+ /* Combine cpreg and name into one allocation. */
70
+ name_len = strlen(name) + 1;
71
+ r2 = g_malloc(sizeof(*r2) + name_len);
72
+ *r2 = *r;
73
+ r2->name = memcpy(r2 + 1, name, name_len);
74
75
- r2->name = g_strdup(name);
76
/* Reset the secure state to the specific incoming state. This is
77
* necessary as the register may have been defined with both states.
78
*/
79
--
30
--
80
2.25.1
31
2.43.0
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: JianChunfu <jansef.jian@hj-micro.com>
2
2
3
Standardize on g_assert_not_reached() for "should not happen".
3
Use a similar terminology smmu_hash_remove_by_sid_range() as the one
4
Retain abort() when preceeded by fprintf or error_report.
4
being used for other hash table matching functions since
5
smmuv3_invalidate_ste() name is not self explanatory, and introduce a
6
helper that invokes the g_hash_table_foreach_remove.
5
7
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
No functional change intended.
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
8
Message-id: 20220501055028.646596-7-richard.henderson@linaro.org
10
Signed-off-by: JianChunfu <jansef.jian@hj-micro.com>
11
Reviewed-by: Eric Auger <eric.auger@redhat.com>
12
Message-id: 20250228031438.3916-1-jansef.jian@hj-micro.com
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
14
---
11
target/arm/helper.c | 7 +++----
15
hw/arm/smmu-internal.h | 5 -----
12
target/arm/hvf/hvf.c | 2 +-
16
include/hw/arm/smmu-common.h | 6 ++++++
13
target/arm/kvm-stub.c | 4 ++--
17
hw/arm/smmu-common.c | 21 +++++++++++++++++++++
14
target/arm/kvm.c | 4 ++--
18
hw/arm/smmuv3.c | 19 ++-----------------
15
target/arm/machine.c | 4 ++--
19
hw/arm/trace-events | 3 ++-
16
target/arm/translate-a64.c | 4 ++--
20
5 files changed, 31 insertions(+), 23 deletions(-)
17
target/arm/translate-neon.c | 2 +-
18
target/arm/translate.c | 4 ++--
19
8 files changed, 15 insertions(+), 16 deletions(-)
20
21
21
diff --git a/target/arm/helper.c b/target/arm/helper.c
22
diff --git a/hw/arm/smmu-internal.h b/hw/arm/smmu-internal.h
22
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
23
--- a/target/arm/helper.c
24
--- a/hw/arm/smmu-internal.h
24
+++ b/target/arm/helper.c
25
+++ b/hw/arm/smmu-internal.h
25
@@ -XXX,XX +XXX,XX @@ void define_one_arm_cp_reg_with_opaque(ARMCPU *cpu,
26
@@ -XXX,XX +XXX,XX @@ typedef struct SMMUIOTLBPageInvInfo {
26
break;
27
uint64_t mask;
27
default:
28
} SMMUIOTLBPageInvInfo;
28
/* broken reginfo with out-of-range opc1 */
29
29
- assert(false);
30
-typedef struct SMMUSIDRange {
30
- break;
31
- uint32_t start;
31
+ g_assert_not_reached();
32
- uint32_t end;
32
}
33
-} SMMUSIDRange;
33
/* assert our permissions are not too lax (stricter is fine) */
34
-
34
assert((r->access & ~mask) == 0);
35
#endif
35
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_v5(CPUARMState *env, uint32_t address,
36
diff --git a/include/hw/arm/smmu-common.h b/include/hw/arm/smmu-common.h
36
break;
37
default:
38
/* Never happens, but compiler isn't smart enough to tell. */
39
- abort();
40
+ g_assert_not_reached();
41
}
42
}
43
*prot = ap_to_rw_prot(env, mmu_idx, ap, domain_prot);
44
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_v6(CPUARMState *env, uint32_t address,
45
break;
46
default:
47
/* Never happens, but compiler isn't smart enough to tell. */
48
- abort();
49
+ g_assert_not_reached();
50
}
51
}
52
if (domain_prot == 3) {
53
diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c
54
index XXXXXXX..XXXXXXX 100644
37
index XXXXXXX..XXXXXXX 100644
55
--- a/target/arm/hvf/hvf.c
38
--- a/include/hw/arm/smmu-common.h
56
+++ b/target/arm/hvf/hvf.c
39
+++ b/include/hw/arm/smmu-common.h
57
@@ -XXX,XX +XXX,XX @@ int hvf_vcpu_exec(CPUState *cpu)
40
@@ -XXX,XX +XXX,XX @@ typedef struct SMMUIOTLBKey {
58
/* we got kicked, no exit to process */
41
uint8_t level;
59
return 0;
42
} SMMUIOTLBKey;
60
default:
43
61
- assert(0);
44
+typedef struct SMMUSIDRange {
62
+ g_assert_not_reached();
45
+ uint32_t start;
63
}
46
+ uint32_t end;
64
47
+} SMMUSIDRange;
65
hvf_sync_vtimer(cpu);
48
+
66
diff --git a/target/arm/kvm-stub.c b/target/arm/kvm-stub.c
49
struct SMMUState {
50
/* <private> */
51
SysBusDevice dev;
52
@@ -XXX,XX +XXX,XX @@ void smmu_iotlb_inv_iova(SMMUState *s, int asid, int vmid, dma_addr_t iova,
53
uint8_t tg, uint64_t num_pages, uint8_t ttl);
54
void smmu_iotlb_inv_ipa(SMMUState *s, int vmid, dma_addr_t ipa, uint8_t tg,
55
uint64_t num_pages, uint8_t ttl);
56
+void smmu_configs_inv_sid_range(SMMUState *s, SMMUSIDRange sid_range);
57
/* Unmap the range of all the notifiers registered to any IOMMU mr */
58
void smmu_inv_notifiers_all(SMMUState *s);
59
60
diff --git a/hw/arm/smmu-common.c b/hw/arm/smmu-common.c
67
index XXXXXXX..XXXXXXX 100644
61
index XXXXXXX..XXXXXXX 100644
68
--- a/target/arm/kvm-stub.c
62
--- a/hw/arm/smmu-common.c
69
+++ b/target/arm/kvm-stub.c
63
+++ b/hw/arm/smmu-common.c
70
@@ -XXX,XX +XXX,XX @@
64
@@ -XXX,XX +XXX,XX @@ static gboolean smmu_hash_remove_by_vmid_ipa(gpointer key, gpointer value,
71
65
((entry->iova & ~info->mask) == info->iova);
72
bool write_kvmstate_to_list(ARMCPU *cpu)
66
}
67
68
+static gboolean
69
+smmu_hash_remove_by_sid_range(gpointer key, gpointer value, gpointer user_data)
70
+{
71
+ SMMUDevice *sdev = (SMMUDevice *)key;
72
+ uint32_t sid = smmu_get_sid(sdev);
73
+ SMMUSIDRange *sid_range = (SMMUSIDRange *)user_data;
74
+
75
+ if (sid < sid_range->start || sid > sid_range->end) {
76
+ return false;
77
+ }
78
+ trace_smmu_config_cache_inv(sid);
79
+ return true;
80
+}
81
+
82
+void smmu_configs_inv_sid_range(SMMUState *s, SMMUSIDRange sid_range)
83
+{
84
+ trace_smmu_configs_inv_sid_range(sid_range.start, sid_range.end);
85
+ g_hash_table_foreach_remove(s->configs, smmu_hash_remove_by_sid_range,
86
+ &sid_range);
87
+}
88
+
89
void smmu_iotlb_inv_iova(SMMUState *s, int asid, int vmid, dma_addr_t iova,
90
uint8_t tg, uint64_t num_pages, uint8_t ttl)
73
{
91
{
74
- abort();
92
diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c
75
+ g_assert_not_reached();
93
index XXXXXXX..XXXXXXX 100644
94
--- a/hw/arm/smmuv3.c
95
+++ b/hw/arm/smmuv3.c
96
@@ -XXX,XX +XXX,XX @@ static void smmuv3_flush_config(SMMUDevice *sdev)
97
SMMUv3State *s = sdev->smmu;
98
SMMUState *bc = &s->smmu_state;
99
100
- trace_smmuv3_config_cache_inv(smmu_get_sid(sdev));
101
+ trace_smmu_config_cache_inv(smmu_get_sid(sdev));
102
g_hash_table_remove(bc->configs, sdev);
76
}
103
}
77
104
78
bool write_list_to_kvmstate(ARMCPU *cpu, int level)
105
@@ -XXX,XX +XXX,XX @@ static void smmuv3_range_inval(SMMUState *s, Cmd *cmd, SMMUStage stage)
79
{
80
- abort();
81
+ g_assert_not_reached();
82
}
83
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
84
index XXXXXXX..XXXXXXX 100644
85
--- a/target/arm/kvm.c
86
+++ b/target/arm/kvm.c
87
@@ -XXX,XX +XXX,XX @@ bool write_kvmstate_to_list(ARMCPU *cpu)
88
ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &r);
89
break;
90
default:
91
- abort();
92
+ g_assert_not_reached();
93
}
94
if (ret) {
95
ok = false;
96
@@ -XXX,XX +XXX,XX @@ bool write_list_to_kvmstate(ARMCPU *cpu, int level)
97
r.addr = (uintptr_t)(cpu->cpreg_values + i);
98
break;
99
default:
100
- abort();
101
+ g_assert_not_reached();
102
}
103
ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &r);
104
if (ret) {
105
diff --git a/target/arm/machine.c b/target/arm/machine.c
106
index XXXXXXX..XXXXXXX 100644
107
--- a/target/arm/machine.c
108
+++ b/target/arm/machine.c
109
@@ -XXX,XX +XXX,XX @@ static int cpu_pre_save(void *opaque)
110
if (kvm_enabled()) {
111
if (!write_kvmstate_to_list(cpu)) {
112
/* This should never fail */
113
- abort();
114
+ g_assert_not_reached();
115
}
116
117
/*
118
@@ -XXX,XX +XXX,XX @@ static int cpu_pre_save(void *opaque)
119
} else {
120
if (!write_cpustate_to_list(cpu, false)) {
121
/* This should never fail. */
122
- abort();
123
+ g_assert_not_reached();
124
}
125
}
126
127
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
128
index XXXXXXX..XXXXXXX 100644
129
--- a/target/arm/translate-a64.c
130
+++ b/target/arm/translate-a64.c
131
@@ -XXX,XX +XXX,XX @@ static void handle_fp_1src_half(DisasContext *s, int opcode, int rd, int rn)
132
gen_helper_advsimd_rinth(tcg_res, tcg_op, fpst);
133
break;
134
default:
135
- abort();
136
+ g_assert_not_reached();
137
}
138
139
write_fp_sreg(s, rd, tcg_res);
140
@@ -XXX,XX +XXX,XX @@ static void handle_fp_fcvt(DisasContext *s, int opcode,
141
break;
142
}
143
default:
144
- abort();
145
+ g_assert_not_reached();
146
}
106
}
147
}
107
}
148
108
149
diff --git a/target/arm/translate-neon.c b/target/arm/translate-neon.c
109
-static gboolean
110
-smmuv3_invalidate_ste(gpointer key, gpointer value, gpointer user_data)
111
-{
112
- SMMUDevice *sdev = (SMMUDevice *)key;
113
- uint32_t sid = smmu_get_sid(sdev);
114
- SMMUSIDRange *sid_range = (SMMUSIDRange *)user_data;
115
-
116
- if (sid < sid_range->start || sid > sid_range->end) {
117
- return false;
118
- }
119
- trace_smmuv3_config_cache_inv(sid);
120
- return true;
121
-}
122
-
123
static int smmuv3_cmdq_consume(SMMUv3State *s)
124
{
125
SMMUState *bs = ARM_SMMU(s);
126
@@ -XXX,XX +XXX,XX @@ static int smmuv3_cmdq_consume(SMMUv3State *s)
127
sid_range.end = sid_range.start + mask;
128
129
trace_smmuv3_cmdq_cfgi_ste_range(sid_range.start, sid_range.end);
130
- g_hash_table_foreach_remove(bs->configs, smmuv3_invalidate_ste,
131
- &sid_range);
132
+ smmu_configs_inv_sid_range(bs, sid_range);
133
break;
134
}
135
case SMMU_CMD_CFGI_CD:
136
diff --git a/hw/arm/trace-events b/hw/arm/trace-events
150
index XXXXXXX..XXXXXXX 100644
137
index XXXXXXX..XXXXXXX 100644
151
--- a/target/arm/translate-neon.c
138
--- a/hw/arm/trace-events
152
+++ b/target/arm/translate-neon.c
139
+++ b/hw/arm/trace-events
153
@@ -XXX,XX +XXX,XX @@ static bool trans_VLDST_single(DisasContext *s, arg_VLDST_single *a)
140
@@ -XXX,XX +XXX,XX @@ smmu_iotlb_inv_asid_vmid(int asid, int vmid) "IOTLB invalidate asid=%d vmid=%d"
154
}
141
smmu_iotlb_inv_vmid(int vmid) "IOTLB invalidate vmid=%d"
155
break;
142
smmu_iotlb_inv_vmid_s1(int vmid) "IOTLB invalidate vmid=%d"
156
default:
143
smmu_iotlb_inv_iova(int asid, uint64_t addr) "IOTLB invalidate asid=%d addr=0x%"PRIx64
157
- abort();
144
+smmu_configs_inv_sid_range(uint32_t start, uint32_t end) "Config cache INV SID range from 0x%x to 0x%x"
158
+ g_assert_not_reached();
145
+smmu_config_cache_inv(uint32_t sid) "Config cache INV for sid=0x%x"
159
}
146
smmu_inv_notifiers_mr(const char *name) "iommu mr=%s"
160
if ((vd + a->stride * (nregs - 1)) > 31) {
147
smmu_iotlb_lookup_hit(int asid, int vmid, uint64_t addr, uint32_t hit, uint32_t miss, uint32_t p) "IOTLB cache HIT asid=%d vmid=%d addr=0x%"PRIx64" hit=%d miss=%d hit rate=%d"
161
/*
148
smmu_iotlb_lookup_miss(int asid, int vmid, uint64_t addr, uint32_t hit, uint32_t miss, uint32_t p) "IOTLB cache MISS asid=%d vmid=%d addr=0x%"PRIx64" hit=%d miss=%d hit rate=%d"
162
diff --git a/target/arm/translate.c b/target/arm/translate.c
149
@@ -XXX,XX +XXX,XX @@ smmuv3_cmdq_tlbi_nh(int vmid) "vmid=%d"
163
index XXXXXXX..XXXXXXX 100644
150
smmuv3_cmdq_tlbi_nsnh(void) ""
164
--- a/target/arm/translate.c
151
smmuv3_cmdq_tlbi_nh_asid(int asid) "asid=%d"
165
+++ b/target/arm/translate.c
152
smmuv3_cmdq_tlbi_s12_vmid(int vmid) "vmid=%d"
166
@@ -XXX,XX +XXX,XX @@ static void gen_srs(DisasContext *s,
153
-smmuv3_config_cache_inv(uint32_t sid) "Config cache INV for sid=0x%x"
167
offset = 4;
154
smmuv3_notify_flag_add(const char *iommu) "ADD SMMUNotifier node for iommu mr=%s"
168
break;
155
smmuv3_notify_flag_del(const char *iommu) "DEL SMMUNotifier node for iommu mr=%s"
169
default:
156
smmuv3_inv_notifiers_iova(const char *name, int asid, int vmid, uint64_t iova, uint8_t tg, uint64_t num_pages, int stage) "iommu mr=%s asid=%d vmid=%d iova=0x%"PRIx64" tg=%d num_pages=0x%"PRIx64" stage=%d"
170
- abort();
171
+ g_assert_not_reached();
172
}
173
tcg_gen_addi_i32(addr, addr, offset);
174
tmp = load_reg(s, 14);
175
@@ -XXX,XX +XXX,XX @@ static void gen_srs(DisasContext *s,
176
offset = 0;
177
break;
178
default:
179
- abort();
180
+ g_assert_not_reached();
181
}
182
tcg_gen_addi_i32(addr, addr, offset);
183
gen_helper_set_r13_banked(cpu_env, tcg_constant_i32(mode), addr);
184
--
157
--
185
2.25.1
158
2.43.0
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
Create a typedef as well, and use it in ARMCPRegInfo.
4
This won't be perfect for debugging, but it'll nicely
5
display the most common cases.
6
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20220501055028.646596-8-richard.henderson@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
target/arm/cpregs.h | 44 +++++++++++++++++++++++---------------------
13
target/arm/helper.c | 2 +-
14
2 files changed, 24 insertions(+), 22 deletions(-)
15
16
diff --git a/target/arm/cpregs.h b/target/arm/cpregs.h
17
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/cpregs.h
19
+++ b/target/arm/cpregs.h
20
@@ -XXX,XX +XXX,XX @@ enum {
21
* described with these bits, then use a laxer set of restrictions, and
22
* do the more restrictive/complex check inside a helper function.
23
*/
24
-#define PL3_R 0x80
25
-#define PL3_W 0x40
26
-#define PL2_R (0x20 | PL3_R)
27
-#define PL2_W (0x10 | PL3_W)
28
-#define PL1_R (0x08 | PL2_R)
29
-#define PL1_W (0x04 | PL2_W)
30
-#define PL0_R (0x02 | PL1_R)
31
-#define PL0_W (0x01 | PL1_W)
32
+typedef enum {
33
+ PL3_R = 0x80,
34
+ PL3_W = 0x40,
35
+ PL2_R = 0x20 | PL3_R,
36
+ PL2_W = 0x10 | PL3_W,
37
+ PL1_R = 0x08 | PL2_R,
38
+ PL1_W = 0x04 | PL2_W,
39
+ PL0_R = 0x02 | PL1_R,
40
+ PL0_W = 0x01 | PL1_W,
41
42
-/*
43
- * For user-mode some registers are accessible to EL0 via a kernel
44
- * trap-and-emulate ABI. In this case we define the read permissions
45
- * as actually being PL0_R. However some bits of any given register
46
- * may still be masked.
47
- */
48
+ /*
49
+ * For user-mode some registers are accessible to EL0 via a kernel
50
+ * trap-and-emulate ABI. In this case we define the read permissions
51
+ * as actually being PL0_R. However some bits of any given register
52
+ * may still be masked.
53
+ */
54
#ifdef CONFIG_USER_ONLY
55
-#define PL0U_R PL0_R
56
+ PL0U_R = PL0_R,
57
#else
58
-#define PL0U_R PL1_R
59
+ PL0U_R = PL1_R,
60
#endif
61
62
-#define PL3_RW (PL3_R | PL3_W)
63
-#define PL2_RW (PL2_R | PL2_W)
64
-#define PL1_RW (PL1_R | PL1_W)
65
-#define PL0_RW (PL0_R | PL0_W)
66
+ PL3_RW = PL3_R | PL3_W,
67
+ PL2_RW = PL2_R | PL2_W,
68
+ PL1_RW = PL1_R | PL1_W,
69
+ PL0_RW = PL0_R | PL0_W,
70
+} CPAccessRights;
71
72
typedef enum CPAccessResult {
73
/* Access is permitted */
74
@@ -XXX,XX +XXX,XX @@ struct ARMCPRegInfo {
75
/* Register type: ARM_CP_* bits/values */
76
int type;
77
/* Access rights: PL*_[RW] */
78
- int access;
79
+ CPAccessRights access;
80
/* Security state: ARM_CP_SECSTATE_* bits/values */
81
int secure;
82
/*
83
diff --git a/target/arm/helper.c b/target/arm/helper.c
84
index XXXXXXX..XXXXXXX 100644
85
--- a/target/arm/helper.c
86
+++ b/target/arm/helper.c
87
@@ -XXX,XX +XXX,XX @@ void define_one_arm_cp_reg_with_opaque(ARMCPU *cpu,
88
* to encompass the generic architectural permission check.
89
*/
90
if (r->state != ARM_CP_STATE_AA32) {
91
- int mask = 0;
92
+ CPAccessRights mask;
93
switch (r->opc1) {
94
case 0:
95
/* min_EL EL1, but some accessible to EL0 via kernel ABI */
96
--
97
2.25.1
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Keith Packard <keithp@keithp.com>
2
2
3
Give this enum a name and use in ARMCPRegInfo and add_cpreg_to_hashtable.
3
The documentation says the vector is at 0xffffff80, instead of the
4
Add the enumerator ARM_CP_SECSTATE_BOTH to clarify how 0
4
previous value of 0xffffffc0. That value must have been a bug because
5
is handled in define_one_arm_cp_reg_with_opaque.
5
the standard vector values (20, 21, 23, 25, 30) were all
6
past the end of the array.
6
7
8
Signed-off-by: Keith Packard <keithp@keithp.com>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20220501055028.646596-10-richard.henderson@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
11
---
12
target/arm/cpregs.h | 7 ++++---
12
target/rx/helper.c | 2 +-
13
target/arm/helper.c | 7 +++++--
13
1 file changed, 1 insertion(+), 1 deletion(-)
14
2 files changed, 9 insertions(+), 5 deletions(-)
15
14
16
diff --git a/target/arm/cpregs.h b/target/arm/cpregs.h
15
diff --git a/target/rx/helper.c b/target/rx/helper.c
17
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/cpregs.h
17
--- a/target/rx/helper.c
19
+++ b/target/arm/cpregs.h
18
+++ b/target/rx/helper.c
20
@@ -XXX,XX +XXX,XX @@ typedef enum {
19
@@ -XXX,XX +XXX,XX @@ void rx_cpu_do_interrupt(CPUState *cs)
21
* registered entry will only have one to identify whether the entry is secure
20
cpu_stl_data(env, env->isp, env->pc);
22
* or non-secure.
21
23
*/
22
if (vec < 0x100) {
24
-enum {
23
- env->pc = cpu_ldl_data(env, 0xffffffc0 + vec * 4);
25
+typedef enum {
24
+ env->pc = cpu_ldl_data(env, 0xffffff80 + vec * 4);
26
+ ARM_CP_SECSTATE_BOTH = 0, /* define one cpreg for each secstate */
25
} else {
27
ARM_CP_SECSTATE_S = (1 << 0), /* bit[0]: Secure state register */
26
env->pc = cpu_ldl_data(env, env->intb + (vec & 0xff) * 4);
28
ARM_CP_SECSTATE_NS = (1 << 1), /* bit[1]: Non-secure state register */
27
}
29
-};
30
+} CPSecureState;
31
32
/*
33
* Access rights:
34
@@ -XXX,XX +XXX,XX @@ struct ARMCPRegInfo {
35
/* Access rights: PL*_[RW] */
36
CPAccessRights access;
37
/* Security state: ARM_CP_SECSTATE_* bits/values */
38
- int secure;
39
+ CPSecureState secure;
40
/*
41
* The opaque pointer passed to define_arm_cp_regs_with_opaque() when
42
* this register was defined: can be used to hand data through to the
43
diff --git a/target/arm/helper.c b/target/arm/helper.c
44
index XXXXXXX..XXXXXXX 100644
45
--- a/target/arm/helper.c
46
+++ b/target/arm/helper.c
47
@@ -XXX,XX +XXX,XX @@ CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp)
48
}
49
50
static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
51
- void *opaque, CPState state, int secstate,
52
+ void *opaque, CPState state,
53
+ CPSecureState secstate,
54
int crm, int opc1, int opc2,
55
const char *name)
56
{
57
@@ -XXX,XX +XXX,XX @@ void define_one_arm_cp_reg_with_opaque(ARMCPU *cpu,
58
r->secure, crm, opc1, opc2,
59
r->name);
60
break;
61
- default:
62
+ case ARM_CP_SECSTATE_BOTH:
63
name = g_strdup_printf("%s_S", r->name);
64
add_cpreg_to_hashtable(cpu, r, opaque, state,
65
ARM_CP_SECSTATE_S,
66
@@ -XXX,XX +XXX,XX @@ void define_one_arm_cp_reg_with_opaque(ARMCPU *cpu,
67
ARM_CP_SECSTATE_NS,
68
crm, opc1, opc2, r->name);
69
break;
70
+ default:
71
+ g_assert_not_reached();
72
}
73
} else {
74
/* AArch64 registers get mapped to non-secure instance
75
--
28
--
76
2.25.1
29
2.43.0
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Keith Packard <keithp@keithp.com>
2
2
3
The new_key field is always non-zero -- drop the if.
3
Functions which modify TCG globals must not be marked TCG_CALL_NO_WG,
4
as that tells the optimizer that TCG global values already loaded in
5
machine registers are still valid, and so any changes which these
6
helpers make to the CPU state may be ignored.
4
7
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
The target/rx code chooses to put (among other things) all the PSW
9
bits and also ACC into globals, so the NO_WG flag on various
10
functions that touch the PSW or ACC is incorrect and must be removed.
11
This includes all the floating point helper functions, because
12
update_fpsw() will update PSW Z and S.
13
14
Signed-off-by: Keith Packard <keithp@keithp.com>
15
[PMM: Clarified commit message]
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
16
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Message-id: 20220501055028.646596-11-richard.henderson@linaro.org
8
[PMM: reinstated dropped PL3_RW mask]
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
18
---
11
target/arm/helper.c | 23 +++++++++++------------
19
target/rx/helper.h | 34 +++++++++++++++++-----------------
12
1 file changed, 11 insertions(+), 12 deletions(-)
20
1 file changed, 17 insertions(+), 17 deletions(-)
13
21
14
diff --git a/target/arm/helper.c b/target/arm/helper.c
22
diff --git a/target/rx/helper.h b/target/rx/helper.h
15
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/helper.c
24
--- a/target/rx/helper.h
17
+++ b/target/arm/helper.c
25
+++ b/target/rx/helper.h
18
@@ -XXX,XX +XXX,XX @@ static void define_arm_vh_e2h_redirects_aliases(ARMCPU *cpu)
26
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_1(raise_privilege_violation, noreturn, env)
19
27
DEF_HELPER_1(wait, noreturn, env)
20
for (i = 0; i < ARRAY_SIZE(aliases); i++) {
28
DEF_HELPER_2(rxint, noreturn, env, i32)
21
const struct E2HAlias *a = &aliases[i];
29
DEF_HELPER_1(rxbrk, noreturn, env)
22
- ARMCPRegInfo *src_reg, *dst_reg;
30
-DEF_HELPER_FLAGS_3(fadd, TCG_CALL_NO_WG, f32, env, f32, f32)
23
+ ARMCPRegInfo *src_reg, *dst_reg, *new_reg;
31
-DEF_HELPER_FLAGS_3(fsub, TCG_CALL_NO_WG, f32, env, f32, f32)
24
+ uint32_t *new_key;
32
-DEF_HELPER_FLAGS_3(fmul, TCG_CALL_NO_WG, f32, env, f32, f32)
25
+ bool ok;
33
-DEF_HELPER_FLAGS_3(fdiv, TCG_CALL_NO_WG, f32, env, f32, f32)
26
34
-DEF_HELPER_FLAGS_3(fcmp, TCG_CALL_NO_WG, void, env, f32, f32)
27
if (a->feature && !a->feature(&cpu->isar)) {
35
-DEF_HELPER_FLAGS_2(ftoi, TCG_CALL_NO_WG, i32, env, f32)
28
continue;
36
-DEF_HELPER_FLAGS_2(round, TCG_CALL_NO_WG, i32, env, f32)
29
@@ -XXX,XX +XXX,XX @@ static void define_arm_vh_e2h_redirects_aliases(ARMCPU *cpu)
37
-DEF_HELPER_FLAGS_2(itof, TCG_CALL_NO_WG, f32, env, i32)
30
g_assert(src_reg->opaque == NULL);
38
+DEF_HELPER_3(fadd, f32, env, f32, f32)
31
39
+DEF_HELPER_3(fsub, f32, env, f32, f32)
32
/* Create alias before redirection so we dup the right data. */
40
+DEF_HELPER_3(fmul, f32, env, f32, f32)
33
- if (a->new_key) {
41
+DEF_HELPER_3(fdiv, f32, env, f32, f32)
34
- ARMCPRegInfo *new_reg = g_memdup(src_reg, sizeof(ARMCPRegInfo));
42
+DEF_HELPER_3(fcmp, void, env, f32, f32)
35
- uint32_t *new_key = g_memdup(&a->new_key, sizeof(uint32_t));
43
+DEF_HELPER_2(ftoi, i32, env, f32)
36
- bool ok;
44
+DEF_HELPER_2(round, i32, env, f32)
37
+ new_reg = g_memdup(src_reg, sizeof(ARMCPRegInfo));
45
+DEF_HELPER_2(itof, f32, env, i32)
38
+ new_key = g_memdup(&a->new_key, sizeof(uint32_t));
46
DEF_HELPER_2(set_fpsw, void, env, i32)
39
47
-DEF_HELPER_FLAGS_2(racw, TCG_CALL_NO_WG, void, env, i32)
40
- new_reg->name = a->new_name;
48
-DEF_HELPER_FLAGS_2(set_psw_rte, TCG_CALL_NO_WG, void, env, i32)
41
- new_reg->type |= ARM_CP_ALIAS;
49
-DEF_HELPER_FLAGS_2(set_psw, TCG_CALL_NO_WG, void, env, i32)
42
- /* Remove PL1/PL0 access, leaving PL2/PL3 R/W in place. */
50
+DEF_HELPER_2(racw, void, env, i32)
43
- new_reg->access &= PL2_RW | PL3_RW;
51
+DEF_HELPER_2(set_psw_rte, void, env, i32)
44
+ new_reg->name = a->new_name;
52
+DEF_HELPER_2(set_psw, void, env, i32)
45
+ new_reg->type |= ARM_CP_ALIAS;
53
DEF_HELPER_1(pack_psw, i32, env)
46
+ /* Remove PL1/PL0 access, leaving PL2/PL3 R/W in place. */
54
-DEF_HELPER_FLAGS_3(div, TCG_CALL_NO_WG, i32, env, i32, i32)
47
+ new_reg->access &= PL2_RW | PL3_RW;
55
-DEF_HELPER_FLAGS_3(divu, TCG_CALL_NO_WG, i32, env, i32, i32)
48
56
-DEF_HELPER_FLAGS_1(scmpu, TCG_CALL_NO_WG, void, env)
49
- ok = g_hash_table_insert(cpu->cp_regs, new_key, new_reg);
57
+DEF_HELPER_3(div, i32, env, i32, i32)
50
- g_assert(ok);
58
+DEF_HELPER_3(divu, i32, env, i32, i32)
51
- }
59
+DEF_HELPER_1(scmpu, void, env)
52
+ ok = g_hash_table_insert(cpu->cp_regs, new_key, new_reg);
60
DEF_HELPER_1(smovu, void, env)
53
+ g_assert(ok);
61
DEF_HELPER_1(smovf, void, env)
54
62
DEF_HELPER_1(smovb, void, env)
55
src_reg->opaque = dst_reg;
63
DEF_HELPER_2(sstr, void, env, i32)
56
src_reg->orig_readfn = src_reg->readfn ?: raw_read;
64
-DEF_HELPER_FLAGS_2(swhile, TCG_CALL_NO_WG, void, env, i32)
65
-DEF_HELPER_FLAGS_2(suntil, TCG_CALL_NO_WG, void, env, i32)
66
-DEF_HELPER_FLAGS_2(rmpa, TCG_CALL_NO_WG, void, env, i32)
67
+DEF_HELPER_2(swhile, void, env, i32)
68
+DEF_HELPER_2(suntil, void, env, i32)
69
+DEF_HELPER_2(rmpa, void, env, i32)
70
DEF_HELPER_1(satr, void, env)
57
--
71
--
58
2.25.1
72
2.43.0
diff view generated by jsdifflib