1
Two small bugfixes, plus most of RTH's refactoring of cpregs
1
Hi; this mostly contains the first slice of A64 decodetree
2
handling.
2
patches, plus some other minor pieces. It also has the
3
enablement of MTE for KVM guests.
3
4
5
thanks
4
-- PMM
6
-- PMM
5
7
6
The following changes since commit 1fba9dc71a170b3a05b9d3272dd8ecfe7f26e215:
8
The following changes since commit d27e7c359330ba7020bdbed7ed2316cb4cf6ffc1:
7
9
8
Merge tag 'pull-request-2022-05-04' of https://gitlab.com/thuth/qemu into staging (2022-05-04 08:07:02 -0700)
10
qapi/parser: Drop two bad type hints for now (2023-05-17 10:18:33 -0700)
9
11
10
are available in the Git repository at:
12
are available in the Git repository at:
11
13
12
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20220505
14
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20230518
13
15
14
for you to fetch changes up to 99a50d1a67c602126fc2b3a4812d3000eba9bf34:
16
for you to fetch changes up to 91608e2a44f36e79cb83f863b8a7bb57d2c98061:
15
17
16
target/arm: read access to performance counters from EL0 (2022-05-05 09:36:22 +0100)
18
docs: Convert u2f.txt to rST (2023-05-18 11:40:32 +0100)
17
19
18
----------------------------------------------------------------
20
----------------------------------------------------------------
19
target-arm queue:
21
target-arm queue:
20
* Enable read access to performance counters from EL0
22
* Fix vd == vm overlap in sve_ldff1_z
21
* Enable SCTLR_EL1.BT0 for aarch64-linux-user
23
* Add support for MTE with KVM guests
22
* Refactoring of cpreg handling
24
* Add RAZ/WI handling for DBGDTR[TX|RX]
25
* Start of conversion of A64 decoder to decodetree
26
* Saturate L2CTLR_EL1 core count field rather than overflowing
27
* vexpress: Avoid trivial memory leak of 'flashalias'
28
* sbsa-ref: switch default cpu core to Neoverse-N1
29
* sbsa-ref: use Bochs graphics card instead of VGA
30
* MAINTAINERS: Add Marcin Juszkiewicz to sbsa-ref reviewer list
31
* docs: Convert u2f.txt to rST
23
32
24
----------------------------------------------------------------
33
----------------------------------------------------------------
25
Alex Zuepke (1):
34
Alex Bennée (1):
26
target/arm: read access to performance counters from EL0
35
target/arm: add RAZ/WI handling for DBGDTR[TX|RX]
27
36
28
Richard Henderson (22):
37
Cornelia Huck (1):
29
target/arm: Enable SCTLR_EL1.BT0 for aarch64-linux-user
38
arm/kvm: add support for MTE
30
target/arm: Split out cpregs.h
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
39
52
target/arm/cpregs.h | 453 ++++++++++++++++++++++++++++++++++++++
40
Marcin Juszkiewicz (3):
53
target/arm/cpu.h | 393 +++------------------------------
41
sbsa-ref: switch default cpu core to Neoverse-N1
54
hw/arm/pxa2xx.c | 2 +-
42
Maintainers: add myself as reviewer for sbsa-ref
55
hw/arm/pxa2xx_pic.c | 2 +-
43
sbsa-ref: use Bochs graphics card instead of VGA
56
hw/intc/arm_gicv3_cpuif.c | 6 +-
44
57
hw/intc/arm_gicv3_kvm.c | 3 +-
45
Peter Maydell (14):
58
target/arm/cpu.c | 25 +--
46
target/arm: Create decodetree skeleton for A64
59
target/arm/cpu64.c | 2 +-
47
target/arm: Pull calls to disas_sve() and disas_sme() out of legacy decoder
60
target/arm/cpu_tcg.c | 5 +-
48
target/arm: Convert Extract instructions to decodetree
61
target/arm/gdbstub.c | 5 +-
49
target/arm: Convert unconditional branch immediate to decodetree
62
target/arm/helper.c | 358 +++++++++++++-----------------
50
target/arm: Convert CBZ, CBNZ to decodetree
63
target/arm/hvf/hvf.c | 2 +-
51
target/arm: Convert TBZ, TBNZ to decodetree
64
target/arm/kvm-stub.c | 4 +-
52
target/arm: Convert conditional branch insns to decodetree
65
target/arm/kvm.c | 4 +-
53
target/arm: Convert BR, BLR, RET to decodetree
66
target/arm/machine.c | 4 +-
54
target/arm: Convert BRA[AB]Z, BLR[AB]Z, RETA[AB] to decodetree
67
target/arm/op_helper.c | 57 ++---
55
target/arm: Convert BRAA, BRAB, BLRAA, BLRAB to decodetree
68
target/arm/translate-a64.c | 14 +-
56
target/arm: Convert ERET, ERETAA, ERETAB to decodetree
69
target/arm/translate-neon.c | 2 +-
57
target/arm: Saturate L2CTLR_EL1 core count field rather than overflowing
70
target/arm/translate.c | 13 +-
58
hw/arm/vexpress: Avoid trivial memory leak of 'flashalias'
71
tests/tcg/aarch64/bti-3.c | 42 ++++
59
docs: Convert u2f.txt to rST
72
tests/tcg/aarch64/Makefile.target | 6 +-
60
73
21 files changed, 738 insertions(+), 664 deletions(-)
61
Richard Henderson (10):
74
create mode 100644 target/arm/cpregs.h
62
target/arm: Fix vd == vm overlap in sve_ldff1_z
75
create mode 100644 tests/tcg/aarch64/bti-3.c
63
target/arm: Split out disas_a64_legacy
64
target/arm: Convert PC-rel addressing to decodetree
65
target/arm: Split gen_add_CC and gen_sub_CC
66
target/arm: Convert Add/subtract (immediate) to decodetree
67
target/arm: Convert Add/subtract (immediate with tags) to decodetree
68
target/arm: Replace bitmask64 with MAKE_64BIT_MASK
69
target/arm: Convert Logical (immediate) to decodetree
70
target/arm: Convert Move wide (immediate) to decodetree
71
target/arm: Convert Bitfield to decodetree
72
73
MAINTAINERS | 1 +
74
docs/system/device-emulation.rst | 1 +
75
docs/system/devices/usb-u2f.rst | 93 +++
76
docs/system/devices/usb.rst | 2 +-
77
docs/u2f.txt | 110 ----
78
target/arm/cpu.h | 4 +
79
target/arm/kvm_arm.h | 19 +
80
target/arm/tcg/translate.h | 5 +
81
target/arm/tcg/a64.decode | 152 +++++
82
hw/arm/sbsa-ref.c | 4 +-
83
hw/arm/vexpress.c | 40 +-
84
hw/arm/virt.c | 73 ++-
85
target/arm/cortex-regs.c | 11 +-
86
target/arm/cpu.c | 9 +-
87
target/arm/debug_helper.c | 11 +-
88
target/arm/kvm.c | 35 +
89
target/arm/kvm64.c | 5 +
90
target/arm/tcg/sve_helper.c | 6 +
91
target/arm/tcg/translate-a64.c | 1321 ++++++++++++++++----------------------
92
target/arm/tcg/meson.build | 1 +
93
20 files changed, 979 insertions(+), 924 deletions(-)
94
create mode 100644 docs/system/devices/usb-u2f.rst
95
delete mode 100644 docs/u2f.txt
96
create mode 100644 target/arm/tcg/a64.decode
97
diff view generated by jsdifflib
1
From: Alex Zuepke <alex.zuepke@tum.de>
1
From: Marcin Juszkiewicz <marcin.juszkiewicz@linaro.org>
2
2
3
The ARMv8 manual defines that PMUSERENR_EL0.ER enables read-access
3
The world outside moves to newer and newer cpu cores. Let move SBSA
4
to both PMXEVCNTR_EL0 and PMEVCNTR<n>_EL0 registers, however,
4
Reference Platform to something newer as well.
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: Marcin Juszkiewicz <marcin.juszkiewicz@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Leif Lindholm <quic_llindhol@quicinc.com>
9
Message-id: 20220428132717.84190-1-alex.zuepke@tum.de
8
Message-id: 20230506183417.1360427-1-marcin.juszkiewicz@linaro.org
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
hw/arm/sbsa-ref.c | 2 +-
13
1 file changed, 2 insertions(+), 2 deletions(-)
12
1 file changed, 1 insertion(+), 1 deletion(-)
14
13
15
diff --git a/target/arm/helper.c b/target/arm/helper.c
14
diff --git a/hw/arm/sbsa-ref.c b/hw/arm/sbsa-ref.c
16
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/helper.c
16
--- a/hw/arm/sbsa-ref.c
18
+++ b/target/arm/helper.c
17
+++ b/hw/arm/sbsa-ref.c
19
@@ -XXX,XX +XXX,XX @@ static void define_pmu_regs(ARMCPU *cpu)
18
@@ -XXX,XX +XXX,XX @@ static void sbsa_ref_class_init(ObjectClass *oc, void *data)
20
.crm = 8 | (3 & (i >> 3)), .opc1 = 0, .opc2 = i & 7,
19
21
.access = PL0_RW, .type = ARM_CP_IO | ARM_CP_ALIAS,
20
mc->init = sbsa_ref_init;
22
.readfn = pmevcntr_readfn, .writefn = pmevcntr_writefn,
21
mc->desc = "QEMU 'SBSA Reference' ARM Virtual Machine";
23
- .accessfn = pmreg_access },
22
- mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-a57");
24
+ .accessfn = pmreg_access_xevcntr },
23
+ mc->default_cpu_type = ARM_CPU_TYPE_NAME("neoverse-n1");
25
{ .name = pmevcntr_el0_name, .state = ARM_CP_STATE_AA64,
24
mc->max_cpus = 512;
26
.opc0 = 3, .opc1 = 3, .crn = 14, .crm = 8 | (3 & (i >> 3)),
25
mc->pci_allow_0_address = true;
27
- .opc2 = i & 7, .access = PL0_RW, .accessfn = pmreg_access,
26
mc->minimum_page_bits = 12;
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
--
27
--
33
2.25.1
28
2.34.1
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Create a typedef as well, and use it in ARMCPRegInfo.
3
If vd == vm, copy vm to scratch, so that we can pre-zero
4
This won't be perfect for debugging, but it'll nicely
4
the output and still access the gather indicies.
5
display the most common cases.
6
5
6
Cc: qemu-stable@nongnu.org
7
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1612
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20230504104232.1877774-1-richard.henderson@linaro.org
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
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
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
---
12
target/arm/cpregs.h | 44 +++++++++++++++++++++++---------------------
13
target/arm/tcg/sve_helper.c | 6 ++++++
13
target/arm/helper.c | 2 +-
14
1 file changed, 6 insertions(+)
14
2 files changed, 24 insertions(+), 22 deletions(-)
15
15
16
diff --git a/target/arm/cpregs.h b/target/arm/cpregs.h
16
diff --git a/target/arm/tcg/sve_helper.c b/target/arm/tcg/sve_helper.c
17
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/cpregs.h
18
--- a/target/arm/tcg/sve_helper.c
19
+++ b/target/arm/cpregs.h
19
+++ b/target/arm/tcg/sve_helper.c
20
@@ -XXX,XX +XXX,XX @@ enum {
20
@@ -XXX,XX +XXX,XX @@ void sve_ldff1_z(CPUARMState *env, void *vd, uint64_t *vg, void *vm,
21
* described with these bits, then use a laxer set of restrictions, and
21
intptr_t reg_off;
22
* do the more restrictive/complex check inside a helper function.
22
SVEHostPage info;
23
*/
23
target_ulong addr, in_page;
24
-#define PL3_R 0x80
24
+ ARMVectorReg scratch;
25
-#define PL3_W 0x40
25
26
-#define PL2_R (0x20 | PL3_R)
26
/* Skip to the first true predicate. */
27
-#define PL2_W (0x10 | PL3_W)
27
reg_off = find_next_active(vg, 0, reg_max, esz);
28
-#define PL1_R (0x08 | PL2_R)
28
@@ -XXX,XX +XXX,XX @@ void sve_ldff1_z(CPUARMState *env, void *vd, uint64_t *vg, void *vm,
29
-#define PL1_W (0x04 | PL2_W)
29
return;
30
-#define PL0_R (0x02 | PL1_R)
30
}
31
-#define PL0_W (0x01 | PL1_W)
31
32
+typedef enum {
32
+ /* Protect against overlap between vd and vm. */
33
+ PL3_R = 0x80,
33
+ if (unlikely(vd == vm)) {
34
+ PL3_W = 0x40,
34
+ vm = memcpy(&scratch, vm, reg_max);
35
+ PL2_R = 0x20 | PL3_R,
35
+ }
36
+ PL2_W = 0x10 | PL3_W,
36
+
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
/*
37
/*
83
diff --git a/target/arm/helper.c b/target/arm/helper.c
38
* Probe the first element, allowing faults.
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
*/
39
*/
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
--
40
--
97
2.25.1
41
2.34.1
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Marcin Juszkiewicz <marcin.juszkiewicz@linaro.org>
2
2
3
Rearrange the values of the enumerators of CPAccessResult
3
At Linaro I work on sbsa-ref, know direction it goes.
4
so that we may directly extract the target el. For the two
5
special cases in access_check_cp_reg, use CPAccessResult.
6
4
7
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
5
May not get code details each time.
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Marcin Juszkiewicz <marcin.juszkiewicz@linaro.org>
10
Message-id: 20220501055028.646596-3-richard.henderson@linaro.org
8
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
9
Message-id: 20230515143753.365591-1-marcin.juszkiewicz@linaro.org
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
11
---
13
target/arm/cpregs.h | 26 ++++++++++++--------
12
MAINTAINERS | 1 +
14
target/arm/op_helper.c | 56 +++++++++++++++++++++---------------------
13
1 file changed, 1 insertion(+)
15
2 files changed, 44 insertions(+), 38 deletions(-)
16
14
17
diff --git a/target/arm/cpregs.h b/target/arm/cpregs.h
15
diff --git a/MAINTAINERS b/MAINTAINERS
18
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/cpregs.h
17
--- a/MAINTAINERS
20
+++ b/target/arm/cpregs.h
18
+++ b/MAINTAINERS
21
@@ -XXX,XX +XXX,XX @@ static inline bool cptype_valid(int cptype)
19
@@ -XXX,XX +XXX,XX @@ SBSA-REF
22
typedef enum CPAccessResult {
20
M: Radoslaw Biernacki <rad@semihalf.com>
23
/* Access is permitted */
21
M: Peter Maydell <peter.maydell@linaro.org>
24
CP_ACCESS_OK = 0,
22
R: Leif Lindholm <quic_llindhol@quicinc.com>
25
+
23
+R: Marcin Juszkiewicz <marcin.juszkiewicz@linaro.org>
26
+ /*
24
L: qemu-arm@nongnu.org
27
+ * Combined with one of the following, the low 2 bits indicate the
25
S: Maintained
28
+ * target exception level. If 0, the exception is taken to the usual
26
F: hw/arm/sbsa-ref.c
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
{
71
const ARMCPRegInfo *ri = rip;
72
+ CPAccessResult res = CP_ACCESS_OK;
73
int target_el;
74
75
if (arm_feature(env, ARM_FEATURE_XSCALE) && ri->cp < 14
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
}
156
157
--
27
--
158
2.25.1
28
2.34.1
159
29
160
30
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Cornelia Huck <cohuck@redhat.com>
2
2
3
Instead of defining ARM_CP_FLAG_MASK to remove flags,
3
Extend the 'mte' property for the virt machine to cover KVM as
4
define ARM_CP_SPECIAL_MASK to isolate special cases.
4
well. For KVM, we don't allocate tag memory, but instead enable the
5
Sort the specials to the low bits. Use an enum.
5
capability.
6
6
7
Split the large comment block so as to document each
7
If MTE has been enabled, we need to disable migration, as we do not
8
value separately.
8
yet have a way to migrate the tags as well. Therefore, MTE will stay
9
9
off with KVM unless requested explicitly.
10
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
11
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
Message-id: 20220501055028.646596-6-richard.henderson@linaro.org
13
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
14
Message-id: 20230428095533.21747-2-cohuck@redhat.com
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
16
---
15
target/arm/cpregs.h | 130 +++++++++++++++++++++++--------------
17
target/arm/cpu.h | 4 +++
16
target/arm/cpu.c | 4 +-
18
target/arm/kvm_arm.h | 19 ++++++++++++
17
target/arm/helper.c | 4 +-
19
hw/arm/virt.c | 73 +++++++++++++++++++++++++-------------------
18
target/arm/translate-a64.c | 6 +-
20
target/arm/cpu.c | 9 +++---
19
target/arm/translate.c | 6 +-
21
target/arm/kvm.c | 35 +++++++++++++++++++++
20
5 files changed, 92 insertions(+), 58 deletions(-)
22
target/arm/kvm64.c | 5 +++
21
23
6 files changed, 109 insertions(+), 36 deletions(-)
22
diff --git a/target/arm/cpregs.h b/target/arm/cpregs.h
24
23
index XXXXXXX..XXXXXXX 100644
25
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
24
--- a/target/arm/cpregs.h
26
index XXXXXXX..XXXXXXX 100644
25
+++ b/target/arm/cpregs.h
27
--- a/target/arm/cpu.h
26
@@ -XXX,XX +XXX,XX @@
28
+++ b/target/arm/cpu.h
27
#define TARGET_ARM_CPREGS_H
29
@@ -XXX,XX +XXX,XX @@ struct ArchCPU {
30
*/
31
uint32_t psci_conduit;
32
33
+ /* CPU has Memory Tag Extension */
34
+ bool has_mte;
35
+
36
/* For v8M, initial value of the Secure VTOR */
37
uint32_t init_svtor;
38
/* For v8M, initial value of the Non-secure VTOR */
39
@@ -XXX,XX +XXX,XX @@ struct ArchCPU {
40
bool prop_pauth;
41
bool prop_pauth_impdef;
42
bool prop_lpa2;
43
+ OnOffAuto prop_mte;
44
45
/* DCZ blocksize, in log_2(words), ie low 4 bits of DCZID_EL0 */
46
uint32_t dcz_blocksize;
47
diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h
48
index XXXXXXX..XXXXXXX 100644
49
--- a/target/arm/kvm_arm.h
50
+++ b/target/arm/kvm_arm.h
51
@@ -XXX,XX +XXX,XX @@ bool kvm_arm_pmu_supported(void);
52
*/
53
bool kvm_arm_sve_supported(void);
54
55
+/**
56
+ * kvm_arm_mte_supported:
57
+ *
58
+ * Returns: true if KVM can enable MTE, and false otherwise.
59
+ */
60
+bool kvm_arm_mte_supported(void);
61
+
62
/**
63
* kvm_arm_get_max_vm_ipa_size:
64
* @ms: Machine state handle
65
@@ -XXX,XX +XXX,XX @@ void kvm_arm_pvtime_init(CPUState *cs, uint64_t ipa);
66
67
int kvm_arm_set_irq(int cpu, int irqtype, int irq, int level);
68
69
+void kvm_arm_enable_mte(Object *cpuobj, Error **errp);
70
+
71
#else
28
72
29
/*
73
/*
30
- * ARMCPRegInfo type field bits. If the SPECIAL bit is set this is a
74
@@ -XXX,XX +XXX,XX @@ static inline bool kvm_arm_steal_time_supported(void)
31
- * special-behaviour cp reg and bits [11..8] indicate what behaviour
75
return false;
32
- * it has. Otherwise it is a simple cp reg, where CONST indicates that
76
}
33
- * TCG can assume the value to be constant (ie load at translate time)
77
34
- * and 64BIT indicates a 64 bit wide coprocessor register. SUPPRESS_TB_END
78
+static inline bool kvm_arm_mte_supported(void)
35
- * indicates that the TB should not be ended after a write to this register
79
+{
36
- * (the default is that the TB ends after cp writes). OVERRIDE permits
80
+ return false;
37
- * a register definition to override a previous definition for the
81
+}
38
- * same (cp, is64, crn, crm, opc1, opc2) tuple: either the new or the
82
+
39
- * old must have the OVERRIDE bit set.
83
/*
40
- * ALIAS indicates that this register is an alias view of some underlying
84
* These functions should never actually be called without KVM support.
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
*/
85
*/
59
-#define ARM_CP_SPECIAL 0x0001
86
@@ -XXX,XX +XXX,XX @@ static inline uint32_t kvm_arm_sve_get_vls(CPUState *cs)
60
-#define ARM_CP_CONST 0x0002
87
g_assert_not_reached();
61
-#define ARM_CP_64BIT 0x0004
88
}
62
-#define ARM_CP_SUPPRESS_TB_END 0x0008
89
63
-#define ARM_CP_OVERRIDE 0x0010
90
+static inline void kvm_arm_enable_mte(Object *cpuobj, Error **errp)
64
-#define ARM_CP_ALIAS 0x0020
91
+{
65
-#define ARM_CP_IO 0x0040
92
+ g_assert_not_reached();
66
-#define ARM_CP_NO_RAW 0x0080
93
+}
67
-#define ARM_CP_NOP (ARM_CP_SPECIAL | 0x0100)
94
+
68
-#define ARM_CP_WFI (ARM_CP_SPECIAL | 0x0200)
95
#endif
69
-#define ARM_CP_NZCV (ARM_CP_SPECIAL | 0x0300)
96
70
-#define ARM_CP_CURRENTEL (ARM_CP_SPECIAL | 0x0400)
97
static inline const char *gic_class_name(void)
71
-#define ARM_CP_DC_ZVA (ARM_CP_SPECIAL | 0x0500)
98
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
72
-#define ARM_CP_DC_GVA (ARM_CP_SPECIAL | 0x0600)
99
index XXXXXXX..XXXXXXX 100644
73
-#define ARM_CP_DC_GZVA (ARM_CP_SPECIAL | 0x0700)
100
--- a/hw/arm/virt.c
74
-#define ARM_LAST_SPECIAL ARM_CP_DC_GZVA
101
+++ b/hw/arm/virt.c
75
-#define ARM_CP_FPU 0x1000
102
@@ -XXX,XX +XXX,XX @@ static void machvirt_init(MachineState *machine)
76
-#define ARM_CP_SVE 0x2000
103
exit(1);
77
-#define ARM_CP_NO_GDB 0x4000
104
}
78
-#define ARM_CP_RAISES_EXC 0x8000
105
79
-#define ARM_CP_NEWEL 0x10000
106
- if (vms->mte && (kvm_enabled() || hvf_enabled())) {
80
-/* Mask of only the flag bits in a type field */
107
+ if (vms->mte && hvf_enabled()) {
81
-#define ARM_CP_FLAG_MASK 0x1f0ff
108
error_report("mach-virt: %s does not support providing "
82
+enum {
109
"MTE to the guest CPU",
83
+ /*
110
current_accel_name());
84
+ * Register must be handled specially during translation.
111
@@ -XXX,XX +XXX,XX @@ static void machvirt_init(MachineState *machine)
85
+ * The method is one of the values below:
112
}
86
+ */
113
87
+ ARM_CP_SPECIAL_MASK = 0x000f,
114
if (vms->mte) {
88
+ /* Special: no change to PE state: writes ignored, reads ignored. */
115
- /* Create the memory region only once, but link to all cpus. */
89
+ ARM_CP_NOP = 0x0001,
116
- if (!tag_sysmem) {
90
+ /* Special: sysreg is WFI, for v5 and v6. */
117
- /*
91
+ ARM_CP_WFI = 0x0002,
118
- * The property exists only if MemTag is supported.
92
+ /* Special: sysreg is NZCV. */
119
- * If it is, we must allocate the ram to back that up.
93
+ ARM_CP_NZCV = 0x0003,
120
- */
94
+ /* Special: sysreg is CURRENTEL. */
121
- if (!object_property_find(cpuobj, "tag-memory")) {
95
+ ARM_CP_CURRENTEL = 0x0004,
122
- error_report("MTE requested, but not supported "
96
+ /* Special: sysreg is DC ZVA or similar. */
123
- "by the guest CPU");
97
+ ARM_CP_DC_ZVA = 0x0005,
124
+ if (tcg_enabled()) {
98
+ ARM_CP_DC_GVA = 0x0006,
125
+ /* Create the memory region only once, but link to all cpus. */
99
+ ARM_CP_DC_GZVA = 0x0007,
126
+ if (!tag_sysmem) {
100
+
127
+ /*
101
+ /* Flag: reads produce resetvalue; writes ignored. */
128
+ * The property exists only if MemTag is supported.
102
+ ARM_CP_CONST = 1 << 4,
129
+ * If it is, we must allocate the ram to back that up.
103
+ /* Flag: For ARM_CP_STATE_AA32, sysreg is 64-bit. */
130
+ */
104
+ ARM_CP_64BIT = 1 << 5,
131
+ if (!object_property_find(cpuobj, "tag-memory")) {
105
+ /*
132
+ error_report("MTE requested, but not supported "
106
+ * Flag: TB should not be ended after a write to this register
133
+ "by the guest CPU");
107
+ * (the default is that the TB ends after cp writes).
134
+ exit(1);
108
+ */
135
+ }
109
+ ARM_CP_SUPPRESS_TB_END = 1 << 6,
136
+
110
+ /*
137
+ tag_sysmem = g_new(MemoryRegion, 1);
111
+ * Flag: Permit a register definition to override a previous definition
138
+ memory_region_init(tag_sysmem, OBJECT(machine),
112
+ * for the same (cp, is64, crn, crm, opc1, opc2) tuple: either the new
139
+ "tag-memory", UINT64_MAX / 32);
113
+ * or the old must have the ARM_CP_OVERRIDE bit set.
140
+
114
+ */
141
+ if (vms->secure) {
115
+ ARM_CP_OVERRIDE = 1 << 7,
142
+ secure_tag_sysmem = g_new(MemoryRegion, 1);
116
+ /*
143
+ memory_region_init(secure_tag_sysmem, OBJECT(machine),
117
+ * Flag: Register is an alias view of some underlying state which is also
144
+ "secure-tag-memory",
118
+ * visible via another register, and that the other register is handling
145
+ UINT64_MAX / 32);
119
+ * migration and reset; registers marked ARM_CP_ALIAS will not be migrated
146
+
120
+ * but may have their state set by syncing of register state from KVM.
147
+ /* As with ram, secure-tag takes precedence over tag. */
121
+ */
148
+ memory_region_add_subregion_overlap(secure_tag_sysmem,
122
+ ARM_CP_ALIAS = 1 << 8,
149
+ 0, tag_sysmem, -1);
123
+ /*
150
+ }
124
+ * Flag: Register does I/O and therefore its accesses need to be marked
151
+ }
125
+ * with gen_io_start() and also end the TB. In particular, registers which
152
+
126
+ * implement clocks or timers require this.
153
+ object_property_set_link(cpuobj, "tag-memory",
127
+ */
154
+ OBJECT(tag_sysmem), &error_abort);
128
+ ARM_CP_IO = 1 << 9,
155
+ if (vms->secure) {
129
+ /*
156
+ object_property_set_link(cpuobj, "secure-tag-memory",
130
+ * Flag: Register has no underlying state and does not support raw access
157
+ OBJECT(secure_tag_sysmem),
131
+ * for state saving/loading; it will not be used for either migration or
158
+ &error_abort);
132
+ * KVM state synchronization. Typically this is for "registers" which are
159
+ }
133
+ * actually used as instructions for cache maintenance and so on.
160
+ } else if (kvm_enabled()) {
134
+ */
161
+ if (!kvm_arm_mte_supported()) {
135
+ ARM_CP_NO_RAW = 1 << 10,
162
+ error_report("MTE requested, but not supported by KVM");
136
+ /*
163
exit(1);
137
+ * Flag: The read or write hook might raise an exception; the generated
164
}
138
+ * code will synchronize the CPU state before calling the hook so that it
165
-
139
+ * is safe for the hook to call raise_exception().
166
- tag_sysmem = g_new(MemoryRegion, 1);
140
+ */
167
- memory_region_init(tag_sysmem, OBJECT(machine),
141
+ ARM_CP_RAISES_EXC = 1 << 11,
168
- "tag-memory", UINT64_MAX / 32);
142
+ /*
169
-
143
+ * Flag: Writes to the sysreg might change the exception level - typically
170
- if (vms->secure) {
144
+ * on older ARM chips. For those cases we need to re-read the new el when
171
- secure_tag_sysmem = g_new(MemoryRegion, 1);
145
+ * recomputing the translation flags.
172
- memory_region_init(secure_tag_sysmem, OBJECT(machine),
146
+ */
173
- "secure-tag-memory", UINT64_MAX / 32);
147
+ ARM_CP_NEWEL = 1 << 12,
174
-
148
+ /*
175
- /* As with ram, secure-tag takes precedence over tag. */
149
+ * Flag: Access check for this sysreg is identical to accessing FPU state
176
- memory_region_add_subregion_overlap(secure_tag_sysmem, 0,
150
+ * from an instruction: use translation fp_access_check().
177
- tag_sysmem, -1);
151
+ */
178
- }
152
+ ARM_CP_FPU = 1 << 13,
179
- }
153
+ /*
180
-
154
+ * Flag: Access check for this sysreg is identical to accessing SVE state
181
- object_property_set_link(cpuobj, "tag-memory", OBJECT(tag_sysmem),
155
+ * from an instruction: use translation sve_access_check().
182
- &error_abort);
156
+ */
183
- if (vms->secure) {
157
+ ARM_CP_SVE = 1 << 14,
184
- object_property_set_link(cpuobj, "secure-tag-memory",
158
+ /* Flag: Do not expose in gdb sysreg xml. */
185
- OBJECT(secure_tag_sysmem),
159
+ ARM_CP_NO_GDB = 1 << 15,
186
- &error_abort);
160
+};
187
+ kvm_arm_enable_mte(cpuobj, &error_abort);
161
188
}
162
/*
189
}
163
* Valid values for ARMCPRegInfo state field, indicating which of
190
164
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
191
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
165
index XXXXXXX..XXXXXXX 100644
192
index XXXXXXX..XXXXXXX 100644
166
--- a/target/arm/cpu.c
193
--- a/target/arm/cpu.c
167
+++ b/target/arm/cpu.c
194
+++ b/target/arm/cpu.c
168
@@ -XXX,XX +XXX,XX @@ static void cp_reg_reset(gpointer key, gpointer value, gpointer opaque)
195
@@ -XXX,XX +XXX,XX @@ void arm_cpu_post_init(Object *obj)
169
ARMCPRegInfo *ri = value;
196
qdev_prop_allow_set_link_before_realize,
170
ARMCPU *cpu = opaque;
197
OBJ_PROP_LINK_STRONG);
171
198
}
172
- if (ri->type & (ARM_CP_SPECIAL | ARM_CP_ALIAS)) {
199
+ cpu->has_mte = true;
173
+ if (ri->type & (ARM_CP_SPECIAL_MASK | ARM_CP_ALIAS)) {
174
return;
175
}
200
}
176
201
#endif
177
@@ -XXX,XX +XXX,XX @@ static void cp_reg_check_reset(gpointer key, gpointer value, gpointer opaque)
202
}
178
ARMCPU *cpu = opaque;
203
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
179
uint64_t oldvalue, newvalue;
204
}
180
205
if (cpu->tag_memory) {
181
- if (ri->type & (ARM_CP_SPECIAL | ARM_CP_ALIAS | ARM_CP_NO_RAW)) {
206
error_setg(errp,
182
+ if (ri->type & (ARM_CP_SPECIAL_MASK | ARM_CP_ALIAS | ARM_CP_NO_RAW)) {
207
- "Cannot enable %s when guest CPUs has MTE enabled",
183
return;
208
+ "Cannot enable %s when guest CPUs has tag memory enabled",
209
current_accel_name());
210
return;
211
}
212
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
184
}
213
}
185
214
186
diff --git a/target/arm/helper.c b/target/arm/helper.c
215
#ifndef CONFIG_USER_ONLY
187
index XXXXXXX..XXXXXXX 100644
216
- if (cpu->tag_memory == NULL && cpu_isar_feature(aa64_mte, cpu)) {
188
--- a/target/arm/helper.c
217
+ if (!cpu->has_mte && cpu_isar_feature(aa64_mte, cpu)) {
189
+++ b/target/arm/helper.c
218
/*
190
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
219
- * Disable the MTE feature bits if we do not have tag-memory
191
* multiple times. Special registers (ie NOP/WFI) are
220
- * provided by the machine.
192
* never migratable and not even raw-accessible.
221
+ * Disable the MTE feature bits if we do not have the feature
193
*/
222
+ * setup by the machine.
194
- if ((r->type & ARM_CP_SPECIAL)) {
223
*/
195
+ if (r->type & ARM_CP_SPECIAL_MASK) {
224
cpu->isar.id_aa64pfr1 =
196
r2->type |= ARM_CP_NO_RAW;
225
FIELD_DP64(cpu->isar.id_aa64pfr1, ID_AA64PFR1, MTE, 0);
197
}
226
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
198
if (((r->crm == CP_ANY) && crm != 0) ||
227
index XXXXXXX..XXXXXXX 100644
199
@@ -XXX,XX +XXX,XX @@ void define_one_arm_cp_reg_with_opaque(ARMCPU *cpu,
228
--- a/target/arm/kvm.c
200
/* Check that the register definition has enough info to handle
229
+++ b/target/arm/kvm.c
201
* reads and writes if they are permitted.
230
@@ -XXX,XX +XXX,XX @@
202
*/
231
#include "hw/boards.h"
203
- if (!(r->type & (ARM_CP_SPECIAL|ARM_CP_CONST))) {
232
#include "hw/irq.h"
204
+ if (!(r->type & (ARM_CP_SPECIAL_MASK | ARM_CP_CONST))) {
233
#include "qemu/log.h"
205
if (r->access & PL3_R) {
234
+#include "migration/blocker.h"
206
assert((r->fieldoffset ||
235
207
(r->bank_fieldoffsets[0] && r->bank_fieldoffsets[1])) ||
236
const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
208
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
237
KVM_CAP_LAST_INFO
209
index XXXXXXX..XXXXXXX 100644
238
@@ -XXX,XX +XXX,XX @@ bool kvm_arch_cpu_check_are_resettable(void)
210
--- a/target/arm/translate-a64.c
239
void kvm_arch_accel_class_init(ObjectClass *oc)
211
+++ b/target/arm/translate-a64.c
240
{
212
@@ -XXX,XX +XXX,XX @@ static void handle_sys(DisasContext *s, uint32_t insn, bool isread,
241
}
213
}
242
+
214
243
+void kvm_arm_enable_mte(Object *cpuobj, Error **errp)
215
/* Handle special cases first */
244
+{
216
- switch (ri->type & ~(ARM_CP_FLAG_MASK & ~ARM_CP_SPECIAL)) {
245
+ static bool tried_to_enable;
217
+ switch (ri->type & ARM_CP_SPECIAL_MASK) {
246
+ static bool succeeded_to_enable;
218
+ case 0:
247
+ Error *mte_migration_blocker = NULL;
219
+ break;
248
+ int ret;
220
case ARM_CP_NOP:
249
+
221
return;
250
+ if (!tried_to_enable) {
222
case ARM_CP_NZCV:
251
+ /*
223
@@ -XXX,XX +XXX,XX @@ static void handle_sys(DisasContext *s, uint32_t insn, bool isread,
252
+ * MTE on KVM is enabled on a per-VM basis (and retrying doesn't make
224
}
253
+ * sense), and we only want a single migration blocker as well.
225
return;
254
+ */
226
default:
255
+ tried_to_enable = true;
227
- break;
256
+
228
+ g_assert_not_reached();
257
+ ret = kvm_vm_enable_cap(kvm_state, KVM_CAP_ARM_MTE, 0);
229
}
258
+ if (ret) {
230
if ((ri->type & ARM_CP_FPU) && !fp_access_check(s)) {
259
+ error_setg_errno(errp, -ret, "Failed to enable KVM_CAP_ARM_MTE");
231
return;
260
+ return;
232
diff --git a/target/arm/translate.c b/target/arm/translate.c
261
+ }
233
index XXXXXXX..XXXXXXX 100644
262
+
234
--- a/target/arm/translate.c
263
+ /* TODO: add proper migration support with MTE enabled */
235
+++ b/target/arm/translate.c
264
+ error_setg(&mte_migration_blocker,
236
@@ -XXX,XX +XXX,XX @@ static void do_coproc_insn(DisasContext *s, int cpnum, int is64,
265
+ "Live migration disabled due to MTE enabled");
237
}
266
+ if (migrate_add_blocker(mte_migration_blocker, errp)) {
238
267
+ error_free(mte_migration_blocker);
239
/* Handle special cases first */
268
+ return;
240
- switch (ri->type & ~(ARM_CP_FLAG_MASK & ~ARM_CP_SPECIAL)) {
269
+ }
241
+ switch (ri->type & ARM_CP_SPECIAL_MASK) {
270
+ succeeded_to_enable = true;
242
+ case 0:
271
+ }
243
+ break;
272
+ if (succeeded_to_enable) {
244
case ARM_CP_NOP:
273
+ object_property_set_bool(cpuobj, "has_mte", true, NULL);
245
return;
274
+ }
246
case ARM_CP_WFI:
275
+}
247
@@ -XXX,XX +XXX,XX @@ static void do_coproc_insn(DisasContext *s, int cpnum, int is64,
276
diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
248
s->base.is_jmp = DISAS_WFI;
277
index XXXXXXX..XXXXXXX 100644
249
return;
278
--- a/target/arm/kvm64.c
250
default:
279
+++ b/target/arm/kvm64.c
251
- break;
280
@@ -XXX,XX +XXX,XX @@ bool kvm_arm_steal_time_supported(void)
252
+ g_assert_not_reached();
281
return kvm_check_extension(kvm_state, KVM_CAP_STEAL_TIME);
253
}
282
}
254
283
255
if ((tb_cflags(s->base.tb) & CF_USE_ICOUNT) && (ri->type & ARM_CP_IO)) {
284
+bool kvm_arm_mte_supported(void)
285
+{
286
+ return kvm_check_extension(kvm_state, KVM_CAP_ARM_MTE);
287
+}
288
+
289
QEMU_BUILD_BUG_ON(KVM_ARM64_SVE_VQ_MIN != 1);
290
291
uint32_t kvm_arm_sve_get_vls(CPUState *cs)
256
--
292
--
257
2.25.1
293
2.34.1
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
The commit b3aa2f2128 (target/arm: provide stubs for more external
4
add_cpreg_to_hashtable and define_one_arm_cp_reg_with_opaque.
4
debug registers) was added to handle HyperV's unconditional usage of
5
Debug Communications Channel. It turns out that Linux will similarly
6
break if you enable CONFIG_HVC_DCC "ARM JTAG DCC console".
5
7
6
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
8
Extend the registers we RAZ/WI set to avoid this.
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
Cc: Anders Roxell <anders.roxell@linaro.org>
9
Message-id: 20220501055028.646596-9-richard.henderson@linaro.org
11
Cc: Evgeny Iakovlev <eiakovlev@linux.microsoft.com>
12
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
13
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
14
Message-id: 20230516104420.407912-1-alex.bennee@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
16
---
12
target/arm/cpregs.h | 6 +++---
17
target/arm/debug_helper.c | 11 +++++++++--
13
target/arm/helper.c | 6 ++++--
18
1 file changed, 9 insertions(+), 2 deletions(-)
14
2 files changed, 7 insertions(+), 5 deletions(-)
15
19
16
diff --git a/target/arm/cpregs.h b/target/arm/cpregs.h
20
diff --git a/target/arm/debug_helper.c b/target/arm/debug_helper.c
17
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/cpregs.h
22
--- a/target/arm/debug_helper.c
19
+++ b/target/arm/cpregs.h
23
+++ b/target/arm/debug_helper.c
20
@@ -XXX,XX +XXX,XX @@ enum {
24
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo debug_cp_reginfo[] = {
21
* Note that we rely on the values of these enums as we iterate through
25
.access = PL0_R, .accessfn = access_tdcc,
22
* the various states in some places.
26
.type = ARM_CP_CONST, .resetvalue = 0 },
23
*/
27
/*
24
-enum {
28
- * OSDTRRX_EL1/OSDTRTX_EL1 are used for save and restore of DBGDTRRX_EL0.
25
+typedef enum {
29
- * It is a component of the Debug Communications Channel, which is not implemented.
26
ARM_CP_STATE_AA32 = 0,
30
+ * These registers belong to the Debug Communications Channel,
27
ARM_CP_STATE_AA64 = 1,
31
+ * which is not implemented. However we implement RAZ/WI behaviour
28
ARM_CP_STATE_BOTH = 2,
32
+ * with trapping to prevent spurious SIGILLs if the guest OS does
29
-};
33
+ * access them as the support cannot be probed for.
30
+} CPState;
31
32
/*
33
* ARM CP register secure state flags. These flags identify security state
34
@@ -XXX,XX +XXX,XX @@ struct ARMCPRegInfo {
35
uint8_t opc1;
36
uint8_t opc2;
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
*/
34
*/
60
- int crm, opc1, opc2, state;
35
{ .name = "OSDTRRX_EL1", .state = ARM_CP_STATE_BOTH, .cp = 14,
61
+ int crm, opc1, opc2;
36
.opc0 = 2, .opc1 = 0, .crn = 0, .crm = 0, .opc2 = 2,
62
int crmmin = (r->crm == CP_ANY) ? 0 : r->crm;
37
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo debug_cp_reginfo[] = {
63
int crmmax = (r->crm == CP_ANY) ? 15 : r->crm;
38
.opc0 = 2, .opc1 = 0, .crn = 0, .crm = 3, .opc2 = 2,
64
int opc1min = (r->opc1 == CP_ANY) ? 0 : r->opc1;
39
.access = PL1_RW, .accessfn = access_tdcc,
65
int opc1max = (r->opc1 == CP_ANY) ? 7 : r->opc1;
40
.type = ARM_CP_CONST, .resetvalue = 0 },
66
int opc2min = (r->opc2 == CP_ANY) ? 0 : r->opc2;
41
+ /* DBGDTRTX_EL0/DBGDTRRX_EL0 depend on direction */
67
int opc2max = (r->opc2 == CP_ANY) ? 7 : r->opc2;
42
+ { .name = "DBGDTR_EL0", .state = ARM_CP_STATE_BOTH, .cp = 14,
68
+ CPState state;
43
+ .opc0 = 2, .opc1 = 3, .crn = 0, .crm = 5, .opc2 = 0,
69
+
44
+ .access = PL0_RW, .accessfn = access_tdcc,
70
/* 64 bit registers have only CRm and Opc1 fields */
45
+ .type = ARM_CP_CONST, .resetvalue = 0 },
71
assert(!((r->type & ARM_CP_64BIT) && (r->opc2 || r->crn)));
46
/*
72
/* op0 only exists in the AArch64 encodings */
47
* OSECCR_EL1 provides a mechanism for an operating system
48
* to access the contents of EDECCR. EDECCR is not implemented though,
73
--
49
--
74
2.25.1
50
2.34.1
75
51
76
52
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Marcin Juszkiewicz <marcin.juszkiewicz@linaro.org>
2
2
3
Since e03b56863d2bc, our host endian indicator is unconditionally
3
Bochs card is normal PCI Express card so it fits better in system with
4
set, which means that we can use a normal C condition.
4
PCI Express bus. VGA is simple legacy PCI card.
5
5
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Marcin Juszkiewicz <marcin.juszkiewicz@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Leif Lindholm <quic_llindhol@quicinc.com>
8
Message-id: 20220501055028.646596-20-richard.henderson@linaro.org
8
Message-id: 20230505120936.1097060-1-marcin.juszkiewicz@linaro.org
9
[PMM: quote correct git hash in commit message]
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 | 9 +++------
11
hw/arm/sbsa-ref.c | 2 +-
13
1 file changed, 3 insertions(+), 6 deletions(-)
12
1 file changed, 1 insertion(+), 1 deletion(-)
14
13
15
diff --git a/target/arm/helper.c b/target/arm/helper.c
14
diff --git a/hw/arm/sbsa-ref.c b/hw/arm/sbsa-ref.c
16
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/helper.c
16
--- a/hw/arm/sbsa-ref.c
18
+++ b/target/arm/helper.c
17
+++ b/hw/arm/sbsa-ref.c
19
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
18
@@ -XXX,XX +XXX,XX @@ static void create_pcie(SBSAMachineState *sms)
20
r2->type |= ARM_CP_ALIAS;
21
}
22
23
- if (r->state == ARM_CP_STATE_BOTH) {
24
-#if HOST_BIG_ENDIAN
25
- if (r2->fieldoffset) {
26
- r2->fieldoffset += sizeof(uint32_t);
27
- }
28
-#endif
29
+ if (HOST_BIG_ENDIAN &&
30
+ r->state == ARM_CP_STATE_BOTH && r2->fieldoffset) {
31
+ r2->fieldoffset += sizeof(uint32_t);
32
}
19
}
33
}
20
}
34
21
22
- pci_create_simple(pci->bus, -1, "VGA");
23
+ pci_create_simple(pci->bus, -1, "bochs-display");
24
25
create_smmu(sms, pci->bus);
26
}
35
--
27
--
36
2.25.1
28
2.34.1
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Move the computation of key to the top of the function.
3
Split out all of the decode stuff from aarch64_tr_translate_insn.
4
Hoist the resolution of cp as well, as an input to the
4
Call it disas_a64_legacy to indicate it will be replaced.
5
computation of key.
6
7
This will be required by a subsequent patch.
8
5
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Message-id: 20220501055028.646596-14-richard.henderson@linaro.org
9
Message-id: 20230512144106.3608981-2-peter.maydell@linaro.org
10
[PMM: Rebased]
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
13
---
14
target/arm/helper.c | 49 +++++++++++++++++++++++++--------------------
14
target/arm/tcg/translate-a64.c | 82 ++++++++++++++++++----------------
15
1 file changed, 27 insertions(+), 22 deletions(-)
15
1 file changed, 44 insertions(+), 38 deletions(-)
16
16
17
diff --git a/target/arm/helper.c b/target/arm/helper.c
17
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
18
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/helper.c
19
--- a/target/arm/tcg/translate-a64.c
20
+++ b/target/arm/helper.c
20
+++ b/target/arm/tcg/translate-a64.c
21
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
21
@@ -XXX,XX +XXX,XX @@ static bool btype_destination_ok(uint32_t insn, bool bt, int btype)
22
ARMCPRegInfo *r2;
22
return false;
23
int is64 = (r->type & ARM_CP_64BIT) ? 1 : 0;
23
}
24
int ns = (secstate & ARM_CP_SECSTATE_NS) ? 1 : 0;
24
25
+ int cp = r->cp;
25
+/* C3.1 A64 instruction index by encoding */
26
size_t name_len;
26
+static void disas_a64_legacy(DisasContext *s, uint32_t insn)
27
27
+{
28
+ switch (state) {
28
+ switch (extract32(insn, 25, 4)) {
29
+ case ARM_CP_STATE_AA32:
29
+ case 0x0:
30
+ /* We assume it is a cp15 register if the .cp field is left unset. */
30
+ if (!extract32(insn, 31, 1) || !disas_sme(s, insn)) {
31
+ if (cp == 0 && r->state == ARM_CP_STATE_BOTH) {
31
+ unallocated_encoding(s);
32
+ cp = 15;
33
+ }
32
+ }
34
+ key = ENCODE_CP_REG(cp, is64, ns, r->crn, crm, opc1, opc2);
35
+ break;
33
+ break;
36
+ case ARM_CP_STATE_AA64:
34
+ case 0x1: case 0x3: /* UNALLOCATED */
37
+ /*
35
+ unallocated_encoding(s);
38
+ * To allow abbreviation of ARMCPRegInfo definitions, we treat
36
+ break;
39
+ * cp == 0 as equivalent to the value for "standard guest-visible
37
+ case 0x2:
40
+ * sysreg". STATE_BOTH definitions are also always "standard sysreg"
38
+ if (!disas_sve(s, insn)) {
41
+ * in their AArch64 view (the .cp value may be non-zero for the
39
+ unallocated_encoding(s);
42
+ * benefit of the AArch32 view).
43
+ */
44
+ if (cp == 0 || r->state == ARM_CP_STATE_BOTH) {
45
+ cp = CP_REG_ARM64_SYSREG_CP;
46
+ }
40
+ }
47
+ key = ENCODE_AA64_CP_REG(cp, r->crn, crm, r->opc0, opc1, opc2);
41
+ break;
42
+ case 0x8: case 0x9: /* Data processing - immediate */
43
+ disas_data_proc_imm(s, insn);
44
+ break;
45
+ case 0xa: case 0xb: /* Branch, exception generation and system insns */
46
+ disas_b_exc_sys(s, insn);
47
+ break;
48
+ case 0x4:
49
+ case 0x6:
50
+ case 0xc:
51
+ case 0xe: /* Loads and stores */
52
+ disas_ldst(s, insn);
53
+ break;
54
+ case 0x5:
55
+ case 0xd: /* Data processing - register */
56
+ disas_data_proc_reg(s, insn);
57
+ break;
58
+ case 0x7:
59
+ case 0xf: /* Data processing - SIMD and floating point */
60
+ disas_data_proc_simd_fp(s, insn);
48
+ break;
61
+ break;
49
+ default:
62
+ default:
50
+ g_assert_not_reached();
63
+ assert(FALSE); /* all 15 cases should be handled above */
64
+ break;
51
+ }
65
+ }
66
+}
52
+
67
+
53
/* Combine cpreg and name into one allocation. */
68
static void aarch64_tr_init_disas_context(DisasContextBase *dcbase,
54
name_len = strlen(name) + 1;
69
CPUState *cpu)
55
r2 = g_malloc(sizeof(*r2) + name_len);
70
{
56
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
71
@@ -XXX,XX +XXX,XX @@ static void aarch64_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
57
}
72
disas_sme_fa64(s, insn);
58
59
if (r->state == ARM_CP_STATE_BOTH) {
60
- /* We assume it is a cp15 register if the .cp field is left unset.
61
- */
62
- if (r2->cp == 0) {
63
- r2->cp = 15;
64
- }
65
-
66
#if HOST_BIG_ENDIAN
67
if (r2->fieldoffset) {
68
r2->fieldoffset += sizeof(uint32_t);
69
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
70
#endif
71
}
72
}
73
}
73
- if (state == ARM_CP_STATE_AA64) {
74
74
- /* To allow abbreviation of ARMCPRegInfo
75
- switch (extract32(insn, 25, 4)) {
75
- * definitions, we treat cp == 0 as equivalent to
76
- case 0x0:
76
- * the value for "standard guest-visible sysreg".
77
- if (!extract32(insn, 31, 1) || !disas_sme(s, insn)) {
77
- * STATE_BOTH definitions are also always "standard
78
- unallocated_encoding(s);
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
- }
79
- }
84
- key = ENCODE_AA64_CP_REG(r2->cp, r2->crn, crm,
80
- break;
85
- r2->opc0, opc1, opc2);
81
- case 0x1: case 0x3: /* UNALLOCATED */
86
- } else {
82
- unallocated_encoding(s);
87
- key = ENCODE_CP_REG(r2->cp, is64, ns, r2->crn, crm, opc1, opc2);
83
- break;
84
- case 0x2:
85
- if (!disas_sve(s, insn)) {
86
- unallocated_encoding(s);
87
- }
88
- break;
89
- case 0x8: case 0x9: /* Data processing - immediate */
90
- disas_data_proc_imm(s, insn);
91
- break;
92
- case 0xa: case 0xb: /* Branch, exception generation and system insns */
93
- disas_b_exc_sys(s, insn);
94
- break;
95
- case 0x4:
96
- case 0x6:
97
- case 0xc:
98
- case 0xe: /* Loads and stores */
99
- disas_ldst(s, insn);
100
- break;
101
- case 0x5:
102
- case 0xd: /* Data processing - register */
103
- disas_data_proc_reg(s, insn);
104
- break;
105
- case 0x7:
106
- case 0xf: /* Data processing - SIMD and floating point */
107
- disas_data_proc_simd_fp(s, insn);
108
- break;
109
- default:
110
- assert(FALSE); /* all 15 cases should be handled above */
111
- break;
88
- }
112
- }
89
if (opaque) {
113
+ disas_a64_legacy(s, insn);
90
r2->opaque = opaque;
114
91
}
115
/*
92
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
116
* After execution of most insns, btype is reset to 0.
93
/* Make sure reginfo passed to helpers for wildcarded regs
94
* has the correct crm/opc1/opc2 for this reg, not CP_ANY:
95
*/
96
+ r2->cp = cp;
97
r2->crm = crm;
98
r2->opc1 = opc1;
99
r2->opc2 = opc2;
100
--
117
--
101
2.25.1
118
2.34.1
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
The A64 translator uses a hand-written decoder for everything except
2
SVE or SME. It's fairly well structured, but it's becoming obvious
3
that it's still more painful to add instructions to than the A32
4
translator, because putting a new instruction into the right place in
5
a hand-written decoder is much harder than adding new instruction
6
patterns to a decodetree file.
2
7
3
Move ARMCPRegInfo and all related declarations to a new
8
As the first step in conversion to decodetree, create the skeleton of
4
internal header, out of the public cpu.h.
9
the decodetree decoder; where it does not handle instructions we will
10
fall back to the legacy decoder (which will be for everything at the
11
moment, since there are no patterns in a64.decode).
5
12
6
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
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>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
Message-id: 20230512144106.3608981-3-peter.maydell@linaro.org
11
---
16
---
12
target/arm/cpregs.h | 413 +++++++++++++++++++++++++++++++++++++
17
target/arm/tcg/a64.decode | 20 ++++++++++++++++++++
13
target/arm/cpu.h | 368 ---------------------------------
18
target/arm/tcg/translate-a64.c | 18 +++++++++++-------
14
hw/arm/pxa2xx.c | 1 +
19
target/arm/tcg/meson.build | 1 +
15
hw/arm/pxa2xx_pic.c | 1 +
20
3 files changed, 32 insertions(+), 7 deletions(-)
16
hw/intc/arm_gicv3_cpuif.c | 1 +
21
create mode 100644 target/arm/tcg/a64.decode
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
22
29
diff --git a/target/arm/cpregs.h b/target/arm/cpregs.h
23
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
30
new file mode 100644
24
new file mode 100644
31
index XXXXXXX..XXXXXXX
25
index XXXXXXX..XXXXXXX
32
--- /dev/null
26
--- /dev/null
33
+++ b/target/arm/cpregs.h
27
+++ b/target/arm/tcg/a64.decode
34
@@ -XXX,XX +XXX,XX @@
28
@@ -XXX,XX +XXX,XX @@
29
+# AArch64 A64 allowed instruction decoding
30
+#
31
+# Copyright (c) 2023 Linaro, Ltd
32
+#
33
+# This library is free software; you can redistribute it and/or
34
+# modify it under the terms of the GNU Lesser General Public
35
+# License as published by the Free Software Foundation; either
36
+# version 2.1 of the License, or (at your option) any later version.
37
+#
38
+# This library is distributed in the hope that it will be useful,
39
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
40
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
41
+# Lesser General Public License for more details.
42
+#
43
+# You should have received a copy of the GNU Lesser General Public
44
+# License along with this library; if not, see <http://www.gnu.org/licenses/>.
45
+
46
+#
47
+# This file is processed by scripts/decodetree.py
48
+#
49
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
50
index XXXXXXX..XXXXXXX 100644
51
--- a/target/arm/tcg/translate-a64.c
52
+++ b/target/arm/tcg/translate-a64.c
53
@@ -XXX,XX +XXX,XX @@ enum a64_shift_type {
54
A64_SHIFT_TYPE_ROR = 3
55
};
56
35
+/*
57
+/*
36
+ * QEMU ARM CP Register access and descriptions
58
+ * Include the generated decoders.
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
+ */
59
+ */
54
+
60
+
55
+#ifndef TARGET_ARM_CPREGS_H
61
+#include "decode-sme-fa64.c.inc"
56
+#define TARGET_ARM_CPREGS_H
62
+#include "decode-a64.c.inc"
57
+
63
+
58
+/*
64
/* Table based decoder typedefs - used when the relevant bits for decode
59
+ * ARMCPRegInfo type field bits. If the SPECIAL bit is set this is a
65
* are too awkwardly scattered across the instruction (eg SIMD).
60
+ * special-behaviour cp reg and bits [11..8] indicate what behaviour
66
*/
61
+ * it has. Otherwise it is a simple cp reg, where CONST indicates that
67
@@ -XXX,XX +XXX,XX @@ static void disas_data_proc_simd_fp(DisasContext *s, uint32_t insn)
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
450
--- a/target/arm/cpu.h
451
+++ b/target/arm/cpu.h
452
@@ -XXX,XX +XXX,XX @@ static inline uint64_t cpreg_to_kvm_id(uint32_t cpregid)
453
return kvmid;
454
}
455
456
-/* ARMCPRegInfo type field bits. If the SPECIAL bit is set this is a
457
- * special-behaviour cp reg and bits [11..8] indicate what behaviour
458
- * it has. Otherwise it is a simple cp reg, where CONST indicates that
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
{
597
@@ -XXX,XX +XXX,XX @@ static inline int arm_current_el(CPUARMState *env)
598
}
68
}
599
}
69
}
600
70
601
-typedef struct ARMCPRegInfo ARMCPRegInfo;
71
-/*
72
- * Include the generated SME FA64 decoder.
73
- */
602
-
74
-
603
-typedef enum CPAccessResult {
75
-#include "decode-sme-fa64.c.inc"
604
- /* Access is permitted */
605
- CP_ACCESS_OK = 0,
606
- /* Access fails due to a configurable trap or enable which would
607
- * result in a categorized exception syndrome giving information about
608
- * the failing instruction (ie syndrome category 0x3, 0x4, 0x5, 0x6,
609
- * 0xc or 0x18). The exception is taken to the usual target EL (EL1 or
610
- * PL1 if in EL0, otherwise to the current EL).
611
- */
612
- CP_ACCESS_TRAP = 1,
613
- /* Access fails and results in an exception syndrome 0x0 ("uncategorized").
614
- * Note that this is not a catch-all case -- the set of cases which may
615
- * result in this failure is specifically defined by the architecture.
616
- */
617
- CP_ACCESS_TRAP_UNCATEGORIZED = 2,
618
- /* As CP_ACCESS_TRAP, but for traps directly to EL2 or EL3 */
619
- CP_ACCESS_TRAP_EL2 = 3,
620
- CP_ACCESS_TRAP_EL3 = 4,
621
- /* As CP_ACCESS_UNCATEGORIZED, but for traps directly to EL2 or EL3 */
622
- CP_ACCESS_TRAP_UNCATEGORIZED_EL2 = 5,
623
- CP_ACCESS_TRAP_UNCATEGORIZED_EL3 = 6,
624
-} CPAccessResult;
625
-
76
-
626
-/* Access functions for coprocessor registers. These cannot fail and
77
static bool trans_OK(DisasContext *s, arg_OK *a)
627
- * may not raise exceptions.
78
{
628
- */
79
return true;
629
-typedef uint64_t CPReadFn(CPUARMState *env, const ARMCPRegInfo *opaque);
80
@@ -XXX,XX +XXX,XX @@ static void aarch64_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
630
-typedef void CPWriteFn(CPUARMState *env, const ARMCPRegInfo *opaque,
81
disas_sme_fa64(s, insn);
631
- uint64_t value);
82
}
632
-/* Access permission check functions for coprocessor registers. */
83
633
-typedef CPAccessResult CPAccessFn(CPUARMState *env,
84
- disas_a64_legacy(s, insn);
634
- const ARMCPRegInfo *opaque,
85
+
635
- bool isread);
86
+ if (!disas_a64(s, insn)) {
636
-/* Hook function for register reset */
87
+ disas_a64_legacy(s, insn);
637
-typedef void CPResetFn(CPUARMState *env, const ARMCPRegInfo *opaque);
88
+ }
638
-
89
639
-#define CP_ANY 0xff
90
/*
640
-
91
* After execution of most insns, btype is reset to 0.
641
-/* Definition of an ARM coprocessor register */
92
diff --git a/target/arm/tcg/meson.build b/target/arm/tcg/meson.build
642
-struct ARMCPRegInfo {
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
93
index XXXXXXX..XXXXXXX 100644
836
--- a/hw/arm/pxa2xx.c
94
--- a/target/arm/tcg/meson.build
837
+++ b/hw/arm/pxa2xx.c
95
+++ b/target/arm/tcg/meson.build
838
@@ -XXX,XX +XXX,XX @@
96
@@ -XXX,XX +XXX,XX @@ gen = [
839
#include "qemu/cutils.h"
97
decodetree.process('a32-uncond.decode', extra_args: '--static-decode=disas_a32_uncond'),
840
#include "qemu/log.h"
98
decodetree.process('t32.decode', extra_args: '--static-decode=disas_t32'),
841
#include "qom/object.h"
99
decodetree.process('t16.decode', extra_args: ['-w', '16', '--static-decode=disas_t16']),
842
+#include "target/arm/cpregs.h"
100
+ decodetree.process('a64.decode', extra_args: ['--static-decode=disas_a64']),
843
101
]
844
static struct {
102
845
hwaddr io_base;
103
arm_ss.add(gen)
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
{
895
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
896
index XXXXXXX..XXXXXXX 100644
897
--- a/target/arm/cpu64.c
898
+++ b/target/arm/cpu64.c
899
@@ -XXX,XX +XXX,XX @@
900
#include "hvf_arm.h"
901
#include "qapi/visitor.h"
902
#include "hw/qdev-properties.h"
903
+#include "cpregs.h"
904
905
906
#ifndef CONFIG_USER_ONLY
907
diff --git a/target/arm/cpu_tcg.c b/target/arm/cpu_tcg.c
908
index XXXXXXX..XXXXXXX 100644
909
--- a/target/arm/cpu_tcg.c
910
+++ b/target/arm/cpu_tcg.c
911
@@ -XXX,XX +XXX,XX @@
912
#if !defined(CONFIG_USER_ONLY)
913
#include "hw/boards.h"
914
#endif
915
+#include "cpregs.h"
916
917
/* CPU models. These are not needed for the AArch64 linux-user build. */
918
#if !defined(CONFIG_USER_ONLY) || !defined(TARGET_AARCH64)
919
diff --git a/target/arm/gdbstub.c b/target/arm/gdbstub.c
920
index XXXXXXX..XXXXXXX 100644
921
--- a/target/arm/gdbstub.c
922
+++ b/target/arm/gdbstub.c
923
@@ -XXX,XX +XXX,XX @@
924
*/
925
#include "qemu/osdep.h"
926
#include "cpu.h"
927
-#include "internals.h"
928
#include "exec/gdbstub.h"
929
+#include "internals.h"
930
+#include "cpregs.h"
931
932
typedef struct RegisterSysregXmlParam {
933
CPUState *cs;
934
diff --git a/target/arm/helper.c b/target/arm/helper.c
935
index XXXXXXX..XXXXXXX 100644
936
--- a/target/arm/helper.c
937
+++ b/target/arm/helper.c
938
@@ -XXX,XX +XXX,XX @@
939
#include "exec/cpu_ldst.h"
940
#include "semihosting/common-semi.h"
941
#endif
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
--
104
--
996
2.25.1
105
2.34.1
997
998
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
The SVE and SME decode is already done by decodetree. Pull the calls
2
to these decoders out of the legacy decoder. This doesn't change
3
behaviour because all the patterns in sve.decode and sme.decode
4
already require the bits that the legacy decoder is decoding to have
5
the correct values.
2
6
3
Bool is a more appropriate type for these variables.
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20230512144106.3608981-4-peter.maydell@linaro.org
10
---
11
target/arm/tcg/translate-a64.c | 20 ++++----------------
12
1 file changed, 4 insertions(+), 16 deletions(-)
4
13
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
14
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
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>
9
---
10
target/arm/helper.c | 4 ++--
11
1 file changed, 2 insertions(+), 2 deletions(-)
12
13
diff --git a/target/arm/helper.c b/target/arm/helper.c
14
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/helper.c
16
--- a/target/arm/tcg/translate-a64.c
16
+++ b/target/arm/helper.c
17
+++ b/target/arm/tcg/translate-a64.c
17
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
18
@@ -XXX,XX +XXX,XX @@ static bool btype_destination_ok(uint32_t insn, bool bt, int btype)
18
*/
19
static void disas_a64_legacy(DisasContext *s, uint32_t insn)
19
uint32_t key;
20
{
20
ARMCPRegInfo *r2;
21
switch (extract32(insn, 25, 4)) {
21
- int is64 = (r->type & ARM_CP_64BIT) ? 1 : 0;
22
- case 0x0:
22
- int ns = (secstate & ARM_CP_SECSTATE_NS) ? 1 : 0;
23
- if (!extract32(insn, 31, 1) || !disas_sme(s, insn)) {
23
+ bool is64 = r->type & ARM_CP_64BIT;
24
- unallocated_encoding(s);
24
+ bool ns = secstate & ARM_CP_SECSTATE_NS;
25
- }
25
int cp = r->cp;
26
- break;
26
size_t name_len;
27
- case 0x1: case 0x3: /* UNALLOCATED */
28
- unallocated_encoding(s);
29
- break;
30
- case 0x2:
31
- if (!disas_sve(s, insn)) {
32
- unallocated_encoding(s);
33
- }
34
- break;
35
case 0x8: case 0x9: /* Data processing - immediate */
36
disas_data_proc_imm(s, insn);
37
break;
38
@@ -XXX,XX +XXX,XX @@ static void disas_a64_legacy(DisasContext *s, uint32_t insn)
39
disas_data_proc_simd_fp(s, insn);
40
break;
41
default:
42
- assert(FALSE); /* all 15 cases should be handled above */
43
+ unallocated_encoding(s);
44
break;
45
}
46
}
47
@@ -XXX,XX +XXX,XX @@ static void aarch64_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
48
disas_sme_fa64(s, insn);
49
}
50
51
-
52
- if (!disas_a64(s, insn)) {
53
+ if (!disas_a64(s, insn) &&
54
+ !disas_sme(s, insn) &&
55
+ !disas_sve(s, insn)) {
56
disas_a64_legacy(s, insn);
57
}
27
58
28
--
59
--
29
2.25.1
60
2.34.1
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Put most of the value writeback to the same place,
3
Convert the ADR and ADRP instructions.
4
and improve the comment that goes with them.
5
4
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Message-id: 20220501055028.646596-15-richard.henderson@linaro.org
8
Message-id: 20230512144106.3608981-5-peter.maydell@linaro.org
9
[PMM: Rebased]
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
12
---
11
target/arm/helper.c | 28 ++++++++++++----------------
13
target/arm/tcg/a64.decode | 13 ++++++++++++
12
1 file changed, 12 insertions(+), 16 deletions(-)
14
target/arm/tcg/translate-a64.c | 38 +++++++++++++---------------------
15
2 files changed, 27 insertions(+), 24 deletions(-)
13
16
14
diff --git a/target/arm/helper.c b/target/arm/helper.c
17
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
15
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/helper.c
19
--- a/target/arm/tcg/a64.decode
17
+++ b/target/arm/helper.c
20
+++ b/target/arm/tcg/a64.decode
18
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
21
@@ -XXX,XX +XXX,XX @@
19
*r2 = *r;
22
#
20
r2->name = memcpy(r2 + 1, name, name_len);
23
# This file is processed by scripts/decodetree.py
21
24
#
22
- /* Reset the secure state to the specific incoming state. This is
25
+
23
- * necessary as the register may have been defined with both states.
26
+&ri rd imm
24
+ /*
27
+
25
+ * Update fields to match the instantiation, overwiting wildcards
28
+
26
+ * such as CP_ANY, ARM_CP_STATE_BOTH, or ARM_CP_SECSTATE_BOTH.
29
+### Data Processing - Immediate
27
*/
30
+
28
+ r2->cp = cp;
31
+# PC-rel addressing
29
+ r2->crm = crm;
32
+
30
+ r2->opc1 = opc1;
33
+%imm_pcrel 5:s19 29:2
31
+ r2->opc2 = opc2;
34
+@pcrel . .. ..... ................... rd:5 &ri imm=%imm_pcrel
32
+ r2->state = state;
35
+
33
r2->secure = secstate;
36
+ADR 0 .. 10000 ................... ..... @pcrel
34
+ if (opaque) {
37
+ADRP 1 .. 10000 ................... ..... @pcrel
35
+ r2->opaque = opaque;
38
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
36
+ }
39
index XXXXXXX..XXXXXXX 100644
37
40
--- a/target/arm/tcg/translate-a64.c
38
if (r->bank_fieldoffsets[0] && r->bank_fieldoffsets[1]) {
41
+++ b/target/arm/tcg/translate-a64.c
39
/* Register is banked (using both entries in array).
42
@@ -XXX,XX +XXX,XX @@ static void disas_ldst(DisasContext *s, uint32_t insn)
40
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
41
#endif
42
}
43
}
43
}
44
- if (opaque) {
44
}
45
- r2->opaque = opaque;
45
46
-/* PC-rel. addressing
47
- * 31 30 29 28 24 23 5 4 0
48
- * +----+-------+-----------+-------------------+------+
49
- * | op | immlo | 1 0 0 0 0 | immhi | Rd |
50
- * +----+-------+-----------+-------------------+------+
51
+/*
52
+ * PC-rel. addressing
53
*/
54
-static void disas_pc_rel_adr(DisasContext *s, uint32_t insn)
55
+
56
+static bool trans_ADR(DisasContext *s, arg_ri *a)
57
{
58
- unsigned int page, rd;
59
- int64_t offset;
60
+ gen_pc_plus_diff(s, cpu_reg(s, a->rd), a->imm);
61
+ return true;
62
+}
63
64
- page = extract32(insn, 31, 1);
65
- /* SignExtend(immhi:immlo) -> offset */
66
- offset = sextract64(insn, 5, 19);
67
- offset = offset << 2 | extract32(insn, 29, 2);
68
- rd = extract32(insn, 0, 5);
69
+static bool trans_ADRP(DisasContext *s, arg_ri *a)
70
+{
71
+ int64_t offset = (int64_t)a->imm << 12;
72
73
- if (page) {
74
- /* ADRP (page based) */
75
- offset <<= 12;
76
- /* The page offset is ok for CF_PCREL. */
77
- offset -= s->pc_curr & 0xfff;
46
- }
78
- }
47
- /* reginfo passed to helpers is correct for the actual access,
79
-
48
- * and is never ARM_CP_STATE_BOTH:
80
- gen_pc_plus_diff(s, cpu_reg(s, rd), offset);
49
- */
81
+ /* The page offset is ok for CF_PCREL. */
50
- r2->state = state;
82
+ offset -= s->pc_curr & 0xfff;
51
- /* Make sure reginfo passed to helpers for wildcarded regs
83
+ gen_pc_plus_diff(s, cpu_reg(s, a->rd), offset);
52
- * has the correct crm/opc1/opc2 for this reg, not CP_ANY:
84
+ return true;
53
- */
85
}
54
- r2->cp = cp;
86
55
- r2->crm = crm;
87
/*
56
- r2->opc1 = opc1;
88
@@ -XXX,XX +XXX,XX @@ static void disas_extract(DisasContext *s, uint32_t insn)
57
- r2->opc2 = opc2;
89
static void disas_data_proc_imm(DisasContext *s, uint32_t insn)
58
+
90
{
59
/* By convention, for wildcarded registers only the first
91
switch (extract32(insn, 23, 6)) {
60
* entry is used for migration; the others are marked as
92
- case 0x20: case 0x21: /* PC-rel. addressing */
61
* ALIAS so we don't try to transfer the register
93
- disas_pc_rel_adr(s, insn);
94
- break;
95
case 0x22: /* Add/subtract (immediate) */
96
disas_add_sub_imm(s, insn);
97
break;
62
--
98
--
63
2.25.1
99
2.34.1
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Remove a possible source of error by removing REGINFO_SENTINEL
3
Split out specific 32-bit and 64-bit functions.
4
and using ARRAY_SIZE (convinently hidden inside a macro) to
4
These carry the same signature as tcg_gen_add_i64,
5
find the end of the set of regs being registered or modified.
5
and so will be easier to pass as callbacks.
6
6
7
The space saved by not having the extra array element reduces
7
Retain gen_add_CC and gen_sub_CC during conversion.
8
the executable's .data.rel.ro section by about 9k.
9
8
10
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20230512144106.3608981-6-peter.maydell@linaro.org
13
Message-id: 20220501055028.646596-4-richard.henderson@linaro.org
13
[PMM: rebased]
14
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
---
16
---
16
target/arm/cpregs.h | 53 +++++++++---------
17
target/arm/tcg/translate-a64.c | 149 +++++++++++++++++++--------------
17
hw/arm/pxa2xx.c | 1 -
18
1 file changed, 84 insertions(+), 65 deletions(-)
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
19
26
diff --git a/target/arm/cpregs.h b/target/arm/cpregs.h
20
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
27
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
28
--- a/target/arm/cpregs.h
22
--- a/target/arm/tcg/translate-a64.c
29
+++ b/target/arm/cpregs.h
23
+++ b/target/arm/tcg/translate-a64.c
30
@@ -XXX,XX +XXX,XX @@
24
@@ -XXX,XX +XXX,XX @@ static inline void gen_logic_CC(int sf, TCGv_i64 result)
31
#define ARM_CP_NO_GDB 0x4000
25
}
32
#define ARM_CP_RAISES_EXC 0x8000
26
33
#define ARM_CP_NEWEL 0x10000
27
/* dest = T0 + T1; compute C, N, V and Z flags */
34
-/* Used only as a terminator for ARMCPRegInfo lists */
28
+static void gen_add64_CC(TCGv_i64 dest, TCGv_i64 t0, TCGv_i64 t1)
35
-#define ARM_CP_SENTINEL 0xfffff
29
+{
36
/* Mask of only the flag bits in a type field */
30
+ TCGv_i64 result, flag, tmp;
37
#define ARM_CP_FLAG_MASK 0x1f0ff
31
+ result = tcg_temp_new_i64();
38
32
+ flag = tcg_temp_new_i64();
39
@@ -XXX,XX +XXX,XX @@ enum {
33
+ tmp = tcg_temp_new_i64();
40
ARM_CP_SECSTATE_NS = (1 << 1), /* bit[1]: Non-secure state register */
34
+
41
};
35
+ tcg_gen_movi_i64(tmp, 0);
42
36
+ tcg_gen_add2_i64(result, flag, t0, tmp, t1, tmp);
43
-/*
37
+
44
- * Return true if cptype is a valid type field. This is used to try to
38
+ tcg_gen_extrl_i64_i32(cpu_CF, flag);
45
- * catch errors where the sentinel has been accidentally left off the end
39
+
46
- * of a list of registers.
40
+ gen_set_NZ64(result);
47
- */
41
+
48
-static inline bool cptype_valid(int cptype)
42
+ tcg_gen_xor_i64(flag, result, t0);
49
-{
43
+ tcg_gen_xor_i64(tmp, t0, t1);
50
- return ((cptype & ~ARM_CP_FLAG_MASK) == 0)
44
+ tcg_gen_andc_i64(flag, flag, tmp);
51
- || ((cptype & ARM_CP_SPECIAL) &&
45
+ tcg_gen_extrh_i64_i32(cpu_VF, flag);
52
- ((cptype & ~ARM_CP_FLAG_MASK) <= ARM_LAST_SPECIAL));
46
+
53
-}
47
+ tcg_gen_mov_i64(dest, result);
48
+}
49
+
50
+static void gen_add32_CC(TCGv_i64 dest, TCGv_i64 t0, TCGv_i64 t1)
51
+{
52
+ TCGv_i32 t0_32 = tcg_temp_new_i32();
53
+ TCGv_i32 t1_32 = tcg_temp_new_i32();
54
+ TCGv_i32 tmp = tcg_temp_new_i32();
55
+
56
+ tcg_gen_movi_i32(tmp, 0);
57
+ tcg_gen_extrl_i64_i32(t0_32, t0);
58
+ tcg_gen_extrl_i64_i32(t1_32, t1);
59
+ tcg_gen_add2_i32(cpu_NF, cpu_CF, t0_32, tmp, t1_32, tmp);
60
+ tcg_gen_mov_i32(cpu_ZF, cpu_NF);
61
+ tcg_gen_xor_i32(cpu_VF, cpu_NF, t0_32);
62
+ tcg_gen_xor_i32(tmp, t0_32, t1_32);
63
+ tcg_gen_andc_i32(cpu_VF, cpu_VF, tmp);
64
+ tcg_gen_extu_i32_i64(dest, cpu_NF);
65
+}
66
+
67
static void gen_add_CC(int sf, TCGv_i64 dest, TCGv_i64 t0, TCGv_i64 t1)
68
{
69
if (sf) {
70
- TCGv_i64 result, flag, tmp;
71
- result = tcg_temp_new_i64();
72
- flag = tcg_temp_new_i64();
73
- tmp = tcg_temp_new_i64();
54
-
74
-
55
/*
75
- tcg_gen_movi_i64(tmp, 0);
56
* Access rights:
76
- tcg_gen_add2_i64(result, flag, t0, tmp, t1, tmp);
57
* We define bits for Read and Write access for what rev C of the v7-AR ARM ARM
77
-
58
@@ -XXX,XX +XXX,XX @@ struct ARMCPRegInfo {
78
- tcg_gen_extrl_i64_i32(cpu_CF, flag);
59
#define CPREG_FIELD64(env, ri) \
79
-
60
(*(uint64_t *)((char *)(env) + (ri)->fieldoffset))
80
- gen_set_NZ64(result);
61
81
-
62
-#define REGINFO_SENTINEL { .type = ARM_CP_SENTINEL }
82
- tcg_gen_xor_i64(flag, result, t0);
63
+void define_one_arm_cp_reg_with_opaque(ARMCPU *cpu, const ARMCPRegInfo *reg,
83
- tcg_gen_xor_i64(tmp, t0, t1);
64
+ void *opaque);
84
- tcg_gen_andc_i64(flag, flag, tmp);
65
85
- tcg_gen_extrh_i64_i32(cpu_VF, flag);
66
-void define_arm_cp_regs_with_opaque(ARMCPU *cpu,
86
-
67
- const ARMCPRegInfo *regs, void *opaque);
87
- tcg_gen_mov_i64(dest, result);
68
-void define_one_arm_cp_reg_with_opaque(ARMCPU *cpu,
88
+ gen_add64_CC(dest, t0, t1);
69
- const ARMCPRegInfo *regs, void *opaque);
89
} else {
70
-static inline void define_arm_cp_regs(ARMCPU *cpu, const ARMCPRegInfo *regs)
90
- /* 32 bit arithmetic */
71
-{
91
- TCGv_i32 t0_32 = tcg_temp_new_i32();
72
- define_arm_cp_regs_with_opaque(cpu, regs, 0);
92
- TCGv_i32 t1_32 = tcg_temp_new_i32();
73
-}
93
- TCGv_i32 tmp = tcg_temp_new_i32();
74
static inline void define_one_arm_cp_reg(ARMCPU *cpu, const ARMCPRegInfo *regs)
94
-
75
{
95
- tcg_gen_movi_i32(tmp, 0);
76
- define_one_arm_cp_reg_with_opaque(cpu, regs, 0);
96
- tcg_gen_extrl_i64_i32(t0_32, t0);
77
+ define_one_arm_cp_reg_with_opaque(cpu, regs, NULL);
97
- tcg_gen_extrl_i64_i32(t1_32, t1);
78
}
98
- tcg_gen_add2_i32(cpu_NF, cpu_CF, t0_32, tmp, t1_32, tmp);
79
+
99
- tcg_gen_mov_i32(cpu_ZF, cpu_NF);
80
+void define_arm_cp_regs_with_opaque_len(ARMCPU *cpu, const ARMCPRegInfo *regs,
100
- tcg_gen_xor_i32(cpu_VF, cpu_NF, t0_32);
81
+ void *opaque, size_t len);
101
- tcg_gen_xor_i32(tmp, t0_32, t1_32);
82
+
102
- tcg_gen_andc_i32(cpu_VF, cpu_VF, tmp);
83
+#define define_arm_cp_regs_with_opaque(CPU, REGS, OPAQUE) \
103
- tcg_gen_extu_i32_i64(dest, cpu_NF);
84
+ do { \
104
+ gen_add32_CC(dest, t0, t1);
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
};
526
define_arm_cp_regs(cpu, dbgregs);
527
}
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
}
105
}
840
}
106
}
841
107
842
-void define_arm_cp_regs_with_opaque(ARMCPU *cpu,
108
/* dest = T0 - T1; compute C, N, V and Z flags */
843
- const ARMCPRegInfo *regs, void *opaque)
109
+static void gen_sub64_CC(TCGv_i64 dest, TCGv_i64 t0, TCGv_i64 t1)
844
+/* Define a whole list of registers */
110
+{
845
+void define_arm_cp_regs_with_opaque_len(ARMCPU *cpu, const ARMCPRegInfo *regs,
111
+ /* 64 bit arithmetic */
846
+ void *opaque, size_t len)
112
+ TCGv_i64 result, flag, tmp;
113
+
114
+ result = tcg_temp_new_i64();
115
+ flag = tcg_temp_new_i64();
116
+ tcg_gen_sub_i64(result, t0, t1);
117
+
118
+ gen_set_NZ64(result);
119
+
120
+ tcg_gen_setcond_i64(TCG_COND_GEU, flag, t0, t1);
121
+ tcg_gen_extrl_i64_i32(cpu_CF, flag);
122
+
123
+ tcg_gen_xor_i64(flag, result, t0);
124
+ tmp = tcg_temp_new_i64();
125
+ tcg_gen_xor_i64(tmp, t0, t1);
126
+ tcg_gen_and_i64(flag, flag, tmp);
127
+ tcg_gen_extrh_i64_i32(cpu_VF, flag);
128
+ tcg_gen_mov_i64(dest, result);
129
+}
130
+
131
+static void gen_sub32_CC(TCGv_i64 dest, TCGv_i64 t0, TCGv_i64 t1)
132
+{
133
+ /* 32 bit arithmetic */
134
+ TCGv_i32 t0_32 = tcg_temp_new_i32();
135
+ TCGv_i32 t1_32 = tcg_temp_new_i32();
136
+ TCGv_i32 tmp;
137
+
138
+ tcg_gen_extrl_i64_i32(t0_32, t0);
139
+ tcg_gen_extrl_i64_i32(t1_32, t1);
140
+ tcg_gen_sub_i32(cpu_NF, t0_32, t1_32);
141
+ tcg_gen_mov_i32(cpu_ZF, cpu_NF);
142
+ tcg_gen_setcond_i32(TCG_COND_GEU, cpu_CF, t0_32, t1_32);
143
+ tcg_gen_xor_i32(cpu_VF, cpu_NF, t0_32);
144
+ tmp = tcg_temp_new_i32();
145
+ tcg_gen_xor_i32(tmp, t0_32, t1_32);
146
+ tcg_gen_and_i32(cpu_VF, cpu_VF, tmp);
147
+ tcg_gen_extu_i32_i64(dest, cpu_NF);
148
+}
149
+
150
static void gen_sub_CC(int sf, TCGv_i64 dest, TCGv_i64 t0, TCGv_i64 t1)
847
{
151
{
848
- /* Define a whole list of registers */
152
if (sf) {
849
- const ARMCPRegInfo *r;
153
- /* 64 bit arithmetic */
850
- for (r = regs; r->type != ARM_CP_SENTINEL; r++) {
154
- TCGv_i64 result, flag, tmp;
851
- define_one_arm_cp_reg_with_opaque(cpu, r, opaque);
155
-
852
+ size_t i;
156
- result = tcg_temp_new_i64();
853
+ for (i = 0; i < len; ++i) {
157
- flag = tcg_temp_new_i64();
854
+ define_one_arm_cp_reg_with_opaque(cpu, regs + i, opaque);
158
- tcg_gen_sub_i64(result, t0, t1);
159
-
160
- gen_set_NZ64(result);
161
-
162
- tcg_gen_setcond_i64(TCG_COND_GEU, flag, t0, t1);
163
- tcg_gen_extrl_i64_i32(cpu_CF, flag);
164
-
165
- tcg_gen_xor_i64(flag, result, t0);
166
- tmp = tcg_temp_new_i64();
167
- tcg_gen_xor_i64(tmp, t0, t1);
168
- tcg_gen_and_i64(flag, flag, tmp);
169
- tcg_gen_extrh_i64_i32(cpu_VF, flag);
170
- tcg_gen_mov_i64(dest, result);
171
+ gen_sub64_CC(dest, t0, t1);
172
} else {
173
- /* 32 bit arithmetic */
174
- TCGv_i32 t0_32 = tcg_temp_new_i32();
175
- TCGv_i32 t1_32 = tcg_temp_new_i32();
176
- TCGv_i32 tmp;
177
-
178
- tcg_gen_extrl_i64_i32(t0_32, t0);
179
- tcg_gen_extrl_i64_i32(t1_32, t1);
180
- tcg_gen_sub_i32(cpu_NF, t0_32, t1_32);
181
- tcg_gen_mov_i32(cpu_ZF, cpu_NF);
182
- tcg_gen_setcond_i32(TCG_COND_GEU, cpu_CF, t0_32, t1_32);
183
- tcg_gen_xor_i32(cpu_VF, cpu_NF, t0_32);
184
- tmp = tcg_temp_new_i32();
185
- tcg_gen_xor_i32(tmp, t0_32, t1_32);
186
- tcg_gen_and_i32(cpu_VF, cpu_VF, tmp);
187
- tcg_gen_extu_i32_i64(dest, cpu_NF);
188
+ gen_sub32_CC(dest, t0, t1);
855
}
189
}
856
}
190
}
857
191
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
--
192
--
886
2.25.1
193
2.34.1
887
888
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Add the aa64 predicate for detecting RAS support from id registers.
3
Convert the ADD and SUB (immediate) instructions.
4
We already have the aa32 version from the M-profile work.
5
Add the 'any' predicate for testing both aa64 and aa32.
6
4
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20230512144106.3608981-7-peter.maydell@linaro.org
9
Message-id: 20220501055028.646596-34-richard.henderson@linaro.org
9
[PMM: Rebased; adjusted to use translate.h's TRANS macro]
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
---
12
target/arm/cpu.h | 10 ++++++++++
13
target/arm/tcg/translate.h | 5 +++
13
1 file changed, 10 insertions(+)
14
target/arm/tcg/a64.decode | 17 ++++++++
15
target/arm/tcg/translate-a64.c | 73 ++++++++++------------------------
16
3 files changed, 42 insertions(+), 53 deletions(-)
14
17
15
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
18
diff --git a/target/arm/tcg/translate.h b/target/arm/tcg/translate.h
16
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/cpu.h
20
--- a/target/arm/tcg/translate.h
18
+++ b/target/arm/cpu.h
21
+++ b/target/arm/tcg/translate.h
19
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa64_aa32_el1(const ARMISARegisters *id)
22
@@ -XXX,XX +XXX,XX @@ static inline int rsub_8(DisasContext *s, int x)
20
return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, EL1) >= 2;
23
return 8 - x;
21
}
24
}
22
25
23
+static inline bool isar_feature_aa64_ras(const ARMISARegisters *id)
26
+static inline int shl_12(DisasContext *s, int x)
24
+{
27
+{
25
+ return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, RAS) != 0;
28
+ return x << 12;
26
+}
29
+}
27
+
30
+
28
static inline bool isar_feature_aa64_sve(const ARMISARegisters *id)
31
static inline int neon_3same_fp_size(DisasContext *s, int x)
29
{
32
{
30
return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, SVE) != 0;
33
/* Convert 0==fp32, 1==fp16 into a MO_* value */
31
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_any_debugv8p2(const ARMISARegisters *id)
34
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
32
return isar_feature_aa64_debugv8p2(id) || isar_feature_aa32_debugv8p2(id);
35
index XXXXXXX..XXXXXXX 100644
36
--- a/target/arm/tcg/a64.decode
37
+++ b/target/arm/tcg/a64.decode
38
@@ -XXX,XX +XXX,XX @@
39
#
40
41
&ri rd imm
42
+&rri_sf rd rn imm sf
43
44
45
### Data Processing - Immediate
46
@@ -XXX,XX +XXX,XX @@
47
48
ADR 0 .. 10000 ................... ..... @pcrel
49
ADRP 1 .. 10000 ................... ..... @pcrel
50
+
51
+# Add/subtract (immediate)
52
+
53
+%imm12_sh12 10:12 !function=shl_12
54
+@addsub_imm sf:1 .. ...... . imm:12 rn:5 rd:5
55
+@addsub_imm12 sf:1 .. ...... . ............ rn:5 rd:5 imm=%imm12_sh12
56
+
57
+ADD_i . 00 100010 0 ............ ..... ..... @addsub_imm
58
+ADD_i . 00 100010 1 ............ ..... ..... @addsub_imm12
59
+ADDS_i . 01 100010 0 ............ ..... ..... @addsub_imm
60
+ADDS_i . 01 100010 1 ............ ..... ..... @addsub_imm12
61
+
62
+SUB_i . 10 100010 0 ............ ..... ..... @addsub_imm
63
+SUB_i . 10 100010 1 ............ ..... ..... @addsub_imm12
64
+SUBS_i . 11 100010 0 ............ ..... ..... @addsub_imm
65
+SUBS_i . 11 100010 1 ............ ..... ..... @addsub_imm12
66
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
67
index XXXXXXX..XXXXXXX 100644
68
--- a/target/arm/tcg/translate-a64.c
69
+++ b/target/arm/tcg/translate-a64.c
70
@@ -XXX,XX +XXX,XX @@ static void disas_ldst(DisasContext *s, uint32_t insn)
71
}
33
}
72
}
34
73
35
+static inline bool isar_feature_any_ras(const ARMISARegisters *id)
74
+typedef void ArithTwoOp(TCGv_i64, TCGv_i64, TCGv_i64);
75
+
76
+static bool gen_rri(DisasContext *s, arg_rri_sf *a,
77
+ bool rd_sp, bool rn_sp, ArithTwoOp *fn)
36
+{
78
+{
37
+ return isar_feature_aa64_ras(id) || isar_feature_aa32_ras(id);
79
+ TCGv_i64 tcg_rn = rn_sp ? cpu_reg_sp(s, a->rn) : cpu_reg(s, a->rn);
80
+ TCGv_i64 tcg_rd = rd_sp ? cpu_reg_sp(s, a->rd) : cpu_reg(s, a->rd);
81
+ TCGv_i64 tcg_imm = tcg_constant_i64(a->imm);
82
+
83
+ fn(tcg_rd, tcg_rn, tcg_imm);
84
+ if (!a->sf) {
85
+ tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
86
+ }
87
+ return true;
38
+}
88
+}
39
+
89
+
40
/*
90
/*
41
* Forward to the above feature tests given an ARMCPU pointer.
91
* PC-rel. addressing
42
*/
92
*/
93
@@ -XXX,XX +XXX,XX @@ static bool trans_ADRP(DisasContext *s, arg_ri *a)
94
95
/*
96
* Add/subtract (immediate)
97
- *
98
- * 31 30 29 28 23 22 21 10 9 5 4 0
99
- * +--+--+--+-------------+--+-------------+-----+-----+
100
- * |sf|op| S| 1 0 0 0 1 0 |sh| imm12 | Rn | Rd |
101
- * +--+--+--+-------------+--+-------------+-----+-----+
102
- *
103
- * sf: 0 -> 32bit, 1 -> 64bit
104
- * op: 0 -> add , 1 -> sub
105
- * S: 1 -> set flags
106
- * sh: 1 -> LSL imm by 12
107
*/
108
-static void disas_add_sub_imm(DisasContext *s, uint32_t insn)
109
-{
110
- int rd = extract32(insn, 0, 5);
111
- int rn = extract32(insn, 5, 5);
112
- uint64_t imm = extract32(insn, 10, 12);
113
- bool shift = extract32(insn, 22, 1);
114
- bool setflags = extract32(insn, 29, 1);
115
- bool sub_op = extract32(insn, 30, 1);
116
- bool is_64bit = extract32(insn, 31, 1);
117
-
118
- TCGv_i64 tcg_rn = cpu_reg_sp(s, rn);
119
- TCGv_i64 tcg_rd = setflags ? cpu_reg(s, rd) : cpu_reg_sp(s, rd);
120
- TCGv_i64 tcg_result;
121
-
122
- if (shift) {
123
- imm <<= 12;
124
- }
125
-
126
- tcg_result = tcg_temp_new_i64();
127
- if (!setflags) {
128
- if (sub_op) {
129
- tcg_gen_subi_i64(tcg_result, tcg_rn, imm);
130
- } else {
131
- tcg_gen_addi_i64(tcg_result, tcg_rn, imm);
132
- }
133
- } else {
134
- TCGv_i64 tcg_imm = tcg_constant_i64(imm);
135
- if (sub_op) {
136
- gen_sub_CC(is_64bit, tcg_result, tcg_rn, tcg_imm);
137
- } else {
138
- gen_add_CC(is_64bit, tcg_result, tcg_rn, tcg_imm);
139
- }
140
- }
141
-
142
- if (is_64bit) {
143
- tcg_gen_mov_i64(tcg_rd, tcg_result);
144
- } else {
145
- tcg_gen_ext32u_i64(tcg_rd, tcg_result);
146
- }
147
-}
148
+TRANS(ADD_i, gen_rri, a, 1, 1, tcg_gen_add_i64)
149
+TRANS(SUB_i, gen_rri, a, 1, 1, tcg_gen_sub_i64)
150
+TRANS(ADDS_i, gen_rri, a, 0, 1, a->sf ? gen_add64_CC : gen_add32_CC)
151
+TRANS(SUBS_i, gen_rri, a, 0, 1, a->sf ? gen_sub64_CC : gen_sub32_CC)
152
153
/*
154
* Add/subtract (immediate, with tags)
155
@@ -XXX,XX +XXX,XX @@ static void disas_extract(DisasContext *s, uint32_t insn)
156
static void disas_data_proc_imm(DisasContext *s, uint32_t insn)
157
{
158
switch (extract32(insn, 23, 6)) {
159
- case 0x22: /* Add/subtract (immediate) */
160
- disas_add_sub_imm(s, insn);
161
- break;
162
case 0x23: /* Add/subtract (immediate, with tags) */
163
disas_add_sub_imm_with_tags(s, insn);
164
break;
43
--
165
--
44
2.25.1
166
2.34.1
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Computing isbanked only once makes the code
3
Convert the ADDG and SUBG (immediate) instructions.
4
a bit easier to read.
5
4
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Message-id: 20220501055028.646596-17-richard.henderson@linaro.org
8
Message-id: 20230512144106.3608981-8-peter.maydell@linaro.org
9
[PMM: Rebased; use TRANS_FEAT()]
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
12
---
11
target/arm/helper.c | 6 ++++--
13
target/arm/tcg/a64.decode | 8 +++++++
12
1 file changed, 4 insertions(+), 2 deletions(-)
14
target/arm/tcg/translate-a64.c | 38 ++++++++++------------------------
15
2 files changed, 19 insertions(+), 27 deletions(-)
13
16
14
diff --git a/target/arm/helper.c b/target/arm/helper.c
17
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
15
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/helper.c
19
--- a/target/arm/tcg/a64.decode
17
+++ b/target/arm/helper.c
20
+++ b/target/arm/tcg/a64.decode
18
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
21
@@ -XXX,XX +XXX,XX @@ SUB_i . 10 100010 0 ............ ..... ..... @addsub_imm
19
bool is64 = r->type & ARM_CP_64BIT;
22
SUB_i . 10 100010 1 ............ ..... ..... @addsub_imm12
20
bool ns = secstate & ARM_CP_SECSTATE_NS;
23
SUBS_i . 11 100010 0 ............ ..... ..... @addsub_imm
21
int cp = r->cp;
24
SUBS_i . 11 100010 1 ............ ..... ..... @addsub_imm12
22
+ bool isbanked;
25
+
23
size_t name_len;
26
+# Add/subtract (immediate with tags)
24
27
+
25
switch (state) {
28
+&rri_tag rd rn uimm6 uimm4
26
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
29
+@addsub_imm_tag . .. ...... . uimm6:6 .. uimm4:4 rn:5 rd:5 &rri_tag
27
r2->opaque = opaque;
30
+
31
+ADDG_i 1 00 100011 0 ...... 00 .... ..... ..... @addsub_imm_tag
32
+SUBG_i 1 10 100011 0 ...... 00 .... ..... ..... @addsub_imm_tag
33
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
34
index XXXXXXX..XXXXXXX 100644
35
--- a/target/arm/tcg/translate-a64.c
36
+++ b/target/arm/tcg/translate-a64.c
37
@@ -XXX,XX +XXX,XX @@ TRANS(SUBS_i, gen_rri, a, 0, 1, a->sf ? gen_sub64_CC : gen_sub32_CC)
38
39
/*
40
* Add/subtract (immediate, with tags)
41
- *
42
- * 31 30 29 28 23 22 21 16 14 10 9 5 4 0
43
- * +--+--+--+-------------+--+---------+--+-------+-----+-----+
44
- * |sf|op| S| 1 0 0 0 1 1 |o2| uimm6 |o3| uimm4 | Rn | Rd |
45
- * +--+--+--+-------------+--+---------+--+-------+-----+-----+
46
- *
47
- * op: 0 -> add, 1 -> sub
48
*/
49
-static void disas_add_sub_imm_with_tags(DisasContext *s, uint32_t insn)
50
+
51
+static bool gen_add_sub_imm_with_tags(DisasContext *s, arg_rri_tag *a,
52
+ bool sub_op)
53
{
54
- int rd = extract32(insn, 0, 5);
55
- int rn = extract32(insn, 5, 5);
56
- int uimm4 = extract32(insn, 10, 4);
57
- int uimm6 = extract32(insn, 16, 6);
58
- bool sub_op = extract32(insn, 30, 1);
59
TCGv_i64 tcg_rn, tcg_rd;
60
int imm;
61
62
- /* Test all of sf=1, S=0, o2=0, o3=0. */
63
- if ((insn & 0xa040c000u) != 0x80000000u ||
64
- !dc_isar_feature(aa64_mte_insn_reg, s)) {
65
- unallocated_encoding(s);
66
- return;
67
- }
68
-
69
- imm = uimm6 << LOG2_TAG_GRANULE;
70
+ imm = a->uimm6 << LOG2_TAG_GRANULE;
71
if (sub_op) {
72
imm = -imm;
28
}
73
}
29
74
30
- if (r->bank_fieldoffsets[0] && r->bank_fieldoffsets[1]) {
75
- tcg_rn = cpu_reg_sp(s, rn);
31
+ isbanked = r->bank_fieldoffsets[0] && r->bank_fieldoffsets[1];
76
- tcg_rd = cpu_reg_sp(s, rd);
32
+ if (isbanked) {
77
+ tcg_rn = cpu_reg_sp(s, a->rn);
33
/* Register is banked (using both entries in array).
78
+ tcg_rd = cpu_reg_sp(s, a->rd);
34
* Overwriting fieldoffset as the array is only used to define
79
35
* banked registers but later only fieldoffset is used.
80
if (s->ata) {
36
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
81
gen_helper_addsubg(tcg_rd, cpu_env, tcg_rn,
82
tcg_constant_i32(imm),
83
- tcg_constant_i32(uimm4));
84
+ tcg_constant_i32(a->uimm4));
85
} else {
86
tcg_gen_addi_i64(tcg_rd, tcg_rn, imm);
87
gen_address_with_allocation_tag0(tcg_rd, tcg_rd);
37
}
88
}
38
89
+ return true;
39
if (state == ARM_CP_STATE_AA32) {
90
}
40
- if (r->bank_fieldoffsets[0] && r->bank_fieldoffsets[1]) {
91
41
+ if (isbanked) {
92
+TRANS_FEAT(ADDG_i, aa64_mte_insn_reg, gen_add_sub_imm_with_tags, a, false)
42
/* If the register is banked then we don't need to migrate or
93
+TRANS_FEAT(SUBG_i, aa64_mte_insn_reg, gen_add_sub_imm_with_tags, a, true)
43
* reset the 32-bit instance in certain cases:
94
+
44
*
95
/* The input should be a value in the bottom e bits (with higher
96
* bits zero); returns that value replicated into every element
97
* of size e in a 64 bit integer.
98
@@ -XXX,XX +XXX,XX @@ static void disas_extract(DisasContext *s, uint32_t insn)
99
static void disas_data_proc_imm(DisasContext *s, uint32_t insn)
100
{
101
switch (extract32(insn, 23, 6)) {
102
- case 0x23: /* Add/subtract (immediate, with tags) */
103
- disas_add_sub_imm_with_tags(s, insn);
104
- break;
105
case 0x24: /* Logical (immediate) */
106
disas_logic_imm(s, insn);
107
break;
45
--
108
--
46
2.25.1
109
2.34.1
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Simplify freeing cp_regs hash table entries by using a single
3
Use the bitops.h macro rather than rolling our own here.
4
allocation for the entire value.
5
6
This fixes a theoretical bug if we were to ever free the entire
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
4
13
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
14
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
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>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Message-id: 20230512144106.3608981-9-peter.maydell@linaro.org
17
---
9
---
18
target/arm/cpu.c | 16 +---------------
10
target/arm/tcg/translate-a64.c | 11 ++---------
19
target/arm/helper.c | 10 ++++++++--
11
1 file changed, 2 insertions(+), 9 deletions(-)
20
2 files changed, 9 insertions(+), 17 deletions(-)
21
12
22
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
13
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
23
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
24
--- a/target/arm/cpu.c
15
--- a/target/arm/tcg/translate-a64.c
25
+++ b/target/arm/cpu.c
16
+++ b/target/arm/tcg/translate-a64.c
26
@@ -XXX,XX +XXX,XX @@ uint64_t arm_cpu_mp_affinity(int idx, uint8_t clustersz)
17
@@ -XXX,XX +XXX,XX @@ static uint64_t bitfield_replicate(uint64_t mask, unsigned int e)
27
return (Aff1 << ARM_AFF1_SHIFT) | Aff0;
18
return mask;
28
}
19
}
29
20
30
-static void cpreg_hashtable_data_destroy(gpointer data)
21
-/* Return a value with the bottom len bits set (where 0 < len <= 64) */
22
-static inline uint64_t bitmask64(unsigned int length)
31
-{
23
-{
32
- /*
24
- assert(length > 0 && length <= 64);
33
- * Destroy function for cpu->cp_regs hashtable data entries.
25
- return ~0ULL >> (64 - length);
34
- * We must free the name string because it was g_strdup()ed in
35
- * add_cpreg_to_hashtable(). It's OK to cast away the 'const'
36
- * from r->name because we know we definitely allocated it.
37
- */
38
- ARMCPRegInfo *r = data;
39
-
40
- g_free((void *)r->name);
41
- g_free(r);
42
-}
26
-}
43
-
27
-
44
static void arm_cpu_initfn(Object *obj)
28
/* Simplified variant of pseudocode DecodeBitMasks() for the case where we
45
{
29
* only require the wmask. Returns false if the imms/immr/immn are a reserved
46
ARMCPU *cpu = ARM_CPU(obj);
30
* value (ie should cause a guest UNDEF exception), and true if they are
47
31
@@ -XXX,XX +XXX,XX @@ bool logic_imm_decode_wmask(uint64_t *result, unsigned int immn,
48
cpu_set_cpustate_pointers(cpu);
32
/* Create the value of one element: s+1 set bits rotated
49
cpu->cp_regs = g_hash_table_new_full(g_direct_hash, g_direct_equal,
33
* by r within the element (which is e bits wide)...
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
*/
34
*/
62
uint32_t key;
35
- mask = bitmask64(s + 1);
63
- ARMCPRegInfo *r2 = g_memdup(r, sizeof(ARMCPRegInfo));
36
+ mask = MAKE_64BIT_MASK(0, s + 1);
64
+ ARMCPRegInfo *r2;
37
if (r) {
65
int is64 = (r->type & ARM_CP_64BIT) ? 1 : 0;
38
mask = (mask >> r) | (mask << (e - r));
66
int ns = (secstate & ARM_CP_SECSTATE_NS) ? 1 : 0;
39
- mask &= bitmask64(e);
67
+ size_t name_len;
40
+ mask &= MAKE_64BIT_MASK(0, e);
68
+
41
}
69
+ /* Combine cpreg and name into one allocation. */
42
/* ...then replicate the element over the whole 64 bit value */
70
+ name_len = strlen(name) + 1;
43
mask = bitfield_replicate(mask, e);
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
--
44
--
80
2.25.1
45
2.34.1
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Put the block comments into the current coding style.
3
Convert the ADD, ORR, EOR, ANDS (immediate) instructions.
4
4
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Message-id: 20220501055028.646596-19-richard.henderson@linaro.org
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Message-id: 20230512144106.3608981-10-peter.maydell@linaro.org
9
[PMM: rebased]
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
11
---
10
target/arm/helper.c | 24 +++++++++++++++---------
12
target/arm/tcg/a64.decode | 15 ++++++
11
1 file changed, 15 insertions(+), 9 deletions(-)
13
target/arm/tcg/translate-a64.c | 94 +++++++++++-----------------------
14
2 files changed, 44 insertions(+), 65 deletions(-)
12
15
13
diff --git a/target/arm/helper.c b/target/arm/helper.c
16
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
14
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/helper.c
18
--- a/target/arm/tcg/a64.decode
16
+++ b/target/arm/helper.c
19
+++ b/target/arm/tcg/a64.decode
17
@@ -XXX,XX +XXX,XX @@ CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp)
20
@@ -XXX,XX +XXX,XX @@ SUBS_i . 11 100010 1 ............ ..... ..... @addsub_imm12
18
return cpu_list;
21
22
ADDG_i 1 00 100011 0 ...... 00 .... ..... ..... @addsub_imm_tag
23
SUBG_i 1 10 100011 0 ...... 00 .... ..... ..... @addsub_imm_tag
24
+
25
+# Logical (immediate)
26
+
27
+&rri_log rd rn sf dbm
28
+@logic_imm_64 1 .. ...... dbm:13 rn:5 rd:5 &rri_log sf=1
29
+@logic_imm_32 0 .. ...... 0 dbm:12 rn:5 rd:5 &rri_log sf=0
30
+
31
+AND_i . 00 100100 . ...... ...... ..... ..... @logic_imm_64
32
+AND_i . 00 100100 . ...... ...... ..... ..... @logic_imm_32
33
+ORR_i . 01 100100 . ...... ...... ..... ..... @logic_imm_64
34
+ORR_i . 01 100100 . ...... ...... ..... ..... @logic_imm_32
35
+EOR_i . 10 100100 . ...... ...... ..... ..... @logic_imm_64
36
+EOR_i . 10 100100 . ...... ...... ..... ..... @logic_imm_32
37
+ANDS_i . 11 100100 . ...... ...... ..... ..... @logic_imm_64
38
+ANDS_i . 11 100100 . ...... ...... ..... ..... @logic_imm_32
39
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
40
index XXXXXXX..XXXXXXX 100644
41
--- a/target/arm/tcg/translate-a64.c
42
+++ b/target/arm/tcg/translate-a64.c
43
@@ -XXX,XX +XXX,XX @@ static uint64_t bitfield_replicate(uint64_t mask, unsigned int e)
44
return mask;
19
}
45
}
20
46
47
-/* Simplified variant of pseudocode DecodeBitMasks() for the case where we
21
+/*
48
+/*
22
+ * Private utility function for define_one_arm_cp_reg_with_opaque():
49
+ * Logical (immediate)
23
+ * add a single reginfo struct to the hash table.
24
+ */
50
+ */
25
static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
51
+
26
void *opaque, CPState state,
52
+/*
27
CPSecureState secstate,
53
+ * Simplified variant of pseudocode DecodeBitMasks() for the case where we
28
int crm, int opc1, int opc2,
54
* only require the wmask. Returns false if the imms/immr/immn are a reserved
29
const char *name)
55
* value (ie should cause a guest UNDEF exception), and true if they are
56
* valid, in which case the decoded bit pattern is written to result.
57
@@ -XXX,XX +XXX,XX @@ bool logic_imm_decode_wmask(uint64_t *result, unsigned int immn,
58
return true;
59
}
60
61
-/* Logical (immediate)
62
- * 31 30 29 28 23 22 21 16 15 10 9 5 4 0
63
- * +----+-----+-------------+---+------+------+------+------+
64
- * | sf | opc | 1 0 0 1 0 0 | N | immr | imms | Rn | Rd |
65
- * +----+-----+-------------+---+------+------+------+------+
66
- */
67
-static void disas_logic_imm(DisasContext *s, uint32_t insn)
68
+static bool gen_rri_log(DisasContext *s, arg_rri_log *a, bool set_cc,
69
+ void (*fn)(TCGv_i64, TCGv_i64, int64_t))
30
{
70
{
31
- /* Private utility function for define_one_arm_cp_reg_with_opaque():
71
- unsigned int sf, opc, is_n, immr, imms, rn, rd;
32
- * add a single reginfo struct to the hash table.
72
TCGv_i64 tcg_rd, tcg_rn;
33
- */
73
- uint64_t wmask;
34
uint32_t key;
74
- bool is_and = false;
35
ARMCPRegInfo *r2;
75
+ uint64_t imm;
36
bool is64 = r->type & ARM_CP_64BIT;
76
37
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
77
- sf = extract32(insn, 31, 1);
38
78
- opc = extract32(insn, 29, 2);
39
isbanked = r->bank_fieldoffsets[0] && r->bank_fieldoffsets[1];
79
- is_n = extract32(insn, 22, 1);
40
if (isbanked) {
80
- immr = extract32(insn, 16, 6);
41
- /* Register is banked (using both entries in array).
81
- imms = extract32(insn, 10, 6);
42
+ /*
82
- rn = extract32(insn, 5, 5);
43
+ * Register is banked (using both entries in array).
83
- rd = extract32(insn, 0, 5);
44
* Overwriting fieldoffset as the array is only used to define
84
-
45
* banked registers but later only fieldoffset is used.
85
- if (!sf && is_n) {
46
*/
86
- unallocated_encoding(s);
47
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
87
- return;
48
88
+ /* Some immediate field values are reserved. */
49
if (state == ARM_CP_STATE_AA32) {
89
+ if (!logic_imm_decode_wmask(&imm, extract32(a->dbm, 12, 1),
50
if (isbanked) {
90
+ extract32(a->dbm, 0, 6),
51
- /* If the register is banked then we don't need to migrate or
91
+ extract32(a->dbm, 6, 6))) {
52
+ /*
92
+ return false;
53
+ * If the register is banked then we don't need to migrate or
93
+ }
54
* reset the 32-bit instance in certain cases:
94
+ if (!a->sf) {
55
*
95
+ imm &= 0xffffffffull;
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
}
96
}
72
97
73
- /* By convention, for wildcarded registers only the first
98
- if (opc == 0x3) { /* ANDS */
74
+ /*
99
- tcg_rd = cpu_reg(s, rd);
75
+ * By convention, for wildcarded registers only the first
100
- } else {
76
* entry is used for migration; the others are marked as
101
- tcg_rd = cpu_reg_sp(s, rd);
77
* ALIAS so we don't try to transfer the register
102
- }
78
* multiple times. Special registers (ie NOP/WFI) are
103
- tcg_rn = cpu_reg(s, rn);
79
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
104
+ tcg_rd = set_cc ? cpu_reg(s, a->rd) : cpu_reg_sp(s, a->rd);
80
r2->type |= ARM_CP_ALIAS | ARM_CP_NO_GDB;
105
+ tcg_rn = cpu_reg(s, a->rn);
106
107
- if (!logic_imm_decode_wmask(&wmask, is_n, imms, immr)) {
108
- /* some immediate field values are reserved */
109
- unallocated_encoding(s);
110
- return;
111
+ fn(tcg_rd, tcg_rn, imm);
112
+ if (set_cc) {
113
+ gen_logic_CC(a->sf, tcg_rd);
81
}
114
}
82
115
-
83
- /* Check that raw accesses are either forbidden or handled. Note that
116
- if (!sf) {
84
+ /*
117
- wmask &= 0xffffffff;
85
+ * Check that raw accesses are either forbidden or handled. Note that
118
- }
86
* we can't assert this earlier because the setup of fieldoffset for
119
-
87
* banked registers has to be done first.
120
- switch (opc) {
88
*/
121
- case 0x3: /* ANDS */
122
- case 0x0: /* AND */
123
- tcg_gen_andi_i64(tcg_rd, tcg_rn, wmask);
124
- is_and = true;
125
- break;
126
- case 0x1: /* ORR */
127
- tcg_gen_ori_i64(tcg_rd, tcg_rn, wmask);
128
- break;
129
- case 0x2: /* EOR */
130
- tcg_gen_xori_i64(tcg_rd, tcg_rn, wmask);
131
- break;
132
- default:
133
- assert(FALSE); /* must handle all above */
134
- break;
135
- }
136
-
137
- if (!sf && !is_and) {
138
- /* zero extend final result; we know we can skip this for AND
139
- * since the immediate had the high 32 bits clear.
140
- */
141
+ if (!a->sf) {
142
tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
143
}
144
-
145
- if (opc == 3) { /* ANDS */
146
- gen_logic_CC(sf, tcg_rd);
147
- }
148
+ return true;
149
}
150
151
+TRANS(AND_i, gen_rri_log, a, false, tcg_gen_andi_i64)
152
+TRANS(ORR_i, gen_rri_log, a, false, tcg_gen_ori_i64)
153
+TRANS(EOR_i, gen_rri_log, a, false, tcg_gen_xori_i64)
154
+TRANS(ANDS_i, gen_rri_log, a, true, tcg_gen_andi_i64)
155
+
156
/*
157
* Move wide (immediate)
158
*
159
@@ -XXX,XX +XXX,XX @@ static void disas_extract(DisasContext *s, uint32_t insn)
160
static void disas_data_proc_imm(DisasContext *s, uint32_t insn)
161
{
162
switch (extract32(insn, 23, 6)) {
163
- case 0x24: /* Logical (immediate) */
164
- disas_logic_imm(s, insn);
165
- break;
166
case 0x25: /* Move wide (immediate) */
167
disas_movw_imm(s, insn);
168
break;
89
--
169
--
90
2.25.1
170
2.34.1
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
The new_key field is always non-zero -- drop the if.
3
Convert the MON, MOVZ, MOVK instructions.
4
4
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Message-id: 20220501055028.646596-11-richard.henderson@linaro.org
8
Message-id: 20230512144106.3608981-11-peter.maydell@linaro.org
8
[PMM: reinstated dropped PL3_RW mask]
9
[PMM: Rebased]
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
12
---
11
target/arm/helper.c | 23 +++++++++++------------
13
target/arm/tcg/a64.decode | 13 ++++++
12
1 file changed, 11 insertions(+), 12 deletions(-)
14
target/arm/tcg/translate-a64.c | 73 ++++++++++++++--------------------
15
2 files changed, 42 insertions(+), 44 deletions(-)
13
16
14
diff --git a/target/arm/helper.c b/target/arm/helper.c
17
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
15
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/helper.c
19
--- a/target/arm/tcg/a64.decode
17
+++ b/target/arm/helper.c
20
+++ b/target/arm/tcg/a64.decode
18
@@ -XXX,XX +XXX,XX @@ static void define_arm_vh_e2h_redirects_aliases(ARMCPU *cpu)
21
@@ -XXX,XX +XXX,XX @@ EOR_i . 10 100100 . ...... ...... ..... ..... @logic_imm_64
19
22
EOR_i . 10 100100 . ...... ...... ..... ..... @logic_imm_32
20
for (i = 0; i < ARRAY_SIZE(aliases); i++) {
23
ANDS_i . 11 100100 . ...... ...... ..... ..... @logic_imm_64
21
const struct E2HAlias *a = &aliases[i];
24
ANDS_i . 11 100100 . ...... ...... ..... ..... @logic_imm_32
22
- ARMCPRegInfo *src_reg, *dst_reg;
25
+
23
+ ARMCPRegInfo *src_reg, *dst_reg, *new_reg;
26
+# Move wide (immediate)
24
+ uint32_t *new_key;
27
+
25
+ bool ok;
28
+&movw rd sf imm hw
26
29
+@movw_64 1 .. ...... hw:2 imm:16 rd:5 &movw sf=1
27
if (a->feature && !a->feature(&cpu->isar)) {
30
+@movw_32 0 .. ...... 0 hw:1 imm:16 rd:5 &movw sf=0
28
continue;
31
+
29
@@ -XXX,XX +XXX,XX @@ static void define_arm_vh_e2h_redirects_aliases(ARMCPU *cpu)
32
+MOVN . 00 100101 .. ................ ..... @movw_64
30
g_assert(src_reg->opaque == NULL);
33
+MOVN . 00 100101 .. ................ ..... @movw_32
31
34
+MOVZ . 10 100101 .. ................ ..... @movw_64
32
/* Create alias before redirection so we dup the right data. */
35
+MOVZ . 10 100101 .. ................ ..... @movw_32
33
- if (a->new_key) {
36
+MOVK . 11 100101 .. ................ ..... @movw_64
34
- ARMCPRegInfo *new_reg = g_memdup(src_reg, sizeof(ARMCPRegInfo));
37
+MOVK . 11 100101 .. ................ ..... @movw_32
35
- uint32_t *new_key = g_memdup(&a->new_key, sizeof(uint32_t));
38
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
36
- bool ok;
39
index XXXXXXX..XXXXXXX 100644
37
+ new_reg = g_memdup(src_reg, sizeof(ARMCPRegInfo));
40
--- a/target/arm/tcg/translate-a64.c
38
+ new_key = g_memdup(&a->new_key, sizeof(uint32_t));
41
+++ b/target/arm/tcg/translate-a64.c
39
42
@@ -XXX,XX +XXX,XX @@ TRANS(ANDS_i, gen_rri_log, a, true, tcg_gen_andi_i64)
40
- new_reg->name = a->new_name;
43
41
- new_reg->type |= ARM_CP_ALIAS;
44
/*
42
- /* Remove PL1/PL0 access, leaving PL2/PL3 R/W in place. */
45
* Move wide (immediate)
43
- new_reg->access &= PL2_RW | PL3_RW;
46
- *
44
+ new_reg->name = a->new_name;
47
- * 31 30 29 28 23 22 21 20 5 4 0
45
+ new_reg->type |= ARM_CP_ALIAS;
48
- * +--+-----+-------------+-----+----------------+------+
46
+ /* Remove PL1/PL0 access, leaving PL2/PL3 R/W in place. */
49
- * |sf| opc | 1 0 0 1 0 1 | hw | imm16 | Rd |
47
+ new_reg->access &= PL2_RW | PL3_RW;
50
- * +--+-----+-------------+-----+----------------+------+
48
51
- *
49
- ok = g_hash_table_insert(cpu->cp_regs, new_key, new_reg);
52
- * sf: 0 -> 32 bit, 1 -> 64 bit
50
- g_assert(ok);
53
- * opc: 00 -> N, 10 -> Z, 11 -> K
54
- * hw: shift/16 (0,16, and sf only 32, 48)
55
*/
56
-static void disas_movw_imm(DisasContext *s, uint32_t insn)
57
+
58
+static bool trans_MOVZ(DisasContext *s, arg_movw *a)
59
{
60
- int rd = extract32(insn, 0, 5);
61
- uint64_t imm = extract32(insn, 5, 16);
62
- int sf = extract32(insn, 31, 1);
63
- int opc = extract32(insn, 29, 2);
64
- int pos = extract32(insn, 21, 2) << 4;
65
- TCGv_i64 tcg_rd = cpu_reg(s, rd);
66
+ int pos = a->hw << 4;
67
+ tcg_gen_movi_i64(cpu_reg(s, a->rd), (uint64_t)a->imm << pos);
68
+ return true;
69
+}
70
71
- if (!sf && (pos >= 32)) {
72
- unallocated_encoding(s);
73
- return;
74
- }
75
+static bool trans_MOVN(DisasContext *s, arg_movw *a)
76
+{
77
+ int pos = a->hw << 4;
78
+ uint64_t imm = a->imm;
79
80
- switch (opc) {
81
- case 0: /* MOVN */
82
- case 2: /* MOVZ */
83
- imm <<= pos;
84
- if (opc == 0) {
85
- imm = ~imm;
51
- }
86
- }
52
+ ok = g_hash_table_insert(cpu->cp_regs, new_key, new_reg);
87
- if (!sf) {
53
+ g_assert(ok);
88
- imm &= 0xffffffffu;
54
89
- }
55
src_reg->opaque = dst_reg;
90
- tcg_gen_movi_i64(tcg_rd, imm);
56
src_reg->orig_readfn = src_reg->readfn ?: raw_read;
91
- break;
92
- case 3: /* MOVK */
93
- tcg_gen_deposit_i64(tcg_rd, tcg_rd, tcg_constant_i64(imm), pos, 16);
94
- if (!sf) {
95
- tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
96
- }
97
- break;
98
- default:
99
- unallocated_encoding(s);
100
- break;
101
+ imm = ~(imm << pos);
102
+ if (!a->sf) {
103
+ imm = (uint32_t)imm;
104
}
105
+ tcg_gen_movi_i64(cpu_reg(s, a->rd), imm);
106
+ return true;
107
+}
108
+
109
+static bool trans_MOVK(DisasContext *s, arg_movw *a)
110
+{
111
+ int pos = a->hw << 4;
112
+ TCGv_i64 tcg_rd, tcg_im;
113
+
114
+ tcg_rd = cpu_reg(s, a->rd);
115
+ tcg_im = tcg_constant_i64(a->imm);
116
+ tcg_gen_deposit_i64(tcg_rd, tcg_rd, tcg_im, pos, 16);
117
+ if (!a->sf) {
118
+ tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
119
+ }
120
+ return true;
121
}
122
123
/* Bitfield
124
@@ -XXX,XX +XXX,XX @@ static void disas_extract(DisasContext *s, uint32_t insn)
125
static void disas_data_proc_imm(DisasContext *s, uint32_t insn)
126
{
127
switch (extract32(insn, 23, 6)) {
128
- case 0x25: /* Move wide (immediate) */
129
- disas_movw_imm(s, insn);
130
- break;
131
case 0x26: /* Bitfield */
132
disas_bitfield(s, insn);
133
break;
57
--
134
--
58
2.25.1
135
2.34.1
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Perform the override check early, so that it is still done
3
Convert the BFM, SBFM, UBFM instructions.
4
even when we decide to discard an unreachable cpreg.
5
6
Use assert not printf+abort.
7
4
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Message-id: 20220501055028.646596-18-richard.henderson@linaro.org
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Message-id: 20230512144106.3608981-12-peter.maydell@linaro.org
9
[PMM: Rebased]
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
11
---
13
target/arm/helper.c | 22 ++++++++--------------
12
target/arm/tcg/a64.decode | 13 +++
14
1 file changed, 8 insertions(+), 14 deletions(-)
13
target/arm/tcg/translate-a64.c | 144 ++++++++++++++++++---------------
14
2 files changed, 94 insertions(+), 63 deletions(-)
15
15
16
diff --git a/target/arm/helper.c b/target/arm/helper.c
16
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
17
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/helper.c
18
--- a/target/arm/tcg/a64.decode
19
+++ b/target/arm/helper.c
19
+++ b/target/arm/tcg/a64.decode
20
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
20
@@ -XXX,XX +XXX,XX @@ MOVZ . 10 100101 .. ................ ..... @movw_64
21
g_assert_not_reached();
21
MOVZ . 10 100101 .. ................ ..... @movw_32
22
MOVK . 11 100101 .. ................ ..... @movw_64
23
MOVK . 11 100101 .. ................ ..... @movw_32
24
+
25
+# Bitfield
26
+
27
+&bitfield rd rn sf immr imms
28
+@bitfield_64 1 .. ...... 1 immr:6 imms:6 rn:5 rd:5 &bitfield sf=1
29
+@bitfield_32 0 .. ...... 0 0 immr:5 0 imms:5 rn:5 rd:5 &bitfield sf=0
30
+
31
+SBFM . 00 100110 . ...... ...... ..... ..... @bitfield_64
32
+SBFM . 00 100110 . ...... ...... ..... ..... @bitfield_32
33
+BFM . 01 100110 . ...... ...... ..... ..... @bitfield_64
34
+BFM . 01 100110 . ...... ...... ..... ..... @bitfield_32
35
+UBFM . 10 100110 . ...... ...... ..... ..... @bitfield_64
36
+UBFM . 10 100110 . ...... ...... ..... ..... @bitfield_32
37
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
38
index XXXXXXX..XXXXXXX 100644
39
--- a/target/arm/tcg/translate-a64.c
40
+++ b/target/arm/tcg/translate-a64.c
41
@@ -XXX,XX +XXX,XX @@ static bool trans_MOVK(DisasContext *s, arg_movw *a)
42
return true;
43
}
44
45
-/* Bitfield
46
- * 31 30 29 28 23 22 21 16 15 10 9 5 4 0
47
- * +----+-----+-------------+---+------+------+------+------+
48
- * | sf | opc | 1 0 0 1 1 0 | N | immr | imms | Rn | Rd |
49
- * +----+-----+-------------+---+------+------+------+------+
50
+/*
51
+ * Bitfield
52
*/
53
-static void disas_bitfield(DisasContext *s, uint32_t insn)
54
+
55
+static bool trans_SBFM(DisasContext *s, arg_SBFM *a)
56
{
57
- unsigned int sf, n, opc, ri, si, rn, rd, bitsize, pos, len;
58
- TCGv_i64 tcg_rd, tcg_tmp;
59
+ TCGv_i64 tcg_rd = cpu_reg(s, a->rd);
60
+ TCGv_i64 tcg_tmp = read_cpu_reg(s, a->rn, 1);
61
+ unsigned int bitsize = a->sf ? 64 : 32;
62
+ unsigned int ri = a->immr;
63
+ unsigned int si = a->imms;
64
+ unsigned int pos, len;
65
66
- sf = extract32(insn, 31, 1);
67
- opc = extract32(insn, 29, 2);
68
- n = extract32(insn, 22, 1);
69
- ri = extract32(insn, 16, 6);
70
- si = extract32(insn, 10, 6);
71
- rn = extract32(insn, 5, 5);
72
- rd = extract32(insn, 0, 5);
73
- bitsize = sf ? 64 : 32;
74
-
75
- if (sf != n || ri >= bitsize || si >= bitsize || opc > 2) {
76
- unallocated_encoding(s);
77
- return;
78
- }
79
-
80
- tcg_rd = cpu_reg(s, rd);
81
-
82
- /* Suppress the zero-extend for !sf. Since RI and SI are constrained
83
- to be smaller than bitsize, we'll never reference data outside the
84
- low 32-bits anyway. */
85
- tcg_tmp = read_cpu_reg(s, rn, 1);
86
-
87
- /* Recognize simple(r) extractions. */
88
if (si >= ri) {
89
/* Wd<s-r:0> = Wn<s:r> */
90
len = (si - ri) + 1;
91
- if (opc == 0) { /* SBFM: ASR, SBFX, SXTB, SXTH, SXTW */
92
- tcg_gen_sextract_i64(tcg_rd, tcg_tmp, ri, len);
93
- goto done;
94
- } else if (opc == 2) { /* UBFM: UBFX, LSR, UXTB, UXTH */
95
- tcg_gen_extract_i64(tcg_rd, tcg_tmp, ri, len);
96
- return;
97
+ tcg_gen_sextract_i64(tcg_rd, tcg_tmp, ri, len);
98
+ if (!a->sf) {
99
+ tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
100
}
101
- /* opc == 1, BFXIL fall through to deposit */
102
+ } else {
103
+ /* Wd<32+s-r,32-r> = Wn<s:0> */
104
+ len = si + 1;
105
+ pos = (bitsize - ri) & (bitsize - 1);
106
+
107
+ if (len < ri) {
108
+ /*
109
+ * Sign extend the destination field from len to fill the
110
+ * balance of the word. Let the deposit below insert all
111
+ * of those sign bits.
112
+ */
113
+ tcg_gen_sextract_i64(tcg_tmp, tcg_tmp, 0, len);
114
+ len = ri;
115
+ }
116
+
117
+ /*
118
+ * We start with zero, and we haven't modified any bits outside
119
+ * bitsize, therefore no final zero-extension is unneeded for !sf.
120
+ */
121
+ tcg_gen_deposit_z_i64(tcg_rd, tcg_tmp, pos, len);
122
+ }
123
+ return true;
124
+}
125
+
126
+static bool trans_UBFM(DisasContext *s, arg_UBFM *a)
127
+{
128
+ TCGv_i64 tcg_rd = cpu_reg(s, a->rd);
129
+ TCGv_i64 tcg_tmp = read_cpu_reg(s, a->rn, 1);
130
+ unsigned int bitsize = a->sf ? 64 : 32;
131
+ unsigned int ri = a->immr;
132
+ unsigned int si = a->imms;
133
+ unsigned int pos, len;
134
+
135
+ tcg_rd = cpu_reg(s, a->rd);
136
+ tcg_tmp = read_cpu_reg(s, a->rn, 1);
137
+
138
+ if (si >= ri) {
139
+ /* Wd<s-r:0> = Wn<s:r> */
140
+ len = (si - ri) + 1;
141
+ tcg_gen_extract_i64(tcg_rd, tcg_tmp, ri, len);
142
+ } else {
143
+ /* Wd<32+s-r,32-r> = Wn<s:0> */
144
+ len = si + 1;
145
+ pos = (bitsize - ri) & (bitsize - 1);
146
+ tcg_gen_deposit_z_i64(tcg_rd, tcg_tmp, pos, len);
147
+ }
148
+ return true;
149
+}
150
+
151
+static bool trans_BFM(DisasContext *s, arg_BFM *a)
152
+{
153
+ TCGv_i64 tcg_rd = cpu_reg(s, a->rd);
154
+ TCGv_i64 tcg_tmp = read_cpu_reg(s, a->rn, 1);
155
+ unsigned int bitsize = a->sf ? 64 : 32;
156
+ unsigned int ri = a->immr;
157
+ unsigned int si = a->imms;
158
+ unsigned int pos, len;
159
+
160
+ tcg_rd = cpu_reg(s, a->rd);
161
+ tcg_tmp = read_cpu_reg(s, a->rn, 1);
162
+
163
+ if (si >= ri) {
164
+ /* Wd<s-r:0> = Wn<s:r> */
165
tcg_gen_shri_i64(tcg_tmp, tcg_tmp, ri);
166
+ len = (si - ri) + 1;
167
pos = 0;
168
} else {
169
- /* Handle the ri > si case with a deposit
170
- * Wd<32+s-r,32-r> = Wn<s:0>
171
- */
172
+ /* Wd<32+s-r,32-r> = Wn<s:0> */
173
len = si + 1;
174
pos = (bitsize - ri) & (bitsize - 1);
22
}
175
}
23
176
24
+ /* Overriding of an existing definition must be explicitly requested. */
177
- if (opc == 0 && len < ri) {
25
+ if (!(r->type & ARM_CP_OVERRIDE)) {
178
- /* SBFM: sign extend the destination field from len to fill
26
+ const ARMCPRegInfo *oldreg = get_arm_cp_reginfo(cpu->cp_regs, key);
179
- the balance of the word. Let the deposit below insert all
27
+ if (oldreg) {
180
- of those sign bits. */
28
+ assert(oldreg->type & ARM_CP_OVERRIDE);
181
- tcg_gen_sextract_i64(tcg_tmp, tcg_tmp, 0, len);
29
+ }
182
- len = ri;
30
+ }
183
- }
31
+
184
-
32
/* Combine cpreg and name into one allocation. */
185
- if (opc == 1) { /* BFM, BFXIL */
33
name_len = strlen(name) + 1;
186
- tcg_gen_deposit_i64(tcg_rd, tcg_rd, tcg_tmp, pos, len);
34
r2 = g_malloc(sizeof(*r2) + name_len);
187
- } else {
35
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
188
- /* SBFM or UBFM: We start with zero, and we haven't modified
36
assert(!raw_accessors_invalid(r2));
189
- any bits outside bitsize, therefore the zero-extension
190
- below is unneeded. */
191
- tcg_gen_deposit_z_i64(tcg_rd, tcg_tmp, pos, len);
192
- return;
193
- }
194
-
195
- done:
196
- if (!sf) { /* zero extend final result */
197
+ tcg_gen_deposit_i64(tcg_rd, tcg_rd, tcg_tmp, pos, len);
198
+ if (!a->sf) {
199
tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
37
}
200
}
38
201
+ return true;
39
- /* Overriding of an existing definition must be explicitly
40
- * requested.
41
- */
42
- if (!(r->type & ARM_CP_OVERRIDE)) {
43
- const ARMCPRegInfo *oldreg = get_arm_cp_reginfo(cpu->cp_regs, key);
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
}
202
}
55
203
204
/* Extract
205
@@ -XXX,XX +XXX,XX @@ static void disas_extract(DisasContext *s, uint32_t insn)
206
static void disas_data_proc_imm(DisasContext *s, uint32_t insn)
207
{
208
switch (extract32(insn, 23, 6)) {
209
- case 0x26: /* Bitfield */
210
- disas_bitfield(s, insn);
211
- break;
212
case 0x27: /* Extract */
213
disas_extract(s, insn);
214
break;
56
--
215
--
57
2.25.1
216
2.34.1
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
Convert the EXTR instruction to decodetree (this is the
2
only one in the 'Extract" class). This is the last of
3
the dp-immediate insns in the legacy decoder, so we
4
can now remove disas_data_proc_imm().
2
5
3
Cast the uint32_t key into a gpointer directly, which
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
allows us to avoid allocating storage for each key.
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20230512144106.3608981-13-peter.maydell@linaro.org
9
---
10
target/arm/tcg/a64.decode | 7 +++
11
target/arm/tcg/translate-a64.c | 94 +++++++++++-----------------------
12
2 files changed, 36 insertions(+), 65 deletions(-)
5
13
6
Use g_hash_table_lookup when we already have a gpointer
14
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
7
(e.g. for callbacks like count_cpreg), or when using
8
get_arm_cp_reginfo would require casting away const.
9
10
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
Message-id: 20220501055028.646596-12-richard.henderson@linaro.org
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
15
target/arm/cpu.c | 4 ++--
16
target/arm/gdbstub.c | 2 +-
17
target/arm/helper.c | 41 ++++++++++++++++++-----------------------
18
3 files changed, 21 insertions(+), 26 deletions(-)
19
20
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
21
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
22
--- a/target/arm/cpu.c
16
--- a/target/arm/tcg/a64.decode
23
+++ b/target/arm/cpu.c
17
+++ b/target/arm/tcg/a64.decode
24
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_initfn(Object *obj)
18
@@ -XXX,XX +XXX,XX @@ BFM . 01 100110 . ...... ...... ..... ..... @bitfield_64
25
ARMCPU *cpu = ARM_CPU(obj);
19
BFM . 01 100110 . ...... ...... ..... ..... @bitfield_32
26
20
UBFM . 10 100110 . ...... ...... ..... ..... @bitfield_64
27
cpu_set_cpustate_pointers(cpu);
21
UBFM . 10 100110 . ...... ...... ..... ..... @bitfield_32
28
- cpu->cp_regs = g_hash_table_new_full(g_int_hash, g_int_equal,
22
+
29
- g_free, cpreg_hashtable_data_destroy);
23
+# Extract
30
+ cpu->cp_regs = g_hash_table_new_full(g_direct_hash, g_direct_equal,
24
+
31
+ NULL, cpreg_hashtable_data_destroy);
25
+&extract rd rn rm imm sf
32
26
+
33
QLIST_INIT(&cpu->pre_el_change_hooks);
27
+EXTR 1 00 100111 1 0 rm:5 imm:6 rn:5 rd:5 &extract sf=1
34
QLIST_INIT(&cpu->el_change_hooks);
28
+EXTR 0 00 100111 0 0 rm:5 0 imm:5 rn:5 rd:5 &extract sf=0
35
diff --git a/target/arm/gdbstub.c b/target/arm/gdbstub.c
29
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
36
index XXXXXXX..XXXXXXX 100644
30
index XXXXXXX..XXXXXXX 100644
37
--- a/target/arm/gdbstub.c
31
--- a/target/arm/tcg/translate-a64.c
38
+++ b/target/arm/gdbstub.c
32
+++ b/target/arm/tcg/translate-a64.c
39
@@ -XXX,XX +XXX,XX @@ static void arm_gen_one_xml_sysreg_tag(GString *s, DynamicGDBXMLInfo *dyn_xml,
33
@@ -XXX,XX +XXX,XX @@ static bool trans_BFM(DisasContext *s, arg_BFM *a)
40
static void arm_register_sysreg_for_xml(gpointer key, gpointer value,
34
return true;
41
gpointer p)
35
}
36
37
-/* Extract
38
- * 31 30 29 28 23 22 21 20 16 15 10 9 5 4 0
39
- * +----+------+-------------+---+----+------+--------+------+------+
40
- * | sf | op21 | 1 0 0 1 1 1 | N | o0 | Rm | imms | Rn | Rd |
41
- * +----+------+-------------+---+----+------+--------+------+------+
42
- */
43
-static void disas_extract(DisasContext *s, uint32_t insn)
44
+static bool trans_EXTR(DisasContext *s, arg_extract *a)
42
{
45
{
43
- uint32_t ri_key = *(uint32_t *)key;
46
- unsigned int sf, n, rm, imm, rn, rd, bitsize, op21, op0;
44
+ uint32_t ri_key = (uintptr_t)key;
47
+ TCGv_i64 tcg_rd, tcg_rm, tcg_rn;
45
ARMCPRegInfo *ri = value;
48
46
RegisterSysregXmlParam *param = (RegisterSysregXmlParam *)p;
49
- sf = extract32(insn, 31, 1);
47
GString *s = param->s;
50
- n = extract32(insn, 22, 1);
48
diff --git a/target/arm/helper.c b/target/arm/helper.c
51
- rm = extract32(insn, 16, 5);
49
index XXXXXXX..XXXXXXX 100644
52
- imm = extract32(insn, 10, 6);
50
--- a/target/arm/helper.c
53
- rn = extract32(insn, 5, 5);
51
+++ b/target/arm/helper.c
54
- rd = extract32(insn, 0, 5);
52
@@ -XXX,XX +XXX,XX @@ bool write_list_to_cpustate(ARMCPU *cpu)
55
- op21 = extract32(insn, 29, 2);
53
static void add_cpreg_to_list(gpointer key, gpointer opaque)
56
- op0 = extract32(insn, 21, 1);
54
{
57
- bitsize = sf ? 64 : 32;
55
ARMCPU *cpu = opaque;
58
+ tcg_rd = cpu_reg(s, a->rd);
56
- uint64_t regidx;
59
57
- const ARMCPRegInfo *ri;
60
- if (sf != n || op21 || op0 || imm >= bitsize) {
61
- unallocated_encoding(s);
62
- } else {
63
- TCGv_i64 tcg_rd, tcg_rm, tcg_rn;
58
-
64
-
59
- regidx = *(uint32_t *)key;
65
- tcg_rd = cpu_reg(s, rd);
60
- ri = get_arm_cp_reginfo(cpu->cp_regs, regidx);
66
-
61
+ uint32_t regidx = (uintptr_t)key;
67
- if (unlikely(imm == 0)) {
62
+ const ARMCPRegInfo *ri = get_arm_cp_reginfo(cpu->cp_regs, regidx);
68
- /* tcg shl_i32/shl_i64 is undefined for 32/64 bit shifts,
63
69
- * so an extract from bit 0 is a special case.
64
if (!(ri->type & (ARM_CP_NO_RAW|ARM_CP_ALIAS))) {
70
- */
65
cpu->cpreg_indexes[cpu->cpreg_array_len] = cpreg_to_kvm_id(regidx);
71
- if (sf) {
66
@@ -XXX,XX +XXX,XX @@ static void add_cpreg_to_list(gpointer key, gpointer opaque)
72
- tcg_gen_mov_i64(tcg_rd, cpu_reg(s, rm));
67
static void count_cpreg(gpointer key, gpointer opaque)
73
- } else {
68
{
74
- tcg_gen_ext32u_i64(tcg_rd, cpu_reg(s, rm));
69
ARMCPU *cpu = opaque;
75
- }
70
- uint64_t regidx;
76
+ if (unlikely(a->imm == 0)) {
71
const ARMCPRegInfo *ri;
77
+ /*
72
78
+ * tcg shl_i32/shl_i64 is undefined for 32/64 bit shifts,
73
- regidx = *(uint32_t *)key;
79
+ * so an extract from bit 0 is a special case.
74
- ri = get_arm_cp_reginfo(cpu->cp_regs, regidx);
80
+ */
75
+ ri = g_hash_table_lookup(cpu->cp_regs, key);
81
+ if (a->sf) {
76
82
+ tcg_gen_mov_i64(tcg_rd, cpu_reg(s, a->rm));
77
if (!(ri->type & (ARM_CP_NO_RAW|ARM_CP_ALIAS))) {
83
} else {
78
cpu->cpreg_array_len++;
84
- tcg_rm = cpu_reg(s, rm);
79
@@ -XXX,XX +XXX,XX @@ static void count_cpreg(gpointer key, gpointer opaque)
85
- tcg_rn = cpu_reg(s, rn);
80
86
+ tcg_gen_ext32u_i64(tcg_rd, cpu_reg(s, a->rm));
81
static gint cpreg_key_compare(gconstpointer a, gconstpointer b)
87
+ }
82
{
88
+ } else {
83
- uint64_t aidx = cpreg_to_kvm_id(*(uint32_t *)a);
89
+ tcg_rm = cpu_reg(s, a->rm);
84
- uint64_t bidx = cpreg_to_kvm_id(*(uint32_t *)b);
90
+ tcg_rn = cpu_reg(s, a->rn);
85
+ uint64_t aidx = cpreg_to_kvm_id((uintptr_t)a);
91
86
+ uint64_t bidx = cpreg_to_kvm_id((uintptr_t)b);
92
- if (sf) {
87
93
- /* Specialization to ROR happens in EXTRACT2. */
88
if (aidx > bidx) {
94
- tcg_gen_extract2_i64(tcg_rd, tcg_rm, tcg_rn, imm);
89
return 1;
95
+ if (a->sf) {
90
@@ -XXX,XX +XXX,XX @@ static void define_arm_vh_e2h_redirects_aliases(ARMCPU *cpu)
96
+ /* Specialization to ROR happens in EXTRACT2. */
91
for (i = 0; i < ARRAY_SIZE(aliases); i++) {
97
+ tcg_gen_extract2_i64(tcg_rd, tcg_rm, tcg_rn, a->imm);
92
const struct E2HAlias *a = &aliases[i];
98
+ } else {
93
ARMCPRegInfo *src_reg, *dst_reg, *new_reg;
99
+ TCGv_i32 t0 = tcg_temp_new_i32();
94
- uint32_t *new_key;
100
+
95
bool ok;
101
+ tcg_gen_extrl_i64_i32(t0, tcg_rm);
96
102
+ if (a->rm == a->rn) {
97
if (a->feature && !a->feature(&cpu->isar)) {
103
+ tcg_gen_rotri_i32(t0, t0, a->imm);
98
continue;
104
} else {
99
}
105
- TCGv_i32 t0 = tcg_temp_new_i32();
100
106
-
101
- src_reg = g_hash_table_lookup(cpu->cp_regs, &a->src_key);
107
- tcg_gen_extrl_i64_i32(t0, tcg_rm);
102
- dst_reg = g_hash_table_lookup(cpu->cp_regs, &a->dst_key);
108
- if (rm == rn) {
103
+ src_reg = g_hash_table_lookup(cpu->cp_regs,
109
- tcg_gen_rotri_i32(t0, t0, imm);
104
+ (gpointer)(uintptr_t)a->src_key);
110
- } else {
105
+ dst_reg = g_hash_table_lookup(cpu->cp_regs,
111
- TCGv_i32 t1 = tcg_temp_new_i32();
106
+ (gpointer)(uintptr_t)a->dst_key);
112
- tcg_gen_extrl_i64_i32(t1, tcg_rn);
107
g_assert(src_reg != NULL);
113
- tcg_gen_extract2_i32(t0, t0, t1, imm);
108
g_assert(dst_reg != NULL);
114
- }
109
115
- tcg_gen_extu_i32_i64(tcg_rd, t0);
110
@@ -XXX,XX +XXX,XX @@ static void define_arm_vh_e2h_redirects_aliases(ARMCPU *cpu)
116
+ TCGv_i32 t1 = tcg_temp_new_i32();
111
117
+ tcg_gen_extrl_i64_i32(t1, tcg_rn);
112
/* Create alias before redirection so we dup the right data. */
118
+ tcg_gen_extract2_i32(t0, t0, t1, a->imm);
113
new_reg = g_memdup(src_reg, sizeof(ARMCPRegInfo));
119
}
114
- new_key = g_memdup(&a->new_key, sizeof(uint32_t));
120
+ tcg_gen_extu_i32_i64(tcg_rd, t0);
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
}
121
}
163
}
122
}
164
- g_hash_table_insert(cpu->cp_regs, key, r2);
123
-}
165
+ g_hash_table_insert(cpu->cp_regs, (gpointer)(uintptr_t)key, r2);
124
-
125
-/* Data processing - immediate */
126
-static void disas_data_proc_imm(DisasContext *s, uint32_t insn)
127
-{
128
- switch (extract32(insn, 23, 6)) {
129
- case 0x27: /* Extract */
130
- disas_extract(s, insn);
131
- break;
132
- default:
133
- unallocated_encoding(s);
134
- break;
135
- }
136
+ return true;
166
}
137
}
167
138
168
139
/* Shift a TCGv src by TCGv shift_amount, put result in dst.
169
@@ -XXX,XX +XXX,XX @@ void modify_arm_cp_regs_with_len(ARMCPRegInfo *regs, size_t regs_len,
140
@@ -XXX,XX +XXX,XX @@ static bool btype_destination_ok(uint32_t insn, bool bt, int btype)
170
141
static void disas_a64_legacy(DisasContext *s, uint32_t insn)
171
const ARMCPRegInfo *get_arm_cp_reginfo(GHashTable *cpregs, uint32_t encoded_cp)
172
{
142
{
173
- return g_hash_table_lookup(cpregs, &encoded_cp);
143
switch (extract32(insn, 25, 4)) {
174
+ return g_hash_table_lookup(cpregs, (gpointer)(uintptr_t)encoded_cp);
144
- case 0x8: case 0x9: /* Data processing - immediate */
175
}
145
- disas_data_proc_imm(s, insn);
176
146
- break;
177
void arm_cp_write_ignore(CPUARMState *env, const ARMCPRegInfo *ri,
147
case 0xa: case 0xb: /* Branch, exception generation and system insns */
148
disas_b_exc_sys(s, insn);
149
break;
178
--
150
--
179
2.25.1
151
2.34.1
diff view generated by jsdifflib
New patch
1
Convert the unconditional branch immediate insns B and BL to
2
decodetree.
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20230512144106.3608981-14-peter.maydell@linaro.org
7
---
8
target/arm/tcg/a64.decode | 9 +++++++++
9
target/arm/tcg/translate-a64.c | 31 +++++++++++--------------------
10
2 files changed, 20 insertions(+), 20 deletions(-)
11
12
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/tcg/a64.decode
15
+++ b/target/arm/tcg/a64.decode
16
@@ -XXX,XX +XXX,XX @@
17
18
&ri rd imm
19
&rri_sf rd rn imm sf
20
+&i imm
21
22
23
### Data Processing - Immediate
24
@@ -XXX,XX +XXX,XX @@ UBFM . 10 100110 . ...... ...... ..... ..... @bitfield_32
25
26
EXTR 1 00 100111 1 0 rm:5 imm:6 rn:5 rd:5 &extract sf=1
27
EXTR 0 00 100111 0 0 rm:5 0 imm:5 rn:5 rd:5 &extract sf=0
28
+
29
+# Branches
30
+
31
+%imm26 0:s26 !function=times_4
32
+@branch . ..... .......................... &i imm=%imm26
33
+
34
+B 0 00101 .......................... @branch
35
+BL 1 00101 .......................... @branch
36
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
37
index XXXXXXX..XXXXXXX 100644
38
--- a/target/arm/tcg/translate-a64.c
39
+++ b/target/arm/tcg/translate-a64.c
40
@@ -XXX,XX +XXX,XX @@ static inline AArch64DecodeFn *lookup_disas_fn(const AArch64DecodeTable *table,
41
* match up with those in the manual.
42
*/
43
44
-/* Unconditional branch (immediate)
45
- * 31 30 26 25 0
46
- * +----+-----------+-------------------------------------+
47
- * | op | 0 0 1 0 1 | imm26 |
48
- * +----+-----------+-------------------------------------+
49
- */
50
-static void disas_uncond_b_imm(DisasContext *s, uint32_t insn)
51
+static bool trans_B(DisasContext *s, arg_i *a)
52
{
53
- int64_t diff = sextract32(insn, 0, 26) * 4;
54
-
55
- if (insn & (1U << 31)) {
56
- /* BL Branch with link */
57
- gen_pc_plus_diff(s, cpu_reg(s, 30), curr_insn_len(s));
58
- }
59
-
60
- /* B Branch / BL Branch with link */
61
reset_btype(s);
62
- gen_goto_tb(s, 0, diff);
63
+ gen_goto_tb(s, 0, a->imm);
64
+ return true;
65
+}
66
+
67
+static bool trans_BL(DisasContext *s, arg_i *a)
68
+{
69
+ gen_pc_plus_diff(s, cpu_reg(s, 30), curr_insn_len(s));
70
+ reset_btype(s);
71
+ gen_goto_tb(s, 0, a->imm);
72
+ return true;
73
}
74
75
/* Compare and branch (immediate)
76
@@ -XXX,XX +XXX,XX @@ static void disas_uncond_b_reg(DisasContext *s, uint32_t insn)
77
static void disas_b_exc_sys(DisasContext *s, uint32_t insn)
78
{
79
switch (extract32(insn, 25, 7)) {
80
- case 0x0a: case 0x0b:
81
- case 0x4a: case 0x4b: /* Unconditional branch (immediate) */
82
- disas_uncond_b_imm(s, insn);
83
- break;
84
case 0x1a: case 0x5a: /* Compare & branch (immediate) */
85
disas_comp_b_imm(s, insn);
86
break;
87
--
88
2.34.1
diff view generated by jsdifflib
New patch
1
Convert the compare-and-branch-immediate insns CBZ and CBNZ
2
to decodetree.
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20230512144106.3608981-15-peter.maydell@linaro.org
7
---
8
target/arm/tcg/a64.decode | 5 +++++
9
target/arm/tcg/translate-a64.c | 26 ++++++--------------------
10
2 files changed, 11 insertions(+), 20 deletions(-)
11
12
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/tcg/a64.decode
15
+++ b/target/arm/tcg/a64.decode
16
@@ -XXX,XX +XXX,XX @@ EXTR 0 00 100111 0 0 rm:5 0 imm:5 rn:5 rd:5 &extract sf=0
17
18
B 0 00101 .......................... @branch
19
BL 1 00101 .......................... @branch
20
+
21
+%imm19 5:s19 !function=times_4
22
+&cbz rt imm sf nz
23
+
24
+CBZ sf:1 011010 nz:1 ................... rt:5 &cbz imm=%imm19
25
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
26
index XXXXXXX..XXXXXXX 100644
27
--- a/target/arm/tcg/translate-a64.c
28
+++ b/target/arm/tcg/translate-a64.c
29
@@ -XXX,XX +XXX,XX @@ static bool trans_BL(DisasContext *s, arg_i *a)
30
return true;
31
}
32
33
-/* Compare and branch (immediate)
34
- * 31 30 25 24 23 5 4 0
35
- * +----+-------------+----+---------------------+--------+
36
- * | sf | 0 1 1 0 1 0 | op | imm19 | Rt |
37
- * +----+-------------+----+---------------------+--------+
38
- */
39
-static void disas_comp_b_imm(DisasContext *s, uint32_t insn)
40
+
41
+static bool trans_CBZ(DisasContext *s, arg_cbz *a)
42
{
43
- unsigned int sf, op, rt;
44
- int64_t diff;
45
DisasLabel match;
46
TCGv_i64 tcg_cmp;
47
48
- sf = extract32(insn, 31, 1);
49
- op = extract32(insn, 24, 1); /* 0: CBZ; 1: CBNZ */
50
- rt = extract32(insn, 0, 5);
51
- diff = sextract32(insn, 5, 19) * 4;
52
-
53
- tcg_cmp = read_cpu_reg(s, rt, sf);
54
+ tcg_cmp = read_cpu_reg(s, a->rt, a->sf);
55
reset_btype(s);
56
57
match = gen_disas_label(s);
58
- tcg_gen_brcondi_i64(op ? TCG_COND_NE : TCG_COND_EQ,
59
+ tcg_gen_brcondi_i64(a->nz ? TCG_COND_NE : TCG_COND_EQ,
60
tcg_cmp, 0, match.label);
61
gen_goto_tb(s, 0, 4);
62
set_disas_label(s, match);
63
- gen_goto_tb(s, 1, diff);
64
+ gen_goto_tb(s, 1, a->imm);
65
+ return true;
66
}
67
68
/* Test and branch (immediate)
69
@@ -XXX,XX +XXX,XX @@ static void disas_uncond_b_reg(DisasContext *s, uint32_t insn)
70
static void disas_b_exc_sys(DisasContext *s, uint32_t insn)
71
{
72
switch (extract32(insn, 25, 7)) {
73
- case 0x1a: case 0x5a: /* Compare & branch (immediate) */
74
- disas_comp_b_imm(s, insn);
75
- break;
76
case 0x1b: case 0x5b: /* Test & branch (immediate) */
77
disas_test_b_imm(s, insn);
78
break;
79
--
80
2.34.1
diff view generated by jsdifflib
New patch
1
Convert the test-and-branch-immediate insns TBZ and TBNZ
2
to decodetree.
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20230512144106.3608981-16-peter.maydell@linaro.org
7
---
8
target/arm/tcg/a64.decode | 6 ++++++
9
target/arm/tcg/translate-a64.c | 25 +++++--------------------
10
2 files changed, 11 insertions(+), 20 deletions(-)
11
12
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/tcg/a64.decode
15
+++ b/target/arm/tcg/a64.decode
16
@@ -XXX,XX +XXX,XX @@ BL 1 00101 .......................... @branch
17
&cbz rt imm sf nz
18
19
CBZ sf:1 011010 nz:1 ................... rt:5 &cbz imm=%imm19
20
+
21
+%imm14 5:s14 !function=times_4
22
+%imm31_19 31:1 19:5
23
+&tbz rt imm nz bitpos
24
+
25
+TBZ . 011011 nz:1 ..... .............. rt:5 &tbz imm=%imm14 bitpos=%imm31_19
26
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
27
index XXXXXXX..XXXXXXX 100644
28
--- a/target/arm/tcg/translate-a64.c
29
+++ b/target/arm/tcg/translate-a64.c
30
@@ -XXX,XX +XXX,XX @@ static bool trans_CBZ(DisasContext *s, arg_cbz *a)
31
return true;
32
}
33
34
-/* Test and branch (immediate)
35
- * 31 30 25 24 23 19 18 5 4 0
36
- * +----+-------------+----+-------+-------------+------+
37
- * | b5 | 0 1 1 0 1 1 | op | b40 | imm14 | Rt |
38
- * +----+-------------+----+-------+-------------+------+
39
- */
40
-static void disas_test_b_imm(DisasContext *s, uint32_t insn)
41
+static bool trans_TBZ(DisasContext *s, arg_tbz *a)
42
{
43
- unsigned int bit_pos, op, rt;
44
- int64_t diff;
45
DisasLabel match;
46
TCGv_i64 tcg_cmp;
47
48
- bit_pos = (extract32(insn, 31, 1) << 5) | extract32(insn, 19, 5);
49
- op = extract32(insn, 24, 1); /* 0: TBZ; 1: TBNZ */
50
- diff = sextract32(insn, 5, 14) * 4;
51
- rt = extract32(insn, 0, 5);
52
-
53
tcg_cmp = tcg_temp_new_i64();
54
- tcg_gen_andi_i64(tcg_cmp, cpu_reg(s, rt), (1ULL << bit_pos));
55
+ tcg_gen_andi_i64(tcg_cmp, cpu_reg(s, a->rt), 1ULL << a->bitpos);
56
57
reset_btype(s);
58
59
match = gen_disas_label(s);
60
- tcg_gen_brcondi_i64(op ? TCG_COND_NE : TCG_COND_EQ,
61
+ tcg_gen_brcondi_i64(a->nz ? TCG_COND_NE : TCG_COND_EQ,
62
tcg_cmp, 0, match.label);
63
gen_goto_tb(s, 0, 4);
64
set_disas_label(s, match);
65
- gen_goto_tb(s, 1, diff);
66
+ gen_goto_tb(s, 1, a->imm);
67
+ return true;
68
}
69
70
/* Conditional branch (immediate)
71
@@ -XXX,XX +XXX,XX @@ static void disas_uncond_b_reg(DisasContext *s, uint32_t insn)
72
static void disas_b_exc_sys(DisasContext *s, uint32_t insn)
73
{
74
switch (extract32(insn, 25, 7)) {
75
- case 0x1b: case 0x5b: /* Test & branch (immediate) */
76
- disas_test_b_imm(s, insn);
77
- break;
78
case 0x2a: /* Conditional branch (immediate) */
79
disas_cond_b_imm(s, insn);
80
break;
81
--
82
2.34.1
diff view generated by jsdifflib
New patch
1
Convert the immediate conditional branch insn B.cond to
2
decodetree.
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20230512144106.3608981-17-peter.maydell@linaro.org
7
---
8
target/arm/tcg/a64.decode | 2 ++
9
target/arm/tcg/translate-a64.c | 30 ++++++------------------------
10
2 files changed, 8 insertions(+), 24 deletions(-)
11
12
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/tcg/a64.decode
15
+++ b/target/arm/tcg/a64.decode
16
@@ -XXX,XX +XXX,XX @@ CBZ sf:1 011010 nz:1 ................... rt:5 &cbz imm=%imm19
17
&tbz rt imm nz bitpos
18
19
TBZ . 011011 nz:1 ..... .............. rt:5 &tbz imm=%imm14 bitpos=%imm31_19
20
+
21
+B_cond 0101010 0 ................... 0 cond:4 imm=%imm19
22
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
23
index XXXXXXX..XXXXXXX 100644
24
--- a/target/arm/tcg/translate-a64.c
25
+++ b/target/arm/tcg/translate-a64.c
26
@@ -XXX,XX +XXX,XX @@ static bool trans_TBZ(DisasContext *s, arg_tbz *a)
27
return true;
28
}
29
30
-/* Conditional branch (immediate)
31
- * 31 25 24 23 5 4 3 0
32
- * +---------------+----+---------------------+----+------+
33
- * | 0 1 0 1 0 1 0 | o1 | imm19 | o0 | cond |
34
- * +---------------+----+---------------------+----+------+
35
- */
36
-static void disas_cond_b_imm(DisasContext *s, uint32_t insn)
37
+static bool trans_B_cond(DisasContext *s, arg_B_cond *a)
38
{
39
- unsigned int cond;
40
- int64_t diff;
41
-
42
- if ((insn & (1 << 4)) || (insn & (1 << 24))) {
43
- unallocated_encoding(s);
44
- return;
45
- }
46
- diff = sextract32(insn, 5, 19) * 4;
47
- cond = extract32(insn, 0, 4);
48
-
49
reset_btype(s);
50
- if (cond < 0x0e) {
51
+ if (a->cond < 0x0e) {
52
/* genuinely conditional branches */
53
DisasLabel match = gen_disas_label(s);
54
- arm_gen_test_cc(cond, match.label);
55
+ arm_gen_test_cc(a->cond, match.label);
56
gen_goto_tb(s, 0, 4);
57
set_disas_label(s, match);
58
- gen_goto_tb(s, 1, diff);
59
+ gen_goto_tb(s, 1, a->imm);
60
} else {
61
/* 0xe and 0xf are both "always" conditions */
62
- gen_goto_tb(s, 0, diff);
63
+ gen_goto_tb(s, 0, a->imm);
64
}
65
+ return true;
66
}
67
68
/* HINT instruction group, including various allocated HINTs */
69
@@ -XXX,XX +XXX,XX @@ static void disas_uncond_b_reg(DisasContext *s, uint32_t insn)
70
static void disas_b_exc_sys(DisasContext *s, uint32_t insn)
71
{
72
switch (extract32(insn, 25, 7)) {
73
- case 0x2a: /* Conditional branch (immediate) */
74
- disas_cond_b_imm(s, insn);
75
- break;
76
case 0x6a: /* Exception generation / System */
77
if (insn & (1 << 24)) {
78
if (extract32(insn, 22, 2) == 0) {
79
--
80
2.34.1
diff view generated by jsdifflib
New patch
1
Convert the simple (non-pointer-auth) BR, BLR and RET insns
2
to decodetree.
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20230512144106.3608981-18-peter.maydell@linaro.org
7
---
8
target/arm/tcg/a64.decode | 5 ++++
9
target/arm/tcg/translate-a64.c | 55 ++++++++++++++++++++++++++++++----
10
2 files changed, 54 insertions(+), 6 deletions(-)
11
12
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/tcg/a64.decode
15
+++ b/target/arm/tcg/a64.decode
16
@@ -XXX,XX +XXX,XX @@
17
# This file is processed by scripts/decodetree.py
18
#
19
20
+&r rn
21
&ri rd imm
22
&rri_sf rd rn imm sf
23
&i imm
24
@@ -XXX,XX +XXX,XX @@ CBZ sf:1 011010 nz:1 ................... rt:5 &cbz imm=%imm19
25
TBZ . 011011 nz:1 ..... .............. rt:5 &tbz imm=%imm14 bitpos=%imm31_19
26
27
B_cond 0101010 0 ................... 0 cond:4 imm=%imm19
28
+
29
+BR 1101011 0000 11111 000000 rn:5 00000 &r
30
+BLR 1101011 0001 11111 000000 rn:5 00000 &r
31
+RET 1101011 0010 11111 000000 rn:5 00000 &r
32
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
33
index XXXXXXX..XXXXXXX 100644
34
--- a/target/arm/tcg/translate-a64.c
35
+++ b/target/arm/tcg/translate-a64.c
36
@@ -XXX,XX +XXX,XX @@ static bool trans_B_cond(DisasContext *s, arg_B_cond *a)
37
return true;
38
}
39
40
+static void set_btype_for_br(DisasContext *s, int rn)
41
+{
42
+ if (dc_isar_feature(aa64_bti, s)) {
43
+ /* BR to {x16,x17} or !guard -> 1, else 3. */
44
+ set_btype(s, rn == 16 || rn == 17 || !s->guarded_page ? 1 : 3);
45
+ }
46
+}
47
+
48
+static void set_btype_for_blr(DisasContext *s)
49
+{
50
+ if (dc_isar_feature(aa64_bti, s)) {
51
+ /* BLR sets BTYPE to 2, regardless of source guarded page. */
52
+ set_btype(s, 2);
53
+ }
54
+}
55
+
56
+static bool trans_BR(DisasContext *s, arg_r *a)
57
+{
58
+ gen_a64_set_pc(s, cpu_reg(s, a->rn));
59
+ set_btype_for_br(s, a->rn);
60
+ s->base.is_jmp = DISAS_JUMP;
61
+ return true;
62
+}
63
+
64
+static bool trans_BLR(DisasContext *s, arg_r *a)
65
+{
66
+ TCGv_i64 dst = cpu_reg(s, a->rn);
67
+ TCGv_i64 lr = cpu_reg(s, 30);
68
+ if (dst == lr) {
69
+ TCGv_i64 tmp = tcg_temp_new_i64();
70
+ tcg_gen_mov_i64(tmp, dst);
71
+ dst = tmp;
72
+ }
73
+ gen_pc_plus_diff(s, lr, curr_insn_len(s));
74
+ gen_a64_set_pc(s, dst);
75
+ set_btype_for_blr(s);
76
+ s->base.is_jmp = DISAS_JUMP;
77
+ return true;
78
+}
79
+
80
+static bool trans_RET(DisasContext *s, arg_r *a)
81
+{
82
+ gen_a64_set_pc(s, cpu_reg(s, a->rn));
83
+ s->base.is_jmp = DISAS_JUMP;
84
+ return true;
85
+}
86
+
87
/* HINT instruction group, including various allocated HINTs */
88
static void handle_hint(DisasContext *s, uint32_t insn,
89
unsigned int op1, unsigned int op2, unsigned int crm)
90
@@ -XXX,XX +XXX,XX @@ static void disas_uncond_b_reg(DisasContext *s, uint32_t insn)
91
btype_mod = opc;
92
switch (op3) {
93
case 0:
94
- /* BR, BLR, RET */
95
- if (op4 != 0) {
96
- goto do_unallocated;
97
- }
98
- dst = cpu_reg(s, rn);
99
- break;
100
+ /* BR, BLR, RET : handled in decodetree */
101
+ goto do_unallocated;
102
103
case 2:
104
case 3:
105
--
106
2.34.1
diff view generated by jsdifflib
New patch
1
Convert the single-register pointer-authentication variants of BR,
2
BLR, RET to decodetree. (BRAA/BLRAA are in a different branch of
3
the legacy decoder and will be dealt with in the next commit.)
1
4
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20230512144106.3608981-19-peter.maydell@linaro.org
8
---
9
target/arm/tcg/a64.decode | 7 ++
10
target/arm/tcg/translate-a64.c | 132 +++++++++++++++++++--------------
11
2 files changed, 84 insertions(+), 55 deletions(-)
12
13
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/tcg/a64.decode
16
+++ b/target/arm/tcg/a64.decode
17
@@ -XXX,XX +XXX,XX @@ B_cond 0101010 0 ................... 0 cond:4 imm=%imm19
18
BR 1101011 0000 11111 000000 rn:5 00000 &r
19
BLR 1101011 0001 11111 000000 rn:5 00000 &r
20
RET 1101011 0010 11111 000000 rn:5 00000 &r
21
+
22
+&braz rn m
23
+BRAZ 1101011 0000 11111 00001 m:1 rn:5 11111 &braz # BRAAZ, BRABZ
24
+BLRAZ 1101011 0001 11111 00001 m:1 rn:5 11111 &braz # BLRAAZ, BLRABZ
25
+
26
+&reta m
27
+RETA 1101011 0010 11111 00001 m:1 11111 11111 &reta # RETAA, RETAB
28
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
29
index XXXXXXX..XXXXXXX 100644
30
--- a/target/arm/tcg/translate-a64.c
31
+++ b/target/arm/tcg/translate-a64.c
32
@@ -XXX,XX +XXX,XX @@ static bool trans_RET(DisasContext *s, arg_r *a)
33
return true;
34
}
35
36
+static TCGv_i64 auth_branch_target(DisasContext *s, TCGv_i64 dst,
37
+ TCGv_i64 modifier, bool use_key_a)
38
+{
39
+ TCGv_i64 truedst;
40
+ /*
41
+ * Return the branch target for a BRAA/RETA/etc, which is either
42
+ * just the destination dst, or that value with the pauth check
43
+ * done and the code removed from the high bits.
44
+ */
45
+ if (!s->pauth_active) {
46
+ return dst;
47
+ }
48
+
49
+ truedst = tcg_temp_new_i64();
50
+ if (use_key_a) {
51
+ gen_helper_autia(truedst, cpu_env, dst, modifier);
52
+ } else {
53
+ gen_helper_autib(truedst, cpu_env, dst, modifier);
54
+ }
55
+ return truedst;
56
+}
57
+
58
+static bool trans_BRAZ(DisasContext *s, arg_braz *a)
59
+{
60
+ TCGv_i64 dst;
61
+
62
+ if (!dc_isar_feature(aa64_pauth, s)) {
63
+ return false;
64
+ }
65
+
66
+ dst = auth_branch_target(s, cpu_reg(s, a->rn), tcg_constant_i64(0), !a->m);
67
+ gen_a64_set_pc(s, dst);
68
+ set_btype_for_br(s, a->rn);
69
+ s->base.is_jmp = DISAS_JUMP;
70
+ return true;
71
+}
72
+
73
+static bool trans_BLRAZ(DisasContext *s, arg_braz *a)
74
+{
75
+ TCGv_i64 dst, lr;
76
+
77
+ if (!dc_isar_feature(aa64_pauth, s)) {
78
+ return false;
79
+ }
80
+
81
+ dst = auth_branch_target(s, cpu_reg(s, a->rn), tcg_constant_i64(0), !a->m);
82
+ lr = cpu_reg(s, 30);
83
+ if (dst == lr) {
84
+ TCGv_i64 tmp = tcg_temp_new_i64();
85
+ tcg_gen_mov_i64(tmp, dst);
86
+ dst = tmp;
87
+ }
88
+ gen_pc_plus_diff(s, lr, curr_insn_len(s));
89
+ gen_a64_set_pc(s, dst);
90
+ set_btype_for_blr(s);
91
+ s->base.is_jmp = DISAS_JUMP;
92
+ return true;
93
+}
94
+
95
+static bool trans_RETA(DisasContext *s, arg_reta *a)
96
+{
97
+ TCGv_i64 dst;
98
+
99
+ dst = auth_branch_target(s, cpu_reg(s, 30), cpu_X[31], !a->m);
100
+ gen_a64_set_pc(s, dst);
101
+ s->base.is_jmp = DISAS_JUMP;
102
+ return true;
103
+}
104
+
105
/* HINT instruction group, including various allocated HINTs */
106
static void handle_hint(DisasContext *s, uint32_t insn,
107
unsigned int op1, unsigned int op2, unsigned int crm)
108
@@ -XXX,XX +XXX,XX @@ static void disas_uncond_b_reg(DisasContext *s, uint32_t insn)
109
}
110
111
switch (opc) {
112
- case 0: /* BR */
113
- case 1: /* BLR */
114
- case 2: /* RET */
115
- btype_mod = opc;
116
- switch (op3) {
117
- case 0:
118
- /* BR, BLR, RET : handled in decodetree */
119
- goto do_unallocated;
120
-
121
- case 2:
122
- case 3:
123
- if (!dc_isar_feature(aa64_pauth, s)) {
124
- goto do_unallocated;
125
- }
126
- if (opc == 2) {
127
- /* RETAA, RETAB */
128
- if (rn != 0x1f || op4 != 0x1f) {
129
- goto do_unallocated;
130
- }
131
- rn = 30;
132
- modifier = cpu_X[31];
133
- } else {
134
- /* BRAAZ, BRABZ, BLRAAZ, BLRABZ */
135
- if (op4 != 0x1f) {
136
- goto do_unallocated;
137
- }
138
- modifier = tcg_constant_i64(0);
139
- }
140
- if (s->pauth_active) {
141
- dst = tcg_temp_new_i64();
142
- if (op3 == 2) {
143
- gen_helper_autia(dst, cpu_env, cpu_reg(s, rn), modifier);
144
- } else {
145
- gen_helper_autib(dst, cpu_env, cpu_reg(s, rn), modifier);
146
- }
147
- } else {
148
- dst = cpu_reg(s, rn);
149
- }
150
- break;
151
-
152
- default:
153
- goto do_unallocated;
154
- }
155
- /* BLR also needs to load return address */
156
- if (opc == 1) {
157
- TCGv_i64 lr = cpu_reg(s, 30);
158
- if (dst == lr) {
159
- TCGv_i64 tmp = tcg_temp_new_i64();
160
- tcg_gen_mov_i64(tmp, dst);
161
- dst = tmp;
162
- }
163
- gen_pc_plus_diff(s, lr, curr_insn_len(s));
164
- }
165
- gen_a64_set_pc(s, dst);
166
- break;
167
+ case 0:
168
+ case 1:
169
+ case 2:
170
+ /*
171
+ * BR, BLR, RET, RETAA, RETAB, BRAAZ, BRABZ, BLRAAZ, BLRABZ:
172
+ * handled in decodetree
173
+ */
174
+ goto do_unallocated;
175
176
case 8: /* BRAA */
177
case 9: /* BLRAA */
178
--
179
2.34.1
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
Convert the last four BR-with-pointer-auth insns to decodetree.
2
The remaining cases in the outer switch in disas_uncond_b_reg()
3
all return early rather than leaving the case statement, so we
4
can delete the now-unused code at the end of that function.
2
5
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20220501055028.646596-24-richard.henderson@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20230512144106.3608981-20-peter.maydell@linaro.org
7
---
9
---
8
target/arm/cpu.h | 15 +++++++++++++++
10
target/arm/tcg/a64.decode | 4 ++
9
1 file changed, 15 insertions(+)
11
target/arm/tcg/translate-a64.c | 97 ++++++++++++++--------------------
12
2 files changed, 43 insertions(+), 58 deletions(-)
10
13
11
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
14
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
12
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
13
--- a/target/arm/cpu.h
16
--- a/target/arm/tcg/a64.decode
14
+++ b/target/arm/cpu.h
17
+++ b/target/arm/tcg/a64.decode
15
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa32_ssbs(const ARMISARegisters *id)
18
@@ -XXX,XX +XXX,XX @@ BLRAZ 1101011 0001 11111 00001 m:1 rn:5 11111 &braz # BLRAAZ, BLRABZ
16
return FIELD_EX32(id->id_pfr2, ID_PFR2, SSBS) != 0;
19
20
&reta m
21
RETA 1101011 0010 11111 00001 m:1 11111 11111 &reta # RETAA, RETAB
22
+
23
+&bra rn rm m
24
+BRA 1101011 1000 11111 00001 m:1 rn:5 rm:5 &bra # BRAA, BRAB
25
+BLRA 1101011 1001 11111 00001 m:1 rn:5 rm:5 &bra # BLRAA, BLRAB
26
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
27
index XXXXXXX..XXXXXXX 100644
28
--- a/target/arm/tcg/translate-a64.c
29
+++ b/target/arm/tcg/translate-a64.c
30
@@ -XXX,XX +XXX,XX @@ static bool trans_RETA(DisasContext *s, arg_reta *a)
31
return true;
17
}
32
}
18
33
19
+static inline bool isar_feature_aa32_debugv8p2(const ARMISARegisters *id)
34
+static bool trans_BRA(DisasContext *s, arg_bra *a)
20
+{
35
+{
21
+ return FIELD_EX32(id->id_dfr0, ID_DFR0, COPDBG) >= 8;
36
+ TCGv_i64 dst;
37
+
38
+ if (!dc_isar_feature(aa64_pauth, s)) {
39
+ return false;
40
+ }
41
+ dst = auth_branch_target(s, cpu_reg(s,a->rn), cpu_reg_sp(s, a->rm), !a->m);
42
+ gen_a64_set_pc(s, dst);
43
+ set_btype_for_br(s, a->rn);
44
+ s->base.is_jmp = DISAS_JUMP;
45
+ return true;
22
+}
46
+}
23
+
47
+
24
/*
48
+static bool trans_BLRA(DisasContext *s, arg_bra *a)
25
* 64-bit feature tests via id registers.
26
*/
27
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa64_ssbs(const ARMISARegisters *id)
28
return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, SSBS) != 0;
29
}
30
31
+static inline bool isar_feature_aa64_debugv8p2(const ARMISARegisters *id)
32
+{
49
+{
33
+ return FIELD_EX64(id->id_aa64dfr0, ID_AA64DFR0, DEBUGVER) >= 8;
50
+ TCGv_i64 dst, lr;
51
+
52
+ if (!dc_isar_feature(aa64_pauth, s)) {
53
+ return false;
54
+ }
55
+ dst = auth_branch_target(s, cpu_reg(s, a->rn), cpu_reg_sp(s, a->rm), !a->m);
56
+ lr = cpu_reg(s, 30);
57
+ if (dst == lr) {
58
+ TCGv_i64 tmp = tcg_temp_new_i64();
59
+ tcg_gen_mov_i64(tmp, dst);
60
+ dst = tmp;
61
+ }
62
+ gen_pc_plus_diff(s, lr, curr_insn_len(s));
63
+ gen_a64_set_pc(s, dst);
64
+ set_btype_for_blr(s);
65
+ s->base.is_jmp = DISAS_JUMP;
66
+ return true;
34
+}
67
+}
35
+
68
+
36
static inline bool isar_feature_aa64_sve2(const ARMISARegisters *id)
69
/* HINT instruction group, including various allocated HINTs */
70
static void handle_hint(DisasContext *s, uint32_t insn,
71
unsigned int op1, unsigned int op2, unsigned int crm)
72
@@ -XXX,XX +XXX,XX @@ static void disas_exc(DisasContext *s, uint32_t insn)
73
static void disas_uncond_b_reg(DisasContext *s, uint32_t insn)
37
{
74
{
38
return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, SVEVER) != 0;
75
unsigned int opc, op2, op3, rn, op4;
39
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_any_tts2uxn(const ARMISARegisters *id)
76
- unsigned btype_mod = 2; /* 0: BR, 1: BLR, 2: other */
40
return isar_feature_aa64_tts2uxn(id) || isar_feature_aa32_tts2uxn(id);
77
TCGv_i64 dst;
78
TCGv_i64 modifier;
79
80
@@ -XXX,XX +XXX,XX @@ static void disas_uncond_b_reg(DisasContext *s, uint32_t insn)
81
case 0:
82
case 1:
83
case 2:
84
+ case 8:
85
+ case 9:
86
/*
87
- * BR, BLR, RET, RETAA, RETAB, BRAAZ, BRABZ, BLRAAZ, BLRABZ:
88
- * handled in decodetree
89
+ * BR, BLR, RET, RETAA, RETAB, BRAAZ, BRABZ, BLRAAZ, BLRABZ,
90
+ * BRAA, BLRAA: handled in decodetree
91
*/
92
goto do_unallocated;
93
94
- case 8: /* BRAA */
95
- case 9: /* BLRAA */
96
- if (!dc_isar_feature(aa64_pauth, s)) {
97
- goto do_unallocated;
98
- }
99
- if ((op3 & ~1) != 2) {
100
- goto do_unallocated;
101
- }
102
- btype_mod = opc & 1;
103
- if (s->pauth_active) {
104
- dst = tcg_temp_new_i64();
105
- modifier = cpu_reg_sp(s, op4);
106
- if (op3 == 2) {
107
- gen_helper_autia(dst, cpu_env, cpu_reg(s, rn), modifier);
108
- } else {
109
- gen_helper_autib(dst, cpu_env, cpu_reg(s, rn), modifier);
110
- }
111
- } else {
112
- dst = cpu_reg(s, rn);
113
- }
114
- /* BLRAA also needs to load return address */
115
- if (opc == 9) {
116
- TCGv_i64 lr = cpu_reg(s, 30);
117
- if (dst == lr) {
118
- TCGv_i64 tmp = tcg_temp_new_i64();
119
- tcg_gen_mov_i64(tmp, dst);
120
- dst = tmp;
121
- }
122
- gen_pc_plus_diff(s, lr, curr_insn_len(s));
123
- }
124
- gen_a64_set_pc(s, dst);
125
- break;
126
-
127
case 4: /* ERET */
128
if (s->current_el == 0) {
129
goto do_unallocated;
130
@@ -XXX,XX +XXX,XX @@ static void disas_uncond_b_reg(DisasContext *s, uint32_t insn)
131
unallocated_encoding(s);
132
return;
133
}
134
-
135
- switch (btype_mod) {
136
- case 0: /* BR */
137
- if (dc_isar_feature(aa64_bti, s)) {
138
- /* BR to {x16,x17} or !guard -> 1, else 3. */
139
- set_btype(s, rn == 16 || rn == 17 || !s->guarded_page ? 1 : 3);
140
- }
141
- break;
142
-
143
- case 1: /* BLR */
144
- if (dc_isar_feature(aa64_bti, s)) {
145
- /* BLR sets BTYPE to 2, regardless of source guarded page. */
146
- set_btype(s, 2);
147
- }
148
- break;
149
-
150
- default: /* RET or none of the above. */
151
- /* BTYPE will be set to 0 by normal end-of-insn processing. */
152
- break;
153
- }
154
-
155
- s->base.is_jmp = DISAS_JUMP;
41
}
156
}
42
157
43
+static inline bool isar_feature_any_debugv8p2(const ARMISARegisters *id)
158
/* Branches, exception generating and system instructions */
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
--
159
--
52
2.25.1
160
2.34.1
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
Convert the exception-return insns ERET, ERETA and ERETB to
2
decodetree. These were the last insns left in the legacy
3
decoder function disas_uncond_reg_b(), which allows us to
4
remove it.
2
5
3
Standardize on g_assert_not_reached() for "should not happen".
6
The old decoder explicitly decoded the DRPS instruction,
4
Retain abort() when preceeded by fprintf or error_report.
7
only in order to call unallocated_encoding() on it, exactly
8
as would have happened if it hadn't decoded it. This is
9
because this insn always UNDEFs unless the CPU is in
10
halting-debug state, which we don't emulate. So we list
11
the pattern in a comment in a64.decode, but don't actively
12
decode it.
5
13
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Message-id: 20220501055028.646596-7-richard.henderson@linaro.org
9
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: 20230512144106.3608981-21-peter.maydell@linaro.org
10
---
17
---
11
target/arm/helper.c | 7 +++----
18
target/arm/tcg/a64.decode | 8 ++
12
target/arm/hvf/hvf.c | 2 +-
19
target/arm/tcg/translate-a64.c | 163 +++++++++++----------------------
13
target/arm/kvm-stub.c | 4 ++--
20
2 files changed, 63 insertions(+), 108 deletions(-)
14
target/arm/kvm.c | 4 ++--
15
target/arm/machine.c | 4 ++--
16
target/arm/translate-a64.c | 4 ++--
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/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
22
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
23
--- a/target/arm/helper.c
24
--- a/target/arm/tcg/a64.decode
24
+++ b/target/arm/helper.c
25
+++ b/target/arm/tcg/a64.decode
25
@@ -XXX,XX +XXX,XX @@ void define_one_arm_cp_reg_with_opaque(ARMCPU *cpu,
26
@@ -XXX,XX +XXX,XX @@ RETA 1101011 0010 11111 00001 m:1 11111 11111 &reta # RETAA, RETAB
26
break;
27
&bra rn rm m
27
default:
28
BRA 1101011 1000 11111 00001 m:1 rn:5 rm:5 &bra # BRAA, BRAB
28
/* broken reginfo with out-of-range opc1 */
29
BLRA 1101011 1001 11111 00001 m:1 rn:5 rm:5 &bra # BLRAA, BLRAB
29
- assert(false);
30
+
30
- break;
31
+ERET 1101011 0100 11111 000000 11111 00000
31
+ g_assert_not_reached();
32
+ERETA 1101011 0100 11111 00001 m:1 11111 11111 &reta # ERETAA, ERETAB
32
}
33
+
33
/* assert our permissions are not too lax (stricter is fine) */
34
+# We don't need to decode DRPS because it always UNDEFs except when
34
assert((r->access & ~mask) == 0);
35
+# the processor is in halting debug state (which we don't implement).
35
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_v5(CPUARMState *env, uint32_t address,
36
+# The pattern is listed here as documentation.
36
break;
37
+# DRPS 1101011 0101 11111 000000 11111 00000
37
default:
38
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
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
39
index XXXXXXX..XXXXXXX 100644
55
--- a/target/arm/hvf/hvf.c
40
--- a/target/arm/tcg/translate-a64.c
56
+++ b/target/arm/hvf/hvf.c
41
+++ b/target/arm/tcg/translate-a64.c
57
@@ -XXX,XX +XXX,XX @@ int hvf_vcpu_exec(CPUState *cpu)
42
@@ -XXX,XX +XXX,XX @@ static bool trans_BLRA(DisasContext *s, arg_bra *a)
58
/* we got kicked, no exit to process */
43
return true;
59
return 0;
60
default:
61
- assert(0);
62
+ g_assert_not_reached();
63
}
64
65
hvf_sync_vtimer(cpu);
66
diff --git a/target/arm/kvm-stub.c b/target/arm/kvm-stub.c
67
index XXXXXXX..XXXXXXX 100644
68
--- a/target/arm/kvm-stub.c
69
+++ b/target/arm/kvm-stub.c
70
@@ -XXX,XX +XXX,XX @@
71
72
bool write_kvmstate_to_list(ARMCPU *cpu)
73
{
74
- abort();
75
+ g_assert_not_reached();
76
}
44
}
77
45
78
bool write_list_to_kvmstate(ARMCPU *cpu, int level)
46
+static bool trans_ERET(DisasContext *s, arg_ERET *a)
79
{
47
+{
80
- abort();
48
+ TCGv_i64 dst;
81
+ g_assert_not_reached();
49
+
82
}
50
+ if (s->current_el == 0) {
83
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
51
+ return false;
84
index XXXXXXX..XXXXXXX 100644
52
+ }
85
--- a/target/arm/kvm.c
53
+ if (s->fgt_eret) {
86
+++ b/target/arm/kvm.c
54
+ gen_exception_insn_el(s, 0, EXCP_UDEF, 0, 2);
87
@@ -XXX,XX +XXX,XX @@ bool write_kvmstate_to_list(ARMCPU *cpu)
55
+ return true;
88
ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &r);
56
+ }
89
break;
57
+ dst = tcg_temp_new_i64();
90
default:
58
+ tcg_gen_ld_i64(dst, cpu_env,
91
- abort();
59
+ offsetof(CPUARMState, elr_el[s->current_el]));
92
+ g_assert_not_reached();
60
+
93
}
61
+ if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
94
if (ret) {
62
+ gen_io_start();
95
ok = false;
63
+ }
96
@@ -XXX,XX +XXX,XX @@ bool write_list_to_kvmstate(ARMCPU *cpu, int level)
64
+
97
r.addr = (uintptr_t)(cpu->cpreg_values + i);
65
+ gen_helper_exception_return(cpu_env, dst);
98
break;
66
+ /* Must exit loop to check un-masked IRQs */
99
default:
67
+ s->base.is_jmp = DISAS_EXIT;
100
- abort();
68
+ return true;
101
+ g_assert_not_reached();
69
+}
102
}
70
+
103
ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &r);
71
+static bool trans_ERETA(DisasContext *s, arg_reta *a)
104
if (ret) {
72
+{
105
diff --git a/target/arm/machine.c b/target/arm/machine.c
73
+ TCGv_i64 dst;
106
index XXXXXXX..XXXXXXX 100644
74
+
107
--- a/target/arm/machine.c
75
+ if (!dc_isar_feature(aa64_pauth, s)) {
108
+++ b/target/arm/machine.c
76
+ return false;
109
@@ -XXX,XX +XXX,XX @@ static int cpu_pre_save(void *opaque)
77
+ }
110
if (kvm_enabled()) {
78
+ if (s->current_el == 0) {
111
if (!write_kvmstate_to_list(cpu)) {
79
+ return false;
112
/* This should never fail */
80
+ }
113
- abort();
81
+ /* The FGT trap takes precedence over an auth trap. */
114
+ g_assert_not_reached();
82
+ if (s->fgt_eret) {
115
}
83
+ gen_exception_insn_el(s, 0, EXCP_UDEF, a->m ? 3 : 2, 2);
116
84
+ return true;
117
/*
85
+ }
118
@@ -XXX,XX +XXX,XX @@ static int cpu_pre_save(void *opaque)
86
+ dst = tcg_temp_new_i64();
119
} else {
87
+ tcg_gen_ld_i64(dst, cpu_env,
120
if (!write_cpustate_to_list(cpu, false)) {
88
+ offsetof(CPUARMState, elr_el[s->current_el]));
121
/* This should never fail. */
89
+
122
- abort();
90
+ dst = auth_branch_target(s, dst, cpu_X[31], !a->m);
123
+ g_assert_not_reached();
91
+ if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
124
}
92
+ gen_io_start();
125
}
93
+ }
126
94
+
127
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
95
+ gen_helper_exception_return(cpu_env, dst);
128
index XXXXXXX..XXXXXXX 100644
96
+ /* Must exit loop to check un-masked IRQs */
129
--- a/target/arm/translate-a64.c
97
+ s->base.is_jmp = DISAS_EXIT;
130
+++ b/target/arm/translate-a64.c
98
+ return true;
131
@@ -XXX,XX +XXX,XX @@ static void handle_fp_1src_half(DisasContext *s, int opcode, int rd, int rn)
99
+}
132
gen_helper_advsimd_rinth(tcg_res, tcg_op, fpst);
100
+
133
break;
101
/* HINT instruction group, including various allocated HINTs */
134
default:
102
static void handle_hint(DisasContext *s, uint32_t insn,
135
- abort();
103
unsigned int op1, unsigned int op2, unsigned int crm)
136
+ g_assert_not_reached();
104
@@ -XXX,XX +XXX,XX @@ static void disas_exc(DisasContext *s, uint32_t insn)
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
}
105
}
147
}
106
}
148
107
149
diff --git a/target/arm/translate-neon.c b/target/arm/translate-neon.c
108
-/* Unconditional branch (register)
150
index XXXXXXX..XXXXXXX 100644
109
- * 31 25 24 21 20 16 15 10 9 5 4 0
151
--- a/target/arm/translate-neon.c
110
- * +---------------+-------+-------+-------+------+-------+
152
+++ b/target/arm/translate-neon.c
111
- * | 1 1 0 1 0 1 1 | opc | op2 | op3 | Rn | op4 |
153
@@ -XXX,XX +XXX,XX @@ static bool trans_VLDST_single(DisasContext *s, arg_VLDST_single *a)
112
- * +---------------+-------+-------+-------+------+-------+
113
- */
114
-static void disas_uncond_b_reg(DisasContext *s, uint32_t insn)
115
-{
116
- unsigned int opc, op2, op3, rn, op4;
117
- TCGv_i64 dst;
118
- TCGv_i64 modifier;
119
-
120
- opc = extract32(insn, 21, 4);
121
- op2 = extract32(insn, 16, 5);
122
- op3 = extract32(insn, 10, 6);
123
- rn = extract32(insn, 5, 5);
124
- op4 = extract32(insn, 0, 5);
125
-
126
- if (op2 != 0x1f) {
127
- goto do_unallocated;
128
- }
129
-
130
- switch (opc) {
131
- case 0:
132
- case 1:
133
- case 2:
134
- case 8:
135
- case 9:
136
- /*
137
- * BR, BLR, RET, RETAA, RETAB, BRAAZ, BRABZ, BLRAAZ, BLRABZ,
138
- * BRAA, BLRAA: handled in decodetree
139
- */
140
- goto do_unallocated;
141
-
142
- case 4: /* ERET */
143
- if (s->current_el == 0) {
144
- goto do_unallocated;
145
- }
146
- switch (op3) {
147
- case 0: /* ERET */
148
- if (op4 != 0) {
149
- goto do_unallocated;
150
- }
151
- if (s->fgt_eret) {
152
- gen_exception_insn_el(s, 0, EXCP_UDEF, syn_erettrap(op3), 2);
153
- return;
154
- }
155
- dst = tcg_temp_new_i64();
156
- tcg_gen_ld_i64(dst, cpu_env,
157
- offsetof(CPUARMState, elr_el[s->current_el]));
158
- break;
159
-
160
- case 2: /* ERETAA */
161
- case 3: /* ERETAB */
162
- if (!dc_isar_feature(aa64_pauth, s)) {
163
- goto do_unallocated;
164
- }
165
- if (rn != 0x1f || op4 != 0x1f) {
166
- goto do_unallocated;
167
- }
168
- /* The FGT trap takes precedence over an auth trap. */
169
- if (s->fgt_eret) {
170
- gen_exception_insn_el(s, 0, EXCP_UDEF, syn_erettrap(op3), 2);
171
- return;
172
- }
173
- dst = tcg_temp_new_i64();
174
- tcg_gen_ld_i64(dst, cpu_env,
175
- offsetof(CPUARMState, elr_el[s->current_el]));
176
- if (s->pauth_active) {
177
- modifier = cpu_X[31];
178
- if (op3 == 2) {
179
- gen_helper_autia(dst, cpu_env, dst, modifier);
180
- } else {
181
- gen_helper_autib(dst, cpu_env, dst, modifier);
182
- }
183
- }
184
- break;
185
-
186
- default:
187
- goto do_unallocated;
188
- }
189
- if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
190
- gen_io_start();
191
- }
192
-
193
- gen_helper_exception_return(cpu_env, dst);
194
- /* Must exit loop to check un-masked IRQs */
195
- s->base.is_jmp = DISAS_EXIT;
196
- return;
197
-
198
- case 5: /* DRPS */
199
- if (op3 != 0 || op4 != 0 || rn != 0x1f) {
200
- goto do_unallocated;
201
- } else {
202
- unallocated_encoding(s);
203
- }
204
- return;
205
-
206
- default:
207
- do_unallocated:
208
- unallocated_encoding(s);
209
- return;
210
- }
211
-}
212
-
213
/* Branches, exception generating and system instructions */
214
static void disas_b_exc_sys(DisasContext *s, uint32_t insn)
215
{
216
@@ -XXX,XX +XXX,XX @@ static void disas_b_exc_sys(DisasContext *s, uint32_t insn)
217
disas_exc(s, insn);
154
}
218
}
155
break;
219
break;
220
- case 0x6b: /* Unconditional branch (register) */
221
- disas_uncond_b_reg(s, insn);
222
- break;
156
default:
223
default:
157
- abort();
224
unallocated_encoding(s);
158
+ g_assert_not_reached();
159
}
160
if ((vd + a->stride * (nregs - 1)) > 31) {
161
/*
162
diff --git a/target/arm/translate.c b/target/arm/translate.c
163
index XXXXXXX..XXXXXXX 100644
164
--- a/target/arm/translate.c
165
+++ b/target/arm/translate.c
166
@@ -XXX,XX +XXX,XX @@ static void gen_srs(DisasContext *s,
167
offset = 4;
168
break;
225
break;
169
default:
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
--
226
--
185
2.25.1
227
2.34.1
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
The IMPDEF sysreg L2CTLR_EL1 found on the Cortex-A35, A53, A57, A72
2
and which we (arguably dubiously) also provide in '-cpu max' has a
3
2 bit field for the number of processors in the cluster. On real
4
hardware this must be sufficient because it can only be configured
5
with up to 4 CPUs in the cluster. However on QEMU if the board code
6
does not explicitly configure the code into clusters with the right
7
CPU count we default to "give the value assuming that all CPUs in
8
the system are in a single cluster", which might be too big to fit
9
in the field.
2
10
3
Give this enum a name and use in ARMCPRegInfo and add_cpreg_to_hashtable.
11
Instead of just overflowing this 2-bit field, saturate to 3 (meaning
4
Add the enumerator ARM_CP_SECSTATE_BOTH to clarify how 0
12
"4 CPUs", so at least we don't overwrite other fields in the register.
5
is handled in define_one_arm_cp_reg_with_opaque.
13
It's unlikely that any guest code really cares about the value in
14
this field; at least, if it does it probably also wants the system
15
to be more closely matching real hardware, i.e. not to have more
16
than 4 CPUs.
6
17
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
18
This issue has been present since the L2CTLR was first added in
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
19
commit 377a44ec8f2fac5b back in 2014. It was only noticed because
9
Message-id: 20220501055028.646596-10-richard.henderson@linaro.org
20
Coverity complains (CID 1509227) that the shift might overflow 32 bits
21
and inadvertently sign extend into the top half of the 64 bit value.
22
10
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: 20230512170223.3801643-2-peter.maydell@linaro.org
11
---
26
---
12
target/arm/cpregs.h | 7 ++++---
27
target/arm/cortex-regs.c | 11 +++++++++--
13
target/arm/helper.c | 7 +++++--
28
1 file changed, 9 insertions(+), 2 deletions(-)
14
2 files changed, 9 insertions(+), 5 deletions(-)
15
29
16
diff --git a/target/arm/cpregs.h b/target/arm/cpregs.h
30
diff --git a/target/arm/cortex-regs.c b/target/arm/cortex-regs.c
17
index XXXXXXX..XXXXXXX 100644
31
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/cpregs.h
32
--- a/target/arm/cortex-regs.c
19
+++ b/target/arm/cpregs.h
33
+++ b/target/arm/cortex-regs.c
20
@@ -XXX,XX +XXX,XX @@ typedef enum {
34
@@ -XXX,XX +XXX,XX @@ static uint64_t l2ctlr_read(CPUARMState *env, const ARMCPRegInfo *ri)
21
* registered entry will only have one to identify whether the entry is secure
35
{
22
* or non-secure.
36
ARMCPU *cpu = env_archcpu(env);
23
*/
37
24
-enum {
38
- /* Number of cores is in [25:24]; otherwise we RAZ */
25
+typedef enum {
39
- return (cpu->core_count - 1) << 24;
26
+ ARM_CP_SECSTATE_BOTH = 0, /* define one cpreg for each secstate */
40
+ /*
27
ARM_CP_SECSTATE_S = (1 << 0), /* bit[0]: Secure state register */
41
+ * Number of cores is in [25:24]; otherwise we RAZ.
28
ARM_CP_SECSTATE_NS = (1 << 1), /* bit[1]: Non-secure state register */
42
+ * If the board didn't configure the CPUs into clusters,
29
-};
43
+ * we default to "all CPUs in one cluster", which might be
30
+} CPSecureState;
44
+ * more than the 4 that the hardware permits and which is
31
45
+ * all you can report in this two-bit field. Saturate to
32
/*
46
+ * 0b11 (== 4 CPUs) rather than overflowing the field.
33
* Access rights:
47
+ */
34
@@ -XXX,XX +XXX,XX @@ struct ARMCPRegInfo {
48
+ return MIN(cpu->core_count - 1, 3) << 24;
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
}
49
50
50
static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
51
static const ARMCPRegInfo cortex_a72_a57_a53_cp_reginfo[] = {
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
--
52
--
76
2.25.1
53
2.34.1
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
In the vexpress board code, we allocate a new MemoryRegion at the top
2
of vexpress_common_init() but only set it up and use it inside the
3
"if (map[VE_NORFLASHALIAS] != -1)" conditional, so we leak it if not.
4
This isn't a very interesting leak as it's a tiny amount of memory
5
once at startup, but it's easy to fix.
2
6
3
These particular data structures are not modified at runtime.
7
We could silence Coverity simply by moving the g_new() into the
8
if() block, but this use of g_new(MemoryRegion, 1) is a legacy from
9
when this board model was originally written; we wouldn't do that
10
if we wrote it today. The MemoryRegions are conceptually a part of
11
the board and must not go away until the whole board is done with
12
(at the end of the simulation), so they belong in its state struct.
4
13
5
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
14
This machine already has a VexpressMachineState struct that extends
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
15
MachineState, so statically put the MemoryRegions in there instead of
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
16
dynamically allocating them separately at runtime.
8
Message-id: 20220501055028.646596-5-richard.henderson@linaro.org
17
18
Spotted by Coverity (CID 1509083).
19
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
20
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
22
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
23
Message-id: 20230512170223.3801643-3-peter.maydell@linaro.org
10
---
24
---
11
target/arm/helper.c | 16 ++++++++--------
25
hw/arm/vexpress.c | 40 ++++++++++++++++++++--------------------
12
1 file changed, 8 insertions(+), 8 deletions(-)
26
1 file changed, 20 insertions(+), 20 deletions(-)
13
27
14
diff --git a/target/arm/helper.c b/target/arm/helper.c
28
diff --git a/hw/arm/vexpress.c b/hw/arm/vexpress.c
15
index XXXXXXX..XXXXXXX 100644
29
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/helper.c
30
--- a/hw/arm/vexpress.c
17
+++ b/target/arm/helper.c
31
+++ b/hw/arm/vexpress.c
18
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
32
@@ -XXX,XX +XXX,XX @@ struct VexpressMachineClass {
19
.resetvalue = cpu->pmceid1 },
33
20
};
34
struct VexpressMachineState {
21
#ifdef CONFIG_USER_ONLY
35
MachineState parent;
22
- ARMCPRegUserSpaceInfo v8_user_idregs[] = {
36
+ MemoryRegion vram;
23
+ static const ARMCPRegUserSpaceInfo v8_user_idregs[] = {
37
+ MemoryRegion sram;
24
{ .name = "ID_AA64PFR0_EL1",
38
+ MemoryRegion flashalias;
25
.exported_bits = 0x000f000f00ff0000,
39
+ MemoryRegion lowram;
26
.fixed_bits = 0x0000000000000011 },
40
+ MemoryRegion a15sram;
27
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
41
bool secure;
42
bool virt;
43
};
44
@@ -XXX,XX +XXX,XX @@ struct VexpressMachineState {
45
#define TYPE_VEXPRESS_A15_MACHINE MACHINE_TYPE_NAME("vexpress-a15")
46
OBJECT_DECLARE_TYPE(VexpressMachineState, VexpressMachineClass, VEXPRESS_MACHINE)
47
48
-typedef void DBoardInitFn(const VexpressMachineState *machine,
49
+typedef void DBoardInitFn(VexpressMachineState *machine,
50
ram_addr_t ram_size,
51
const char *cpu_type,
52
qemu_irq *pic);
53
@@ -XXX,XX +XXX,XX @@ static void init_cpus(MachineState *ms, const char *cpu_type,
54
}
55
}
56
57
-static void a9_daughterboard_init(const VexpressMachineState *vms,
58
+static void a9_daughterboard_init(VexpressMachineState *vms,
59
ram_addr_t ram_size,
60
const char *cpu_type,
61
qemu_irq *pic)
62
{
63
MachineState *machine = MACHINE(vms);
64
MemoryRegion *sysmem = get_system_memory();
65
- MemoryRegion *lowram = g_new(MemoryRegion, 1);
66
ram_addr_t low_ram_size;
67
68
if (ram_size > 0x40000000) {
69
@@ -XXX,XX +XXX,XX @@ static void a9_daughterboard_init(const VexpressMachineState *vms,
70
* address space should in theory be remappable to various
71
* things including ROM or RAM; we always map the RAM there.
28
*/
72
*/
29
if (arm_feature(env, ARM_FEATURE_EL3)) {
73
- memory_region_init_alias(lowram, NULL, "vexpress.lowmem", machine->ram,
30
if (arm_feature(env, ARM_FEATURE_AARCH64)) {
74
- 0, low_ram_size);
31
- ARMCPRegInfo nsacr = {
75
- memory_region_add_subregion(sysmem, 0x0, lowram);
32
+ static const ARMCPRegInfo nsacr = {
76
+ memory_region_init_alias(&vms->lowram, NULL, "vexpress.lowmem",
33
.name = "NSACR", .type = ARM_CP_CONST,
77
+ machine->ram, 0, low_ram_size);
34
.cp = 15, .opc1 = 0, .crn = 1, .crm = 1, .opc2 = 2,
78
+ memory_region_add_subregion(sysmem, 0x0, &vms->lowram);
35
.access = PL1_RW, .accessfn = nsacr_access,
79
memory_region_add_subregion(sysmem, 0x60000000, machine->ram);
36
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
80
37
};
81
/* 0x1e000000 A9MPCore (SCU) private memory region */
38
define_one_arm_cp_reg(cpu, &nsacr);
82
@@ -XXX,XX +XXX,XX @@ static VEDBoardInfo a9_daughterboard = {
39
} else {
83
.init = a9_daughterboard_init,
40
- ARMCPRegInfo nsacr = {
84
};
41
+ static const ARMCPRegInfo nsacr = {
85
42
.name = "NSACR",
86
-static void a15_daughterboard_init(const VexpressMachineState *vms,
43
.cp = 15, .opc1 = 0, .crn = 1, .crm = 1, .opc2 = 2,
87
+static void a15_daughterboard_init(VexpressMachineState *vms,
44
.access = PL3_RW | PL1_R,
88
ram_addr_t ram_size,
45
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
89
const char *cpu_type,
46
}
90
qemu_irq *pic)
47
} else {
91
{
48
if (arm_feature(env, ARM_FEATURE_V8)) {
92
MachineState *machine = MACHINE(vms);
49
- ARMCPRegInfo nsacr = {
93
MemoryRegion *sysmem = get_system_memory();
50
+ static const ARMCPRegInfo nsacr = {
94
- MemoryRegion *sram = g_new(MemoryRegion, 1);
51
.name = "NSACR", .type = ARM_CP_CONST,
95
52
.cp = 15, .opc1 = 0, .crn = 1, .crm = 1, .opc2 = 2,
96
{
53
.access = PL1_R,
97
/* We have to use a separate 64 bit variable here to avoid the gcc
54
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
98
@@ -XXX,XX +XXX,XX @@ static void a15_daughterboard_init(const VexpressMachineState *vms,
55
.access = PL1_R, .type = ARM_CP_CONST,
99
/* 0x2b060000: SP805 watchdog: not modelled */
56
.resetvalue = cpu->pmsav7_dregion << 8
100
/* 0x2b0a0000: PL341 dynamic memory controller: not modelled */
57
};
101
/* 0x2e000000: system SRAM */
58
- ARMCPRegInfo crn0_wi_reginfo = {
102
- memory_region_init_ram(sram, NULL, "vexpress.a15sram", 0x10000,
59
+ static const ARMCPRegInfo crn0_wi_reginfo = {
103
+ memory_region_init_ram(&vms->a15sram, NULL, "vexpress.a15sram", 0x10000,
60
.name = "CRN0_WI", .cp = 15, .crn = 0, .crm = CP_ANY,
104
&error_fatal);
61
.opc1 = CP_ANY, .opc2 = CP_ANY, .access = PL1_W,
105
- memory_region_add_subregion(sysmem, 0x2e000000, sram);
62
.type = ARM_CP_NOP | ARM_CP_OVERRIDE
106
+ memory_region_add_subregion(sysmem, 0x2e000000, &vms->a15sram);
63
};
107
64
#ifdef CONFIG_USER_ONLY
108
/* 0x7ffb0000: DMA330 DMA controller: not modelled */
65
- ARMCPRegUserSpaceInfo id_v8_user_midr_cp_reginfo[] = {
109
/* 0x7ffd0000: PL354 static memory controller: not modelled */
66
+ static const ARMCPRegUserSpaceInfo id_v8_user_midr_cp_reginfo[] = {
110
@@ -XXX,XX +XXX,XX @@ static void vexpress_common_init(MachineState *machine)
67
{ .name = "MIDR_EL1",
111
I2CBus *i2c;
68
.exported_bits = 0x00000000ffffffff },
112
ram_addr_t vram_size, sram_size;
69
{ .name = "REVIDR_EL1" },
113
MemoryRegion *sysmem = get_system_memory();
70
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
114
- MemoryRegion *vram = g_new(MemoryRegion, 1);
71
.access = PL1_R, .readfn = mpidr_read, .type = ARM_CP_NO_RAW },
115
- MemoryRegion *sram = g_new(MemoryRegion, 1);
72
};
116
- MemoryRegion *flashalias = g_new(MemoryRegion, 1);
73
#ifdef CONFIG_USER_ONLY
117
- MemoryRegion *flash0mem;
74
- ARMCPRegUserSpaceInfo mpidr_user_cp_reginfo[] = {
118
const hwaddr *map = daughterboard->motherboard_map;
75
+ static const ARMCPRegUserSpaceInfo mpidr_user_cp_reginfo[] = {
119
int i;
76
{ .name = "MPIDR_EL1",
120
77
.fixed_bits = 0x0000000080000000 },
121
@@ -XXX,XX +XXX,XX @@ static void vexpress_common_init(MachineState *machine)
78
};
122
79
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
123
if (map[VE_NORFLASHALIAS] != -1) {
124
/* Map flash 0 as an alias into low memory */
125
+ MemoryRegion *flash0mem;
126
flash0mem = sysbus_mmio_get_region(SYS_BUS_DEVICE(pflash0), 0);
127
- memory_region_init_alias(flashalias, NULL, "vexpress.flashalias",
128
+ memory_region_init_alias(&vms->flashalias, NULL, "vexpress.flashalias",
129
flash0mem, 0, VEXPRESS_FLASH_SIZE);
130
- memory_region_add_subregion(sysmem, map[VE_NORFLASHALIAS], flashalias);
131
+ memory_region_add_subregion(sysmem, map[VE_NORFLASHALIAS], &vms->flashalias);
80
}
132
}
81
133
82
if (arm_feature(env, ARM_FEATURE_VBAR)) {
134
dinfo = drive_get(IF_PFLASH, 0, 1);
83
- ARMCPRegInfo vbar_cp_reginfo[] = {
135
ve_pflash_cfi01_register(map[VE_NORFLASH1], "vexpress.flash1", dinfo);
84
+ static const ARMCPRegInfo vbar_cp_reginfo[] = {
136
85
{ .name = "VBAR", .state = ARM_CP_STATE_BOTH,
137
sram_size = 0x2000000;
86
.opc0 = 3, .crn = 12, .crm = 0, .opc1 = 0, .opc2 = 0,
138
- memory_region_init_ram(sram, NULL, "vexpress.sram", sram_size,
87
.access = PL1_RW, .writefn = vbar_write,
139
+ memory_region_init_ram(&vms->sram, NULL, "vexpress.sram", sram_size,
140
&error_fatal);
141
- memory_region_add_subregion(sysmem, map[VE_SRAM], sram);
142
+ memory_region_add_subregion(sysmem, map[VE_SRAM], &vms->sram);
143
144
vram_size = 0x800000;
145
- memory_region_init_ram(vram, NULL, "vexpress.vram", vram_size,
146
+ memory_region_init_ram(&vms->vram, NULL, "vexpress.vram", vram_size,
147
&error_fatal);
148
- memory_region_add_subregion(sysmem, map[VE_VIDEORAM], vram);
149
+ memory_region_add_subregion(sysmem, map[VE_VIDEORAM], &vms->vram);
150
151
/* 0x4e000000 LAN9118 Ethernet */
152
if (nd_table[0].used) {
88
--
153
--
89
2.25.1
154
2.34.1
90
155
91
156
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
Convert the u2f.txt file to rST, and place it in the right place
2
2
in our manual layout. The old text didn't fit very well into our
3
This controls whether the PACI{A,B}SP instructions trap with BTYPE=3
3
manual style, so the new version ends up looking like a rewrite,
4
(indirect branch from register other than x16/x17). The linux kernel
4
although some of the original text is preserved:
5
sets this in bti_enable().
5
6
6
* the 'building' section of the old file is removed, since we
7
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/998
7
generally assume that users have already built QEMU
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
* some rather verbose text has been cut back
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
* document the passthrough device first, on the assumption
10
Message-id: 20220427042312.294300-1-richard.henderson@linaro.org
10
that's most likely to be of interest to users
11
[PMM: remove stray change to makefile comment]
11
* cut back on the duplication of text between sections
12
* format example command lines etc with rST
13
14
As it's a short document it seemed simplest to do this all
15
in one go rather than try to do a minimal syntactic conversion
16
and then clean up the wording and layout.
17
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
Reviewed-by: Thomas Huth <thuth@redhat.com>
20
Message-id: 20230421163734.1152076-1-peter.maydell@linaro.org
13
---
21
---
14
target/arm/cpu.c | 2 ++
22
docs/system/device-emulation.rst | 1 +
15
tests/tcg/aarch64/bti-3.c | 42 +++++++++++++++++++++++++++++++
23
docs/system/devices/usb-u2f.rst | 93 ++++++++++++++++++++++++++
16
tests/tcg/aarch64/Makefile.target | 6 ++---
24
docs/system/devices/usb.rst | 2 +-
17
3 files changed, 47 insertions(+), 3 deletions(-)
25
docs/u2f.txt | 110 -------------------------------
18
create mode 100644 tests/tcg/aarch64/bti-3.c
26
4 files changed, 95 insertions(+), 111 deletions(-)
19
27
create mode 100644 docs/system/devices/usb-u2f.rst
20
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
28
delete mode 100644 docs/u2f.txt
29
30
diff --git a/docs/system/device-emulation.rst b/docs/system/device-emulation.rst
21
index XXXXXXX..XXXXXXX 100644
31
index XXXXXXX..XXXXXXX 100644
22
--- a/target/arm/cpu.c
32
--- a/docs/system/device-emulation.rst
23
+++ b/target/arm/cpu.c
33
+++ b/docs/system/device-emulation.rst
24
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_reset(DeviceState *dev)
34
@@ -XXX,XX +XXX,XX @@ Emulated Devices
25
/* Enable all PAC keys. */
35
devices/virtio-pmem.rst
26
env->cp15.sctlr_el[1] |= (SCTLR_EnIA | SCTLR_EnIB |
36
devices/vhost-user-rng.rst
27
SCTLR_EnDA | SCTLR_EnDB);
37
devices/canokey.rst
28
+ /* Trap on btype=3 for PACIxSP. */
38
+ devices/usb-u2f.rst
29
+ env->cp15.sctlr_el[1] |= SCTLR_BT0;
39
devices/igb.rst
30
/* and to the FP/Neon instructions */
40
diff --git a/docs/system/devices/usb-u2f.rst b/docs/system/devices/usb-u2f.rst
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
41
new file mode 100644
35
index XXXXXXX..XXXXXXX
42
index XXXXXXX..XXXXXXX
36
--- /dev/null
43
--- /dev/null
37
+++ b/tests/tcg/aarch64/bti-3.c
44
+++ b/docs/system/devices/usb-u2f.rst
38
@@ -XXX,XX +XXX,XX @@
45
@@ -XXX,XX +XXX,XX @@
39
+/*
46
+Universal Second Factor (U2F) USB Key Device
40
+ * BTI vs PACIASP
47
+============================================
41
+ */
48
+
42
+
49
+U2F is an open authentication standard that enables relying parties
43
+#include "bti-crt.inc.c"
50
+exposed to the internet to offer a strong second factor option for end
44
+
51
+user authentication.
45
+static void skip2_sigill(int sig, siginfo_t *info, ucontext_t *uc)
52
+
46
+{
53
+The second factor is provided by a device implementing the U2F
47
+ uc->uc_mcontext.pc += 8;
54
+protocol. In case of a USB U2F security key, it is a USB HID device
48
+ uc->uc_mcontext.pstate = 1;
55
+that implements the U2F protocol.
49
+}
56
+
50
+
57
+QEMU supports both pass-through of a host U2F key device to a VM,
51
+#define BTYPE_1() \
58
+and software emulation of a U2F key.
52
+ asm("mov %0,#1; adr x16, 1f; br x16; 1: hint #25; mov %0,#0" \
59
+
53
+ : "=r"(skipped) : : "x16", "x30")
60
+``u2f-passthru``
54
+
61
+----------------
55
+#define BTYPE_2() \
62
+
56
+ asm("mov %0,#1; adr x16, 1f; blr x16; 1: hint #25; mov %0,#0" \
63
+The ``u2f-passthru`` device allows you to connect a real hardware
57
+ : "=r"(skipped) : : "x16", "x30")
64
+U2F key on your host to a guest VM. All requests made from the guest
58
+
65
+are passed through to the physical security key connected to the
59
+#define BTYPE_3() \
66
+host machine and vice versa.
60
+ asm("mov %0,#1; adr x15, 1f; br x15; 1: hint #25; mov %0,#0" \
67
+
61
+ : "=r"(skipped) : : "x15", "x30")
68
+In addition, the dedicated pass-through allows you to share a single
62
+
69
+U2F security key with several guest VMs, which is not possible with a
63
+#define TEST(WHICH, EXPECT) \
70
+simple host device assignment pass-through.
64
+ do { WHICH(); fail += skipped ^ EXPECT; } while (0)
71
+
65
+
72
+You can specify the host U2F key to use with the ``hidraw``
66
+int main()
73
+option, which takes the host path to a Linux ``/dev/hidrawN`` device:
67
+{
74
+
68
+ int fail = 0;
75
+.. parsed-literal::
69
+ int skipped;
76
+ |qemu_system| -usb -device u2f-passthru,hidraw=/dev/hidraw0
70
+
77
+
71
+ /* Signal-like with SA_SIGINFO. */
78
+If you don't specify the device, the ``u2f-passthru`` device will
72
+ signal_info(SIGILL, skip2_sigill);
79
+autoscan to take the first U2F device it finds on the host (this
73
+
80
+requires a working libudev):
74
+ /* With SCTLR_EL1.BT0 set, PACIASP is not compatible with type=3. */
81
+
75
+ TEST(BTYPE_1, 0);
82
+.. parsed-literal::
76
+ TEST(BTYPE_2, 0);
83
+ |qemu_system| -usb -device u2f-passthru
77
+ TEST(BTYPE_3, 1);
84
+
78
+
85
+``u2f-emulated``
79
+ return fail;
86
+----------------
80
+}
87
+
81
diff --git a/tests/tcg/aarch64/Makefile.target b/tests/tcg/aarch64/Makefile.target
88
+``u2f-emulated`` is a completely software emulated U2F device.
89
+It uses `libu2f-emu <https://github.com/MattGorko/libu2f-emu>`__
90
+for the U2F key emulation. libu2f-emu
91
+provides a complete implementation of the U2F protocol device part for
92
+all specified transports given by the FIDO Alliance.
93
+
94
+To work, an emulated U2F device must have four elements:
95
+
96
+ * ec x509 certificate
97
+ * ec private key
98
+ * counter (four bytes value)
99
+ * 48 bytes of entropy (random bits)
100
+
101
+To use this type of device, these have to be configured, and these
102
+four elements must be passed one way or another.
103
+
104
+Assuming that you have a working libu2f-emu installed on the host,
105
+there are three possible ways to configure the ``u2f-emulated`` device:
106
+
107
+ * ephemeral
108
+ * setup directory
109
+ * manual
110
+
111
+Ephemeral is the simplest way to configure; it lets the device generate
112
+all the elements it needs for a single use of the lifetime of the device.
113
+It is the default if you do not pass any other options to the device.
114
+
115
+.. parsed-literal::
116
+ |qemu_system| -usb -device u2f-emulated
117
+
118
+You can pass the device the path of a setup directory on the host
119
+using the ``dir`` option; the directory must contain these four files:
120
+
121
+ * ``certificate.pem``: ec x509 certificate
122
+ * ``private-key.pem``: ec private key
123
+ * ``counter``: counter value
124
+ * ``entropy``: 48 bytes of entropy
125
+
126
+.. parsed-literal::
127
+ |qemu_system| -usb -device u2f-emulated,dir=$dir
128
+
129
+You can also manually pass the device the paths to each of these files,
130
+if you don't want them all to be in the same directory, using the options
131
+
132
+ * ``cert``
133
+ * ``priv``
134
+ * ``counter``
135
+ * ``entropy``
136
+
137
+.. parsed-literal::
138
+ |qemu_system| -usb -device u2f-emulated,cert=$DIR1/$FILE1,priv=$DIR2/$FILE2,counter=$DIR3/$FILE3,entropy=$DIR4/$FILE4
139
diff --git a/docs/system/devices/usb.rst b/docs/system/devices/usb.rst
82
index XXXXXXX..XXXXXXX 100644
140
index XXXXXXX..XXXXXXX 100644
83
--- a/tests/tcg/aarch64/Makefile.target
141
--- a/docs/system/devices/usb.rst
84
+++ b/tests/tcg/aarch64/Makefile.target
142
+++ b/docs/system/devices/usb.rst
85
@@ -XXX,XX +XXX,XX @@ endif
143
@@ -XXX,XX +XXX,XX @@ option or the ``device_add`` monitor command. Available devices are:
86
# BTI Tests
144
USB audio device
87
# bti-1 tests the elf notes, so we require special compiler support.
145
88
ifneq ($(CROSS_CC_HAS_ARMV8_BTI),)
146
``u2f-{emulated,passthru}``
89
-AARCH64_TESTS += bti-1
147
- Universal Second Factor device
90
-bti-1: CFLAGS += -mbranch-protection=standard
148
+ :doc:`usb-u2f`
91
-bti-1: LDFLAGS += -nostdlib
149
92
+AARCH64_TESTS += bti-1 bti-3
150
``canokey``
93
+bti-1 bti-3: CFLAGS += -mbranch-protection=standard
151
An Open-source Secure Key implementing FIDO2, OpenPGP, PIV and more.
94
+bti-1 bti-3: LDFLAGS += -nostdlib
152
diff --git a/docs/u2f.txt b/docs/u2f.txt
95
endif
153
deleted file mode 100644
96
# bti-2 tests PROT_BTI, so no special compiler support required.
154
index XXXXXXX..XXXXXXX
97
AARCH64_TESTS += bti-2
155
--- a/docs/u2f.txt
156
+++ /dev/null
157
@@ -XXX,XX +XXX,XX @@
158
-QEMU U2F Key Device Documentation.
159
-
160
-Contents
161
-1. USB U2F key device
162
-2. Building
163
-3. Using u2f-emulated
164
-4. Using u2f-passthru
165
-5. Libu2f-emu
166
-
167
-1. USB U2F key device
168
-
169
-U2F is an open authentication standard that enables relying parties
170
-exposed to the internet to offer a strong second factor option for end
171
-user authentication.
172
-
173
-The standard brings many advantages to both parties, client and server,
174
-allowing to reduce over-reliance on passwords, it increases authentication
175
-security and simplifies passwords.
176
-
177
-The second factor is materialized by a device implementing the U2F
178
-protocol. In case of a USB U2F security key, it is a USB HID device
179
-that implements the U2F protocol.
180
-
181
-In QEMU, the USB U2F key device offers a dedicated support of U2F, allowing
182
-guest USB FIDO/U2F security keys operating in two possible modes:
183
-pass-through and emulated.
184
-
185
-The pass-through mode consists of passing all requests made from the guest
186
-to the physical security key connected to the host machine and vice versa.
187
-In addition, the dedicated pass-through allows to have a U2F security key
188
-shared on several guests which is not possible with a simple host device
189
-assignment pass-through.
190
-
191
-The emulated mode consists of completely emulating the behavior of an
192
-U2F device through software part. Libu2f-emu is used for that.
193
-
194
-
195
-2. Building
196
-
197
-To ensure the build of the u2f-emulated device variant which depends
198
-on libu2f-emu: configuring and building:
199
-
200
- ./configure --enable-u2f && make
201
-
202
-The pass-through mode is built by default on Linux. To take advantage
203
-of the autoscan option it provides, make sure you have a working libudev
204
-installed on the host.
205
-
206
-
207
-3. Using u2f-emulated
208
-
209
-To work, an emulated U2F device must have four elements:
210
- * ec x509 certificate
211
- * ec private key
212
- * counter (four bytes value)
213
- * 48 bytes of entropy (random bits)
214
-
215
-To use this type of device, this one has to be configured, and these
216
-four elements must be passed one way or another.
217
-
218
-Assuming that you have a working libu2f-emu installed on the host.
219
-There are three possible ways of configurations:
220
- * ephemeral
221
- * setup directory
222
- * manual
223
-
224
-Ephemeral is the simplest way to configure, it lets the device generate
225
-all the elements it needs for a single use of the lifetime of the device.
226
-
227
- qemu -usb -device u2f-emulated
228
-
229
-Setup directory allows to configure the device from a directory containing
230
-four files:
231
- * certificate.pem: ec x509 certificate
232
- * private-key.pem: ec private key
233
- * counter: counter value
234
- * entropy: 48 bytes of entropy
235
-
236
- qemu -usb -device u2f-emulated,dir=$dir
237
-
238
-Manual allows to configure the device more finely by specifying each
239
-of the elements necessary for the device:
240
- * cert
241
- * priv
242
- * counter
243
- * entropy
244
-
245
- qemu -usb -device u2f-emulated,cert=$DIR1/$FILE1,priv=$DIR2/$FILE2,counter=$DIR3/$FILE3,entropy=$DIR4/$FILE4
246
-
247
-
248
-4. Using u2f-passthru
249
-
250
-On the host specify the u2f-passthru device with a suitable hidraw:
251
-
252
- qemu -usb -device u2f-passthru,hidraw=/dev/hidraw0
253
-
254
-Alternately, the u2f-passthru device can autoscan to take the first
255
-U2F device it finds on the host (this requires a working libudev):
256
-
257
- qemu -usb -device u2f-passthru
258
-
259
-
260
-5. Libu2f-emu
261
-
262
-The u2f-emulated device uses libu2f-emu for the U2F key emulation. Libu2f-emu
263
-implements completely the U2F protocol device part for all specified
264
-transport given by the FIDO Alliance.
265
-
266
-For more information about libu2f-emu see this page:
267
-https://github.com/MattGorko/libu2f-emu.
98
--
268
--
99
2.25.1
269
2.34.1
diff view generated by jsdifflib