1
First pullreq for 6.0: mostly my v8.1M work, plus some other
1
Just flushing my target-arm queue since I won't be working next week :-)
2
bits and pieces. (I still have a lot of stuff in my to-review
3
folder, which I may or may not get to before the Christmas break...)
4
2
5
thanks
6
-- PMM
3
-- PMM
7
4
8
The following changes since commit 5e7b204dbfae9a562fc73684986f936b97f63877:
5
The following changes since commit b3cd3b5a66f0dddfe3d5ba2bef13cd4f5b89cde9:
9
6
10
Merge remote-tracking branch 'remotes/mst/tags/for_upstream' into staging (2020-12-09 20:08:54 +0000)
7
Merge tag 'pull-riscv-to-apply-20220610' of github.com:alistair23/qemu into staging (2022-06-09 22:08:27 -0700)
11
8
12
are available in the Git repository at:
9
are available in the Git repository at:
13
10
14
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20201210
11
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20220610
15
12
16
for you to fetch changes up to 71f916be1c7e9ede0e37d9cabc781b5a9e8638ff:
13
for you to fetch changes up to 90c072e063737e9e8f431489bbd334452f89056e:
17
14
18
hw/arm/armv7m: Correct typo in QOM object name (2020-12-10 11:44:56 +0000)
15
semihosting/config: Merge --semihosting-config option groups (2022-06-10 14:32:36 +0100)
19
16
20
----------------------------------------------------------------
17
----------------------------------------------------------------
21
target-arm queue:
18
* refactor exception routing code
22
* hw/arm/smmuv3: Fix up L1STD_SPAN decoding
19
* fix SCR_EL3 RAO/RAZ bits
23
* xlnx-zynqmp: Support Xilinx ZynqMP CAN controllers
20
* gdbstub: Don't use GDB syscalls if no GDB is attached
24
* sbsa-ref: allow to use Cortex-A53/57/72 cpus
21
* semihosting/config: Merge --semihosting-config option groups
25
* Various minor code cleanups
22
* tests/qtest: Reduce npcm7xx_sdhci test image size
26
* hw/intc/armv7m_nvic: Make all of system PPB range be RAZWI/BusFault
27
* Implement more pieces of ARMv8.1M support
28
23
29
----------------------------------------------------------------
24
----------------------------------------------------------------
30
Alex Chen (4):
25
Hao Wu (1):
31
i.MX25: Fix bad printf format specifiers
26
tests/qtest: Reduce npcm7xx_sdhci test image size
32
i.MX31: Fix bad printf format specifiers
33
i.MX6: Fix bad printf format specifiers
34
i.MX6ul: Fix bad printf format specifiers
35
27
36
Havard Skinnemoen (1):
28
Peter Maydell (2):
37
tests/qtest/npcm7xx_rng-test: dump random data on failure
29
gdbstub: Don't use GDB syscalls if no GDB is attached
30
semihosting/config: Merge --semihosting-config option groups
38
31
39
Kunkun Jiang (1):
32
Richard Henderson (25):
40
hw/arm/smmuv3: Fix up L1STD_SPAN decoding
33
target/arm: Mark exception helpers as noreturn
34
target/arm: Add coproc parameter to syn_fp_access_trap
35
target/arm: Move exception_target_el out of line
36
target/arm: Move arm_singlestep_active out of line
37
target/arm: Move arm_generate_debug_exceptions out of line
38
target/arm: Use is_a64 in arm_generate_debug_exceptions
39
target/arm: Move exception_bkpt_insn to debug_helper.c
40
target/arm: Move arm_debug_exception_fsr to debug_helper.c
41
target/arm: Rename helper_exception_with_syndrome
42
target/arm: Introduce gen_exception_insn_el_v
43
target/arm: Rename gen_exception_insn to gen_exception_insn_el
44
target/arm: Introduce gen_exception_insn
45
target/arm: Create helper_exception_swstep
46
target/arm: Remove TBFLAG_ANY.DEBUG_TARGET_EL
47
target/arm: Move gen_exception to translate.c
48
target/arm: Rename gen_exception to gen_exception_el
49
target/arm: Introduce gen_exception
50
target/arm: Introduce gen_exception_el_v
51
target/arm: Introduce helper_exception_with_syndrome
52
target/arm: Remove default_exception_el
53
target/arm: Create raise_exception_debug
54
target/arm: Move arm_debug_target_el to debug_helper.c
55
target/arm: Fix Secure PL1 tests in fp_exception_el
56
target/arm: Adjust format test in scr_write
57
target/arm: SCR_EL3.RW is RAO/WI without AArch32 EL[12]
41
58
42
Marcin Juszkiewicz (1):
59
target/arm/cpu.h | 133 ++---------------------
43
sbsa-ref: allow to use Cortex-A53/57/72 cpus
60
target/arm/helper.h | 8 +-
44
61
target/arm/internals.h | 43 +-------
45
Peter Maydell (25):
62
target/arm/syndrome.h | 7 +-
46
hw/intc/armv7m_nvic: Make all of system PPB range be RAZWI/BusFault
63
target/arm/translate.h | 43 ++------
47
target/arm: Implement v8.1M PXN extension
64
gdbstub.c | 14 ++-
48
target/arm: Don't clobber ID_PFR1.Security on M-profile cores
65
semihosting/config.c | 1 +
49
target/arm: Implement VSCCLRM insn
66
target/arm/debug_helper.c | 220 +++++++++++++++++++++++++++++++++++++--
50
target/arm: Implement CLRM instruction
67
target/arm/helper.c | 53 ++++------
51
target/arm: Enforce M-profile VMRS/VMSR register restrictions
68
target/arm/op_helper.c | 52 +++++----
52
target/arm: Refactor M-profile VMSR/VMRS handling
69
target/arm/translate-a64.c | 34 +++---
53
target/arm: Move general-use constant expanders up in translate.c
70
target/arm/translate-m-nocp.c | 15 ++-
54
target/arm: Implement VLDR/VSTR system register
71
target/arm/translate-mve.c | 3 +-
55
target/arm: Implement M-profile FPSCR_nzcvqc
72
target/arm/translate-vfp.c | 18 +++-
56
target/arm: Use new FPCR_NZCV_MASK constant
73
target/arm/translate.c | 106 ++++++++++---------
57
target/arm: Factor out preserve-fp-state from full_vfp_access_check()
74
tests/qtest/npcm7xx_sdhci-test.c | 2 +-
58
target/arm: Implement FPCXT_S fp system register
75
16 files changed, 390 insertions(+), 362 deletions(-)
59
hw/intc/armv7m_nvic: Update FPDSCR masking for v8.1M
60
target/arm: For v8.1M, always clear R0-R3, R12, APSR, EPSR on exception entry
61
target/arm: In v8.1M, don't set HFSR.FORCED on vector table fetch failures
62
target/arm: Implement v8.1M REVIDR register
63
target/arm: Implement new v8.1M NOCP check for exception return
64
target/arm: Implement new v8.1M VLLDM and VLSTM encodings
65
hw/intc/armv7m_nvic: Support v8.1M CCR.TRD bit
66
target/arm: Implement CCR_S.TRD behaviour for SG insns
67
hw/intc/armv7m_nvic: Fix "return from inactive handler" check
68
target/arm: Implement M-profile "minimal RAS implementation"
69
hw/intc/armv7m_nvic: Implement read/write for RAS register block
70
hw/arm/armv7m: Correct typo in QOM object name
71
72
Vikram Garhwal (4):
73
hw/net/can: Introduce Xilinx ZynqMP CAN controller
74
xlnx-zynqmp: Connect Xilinx ZynqMP CAN controllers
75
tests/qtest: Introduce tests for Xilinx ZynqMP CAN controller
76
MAINTAINERS: Add maintainer entry for Xilinx ZynqMP CAN controller
77
78
meson.build | 1 +
79
hw/arm/smmuv3-internal.h | 2 +-
80
hw/net/can/trace.h | 1 +
81
include/hw/arm/xlnx-zynqmp.h | 8 +
82
include/hw/intc/armv7m_nvic.h | 2 +
83
include/hw/net/xlnx-zynqmp-can.h | 78 +++
84
target/arm/cpu.h | 46 ++
85
target/arm/m-nocp.decode | 10 +-
86
target/arm/t32.decode | 10 +-
87
target/arm/vfp.decode | 14 +
88
hw/arm/armv7m.c | 4 +-
89
hw/arm/sbsa-ref.c | 23 +-
90
hw/arm/xlnx-zcu102.c | 20 +
91
hw/arm/xlnx-zynqmp.c | 34 ++
92
hw/intc/armv7m_nvic.c | 246 ++++++--
93
hw/misc/imx25_ccm.c | 12 +-
94
hw/misc/imx31_ccm.c | 14 +-
95
hw/misc/imx6_ccm.c | 20 +-
96
hw/misc/imx6_src.c | 2 +-
97
hw/misc/imx6ul_ccm.c | 4 +-
98
hw/misc/imx_ccm.c | 4 +-
99
hw/net/can/xlnx-zynqmp-can.c | 1161 ++++++++++++++++++++++++++++++++++++++
100
target/arm/cpu.c | 5 +-
101
target/arm/helper.c | 7 +-
102
target/arm/m_helper.c | 130 ++++-
103
target/arm/translate.c | 105 +++-
104
tests/qtest/npcm7xx_rng-test.c | 12 +
105
tests/qtest/xlnx-can-test.c | 360 ++++++++++++
106
MAINTAINERS | 8 +
107
hw/Kconfig | 1 +
108
hw/net/can/meson.build | 1 +
109
hw/net/can/trace-events | 9 +
110
target/arm/translate-vfp.c.inc | 511 ++++++++++++++++-
111
tests/qtest/meson.build | 1 +
112
34 files changed, 2713 insertions(+), 153 deletions(-)
113
create mode 100644 hw/net/can/trace.h
114
create mode 100644 include/hw/net/xlnx-zynqmp-can.h
115
create mode 100644 hw/net/can/xlnx-zynqmp-can.c
116
create mode 100644 tests/qtest/xlnx-can-test.c
117
create mode 100644 hw/net/can/trace-events
118
diff view generated by jsdifflib
1
From: Alex Chen <alex.chen@huawei.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
We should use printf format specifier "%u" instead of "%d" for
4
argument of type "unsigned int".
5
6
Reported-by: Euler Robot <euler.robot@huawei.com>
7
Signed-off-by: Alex Chen <alex.chen@huawei.com>
8
Message-id: 20201126111109.112238-5-alex.chen@huawei.com
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20220609202901.1177572-2-richard.henderson@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
7
---
12
hw/misc/imx6ul_ccm.c | 4 ++--
8
target/arm/helper.h | 6 +++---
13
1 file changed, 2 insertions(+), 2 deletions(-)
9
1 file changed, 3 insertions(+), 3 deletions(-)
14
10
15
diff --git a/hw/misc/imx6ul_ccm.c b/hw/misc/imx6ul_ccm.c
11
diff --git a/target/arm/helper.h b/target/arm/helper.h
16
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/misc/imx6ul_ccm.c
13
--- a/target/arm/helper.h
18
+++ b/hw/misc/imx6ul_ccm.c
14
+++ b/target/arm/helper.h
19
@@ -XXX,XX +XXX,XX @@ static const char *imx6ul_ccm_reg_name(uint32_t reg)
15
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_2(usad8, TCG_CALL_NO_RWG_SE, i32, i32, i32)
20
case CCM_CMEOR:
16
21
return "CMEOR";
17
DEF_HELPER_FLAGS_3(sel_flags, TCG_CALL_NO_RWG_SE,
22
default:
18
i32, i32, i32, i32)
23
- sprintf(unknown, "%d ?", reg);
19
-DEF_HELPER_2(exception_internal, void, env, i32)
24
+ sprintf(unknown, "%u ?", reg);
20
-DEF_HELPER_4(exception_with_syndrome, void, env, i32, i32, i32)
25
return unknown;
21
-DEF_HELPER_2(exception_bkpt_insn, void, env, i32)
26
}
22
+DEF_HELPER_2(exception_internal, noreturn, env, i32)
27
}
23
+DEF_HELPER_4(exception_with_syndrome, noreturn, env, i32, i32, i32)
28
@@ -XXX,XX +XXX,XX @@ static const char *imx6ul_analog_reg_name(uint32_t reg)
24
+DEF_HELPER_2(exception_bkpt_insn, noreturn, env, i32)
29
case USB_ANALOG_DIGPROG:
25
DEF_HELPER_2(exception_pc_alignment, noreturn, env, tl)
30
return "USB_ANALOG_DIGPROG";
26
DEF_HELPER_1(setend, void, env)
31
default:
27
DEF_HELPER_2(wfi, void, env, i32)
32
- sprintf(unknown, "%d ?", reg);
33
+ sprintf(unknown, "%u ?", reg);
34
return unknown;
35
}
36
}
37
--
28
--
38
2.20.1
29
2.25.1
39
40
diff view generated by jsdifflib
1
From: Marcin Juszkiewicz <marcin.juszkiewicz@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Trusted Firmware now supports A72 on sbsa-ref by default [1] so enable
3
With ARMv8, this field is always RES0.
4
it for QEMU as well. A53 was already enabled there.
4
With ARMv7, targeting EL2 and TA=0, it is always 0xA.
5
5
6
1. https://review.trustedfirmware.org/c/TF-A/trusted-firmware-a/+/7117
7
8
Signed-off-by: Marcin Juszkiewicz <marcin.juszkiewicz@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20201120141705.246690-1-marcin.juszkiewicz@linaro.org
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20220609202901.1177572-3-richard.henderson@linaro.org
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
10
---
14
hw/arm/sbsa-ref.c | 23 ++++++++++++++++++++---
11
target/arm/syndrome.h | 7 ++++---
15
1 file changed, 20 insertions(+), 3 deletions(-)
12
target/arm/translate-a64.c | 3 ++-
13
target/arm/translate-vfp.c | 14 ++++++++++++--
14
3 files changed, 18 insertions(+), 6 deletions(-)
16
15
17
diff --git a/hw/arm/sbsa-ref.c b/hw/arm/sbsa-ref.c
16
diff --git a/target/arm/syndrome.h b/target/arm/syndrome.h
18
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/arm/sbsa-ref.c
18
--- a/target/arm/syndrome.h
20
+++ b/hw/arm/sbsa-ref.c
19
+++ b/target/arm/syndrome.h
21
@@ -XXX,XX +XXX,XX @@ static const int sbsa_ref_irqmap[] = {
20
@@ -XXX,XX +XXX,XX @@ static inline uint32_t syn_cp15_rrt_trap(int cv, int cond, int opc1, int crm,
22
[SBSA_GWDT] = 16,
21
| (rt2 << 10) | (rt << 5) | (crm << 1) | isread;
23
};
22
}
24
23
25
+static const char * const valid_cpus[] = {
24
-static inline uint32_t syn_fp_access_trap(int cv, int cond, bool is_16bit)
26
+ ARM_CPU_TYPE_NAME("cortex-a53"),
25
+static inline uint32_t syn_fp_access_trap(int cv, int cond, bool is_16bit,
27
+ ARM_CPU_TYPE_NAME("cortex-a57"),
26
+ int coproc)
28
+ ARM_CPU_TYPE_NAME("cortex-a72"),
27
{
29
+};
28
- /* AArch32 FP trap or any AArch64 FP/SIMD trap: TA == 0 coproc == 0xa */
29
+ /* AArch32 FP trap or any AArch64 FP/SIMD trap: TA == 0 */
30
return (EC_ADVSIMDFPACCESSTRAP << ARM_EL_EC_SHIFT)
31
| (is_16bit ? 0 : ARM_EL_IL)
32
- | (cv << 24) | (cond << 20) | 0xa;
33
+ | (cv << 24) | (cond << 20) | coproc;
34
}
35
36
static inline uint32_t syn_simd_access_trap(int cv, int cond, bool is_16bit)
37
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
38
index XXXXXXX..XXXXXXX 100644
39
--- a/target/arm/translate-a64.c
40
+++ b/target/arm/translate-a64.c
41
@@ -XXX,XX +XXX,XX @@ static bool fp_access_check(DisasContext *s)
42
s->fp_access_checked = true;
43
44
gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
45
- syn_fp_access_trap(1, 0xe, false), s->fp_excp_el);
46
+ syn_fp_access_trap(1, 0xe, false, 0),
47
+ s->fp_excp_el);
48
return false;
49
}
50
s->fp_access_checked = true;
51
diff --git a/target/arm/translate-vfp.c b/target/arm/translate-vfp.c
52
index XXXXXXX..XXXXXXX 100644
53
--- a/target/arm/translate-vfp.c
54
+++ b/target/arm/translate-vfp.c
55
@@ -XXX,XX +XXX,XX @@ static void gen_update_fp_context(DisasContext *s)
56
static bool vfp_access_check_a(DisasContext *s, bool ignore_vfp_enabled)
57
{
58
if (s->fp_excp_el) {
59
- gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
60
- syn_fp_access_trap(1, 0xe, false), s->fp_excp_el);
61
+ /*
62
+ * The full syndrome is only used for HSR when HCPTR traps:
63
+ * For v8, when TA==0, coproc is RES0.
64
+ * For v7, any use of a Floating-point instruction or access
65
+ * to a Floating-point Extension register that is trapped to
66
+ * Hyp mode because of a trap configured in the HCPTR sets
67
+ * this field to 0xA.
68
+ */
69
+ int coproc = arm_dc_feature(s, ARM_FEATURE_V8) ? 0 : 0xa;
70
+ uint32_t syn = syn_fp_access_trap(1, 0xe, false, coproc);
30
+
71
+
31
+static bool cpu_type_valid(const char *cpu)
72
+ gen_exception_insn(s, s->pc_curr, EXCP_UDEF, syn, s->fp_excp_el);
32
+{
73
return false;
33
+ int i;
34
+
35
+ for (i = 0; i < ARRAY_SIZE(valid_cpus); i++) {
36
+ if (strcmp(cpu, valid_cpus[i]) == 0) {
37
+ return true;
38
+ }
39
+ }
40
+ return false;
41
+}
42
+
43
static uint64_t sbsa_ref_cpu_mp_affinity(SBSAMachineState *sms, int idx)
44
{
45
uint8_t clustersz = ARM_DEFAULT_CPUS_PER_CLUSTER;
46
@@ -XXX,XX +XXX,XX @@ static void sbsa_ref_init(MachineState *machine)
47
const CPUArchIdList *possible_cpus;
48
int n, sbsa_max_cpus;
49
50
- if (strcmp(machine->cpu_type, ARM_CPU_TYPE_NAME("cortex-a57"))) {
51
- error_report("sbsa-ref: CPU type other than the built-in "
52
- "cortex-a57 not supported");
53
+ if (!cpu_type_valid(machine->cpu_type)) {
54
+ error_report("mach-virt: CPU type %s not supported", machine->cpu_type);
55
exit(1);
56
}
74
}
57
75
58
--
76
--
59
2.20.1
77
2.25.1
60
61
diff view generated by jsdifflib
1
The RAS feature has a block of memory-mapped registers at offset
1
From: Richard Henderson <richard.henderson@linaro.org>
2
0x5000 within the PPB. For a "minimal RAS" implementation we provide
3
no error records and so the only registers that exist in the block
4
are ERRIIDR and ERRDEVID.
5
2
6
The "RAZ/WI for privileged, BusFault for nonprivileged" behaviour
3
Move the function to op_helper.c, near raise_exception.
7
of the "nvic-default" region is actually valid for minimal-RAS,
8
so the main benefit of providing an explicit implementation of
9
the register block is more accurate LOG_UNIMP messages, and a
10
framework for where we could add a real RAS implementation later
11
if necessary.
12
4
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20220609202901.1177572-4-richard.henderson@linaro.org
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
Message-id: 20201119215617.29887-27-peter.maydell@linaro.org
16
---
9
---
17
include/hw/intc/armv7m_nvic.h | 1 +
10
target/arm/internals.h | 16 +---------------
18
hw/intc/armv7m_nvic.c | 56 +++++++++++++++++++++++++++++++++++
11
target/arm/op_helper.c | 15 +++++++++++++++
19
2 files changed, 57 insertions(+)
12
2 files changed, 16 insertions(+), 15 deletions(-)
20
13
21
diff --git a/include/hw/intc/armv7m_nvic.h b/include/hw/intc/armv7m_nvic.h
14
diff --git a/target/arm/internals.h b/target/arm/internals.h
22
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
23
--- a/include/hw/intc/armv7m_nvic.h
16
--- a/target/arm/internals.h
24
+++ b/include/hw/intc/armv7m_nvic.h
17
+++ b/target/arm/internals.h
25
@@ -XXX,XX +XXX,XX @@ struct NVICState {
18
@@ -XXX,XX +XXX,XX @@ ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va,
26
MemoryRegion sysreg_ns_mem;
19
int aa64_va_parameter_tbi(uint64_t tcr, ARMMMUIdx mmu_idx);
27
MemoryRegion systickmem;
20
int aa64_va_parameter_tbid(uint64_t tcr, ARMMMUIdx mmu_idx);
28
MemoryRegion systick_ns_mem;
21
29
+ MemoryRegion ras_mem;
22
-static inline int exception_target_el(CPUARMState *env)
30
MemoryRegion container;
23
-{
31
MemoryRegion defaultmem;
24
- int target_el = MAX(1, arm_current_el(env));
32
25
-
33
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
26
- /*
27
- * No such thing as secure EL1 if EL3 is aarch32,
28
- * so update the target EL to EL3 in this case.
29
- */
30
- if (arm_is_secure(env) && !arm_el_is_aa64(env, 3) && target_el == 1) {
31
- target_el = 3;
32
- }
33
-
34
- return target_el;
35
-}
36
-
37
/* Determine if allocation tags are available. */
38
static inline bool allocation_tag_access_enabled(CPUARMState *env, int el,
39
uint64_t sctlr)
40
@@ -XXX,XX +XXX,XX @@ void define_cortex_a72_a57_a53_cp_reginfo(ARMCPU *cpu);
41
bool el_is_in_host(CPUARMState *env, int el);
42
43
void aa32_max_features(ARMCPU *cpu);
44
+int exception_target_el(CPUARMState *env);
45
46
/* Powers of 2 for sve_vq_map et al. */
47
#define SVE_VQ_POW2_MAP \
48
diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c
34
index XXXXXXX..XXXXXXX 100644
49
index XXXXXXX..XXXXXXX 100644
35
--- a/hw/intc/armv7m_nvic.c
50
--- a/target/arm/op_helper.c
36
+++ b/hw/intc/armv7m_nvic.c
51
+++ b/target/arm/op_helper.c
37
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps nvic_systick_ops = {
52
@@ -XXX,XX +XXX,XX @@
38
.endianness = DEVICE_NATIVE_ENDIAN,
53
#define SIGNBIT (uint32_t)0x80000000
39
};
54
#define SIGNBIT64 ((uint64_t)1 << 63)
40
55
56
+int exception_target_el(CPUARMState *env)
57
+{
58
+ int target_el = MAX(1, arm_current_el(env));
41
+
59
+
42
+static MemTxResult ras_read(void *opaque, hwaddr addr,
60
+ /*
43
+ uint64_t *data, unsigned size,
61
+ * No such thing as secure EL1 if EL3 is aarch32,
44
+ MemTxAttrs attrs)
62
+ * so update the target EL to EL3 in this case.
45
+{
63
+ */
46
+ if (attrs.user) {
64
+ if (arm_is_secure(env) && !arm_el_is_aa64(env, 3) && target_el == 1) {
47
+ return MEMTX_ERROR;
65
+ target_el = 3;
48
+ }
66
+ }
49
+
67
+
50
+ switch (addr) {
68
+ return target_el;
51
+ case 0xe10: /* ERRIIDR */
52
+ /* architect field = Arm; product/variant/revision 0 */
53
+ *data = 0x43b;
54
+ break;
55
+ case 0xfc8: /* ERRDEVID */
56
+ /* Minimal RAS: we implement 0 error record indexes */
57
+ *data = 0;
58
+ break;
59
+ default:
60
+ qemu_log_mask(LOG_UNIMP, "Read RAS register offset 0x%x\n",
61
+ (uint32_t)addr);
62
+ *data = 0;
63
+ break;
64
+ }
65
+ return MEMTX_OK;
66
+}
69
+}
67
+
70
+
68
+static MemTxResult ras_write(void *opaque, hwaddr addr,
71
void raise_exception(CPUARMState *env, uint32_t excp,
69
+ uint64_t value, unsigned size,
72
uint32_t syndrome, uint32_t target_el)
70
+ MemTxAttrs attrs)
73
{
71
+{
72
+ if (attrs.user) {
73
+ return MEMTX_ERROR;
74
+ }
75
+
76
+ switch (addr) {
77
+ default:
78
+ qemu_log_mask(LOG_UNIMP, "Write to RAS register offset 0x%x\n",
79
+ (uint32_t)addr);
80
+ break;
81
+ }
82
+ return MEMTX_OK;
83
+}
84
+
85
+static const MemoryRegionOps ras_ops = {
86
+ .read_with_attrs = ras_read,
87
+ .write_with_attrs = ras_write,
88
+ .endianness = DEVICE_NATIVE_ENDIAN,
89
+};
90
+
91
/*
92
* Unassigned portions of the PPB space are RAZ/WI for privileged
93
* accesses, and fault for non-privileged accesses.
94
@@ -XXX,XX +XXX,XX @@ static void armv7m_nvic_realize(DeviceState *dev, Error **errp)
95
&s->systick_ns_mem, 1);
96
}
97
98
+ if (cpu_isar_feature(aa32_ras, s->cpu)) {
99
+ memory_region_init_io(&s->ras_mem, OBJECT(s),
100
+ &ras_ops, s, "nvic_ras", 0x1000);
101
+ memory_region_add_subregion(&s->container, 0x5000, &s->ras_mem);
102
+ }
103
+
104
sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->container);
105
}
106
107
--
74
--
108
2.20.1
75
2.25.1
109
110
diff view generated by jsdifflib
1
v8.1M introduces a new TRD flag in the CCR register, which enables
1
From: Richard Henderson <richard.henderson@linaro.org>
2
checking for stack frame integrity signatures on SG instructions.
3
This bit is not banked, and is always RAZ/WI to Non-secure code.
4
Adjust the code for handling CCR reads and writes to handle this.
5
2
3
Move the function to debug_helper.c, and the
4
declaration to internals.h.
5
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20220609202901.1177572-5-richard.henderson@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20201119215617.29887-23-peter.maydell@linaro.org
9
---
10
---
10
target/arm/cpu.h | 2 ++
11
target/arm/cpu.h | 10 ----------
11
hw/intc/armv7m_nvic.c | 26 ++++++++++++++++++--------
12
target/arm/internals.h | 1 +
12
2 files changed, 20 insertions(+), 8 deletions(-)
13
target/arm/debug_helper.c | 12 ++++++++++++
14
3 files changed, 13 insertions(+), 10 deletions(-)
13
15
14
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
16
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
15
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/cpu.h
18
--- a/target/arm/cpu.h
17
+++ b/target/arm/cpu.h
19
+++ b/target/arm/cpu.h
18
@@ -XXX,XX +XXX,XX @@ FIELD(V7M_CCR, STKOFHFNMIGN, 10, 1)
20
@@ -XXX,XX +XXX,XX @@ static inline bool arm_generate_debug_exceptions(CPUARMState *env)
19
FIELD(V7M_CCR, DC, 16, 1)
21
}
20
FIELD(V7M_CCR, IC, 17, 1)
22
}
21
FIELD(V7M_CCR, BP, 18, 1)
23
22
+FIELD(V7M_CCR, LOB, 19, 1)
24
-/* Is single-stepping active? (Note that the "is EL_D AArch64?" check
23
+FIELD(V7M_CCR, TRD, 20, 1)
25
- * implicitly means this always returns false in pre-v8 CPUs.)
24
26
- */
25
/* V7M SCR bits */
27
-static inline bool arm_singlestep_active(CPUARMState *env)
26
FIELD(V7M_SCR, SLEEPONEXIT, 1, 1)
28
-{
27
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
29
- return extract32(env->cp15.mdscr_el1, 0, 1)
30
- && arm_el_is_aa64(env, arm_debug_target_el(env))
31
- && arm_generate_debug_exceptions(env);
32
-}
33
-
34
static inline bool arm_sctlr_b(CPUARMState *env)
35
{
36
return
37
diff --git a/target/arm/internals.h b/target/arm/internals.h
28
index XXXXXXX..XXXXXXX 100644
38
index XXXXXXX..XXXXXXX 100644
29
--- a/hw/intc/armv7m_nvic.c
39
--- a/target/arm/internals.h
30
+++ b/hw/intc/armv7m_nvic.c
40
+++ b/target/arm/internals.h
31
@@ -XXX,XX +XXX,XX @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
41
@@ -XXX,XX +XXX,XX @@ bool el_is_in_host(CPUARMState *env, int el);
32
}
42
33
return cpu->env.v7m.scr[attrs.secure];
43
void aa32_max_features(ARMCPU *cpu);
34
case 0xd14: /* Configuration Control. */
44
int exception_target_el(CPUARMState *env);
35
- /* The BFHFNMIGN bit is the only non-banked bit; we
45
+bool arm_singlestep_active(CPUARMState *env);
36
- * keep it in the non-secure copy of the register.
46
37
+ /*
47
/* Powers of 2 for sve_vq_map et al. */
38
+ * Non-banked bits: BFHFNMIGN (stored in the NS copy of the register)
48
#define SVE_VQ_POW2_MAP \
39
+ * and TRD (stored in the S copy of the register)
49
diff --git a/target/arm/debug_helper.c b/target/arm/debug_helper.c
40
*/
50
index XXXXXXX..XXXXXXX 100644
41
val = cpu->env.v7m.ccr[attrs.secure];
51
--- a/target/arm/debug_helper.c
42
val |= cpu->env.v7m.ccr[M_REG_NS] & R_V7M_CCR_BFHFNMIGN_MASK;
52
+++ b/target/arm/debug_helper.c
43
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
53
@@ -XXX,XX +XXX,XX @@
44
cpu->env.v7m.scr[attrs.secure] = value;
54
#include "exec/exec-all.h"
45
break;
55
#include "exec/helper-proto.h"
46
case 0xd14: /* Configuration Control. */
56
47
+ {
48
+ uint32_t mask;
49
+
57
+
50
if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) {
58
+/*
51
goto bad_offset;
59
+ * Is single-stepping active? (Note that the "is EL_D AArch64?" check
52
}
60
+ * implicitly means this always returns false in pre-v8 CPUs.)
53
61
+ */
54
/* Enforce RAZ/WI on reserved and must-RAZ/WI bits */
62
+bool arm_singlestep_active(CPUARMState *env)
55
- value &= (R_V7M_CCR_STKALIGN_MASK |
63
+{
56
- R_V7M_CCR_BFHFNMIGN_MASK |
64
+ return extract32(env->cp15.mdscr_el1, 0, 1)
57
- R_V7M_CCR_DIV_0_TRP_MASK |
65
+ && arm_el_is_aa64(env, arm_debug_target_el(env))
58
- R_V7M_CCR_UNALIGN_TRP_MASK |
66
+ && arm_generate_debug_exceptions(env);
59
- R_V7M_CCR_USERSETMPEND_MASK |
67
+}
60
- R_V7M_CCR_NONBASETHRDENA_MASK);
68
+
61
+ mask = R_V7M_CCR_STKALIGN_MASK |
69
/* Return true if the linked breakpoint entry lbn passes its checks */
62
+ R_V7M_CCR_BFHFNMIGN_MASK |
70
static bool linked_bp_matches(ARMCPU *cpu, int lbn)
63
+ R_V7M_CCR_DIV_0_TRP_MASK |
71
{
64
+ R_V7M_CCR_UNALIGN_TRP_MASK |
65
+ R_V7M_CCR_USERSETMPEND_MASK |
66
+ R_V7M_CCR_NONBASETHRDENA_MASK;
67
+ if (arm_feature(&cpu->env, ARM_FEATURE_V8_1M) && attrs.secure) {
68
+ /* TRD is always RAZ/WI from NS */
69
+ mask |= R_V7M_CCR_TRD_MASK;
70
+ }
71
+ value &= mask;
72
73
if (arm_feature(&cpu->env, ARM_FEATURE_V8)) {
74
/* v8M makes NONBASETHRDENA and STKALIGN be RES1 */
75
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
76
77
cpu->env.v7m.ccr[attrs.secure] = value;
78
break;
79
+ }
80
case 0xd24: /* System Handler Control and State (SHCSR) */
81
if (!arm_feature(&cpu->env, ARM_FEATURE_V7)) {
82
goto bad_offset;
83
--
72
--
84
2.20.1
73
2.25.1
85
86
diff view generated by jsdifflib
1
The FPDSCR register has a similar layout to the FPSCR. In v8.1M it
1
From: Richard Henderson <richard.henderson@linaro.org>
2
gains new fields FZ16 (if half-precision floating point is supported)
3
and LTPSIZE (always reads as 4). Update the reset value and the code
4
that handles writes to this register accordingly.
5
2
3
Move arm_generate_debug_exceptions and its two subroutines,
4
{aa32,aa64}_generate_debug_exceptions into debug_helper.c,
5
and the one interface declaration to internals.h.
6
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20220609202901.1177572-6-richard.henderson@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20201119215617.29887-16-peter.maydell@linaro.org
9
---
11
---
10
target/arm/cpu.h | 5 +++++
12
target/arm/cpu.h | 91 -------------------------------------
11
hw/intc/armv7m_nvic.c | 9 ++++++++-
13
target/arm/internals.h | 1 +
12
target/arm/cpu.c | 3 +++
14
target/arm/debug_helper.c | 94 +++++++++++++++++++++++++++++++++++++++
13
3 files changed, 16 insertions(+), 1 deletion(-)
15
3 files changed, 95 insertions(+), 91 deletions(-)
14
16
15
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
17
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
16
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/cpu.h
19
--- a/target/arm/cpu.h
18
+++ b/target/arm/cpu.h
20
+++ b/target/arm/cpu.h
19
@@ -XXX,XX +XXX,XX @@ void vfp_set_fpscr(CPUARMState *env, uint32_t val);
21
@@ -XXX,XX +XXX,XX @@ static inline bool arm_v7m_csselr_razwi(ARMCPU *cpu)
20
#define FPCR_IXE (1 << 12) /* Inexact exception trap enable */
22
return (cpu->clidr & R_V7M_CLIDR_CTYPE_ALL_MASK) != 0;
21
#define FPCR_IDE (1 << 15) /* Input Denormal exception trap enable */
23
}
22
#define FPCR_FZ16 (1 << 19) /* ARMv8.2+, FP16 flush-to-zero */
24
23
+#define FPCR_RMODE_MASK (3 << 22) /* Rounding mode */
25
-/* See AArch64.GenerateDebugExceptionsFrom() in ARM ARM pseudocode */
24
#define FPCR_FZ (1 << 24) /* Flush-to-zero enable bit */
26
-static inline bool aa64_generate_debug_exceptions(CPUARMState *env)
25
#define FPCR_DN (1 << 25) /* Default NaN enable bit */
27
-{
26
+#define FPCR_AHP (1 << 26) /* Alternative half-precision */
28
- int cur_el = arm_current_el(env);
27
#define FPCR_QC (1 << 27) /* Cumulative saturation bit */
29
- int debug_el;
28
#define FPCR_V (1 << 28) /* FP overflow flag */
30
-
29
#define FPCR_C (1 << 29) /* FP carry flag */
31
- if (cur_el == 3) {
30
#define FPCR_Z (1 << 30) /* FP zero flag */
32
- return false;
31
#define FPCR_N (1 << 31) /* FP negative flag */
33
- }
32
34
-
33
+#define FPCR_LTPSIZE_SHIFT 16 /* LTPSIZE, M-profile only */
35
- /* MDCR_EL3.SDD disables debug events from Secure state */
34
+#define FPCR_LTPSIZE_MASK (7 << FPCR_LTPSIZE_SHIFT)
36
- if (arm_is_secure_below_el3(env)
35
+
37
- && extract32(env->cp15.mdcr_el3, 16, 1)) {
36
#define FPCR_NZCV_MASK (FPCR_N | FPCR_Z | FPCR_C | FPCR_V)
38
- return false;
37
#define FPCR_NZCVQC_MASK (FPCR_NZCV_MASK | FPCR_QC)
39
- }
38
40
-
39
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
41
- /*
42
- * Same EL to same EL debug exceptions need MDSCR_KDE enabled
43
- * while not masking the (D)ebug bit in DAIF.
44
- */
45
- debug_el = arm_debug_target_el(env);
46
-
47
- if (cur_el == debug_el) {
48
- return extract32(env->cp15.mdscr_el1, 13, 1)
49
- && !(env->daif & PSTATE_D);
50
- }
51
-
52
- /* Otherwise the debug target needs to be a higher EL */
53
- return debug_el > cur_el;
54
-}
55
-
56
-static inline bool aa32_generate_debug_exceptions(CPUARMState *env)
57
-{
58
- int el = arm_current_el(env);
59
-
60
- if (el == 0 && arm_el_is_aa64(env, 1)) {
61
- return aa64_generate_debug_exceptions(env);
62
- }
63
-
64
- if (arm_is_secure(env)) {
65
- int spd;
66
-
67
- if (el == 0 && (env->cp15.sder & 1)) {
68
- /* SDER.SUIDEN means debug exceptions from Secure EL0
69
- * are always enabled. Otherwise they are controlled by
70
- * SDCR.SPD like those from other Secure ELs.
71
- */
72
- return true;
73
- }
74
-
75
- spd = extract32(env->cp15.mdcr_el3, 14, 2);
76
- switch (spd) {
77
- case 1:
78
- /* SPD == 0b01 is reserved, but behaves as 0b00. */
79
- case 0:
80
- /* For 0b00 we return true if external secure invasive debug
81
- * is enabled. On real hardware this is controlled by external
82
- * signals to the core. QEMU always permits debug, and behaves
83
- * as if DBGEN, SPIDEN, NIDEN and SPNIDEN are all tied high.
84
- */
85
- return true;
86
- case 2:
87
- return false;
88
- case 3:
89
- return true;
90
- }
91
- }
92
-
93
- return el != 2;
94
-}
95
-
96
-/* Return true if debugging exceptions are currently enabled.
97
- * This corresponds to what in ARM ARM pseudocode would be
98
- * if UsingAArch32() then
99
- * return AArch32.GenerateDebugExceptions()
100
- * else
101
- * return AArch64.GenerateDebugExceptions()
102
- * We choose to push the if() down into this function for clarity,
103
- * since the pseudocode has it at all callsites except for the one in
104
- * CheckSoftwareStep(), where it is elided because both branches would
105
- * always return the same value.
106
- */
107
-static inline bool arm_generate_debug_exceptions(CPUARMState *env)
108
-{
109
- if (env->aarch64) {
110
- return aa64_generate_debug_exceptions(env);
111
- } else {
112
- return aa32_generate_debug_exceptions(env);
113
- }
114
-}
115
-
116
static inline bool arm_sctlr_b(CPUARMState *env)
117
{
118
return
119
diff --git a/target/arm/internals.h b/target/arm/internals.h
40
index XXXXXXX..XXXXXXX 100644
120
index XXXXXXX..XXXXXXX 100644
41
--- a/hw/intc/armv7m_nvic.c
121
--- a/target/arm/internals.h
42
+++ b/hw/intc/armv7m_nvic.c
122
+++ b/target/arm/internals.h
43
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
123
@@ -XXX,XX +XXX,XX @@ bool el_is_in_host(CPUARMState *env, int el);
44
break;
124
void aa32_max_features(ARMCPU *cpu);
45
case 0xf3c: /* FPDSCR */
125
int exception_target_el(CPUARMState *env);
46
if (cpu_isar_feature(aa32_vfp_simd, cpu)) {
126
bool arm_singlestep_active(CPUARMState *env);
47
- value &= 0x07c00000;
127
+bool arm_generate_debug_exceptions(CPUARMState *env);
48
+ uint32_t mask = FPCR_AHP | FPCR_DN | FPCR_FZ | FPCR_RMODE_MASK;
128
49
+ if (cpu_isar_feature(any_fp16, cpu)) {
129
/* Powers of 2 for sve_vq_map et al. */
50
+ mask |= FPCR_FZ16;
130
#define SVE_VQ_POW2_MAP \
51
+ }
131
diff --git a/target/arm/debug_helper.c b/target/arm/debug_helper.c
52
+ value &= mask;
53
+ if (cpu_isar_feature(aa32_lob, cpu)) {
54
+ value |= 4 << FPCR_LTPSIZE_SHIFT;
55
+ }
56
cpu->env.v7m.fpdscr[attrs.secure] = value;
57
}
58
break;
59
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
60
index XXXXXXX..XXXXXXX 100644
132
index XXXXXXX..XXXXXXX 100644
61
--- a/target/arm/cpu.c
133
--- a/target/arm/debug_helper.c
62
+++ b/target/arm/cpu.c
134
+++ b/target/arm/debug_helper.c
63
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_reset(DeviceState *dev)
135
@@ -XXX,XX +XXX,XX @@
64
* always reset to 4.
136
#include "exec/helper-proto.h"
65
*/
137
66
env->v7m.ltpsize = 4;
138
67
+ /* The LTPSIZE field in FPDSCR is constant and reads as 4. */
139
+/* See AArch64.GenerateDebugExceptionsFrom() in ARM ARM pseudocode */
68
+ env->v7m.fpdscr[M_REG_NS] = 4 << FPCR_LTPSIZE_SHIFT;
140
+static bool aa64_generate_debug_exceptions(CPUARMState *env)
69
+ env->v7m.fpdscr[M_REG_S] = 4 << FPCR_LTPSIZE_SHIFT;
141
+{
70
}
142
+ int cur_el = arm_current_el(env);
71
143
+ int debug_el;
72
if (arm_feature(env, ARM_FEATURE_M_SECURITY)) {
144
+
145
+ if (cur_el == 3) {
146
+ return false;
147
+ }
148
+
149
+ /* MDCR_EL3.SDD disables debug events from Secure state */
150
+ if (arm_is_secure_below_el3(env)
151
+ && extract32(env->cp15.mdcr_el3, 16, 1)) {
152
+ return false;
153
+ }
154
+
155
+ /*
156
+ * Same EL to same EL debug exceptions need MDSCR_KDE enabled
157
+ * while not masking the (D)ebug bit in DAIF.
158
+ */
159
+ debug_el = arm_debug_target_el(env);
160
+
161
+ if (cur_el == debug_el) {
162
+ return extract32(env->cp15.mdscr_el1, 13, 1)
163
+ && !(env->daif & PSTATE_D);
164
+ }
165
+
166
+ /* Otherwise the debug target needs to be a higher EL */
167
+ return debug_el > cur_el;
168
+}
169
+
170
+static bool aa32_generate_debug_exceptions(CPUARMState *env)
171
+{
172
+ int el = arm_current_el(env);
173
+
174
+ if (el == 0 && arm_el_is_aa64(env, 1)) {
175
+ return aa64_generate_debug_exceptions(env);
176
+ }
177
+
178
+ if (arm_is_secure(env)) {
179
+ int spd;
180
+
181
+ if (el == 0 && (env->cp15.sder & 1)) {
182
+ /*
183
+ * SDER.SUIDEN means debug exceptions from Secure EL0
184
+ * are always enabled. Otherwise they are controlled by
185
+ * SDCR.SPD like those from other Secure ELs.
186
+ */
187
+ return true;
188
+ }
189
+
190
+ spd = extract32(env->cp15.mdcr_el3, 14, 2);
191
+ switch (spd) {
192
+ case 1:
193
+ /* SPD == 0b01 is reserved, but behaves as 0b00. */
194
+ case 0:
195
+ /*
196
+ * For 0b00 we return true if external secure invasive debug
197
+ * is enabled. On real hardware this is controlled by external
198
+ * signals to the core. QEMU always permits debug, and behaves
199
+ * as if DBGEN, SPIDEN, NIDEN and SPNIDEN are all tied high.
200
+ */
201
+ return true;
202
+ case 2:
203
+ return false;
204
+ case 3:
205
+ return true;
206
+ }
207
+ }
208
+
209
+ return el != 2;
210
+}
211
+
212
+/*
213
+ * Return true if debugging exceptions are currently enabled.
214
+ * This corresponds to what in ARM ARM pseudocode would be
215
+ * if UsingAArch32() then
216
+ * return AArch32.GenerateDebugExceptions()
217
+ * else
218
+ * return AArch64.GenerateDebugExceptions()
219
+ * We choose to push the if() down into this function for clarity,
220
+ * since the pseudocode has it at all callsites except for the one in
221
+ * CheckSoftwareStep(), where it is elided because both branches would
222
+ * always return the same value.
223
+ */
224
+bool arm_generate_debug_exceptions(CPUARMState *env)
225
+{
226
+ if (env->aarch64) {
227
+ return aa64_generate_debug_exceptions(env);
228
+ } else {
229
+ return aa32_generate_debug_exceptions(env);
230
+ }
231
+}
232
+
233
/*
234
* Is single-stepping active? (Note that the "is EL_D AArch64?" check
235
* implicitly means this always returns false in pre-v8 CPUs.)
73
--
236
--
74
2.20.1
237
2.25.1
75
76
diff view generated by jsdifflib
1
Correct a typo in the name we give the NVIC object.
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Use the accessor rather than the raw structure member.
4
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20220609202901.1177572-7-richard.henderson@linaro.org
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20201119215617.29887-28-peter.maydell@linaro.org
7
---
9
---
8
hw/arm/armv7m.c | 2 +-
10
target/arm/debug_helper.c | 2 +-
9
1 file changed, 1 insertion(+), 1 deletion(-)
11
1 file changed, 1 insertion(+), 1 deletion(-)
10
12
11
diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c
13
diff --git a/target/arm/debug_helper.c b/target/arm/debug_helper.c
12
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
13
--- a/hw/arm/armv7m.c
15
--- a/target/arm/debug_helper.c
14
+++ b/hw/arm/armv7m.c
16
+++ b/target/arm/debug_helper.c
15
@@ -XXX,XX +XXX,XX @@ static void armv7m_instance_init(Object *obj)
17
@@ -XXX,XX +XXX,XX @@ static bool aa32_generate_debug_exceptions(CPUARMState *env)
16
18
*/
17
memory_region_init(&s->container, obj, "armv7m-container", UINT64_MAX);
19
bool arm_generate_debug_exceptions(CPUARMState *env)
18
20
{
19
- object_initialize_child(obj, "nvnic", &s->nvic, TYPE_NVIC);
21
- if (env->aarch64) {
20
+ object_initialize_child(obj, "nvic", &s->nvic, TYPE_NVIC);
22
+ if (is_a64(env)) {
21
object_property_add_alias(obj, "num-irq",
23
return aa64_generate_debug_exceptions(env);
22
OBJECT(&s->nvic), "num-irq");
24
} else {
23
25
return aa32_generate_debug_exceptions(env);
24
--
26
--
25
2.20.1
27
2.25.1
26
27
diff view generated by jsdifflib
1
Factor out the code which handles M-profile lazy FP state preservation
1
From: Richard Henderson <richard.henderson@linaro.org>
2
from full_vfp_access_check(); accesses to the FPCXT_NS register are
3
a special case which need to do just this part (corresponding in the
4
pseudocode to the PreserveFPState() function), and not the full
5
set of actions matching the pseudocode ExecuteFPCheck() which
6
normal FP instructions need to do.
7
2
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20220609202901.1177572-8-richard.henderson@linaro.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
11
Message-id: 20201119215617.29887-13-peter.maydell@linaro.org
12
---
7
---
13
target/arm/translate-vfp.c.inc | 45 ++++++++++++++++++++--------------
8
target/arm/debug_helper.c | 31 +++++++++++++++++++++++++++++++
14
1 file changed, 27 insertions(+), 18 deletions(-)
9
target/arm/op_helper.c | 29 -----------------------------
10
2 files changed, 31 insertions(+), 29 deletions(-)
15
11
16
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
12
diff --git a/target/arm/debug_helper.c b/target/arm/debug_helper.c
17
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/translate-vfp.c.inc
14
--- a/target/arm/debug_helper.c
19
+++ b/target/arm/translate-vfp.c.inc
15
+++ b/target/arm/debug_helper.c
20
@@ -XXX,XX +XXX,XX @@ static inline long vfp_f16_offset(unsigned reg, bool top)
16
@@ -XXX,XX +XXX,XX @@ void arm_debug_excp_handler(CPUState *cs)
21
return offs;
17
}
22
}
18
}
23
19
24
+/*
20
+/*
25
+ * Generate code for M-profile lazy FP state preservation if needed;
21
+ * Raise an EXCP_BKPT with the specified syndrome register value,
26
+ * this corresponds to the pseudocode PreserveFPState() function.
22
+ * targeting the correct exception level for debug exceptions.
27
+ */
23
+ */
28
+static void gen_preserve_fp_state(DisasContext *s)
24
+void HELPER(exception_bkpt_insn)(CPUARMState *env, uint32_t syndrome)
29
+{
25
+{
30
+ if (s->v7m_lspact) {
26
+ int debug_el = arm_debug_target_el(env);
31
+ /*
27
+ int cur_el = arm_current_el(env);
32
+ * Lazy state saving affects external memory and also the NVIC,
28
+
33
+ * so we must mark it as an IO operation for icount (and cause
29
+ /* FSR will only be used if the debug target EL is AArch32. */
34
+ * this to be the last insn in the TB).
30
+ env->exception.fsr = arm_debug_exception_fsr(env);
35
+ */
31
+ /*
36
+ if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
32
+ * FAR is UNKNOWN: clear vaddress to avoid potentially exposing
37
+ s->base.is_jmp = DISAS_UPDATE_EXIT;
33
+ * values to the guest that it shouldn't be able to see at its
38
+ gen_io_start();
34
+ * exception/security level.
39
+ }
35
+ */
40
+ gen_helper_v7m_preserve_fp_state(cpu_env);
36
+ env->exception.vaddress = 0;
41
+ /*
37
+ /*
42
+ * If the preserve_fp_state helper doesn't throw an exception
38
+ * Other kinds of architectural debug exception are ignored if
43
+ * then it will clear LSPACT; we don't need to repeat this for
39
+ * they target an exception level below the current one (in QEMU
44
+ * any further FP insns in this TB.
40
+ * this is checked by arm_generate_debug_exceptions()). Breakpoint
45
+ */
41
+ * instructions are special because they always generate an exception
46
+ s->v7m_lspact = false;
42
+ * to somewhere: if they can't go to the configured debug exception
43
+ * level they are taken to the current exception level.
44
+ */
45
+ if (debug_el < cur_el) {
46
+ debug_el = cur_el;
47
+ }
47
+ }
48
+ raise_exception(env, EXCP_BKPT, syndrome, debug_el);
48
+}
49
+}
49
+
50
+
50
/*
51
#if !defined(CONFIG_USER_ONLY)
51
* Check that VFP access is enabled. If it is, do the necessary
52
52
* M-profile lazy-FP handling and then return true.
53
vaddr arm_adjust_watchpoint_address(CPUState *cs, vaddr addr, int len)
53
@@ -XXX,XX +XXX,XX @@ static bool full_vfp_access_check(DisasContext *s, bool ignore_vfp_enabled)
54
diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c
54
/* Handle M-profile lazy FP state mechanics */
55
index XXXXXXX..XXXXXXX 100644
55
56
--- a/target/arm/op_helper.c
56
/* Trigger lazy-state preservation if necessary */
57
+++ b/target/arm/op_helper.c
57
- if (s->v7m_lspact) {
58
@@ -XXX,XX +XXX,XX @@ void HELPER(exception_with_syndrome)(CPUARMState *env, uint32_t excp,
58
- /*
59
raise_exception(env, excp, syndrome, target_el);
59
- * Lazy state saving affects external memory and also the NVIC,
60
}
60
- * so we must mark it as an IO operation for icount (and cause
61
61
- * this to be the last insn in the TB).
62
-/* Raise an EXCP_BKPT with the specified syndrome register value,
62
- */
63
- * targeting the correct exception level for debug exceptions.
63
- if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
64
- */
64
- s->base.is_jmp = DISAS_UPDATE_EXIT;
65
-void HELPER(exception_bkpt_insn)(CPUARMState *env, uint32_t syndrome)
65
- gen_io_start();
66
-{
66
- }
67
- int debug_el = arm_debug_target_el(env);
67
- gen_helper_v7m_preserve_fp_state(cpu_env);
68
- int cur_el = arm_current_el(env);
68
- /*
69
-
69
- * If the preserve_fp_state helper doesn't throw an exception
70
- /* FSR will only be used if the debug target EL is AArch32. */
70
- * then it will clear LSPACT; we don't need to repeat this for
71
- env->exception.fsr = arm_debug_exception_fsr(env);
71
- * any further FP insns in this TB.
72
- /* FAR is UNKNOWN: clear vaddress to avoid potentially exposing
72
- */
73
- * values to the guest that it shouldn't be able to see at its
73
- s->v7m_lspact = false;
74
- * exception/security level.
74
- }
75
- */
75
+ gen_preserve_fp_state(s);
76
- env->exception.vaddress = 0;
76
77
- /*
77
/* Update ownership of FP context: set FPCCR.S to match current state */
78
- * Other kinds of architectural debug exception are ignored if
78
if (s->v8m_fpccr_s_wrong) {
79
- * they target an exception level below the current one (in QEMU
80
- * this is checked by arm_generate_debug_exceptions()). Breakpoint
81
- * instructions are special because they always generate an exception
82
- * to somewhere: if they can't go to the configured debug exception
83
- * level they are taken to the current exception level.
84
- */
85
- if (debug_el < cur_el) {
86
- debug_el = cur_el;
87
- }
88
- raise_exception(env, EXCP_BKPT, syndrome, debug_el);
89
-}
90
-
91
uint32_t HELPER(cpsr_read)(CPUARMState *env)
92
{
93
return cpsr_read(env) & ~CPSR_EXEC;
79
--
94
--
80
2.20.1
95
2.25.1
81
82
diff view generated by jsdifflib
1
From: Vikram Garhwal <fnu.vikram@xilinx.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
The Xilinx ZynqMP CAN controller is developed based on SocketCAN, QEMU CAN bus
3
This function now now only used in debug_helper.c, so there is
4
implementation. Bus connection and socketCAN connection for each CAN module
4
no reason to have a declaration in a header.
5
can be set through command lines.
6
5
7
Example for using single CAN:
8
-object can-bus,id=canbus0 \
9
-machine xlnx-zcu102.canbus0=canbus0 \
10
-object can-host-socketcan,id=socketcan0,if=vcan0,canbus=canbus0
11
12
Example for connecting both CAN to same virtual CAN on host machine:
13
-object can-bus,id=canbus0 -object can-bus,id=canbus1 \
14
-machine xlnx-zcu102.canbus0=canbus0 \
15
-machine xlnx-zcu102.canbus1=canbus1 \
16
-object can-host-socketcan,id=socketcan0,if=vcan0,canbus=canbus0 \
17
-object can-host-socketcan,id=socketcan1,if=vcan0,canbus=canbus1
18
19
To create virtual CAN on the host machine, please check the QEMU CAN docs:
20
https://github.com/qemu/qemu/blob/master/docs/can.txt
21
22
Signed-off-by: Vikram Garhwal <fnu.vikram@xilinx.com>
23
Message-id: 1605728926-352690-2-git-send-email-fnu.vikram@xilinx.com
24
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20220609202901.1177572-9-richard.henderson@linaro.org
25
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
26
---
10
---
27
meson.build | 1 +
11
target/arm/internals.h | 25 -------------------------
28
hw/net/can/trace.h | 1 +
12
target/arm/debug_helper.c | 26 ++++++++++++++++++++++++++
29
include/hw/net/xlnx-zynqmp-can.h | 78 ++
13
2 files changed, 26 insertions(+), 25 deletions(-)
30
hw/net/can/xlnx-zynqmp-can.c | 1161 ++++++++++++++++++++++++++++++
31
hw/Kconfig | 1 +
32
hw/net/can/meson.build | 1 +
33
hw/net/can/trace-events | 9 +
34
7 files changed, 1252 insertions(+)
35
create mode 100644 hw/net/can/trace.h
36
create mode 100644 include/hw/net/xlnx-zynqmp-can.h
37
create mode 100644 hw/net/can/xlnx-zynqmp-can.c
38
create mode 100644 hw/net/can/trace-events
39
14
40
diff --git a/meson.build b/meson.build
15
diff --git a/target/arm/internals.h b/target/arm/internals.h
41
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
42
--- a/meson.build
17
--- a/target/arm/internals.h
43
+++ b/meson.build
18
+++ b/target/arm/internals.h
44
@@ -XXX,XX +XXX,XX @@ if have_system
19
@@ -XXX,XX +XXX,XX @@ static inline TCR *regime_tcr(CPUARMState *env, ARMMMUIdx mmu_idx)
45
'hw/misc',
20
return &env->cp15.tcr_el[regime_el(env, mmu_idx)];
46
'hw/misc/macio',
21
}
47
'hw/net',
22
48
+ 'hw/net/can',
23
-/* Return the FSR value for a debug exception (watchpoint, hardware
49
'hw/nvram',
24
- * breakpoint or BKPT insn) targeting the specified exception level.
50
'hw/pci',
25
- */
51
'hw/pci-host',
26
-static inline uint32_t arm_debug_exception_fsr(CPUARMState *env)
52
diff --git a/hw/net/can/trace.h b/hw/net/can/trace.h
27
-{
53
new file mode 100644
28
- ARMMMUFaultInfo fi = { .type = ARMFault_Debug };
54
index XXXXXXX..XXXXXXX
29
- int target_el = arm_debug_target_el(env);
55
--- /dev/null
30
- bool using_lpae = false;
56
+++ b/hw/net/can/trace.h
31
-
57
@@ -0,0 +1 @@
32
- if (target_el == 2 || arm_el_is_aa64(env, target_el)) {
58
+#include "trace/trace-hw_net_can.h"
33
- using_lpae = true;
59
diff --git a/include/hw/net/xlnx-zynqmp-can.h b/include/hw/net/xlnx-zynqmp-can.h
34
- } else {
60
new file mode 100644
35
- if (arm_feature(env, ARM_FEATURE_LPAE) &&
61
index XXXXXXX..XXXXXXX
36
- (env->cp15.tcr_el[target_el].raw_tcr & TTBCR_EAE)) {
62
--- /dev/null
37
- using_lpae = true;
63
+++ b/include/hw/net/xlnx-zynqmp-can.h
38
- }
64
@@ -XXX,XX +XXX,XX @@
39
- }
40
-
41
- if (using_lpae) {
42
- return arm_fi_to_lfsc(&fi);
43
- } else {
44
- return arm_fi_to_sfsc(&fi);
45
- }
46
-}
47
-
48
/**
49
* arm_num_brps: Return number of implemented breakpoints.
50
* Note that the ID register BRPS field is "number of bps - 1",
51
diff --git a/target/arm/debug_helper.c b/target/arm/debug_helper.c
52
index XXXXXXX..XXXXXXX 100644
53
--- a/target/arm/debug_helper.c
54
+++ b/target/arm/debug_helper.c
55
@@ -XXX,XX +XXX,XX @@ bool arm_debug_check_watchpoint(CPUState *cs, CPUWatchpoint *wp)
56
return check_watchpoints(cpu);
57
}
58
65
+/*
59
+/*
66
+ * QEMU model of the Xilinx ZynqMP CAN controller.
60
+ * Return the FSR value for a debug exception (watchpoint, hardware
67
+ *
61
+ * breakpoint or BKPT insn) targeting the specified exception level.
68
+ * Copyright (c) 2020 Xilinx Inc.
69
+ *
70
+ * Written-by: Vikram Garhwal<fnu.vikram@xilinx.com>
71
+ *
72
+ * Based on QEMU CAN Device emulation implemented by Jin Yang, Deniz Eren and
73
+ * Pavel Pisa.
74
+ *
75
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
76
+ * of this software and associated documentation files (the "Software"), to deal
77
+ * in the Software without restriction, including without limitation the rights
78
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
79
+ * copies of the Software, and to permit persons to whom the Software is
80
+ * furnished to do so, subject to the following conditions:
81
+ *
82
+ * The above copyright notice and this permission notice shall be included in
83
+ * all copies or substantial portions of the Software.
84
+ *
85
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
86
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
87
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
88
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
89
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
90
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
91
+ * THE SOFTWARE.
92
+ */
62
+ */
63
+static uint32_t arm_debug_exception_fsr(CPUARMState *env)
64
+{
65
+ ARMMMUFaultInfo fi = { .type = ARMFault_Debug };
66
+ int target_el = arm_debug_target_el(env);
67
+ bool using_lpae = false;
93
+
68
+
94
+#ifndef XLNX_ZYNQMP_CAN_H
69
+ if (target_el == 2 || arm_el_is_aa64(env, target_el)) {
95
+#define XLNX_ZYNQMP_CAN_H
70
+ using_lpae = true;
96
+
97
+#include "hw/register.h"
98
+#include "net/can_emu.h"
99
+#include "net/can_host.h"
100
+#include "qemu/fifo32.h"
101
+#include "hw/ptimer.h"
102
+#include "hw/qdev-clock.h"
103
+
104
+#define TYPE_XLNX_ZYNQMP_CAN "xlnx.zynqmp-can"
105
+
106
+#define XLNX_ZYNQMP_CAN(obj) \
107
+ OBJECT_CHECK(XlnxZynqMPCANState, (obj), TYPE_XLNX_ZYNQMP_CAN)
108
+
109
+#define MAX_CAN_CTRLS 2
110
+#define XLNX_ZYNQMP_CAN_R_MAX (0x84 / 4)
111
+#define MAILBOX_CAPACITY 64
112
+#define CAN_TIMER_MAX 0XFFFFUL
113
+#define CAN_DEFAULT_CLOCK (24 * 1000 * 1000)
114
+
115
+/* Each CAN_FRAME will have 4 * 32bit size. */
116
+#define CAN_FRAME_SIZE 4
117
+#define RXFIFO_SIZE (MAILBOX_CAPACITY * CAN_FRAME_SIZE)
118
+
119
+typedef struct XlnxZynqMPCANState {
120
+ SysBusDevice parent_obj;
121
+ MemoryRegion iomem;
122
+
123
+ qemu_irq irq;
124
+
125
+ CanBusClientState bus_client;
126
+ CanBusState *canbus;
127
+
128
+ struct {
129
+ uint32_t ext_clk_freq;
130
+ } cfg;
131
+
132
+ RegisterInfo reg_info[XLNX_ZYNQMP_CAN_R_MAX];
133
+ uint32_t regs[XLNX_ZYNQMP_CAN_R_MAX];
134
+
135
+ Fifo32 rx_fifo;
136
+ Fifo32 tx_fifo;
137
+ Fifo32 txhpb_fifo;
138
+
139
+ ptimer_state *can_timer;
140
+} XlnxZynqMPCANState;
141
+
142
+#endif
143
diff --git a/hw/net/can/xlnx-zynqmp-can.c b/hw/net/can/xlnx-zynqmp-can.c
144
new file mode 100644
145
index XXXXXXX..XXXXXXX
146
--- /dev/null
147
+++ b/hw/net/can/xlnx-zynqmp-can.c
148
@@ -XXX,XX +XXX,XX @@
149
+/*
150
+ * QEMU model of the Xilinx ZynqMP CAN controller.
151
+ * This implementation is based on the following datasheet:
152
+ * https://www.xilinx.com/support/documentation/user_guides/ug1085-zynq-ultrascale-trm.pdf
153
+ *
154
+ * Copyright (c) 2020 Xilinx Inc.
155
+ *
156
+ * Written-by: Vikram Garhwal<fnu.vikram@xilinx.com>
157
+ *
158
+ * Based on QEMU CAN Device emulation implemented by Jin Yang, Deniz Eren and
159
+ * Pavel Pisa
160
+ *
161
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
162
+ * of this software and associated documentation files (the "Software"), to deal
163
+ * in the Software without restriction, including without limitation the rights
164
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
165
+ * copies of the Software, and to permit persons to whom the Software is
166
+ * furnished to do so, subject to the following conditions:
167
+ *
168
+ * The above copyright notice and this permission notice shall be included in
169
+ * all copies or substantial portions of the Software.
170
+ *
171
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
172
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
173
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
174
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
175
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
176
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
177
+ * THE SOFTWARE.
178
+ */
179
+
180
+#include "qemu/osdep.h"
181
+#include "hw/sysbus.h"
182
+#include "hw/register.h"
183
+#include "hw/irq.h"
184
+#include "qapi/error.h"
185
+#include "qemu/bitops.h"
186
+#include "qemu/log.h"
187
+#include "qemu/cutils.h"
188
+#include "sysemu/sysemu.h"
189
+#include "migration/vmstate.h"
190
+#include "hw/qdev-properties.h"
191
+#include "net/can_emu.h"
192
+#include "net/can_host.h"
193
+#include "qemu/event_notifier.h"
194
+#include "qom/object_interfaces.h"
195
+#include "hw/net/xlnx-zynqmp-can.h"
196
+#include "trace.h"
197
+
198
+#ifndef XLNX_ZYNQMP_CAN_ERR_DEBUG
199
+#define XLNX_ZYNQMP_CAN_ERR_DEBUG 0
200
+#endif
201
+
202
+#define MAX_DLC 8
203
+#undef ERROR
204
+
205
+REG32(SOFTWARE_RESET_REGISTER, 0x0)
206
+ FIELD(SOFTWARE_RESET_REGISTER, CEN, 1, 1)
207
+ FIELD(SOFTWARE_RESET_REGISTER, SRST, 0, 1)
208
+REG32(MODE_SELECT_REGISTER, 0x4)
209
+ FIELD(MODE_SELECT_REGISTER, SNOOP, 2, 1)
210
+ FIELD(MODE_SELECT_REGISTER, LBACK, 1, 1)
211
+ FIELD(MODE_SELECT_REGISTER, SLEEP, 0, 1)
212
+REG32(ARBITRATION_PHASE_BAUD_RATE_PRESCALER_REGISTER, 0x8)
213
+ FIELD(ARBITRATION_PHASE_BAUD_RATE_PRESCALER_REGISTER, BRP, 0, 8)
214
+REG32(ARBITRATION_PHASE_BIT_TIMING_REGISTER, 0xc)
215
+ FIELD(ARBITRATION_PHASE_BIT_TIMING_REGISTER, SJW, 7, 2)
216
+ FIELD(ARBITRATION_PHASE_BIT_TIMING_REGISTER, TS2, 4, 3)
217
+ FIELD(ARBITRATION_PHASE_BIT_TIMING_REGISTER, TS1, 0, 4)
218
+REG32(ERROR_COUNTER_REGISTER, 0x10)
219
+ FIELD(ERROR_COUNTER_REGISTER, REC, 8, 8)
220
+ FIELD(ERROR_COUNTER_REGISTER, TEC, 0, 8)
221
+REG32(ERROR_STATUS_REGISTER, 0x14)
222
+ FIELD(ERROR_STATUS_REGISTER, ACKER, 4, 1)
223
+ FIELD(ERROR_STATUS_REGISTER, BERR, 3, 1)
224
+ FIELD(ERROR_STATUS_REGISTER, STER, 2, 1)
225
+ FIELD(ERROR_STATUS_REGISTER, FMER, 1, 1)
226
+ FIELD(ERROR_STATUS_REGISTER, CRCER, 0, 1)
227
+REG32(STATUS_REGISTER, 0x18)
228
+ FIELD(STATUS_REGISTER, SNOOP, 12, 1)
229
+ FIELD(STATUS_REGISTER, ACFBSY, 11, 1)
230
+ FIELD(STATUS_REGISTER, TXFLL, 10, 1)
231
+ FIELD(STATUS_REGISTER, TXBFLL, 9, 1)
232
+ FIELD(STATUS_REGISTER, ESTAT, 7, 2)
233
+ FIELD(STATUS_REGISTER, ERRWRN, 6, 1)
234
+ FIELD(STATUS_REGISTER, BBSY, 5, 1)
235
+ FIELD(STATUS_REGISTER, BIDLE, 4, 1)
236
+ FIELD(STATUS_REGISTER, NORMAL, 3, 1)
237
+ FIELD(STATUS_REGISTER, SLEEP, 2, 1)
238
+ FIELD(STATUS_REGISTER, LBACK, 1, 1)
239
+ FIELD(STATUS_REGISTER, CONFIG, 0, 1)
240
+REG32(INTERRUPT_STATUS_REGISTER, 0x1c)
241
+ FIELD(INTERRUPT_STATUS_REGISTER, TXFEMP, 14, 1)
242
+ FIELD(INTERRUPT_STATUS_REGISTER, TXFWMEMP, 13, 1)
243
+ FIELD(INTERRUPT_STATUS_REGISTER, RXFWMFLL, 12, 1)
244
+ FIELD(INTERRUPT_STATUS_REGISTER, WKUP, 11, 1)
245
+ FIELD(INTERRUPT_STATUS_REGISTER, SLP, 10, 1)
246
+ FIELD(INTERRUPT_STATUS_REGISTER, BSOFF, 9, 1)
247
+ FIELD(INTERRUPT_STATUS_REGISTER, ERROR, 8, 1)
248
+ FIELD(INTERRUPT_STATUS_REGISTER, RXNEMP, 7, 1)
249
+ FIELD(INTERRUPT_STATUS_REGISTER, RXOFLW, 6, 1)
250
+ FIELD(INTERRUPT_STATUS_REGISTER, RXUFLW, 5, 1)
251
+ FIELD(INTERRUPT_STATUS_REGISTER, RXOK, 4, 1)
252
+ FIELD(INTERRUPT_STATUS_REGISTER, TXBFLL, 3, 1)
253
+ FIELD(INTERRUPT_STATUS_REGISTER, TXFLL, 2, 1)
254
+ FIELD(INTERRUPT_STATUS_REGISTER, TXOK, 1, 1)
255
+ FIELD(INTERRUPT_STATUS_REGISTER, ARBLST, 0, 1)
256
+REG32(INTERRUPT_ENABLE_REGISTER, 0x20)
257
+ FIELD(INTERRUPT_ENABLE_REGISTER, ETXFEMP, 14, 1)
258
+ FIELD(INTERRUPT_ENABLE_REGISTER, ETXFWMEMP, 13, 1)
259
+ FIELD(INTERRUPT_ENABLE_REGISTER, ERXFWMFLL, 12, 1)
260
+ FIELD(INTERRUPT_ENABLE_REGISTER, EWKUP, 11, 1)
261
+ FIELD(INTERRUPT_ENABLE_REGISTER, ESLP, 10, 1)
262
+ FIELD(INTERRUPT_ENABLE_REGISTER, EBSOFF, 9, 1)
263
+ FIELD(INTERRUPT_ENABLE_REGISTER, EERROR, 8, 1)
264
+ FIELD(INTERRUPT_ENABLE_REGISTER, ERXNEMP, 7, 1)
265
+ FIELD(INTERRUPT_ENABLE_REGISTER, ERXOFLW, 6, 1)
266
+ FIELD(INTERRUPT_ENABLE_REGISTER, ERXUFLW, 5, 1)
267
+ FIELD(INTERRUPT_ENABLE_REGISTER, ERXOK, 4, 1)
268
+ FIELD(INTERRUPT_ENABLE_REGISTER, ETXBFLL, 3, 1)
269
+ FIELD(INTERRUPT_ENABLE_REGISTER, ETXFLL, 2, 1)
270
+ FIELD(INTERRUPT_ENABLE_REGISTER, ETXOK, 1, 1)
271
+ FIELD(INTERRUPT_ENABLE_REGISTER, EARBLST, 0, 1)
272
+REG32(INTERRUPT_CLEAR_REGISTER, 0x24)
273
+ FIELD(INTERRUPT_CLEAR_REGISTER, CTXFEMP, 14, 1)
274
+ FIELD(INTERRUPT_CLEAR_REGISTER, CTXFWMEMP, 13, 1)
275
+ FIELD(INTERRUPT_CLEAR_REGISTER, CRXFWMFLL, 12, 1)
276
+ FIELD(INTERRUPT_CLEAR_REGISTER, CWKUP, 11, 1)
277
+ FIELD(INTERRUPT_CLEAR_REGISTER, CSLP, 10, 1)
278
+ FIELD(INTERRUPT_CLEAR_REGISTER, CBSOFF, 9, 1)
279
+ FIELD(INTERRUPT_CLEAR_REGISTER, CERROR, 8, 1)
280
+ FIELD(INTERRUPT_CLEAR_REGISTER, CRXNEMP, 7, 1)
281
+ FIELD(INTERRUPT_CLEAR_REGISTER, CRXOFLW, 6, 1)
282
+ FIELD(INTERRUPT_CLEAR_REGISTER, CRXUFLW, 5, 1)
283
+ FIELD(INTERRUPT_CLEAR_REGISTER, CRXOK, 4, 1)
284
+ FIELD(INTERRUPT_CLEAR_REGISTER, CTXBFLL, 3, 1)
285
+ FIELD(INTERRUPT_CLEAR_REGISTER, CTXFLL, 2, 1)
286
+ FIELD(INTERRUPT_CLEAR_REGISTER, CTXOK, 1, 1)
287
+ FIELD(INTERRUPT_CLEAR_REGISTER, CARBLST, 0, 1)
288
+REG32(TIMESTAMP_REGISTER, 0x28)
289
+ FIELD(TIMESTAMP_REGISTER, CTS, 0, 1)
290
+REG32(WIR, 0x2c)
291
+ FIELD(WIR, EW, 8, 8)
292
+ FIELD(WIR, FW, 0, 8)
293
+REG32(TXFIFO_ID, 0x30)
294
+ FIELD(TXFIFO_ID, IDH, 21, 11)
295
+ FIELD(TXFIFO_ID, SRRRTR, 20, 1)
296
+ FIELD(TXFIFO_ID, IDE, 19, 1)
297
+ FIELD(TXFIFO_ID, IDL, 1, 18)
298
+ FIELD(TXFIFO_ID, RTR, 0, 1)
299
+REG32(TXFIFO_DLC, 0x34)
300
+ FIELD(TXFIFO_DLC, DLC, 28, 4)
301
+REG32(TXFIFO_DATA1, 0x38)
302
+ FIELD(TXFIFO_DATA1, DB0, 24, 8)
303
+ FIELD(TXFIFO_DATA1, DB1, 16, 8)
304
+ FIELD(TXFIFO_DATA1, DB2, 8, 8)
305
+ FIELD(TXFIFO_DATA1, DB3, 0, 8)
306
+REG32(TXFIFO_DATA2, 0x3c)
307
+ FIELD(TXFIFO_DATA2, DB4, 24, 8)
308
+ FIELD(TXFIFO_DATA2, DB5, 16, 8)
309
+ FIELD(TXFIFO_DATA2, DB6, 8, 8)
310
+ FIELD(TXFIFO_DATA2, DB7, 0, 8)
311
+REG32(TXHPB_ID, 0x40)
312
+ FIELD(TXHPB_ID, IDH, 21, 11)
313
+ FIELD(TXHPB_ID, SRRRTR, 20, 1)
314
+ FIELD(TXHPB_ID, IDE, 19, 1)
315
+ FIELD(TXHPB_ID, IDL, 1, 18)
316
+ FIELD(TXHPB_ID, RTR, 0, 1)
317
+REG32(TXHPB_DLC, 0x44)
318
+ FIELD(TXHPB_DLC, DLC, 28, 4)
319
+REG32(TXHPB_DATA1, 0x48)
320
+ FIELD(TXHPB_DATA1, DB0, 24, 8)
321
+ FIELD(TXHPB_DATA1, DB1, 16, 8)
322
+ FIELD(TXHPB_DATA1, DB2, 8, 8)
323
+ FIELD(TXHPB_DATA1, DB3, 0, 8)
324
+REG32(TXHPB_DATA2, 0x4c)
325
+ FIELD(TXHPB_DATA2, DB4, 24, 8)
326
+ FIELD(TXHPB_DATA2, DB5, 16, 8)
327
+ FIELD(TXHPB_DATA2, DB6, 8, 8)
328
+ FIELD(TXHPB_DATA2, DB7, 0, 8)
329
+REG32(RXFIFO_ID, 0x50)
330
+ FIELD(RXFIFO_ID, IDH, 21, 11)
331
+ FIELD(RXFIFO_ID, SRRRTR, 20, 1)
332
+ FIELD(RXFIFO_ID, IDE, 19, 1)
333
+ FIELD(RXFIFO_ID, IDL, 1, 18)
334
+ FIELD(RXFIFO_ID, RTR, 0, 1)
335
+REG32(RXFIFO_DLC, 0x54)
336
+ FIELD(RXFIFO_DLC, DLC, 28, 4)
337
+ FIELD(RXFIFO_DLC, RXT, 0, 16)
338
+REG32(RXFIFO_DATA1, 0x58)
339
+ FIELD(RXFIFO_DATA1, DB0, 24, 8)
340
+ FIELD(RXFIFO_DATA1, DB1, 16, 8)
341
+ FIELD(RXFIFO_DATA1, DB2, 8, 8)
342
+ FIELD(RXFIFO_DATA1, DB3, 0, 8)
343
+REG32(RXFIFO_DATA2, 0x5c)
344
+ FIELD(RXFIFO_DATA2, DB4, 24, 8)
345
+ FIELD(RXFIFO_DATA2, DB5, 16, 8)
346
+ FIELD(RXFIFO_DATA2, DB6, 8, 8)
347
+ FIELD(RXFIFO_DATA2, DB7, 0, 8)
348
+REG32(AFR, 0x60)
349
+ FIELD(AFR, UAF4, 3, 1)
350
+ FIELD(AFR, UAF3, 2, 1)
351
+ FIELD(AFR, UAF2, 1, 1)
352
+ FIELD(AFR, UAF1, 0, 1)
353
+REG32(AFMR1, 0x64)
354
+ FIELD(AFMR1, AMIDH, 21, 11)
355
+ FIELD(AFMR1, AMSRR, 20, 1)
356
+ FIELD(AFMR1, AMIDE, 19, 1)
357
+ FIELD(AFMR1, AMIDL, 1, 18)
358
+ FIELD(AFMR1, AMRTR, 0, 1)
359
+REG32(AFIR1, 0x68)
360
+ FIELD(AFIR1, AIIDH, 21, 11)
361
+ FIELD(AFIR1, AISRR, 20, 1)
362
+ FIELD(AFIR1, AIIDE, 19, 1)
363
+ FIELD(AFIR1, AIIDL, 1, 18)
364
+ FIELD(AFIR1, AIRTR, 0, 1)
365
+REG32(AFMR2, 0x6c)
366
+ FIELD(AFMR2, AMIDH, 21, 11)
367
+ FIELD(AFMR2, AMSRR, 20, 1)
368
+ FIELD(AFMR2, AMIDE, 19, 1)
369
+ FIELD(AFMR2, AMIDL, 1, 18)
370
+ FIELD(AFMR2, AMRTR, 0, 1)
371
+REG32(AFIR2, 0x70)
372
+ FIELD(AFIR2, AIIDH, 21, 11)
373
+ FIELD(AFIR2, AISRR, 20, 1)
374
+ FIELD(AFIR2, AIIDE, 19, 1)
375
+ FIELD(AFIR2, AIIDL, 1, 18)
376
+ FIELD(AFIR2, AIRTR, 0, 1)
377
+REG32(AFMR3, 0x74)
378
+ FIELD(AFMR3, AMIDH, 21, 11)
379
+ FIELD(AFMR3, AMSRR, 20, 1)
380
+ FIELD(AFMR3, AMIDE, 19, 1)
381
+ FIELD(AFMR3, AMIDL, 1, 18)
382
+ FIELD(AFMR3, AMRTR, 0, 1)
383
+REG32(AFIR3, 0x78)
384
+ FIELD(AFIR3, AIIDH, 21, 11)
385
+ FIELD(AFIR3, AISRR, 20, 1)
386
+ FIELD(AFIR3, AIIDE, 19, 1)
387
+ FIELD(AFIR3, AIIDL, 1, 18)
388
+ FIELD(AFIR3, AIRTR, 0, 1)
389
+REG32(AFMR4, 0x7c)
390
+ FIELD(AFMR4, AMIDH, 21, 11)
391
+ FIELD(AFMR4, AMSRR, 20, 1)
392
+ FIELD(AFMR4, AMIDE, 19, 1)
393
+ FIELD(AFMR4, AMIDL, 1, 18)
394
+ FIELD(AFMR4, AMRTR, 0, 1)
395
+REG32(AFIR4, 0x80)
396
+ FIELD(AFIR4, AIIDH, 21, 11)
397
+ FIELD(AFIR4, AISRR, 20, 1)
398
+ FIELD(AFIR4, AIIDE, 19, 1)
399
+ FIELD(AFIR4, AIIDL, 1, 18)
400
+ FIELD(AFIR4, AIRTR, 0, 1)
401
+
402
+static void can_update_irq(XlnxZynqMPCANState *s)
403
+{
404
+ uint32_t irq;
405
+
406
+ /* Watermark register interrupts. */
407
+ if ((fifo32_num_free(&s->tx_fifo) / CAN_FRAME_SIZE) >
408
+ ARRAY_FIELD_EX32(s->regs, WIR, EW)) {
409
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TXFWMEMP, 1);
410
+ }
411
+
412
+ if ((fifo32_num_used(&s->rx_fifo) / CAN_FRAME_SIZE) >
413
+ ARRAY_FIELD_EX32(s->regs, WIR, FW)) {
414
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXFWMFLL, 1);
415
+ }
416
+
417
+ /* RX Interrupts. */
418
+ if (fifo32_num_used(&s->rx_fifo) >= CAN_FRAME_SIZE) {
419
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXNEMP, 1);
420
+ }
421
+
422
+ /* TX interrupts. */
423
+ if (fifo32_is_empty(&s->tx_fifo)) {
424
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TXFEMP, 1);
425
+ }
426
+
427
+ if (fifo32_is_full(&s->tx_fifo)) {
428
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TXFLL, 1);
429
+ }
430
+
431
+ if (fifo32_is_full(&s->txhpb_fifo)) {
432
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TXBFLL, 1);
433
+ }
434
+
435
+ irq = s->regs[R_INTERRUPT_STATUS_REGISTER];
436
+ irq &= s->regs[R_INTERRUPT_ENABLE_REGISTER];
437
+
438
+ trace_xlnx_can_update_irq(s->regs[R_INTERRUPT_STATUS_REGISTER],
439
+ s->regs[R_INTERRUPT_ENABLE_REGISTER], irq);
440
+ qemu_set_irq(s->irq, irq);
441
+}
442
+
443
+static void can_ier_post_write(RegisterInfo *reg, uint64_t val)
444
+{
445
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
446
+
447
+ can_update_irq(s);
448
+}
449
+
450
+static uint64_t can_icr_pre_write(RegisterInfo *reg, uint64_t val)
451
+{
452
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
453
+
454
+ s->regs[R_INTERRUPT_STATUS_REGISTER] &= ~val;
455
+ can_update_irq(s);
456
+
457
+ return 0;
458
+}
459
+
460
+static void can_config_reset(XlnxZynqMPCANState *s)
461
+{
462
+ /* Reset all the configuration registers. */
463
+ register_reset(&s->reg_info[R_SOFTWARE_RESET_REGISTER]);
464
+ register_reset(&s->reg_info[R_MODE_SELECT_REGISTER]);
465
+ register_reset(
466
+ &s->reg_info[R_ARBITRATION_PHASE_BAUD_RATE_PRESCALER_REGISTER]);
467
+ register_reset(&s->reg_info[R_ARBITRATION_PHASE_BIT_TIMING_REGISTER]);
468
+ register_reset(&s->reg_info[R_STATUS_REGISTER]);
469
+ register_reset(&s->reg_info[R_INTERRUPT_STATUS_REGISTER]);
470
+ register_reset(&s->reg_info[R_INTERRUPT_ENABLE_REGISTER]);
471
+ register_reset(&s->reg_info[R_INTERRUPT_CLEAR_REGISTER]);
472
+ register_reset(&s->reg_info[R_WIR]);
473
+}
474
+
475
+static void can_config_mode(XlnxZynqMPCANState *s)
476
+{
477
+ register_reset(&s->reg_info[R_ERROR_COUNTER_REGISTER]);
478
+ register_reset(&s->reg_info[R_ERROR_STATUS_REGISTER]);
479
+
480
+ /* Put XlnxZynqMPCAN in configuration mode. */
481
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, CONFIG, 1);
482
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, WKUP, 0);
483
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, SLP, 0);
484
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, BSOFF, 0);
485
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, ERROR, 0);
486
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXOFLW, 0);
487
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXOK, 0);
488
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TXOK, 0);
489
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, ARBLST, 0);
490
+
491
+ can_update_irq(s);
492
+}
493
+
494
+static void update_status_register_mode_bits(XlnxZynqMPCANState *s)
495
+{
496
+ bool sleep_status = ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, SLEEP);
497
+ bool sleep_mode = ARRAY_FIELD_EX32(s->regs, MODE_SELECT_REGISTER, SLEEP);
498
+ /* Wake up interrupt bit. */
499
+ bool wakeup_irq_val = sleep_status && (sleep_mode == 0);
500
+ /* Sleep interrupt bit. */
501
+ bool sleep_irq_val = sleep_mode && (sleep_status == 0);
502
+
503
+ /* Clear previous core mode status bits. */
504
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, LBACK, 0);
505
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, SLEEP, 0);
506
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, SNOOP, 0);
507
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, NORMAL, 0);
508
+
509
+ /* set current mode bit and generate irqs accordingly. */
510
+ if (ARRAY_FIELD_EX32(s->regs, MODE_SELECT_REGISTER, LBACK)) {
511
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, LBACK, 1);
512
+ } else if (ARRAY_FIELD_EX32(s->regs, MODE_SELECT_REGISTER, SLEEP)) {
513
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, SLEEP, 1);
514
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, SLP,
515
+ sleep_irq_val);
516
+ } else if (ARRAY_FIELD_EX32(s->regs, MODE_SELECT_REGISTER, SNOOP)) {
517
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, SNOOP, 1);
518
+ } else {
71
+ } else {
519
+ /*
72
+ if (arm_feature(env, ARM_FEATURE_LPAE) &&
520
+ * If all bits are zero then XlnxZynqMPCAN is set in normal mode.
73
+ (env->cp15.tcr_el[target_el].raw_tcr & TTBCR_EAE)) {
521
+ */
74
+ using_lpae = true;
522
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, NORMAL, 1);
523
+ /* Set wakeup interrupt bit. */
524
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, WKUP,
525
+ wakeup_irq_val);
526
+ }
527
+
528
+ can_update_irq(s);
529
+}
530
+
531
+static void can_exit_sleep_mode(XlnxZynqMPCANState *s)
532
+{
533
+ ARRAY_FIELD_DP32(s->regs, MODE_SELECT_REGISTER, SLEEP, 0);
534
+ update_status_register_mode_bits(s);
535
+}
536
+
537
+static void generate_frame(qemu_can_frame *frame, uint32_t *data)
538
+{
539
+ frame->can_id = data[0];
540
+ frame->can_dlc = FIELD_EX32(data[1], TXFIFO_DLC, DLC);
541
+
542
+ frame->data[0] = FIELD_EX32(data[2], TXFIFO_DATA1, DB3);
543
+ frame->data[1] = FIELD_EX32(data[2], TXFIFO_DATA1, DB2);
544
+ frame->data[2] = FIELD_EX32(data[2], TXFIFO_DATA1, DB1);
545
+ frame->data[3] = FIELD_EX32(data[2], TXFIFO_DATA1, DB0);
546
+
547
+ frame->data[4] = FIELD_EX32(data[3], TXFIFO_DATA2, DB7);
548
+ frame->data[5] = FIELD_EX32(data[3], TXFIFO_DATA2, DB6);
549
+ frame->data[6] = FIELD_EX32(data[3], TXFIFO_DATA2, DB5);
550
+ frame->data[7] = FIELD_EX32(data[3], TXFIFO_DATA2, DB4);
551
+}
552
+
553
+static bool tx_ready_check(XlnxZynqMPCANState *s)
554
+{
555
+ if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, SRST)) {
556
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
557
+
558
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Attempting to transfer data while"
559
+ " data while controller is in reset mode.\n",
560
+ path);
561
+ return false;
562
+ }
563
+
564
+ if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN) == 0) {
565
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
566
+
567
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Attempting to transfer"
568
+ " data while controller is in configuration mode. Reset"
569
+ " the core so operations can start fresh.\n",
570
+ path);
571
+ return false;
572
+ }
573
+
574
+ if (ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, SNOOP)) {
575
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
576
+
577
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Attempting to transfer"
578
+ " data while controller is in SNOOP MODE.\n",
579
+ path);
580
+ return false;
581
+ }
582
+
583
+ return true;
584
+}
585
+
586
+static void transfer_fifo(XlnxZynqMPCANState *s, Fifo32 *fifo)
587
+{
588
+ qemu_can_frame frame;
589
+ uint32_t data[CAN_FRAME_SIZE];
590
+ int i;
591
+ bool can_tx = tx_ready_check(s);
592
+
593
+ if (!can_tx) {
594
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
595
+
596
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Controller is not enabled for data"
597
+ " transfer.\n", path);
598
+ can_update_irq(s);
599
+ return;
600
+ }
601
+
602
+ while (!fifo32_is_empty(fifo)) {
603
+ for (i = 0; i < CAN_FRAME_SIZE; i++) {
604
+ data[i] = fifo32_pop(fifo);
605
+ }
606
+
607
+ if (ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, LBACK)) {
608
+ /*
609
+ * Controller is in loopback. In Loopback mode, the CAN core
610
+ * transmits a recessive bitstream on to the XlnxZynqMPCAN Bus.
611
+ * Any message transmitted is looped back to the RX line and
612
+ * acknowledged. The XlnxZynqMPCAN core receives any message
613
+ * that it transmits.
614
+ */
615
+ if (fifo32_is_full(&s->rx_fifo)) {
616
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXOFLW, 1);
617
+ } else {
618
+ for (i = 0; i < CAN_FRAME_SIZE; i++) {
619
+ fifo32_push(&s->rx_fifo, data[i]);
620
+ }
621
+
622
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXOK, 1);
623
+ }
624
+ } else {
625
+ /* Normal mode Tx. */
626
+ generate_frame(&frame, data);
627
+
628
+ trace_xlnx_can_tx_data(frame.can_id, frame.can_dlc,
629
+ frame.data[0], frame.data[1],
630
+ frame.data[2], frame.data[3],
631
+ frame.data[4], frame.data[5],
632
+ frame.data[6], frame.data[7]);
633
+ can_bus_client_send(&s->bus_client, &frame, 1);
634
+ }
75
+ }
635
+ }
76
+ }
636
+
77
+
637
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TXOK, 1);
78
+ if (using_lpae) {
638
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, TXBFLL, 0);
79
+ return arm_fi_to_lfsc(&fi);
639
+
640
+ if (ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, SLEEP)) {
641
+ can_exit_sleep_mode(s);
642
+ }
643
+
644
+ can_update_irq(s);
645
+}
646
+
647
+static uint64_t can_srr_pre_write(RegisterInfo *reg, uint64_t val)
648
+{
649
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
650
+
651
+ ARRAY_FIELD_DP32(s->regs, SOFTWARE_RESET_REGISTER, CEN,
652
+ FIELD_EX32(val, SOFTWARE_RESET_REGISTER, CEN));
653
+
654
+ if (FIELD_EX32(val, SOFTWARE_RESET_REGISTER, SRST)) {
655
+ trace_xlnx_can_reset(val);
656
+
657
+ /* First, core will do software reset then will enter in config mode. */
658
+ can_config_reset(s);
659
+ }
660
+
661
+ if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN) == 0) {
662
+ can_config_mode(s);
663
+ } else {
80
+ } else {
664
+ /*
81
+ return arm_fi_to_sfsc(&fi);
665
+ * Leave config mode. Now XlnxZynqMPCAN core will enter normal,
666
+ * sleep, snoop or loopback mode depending upon LBACK, SLEEP, SNOOP
667
+ * register states.
668
+ */
669
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, CONFIG, 0);
670
+
671
+ ptimer_transaction_begin(s->can_timer);
672
+ ptimer_set_count(s->can_timer, 0);
673
+ ptimer_transaction_commit(s->can_timer);
674
+
675
+ /* XlnxZynqMPCAN is out of config mode. It will send pending data. */
676
+ transfer_fifo(s, &s->txhpb_fifo);
677
+ transfer_fifo(s, &s->tx_fifo);
678
+ }
679
+
680
+ update_status_register_mode_bits(s);
681
+
682
+ return s->regs[R_SOFTWARE_RESET_REGISTER];
683
+}
684
+
685
+static uint64_t can_msr_pre_write(RegisterInfo *reg, uint64_t val)
686
+{
687
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
688
+ uint8_t multi_mode;
689
+
690
+ /*
691
+ * Multiple mode set check. This is done to make sure user doesn't set
692
+ * multiple modes.
693
+ */
694
+ multi_mode = FIELD_EX32(val, MODE_SELECT_REGISTER, LBACK) +
695
+ FIELD_EX32(val, MODE_SELECT_REGISTER, SLEEP) +
696
+ FIELD_EX32(val, MODE_SELECT_REGISTER, SNOOP);
697
+
698
+ if (multi_mode > 1) {
699
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
700
+
701
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Attempting to config"
702
+ " several modes simultaneously. One mode will be selected"
703
+ " according to their priority: LBACK > SLEEP > SNOOP.\n",
704
+ path);
705
+ }
706
+
707
+ if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN) == 0) {
708
+ /* We are in configuration mode, any mode can be selected. */
709
+ s->regs[R_MODE_SELECT_REGISTER] = val;
710
+ } else {
711
+ bool sleep_mode_bit = FIELD_EX32(val, MODE_SELECT_REGISTER, SLEEP);
712
+
713
+ ARRAY_FIELD_DP32(s->regs, MODE_SELECT_REGISTER, SLEEP, sleep_mode_bit);
714
+
715
+ if (FIELD_EX32(val, MODE_SELECT_REGISTER, LBACK)) {
716
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
717
+
718
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Attempting to set"
719
+ " LBACK mode without setting CEN bit as 0.\n",
720
+ path);
721
+ } else if (FIELD_EX32(val, MODE_SELECT_REGISTER, SNOOP)) {
722
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
723
+
724
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Attempting to set"
725
+ " SNOOP mode without setting CEN bit as 0.\n",
726
+ path);
727
+ }
728
+
729
+ update_status_register_mode_bits(s);
730
+ }
731
+
732
+ return s->regs[R_MODE_SELECT_REGISTER];
733
+}
734
+
735
+static uint64_t can_brpr_pre_write(RegisterInfo *reg, uint64_t val)
736
+{
737
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
738
+
739
+ /* Only allow writes when in config mode. */
740
+ if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN)) {
741
+ return s->regs[R_ARBITRATION_PHASE_BAUD_RATE_PRESCALER_REGISTER];
742
+ }
743
+
744
+ return val;
745
+}
746
+
747
+static uint64_t can_btr_pre_write(RegisterInfo *reg, uint64_t val)
748
+{
749
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
750
+
751
+ /* Only allow writes when in config mode. */
752
+ if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN)) {
753
+ return s->regs[R_ARBITRATION_PHASE_BIT_TIMING_REGISTER];
754
+ }
755
+
756
+ return val;
757
+}
758
+
759
+static uint64_t can_tcr_pre_write(RegisterInfo *reg, uint64_t val)
760
+{
761
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
762
+
763
+ if (FIELD_EX32(val, TIMESTAMP_REGISTER, CTS)) {
764
+ ptimer_transaction_begin(s->can_timer);
765
+ ptimer_set_count(s->can_timer, 0);
766
+ ptimer_transaction_commit(s->can_timer);
767
+ }
768
+
769
+ return 0;
770
+}
771
+
772
+static void update_rx_fifo(XlnxZynqMPCANState *s, const qemu_can_frame *frame)
773
+{
774
+ bool filter_pass = false;
775
+ uint16_t timestamp = 0;
776
+
777
+ /* If no filter is enabled. Message will be stored in FIFO. */
778
+ if (!((ARRAY_FIELD_EX32(s->regs, AFR, UAF1)) |
779
+ (ARRAY_FIELD_EX32(s->regs, AFR, UAF2)) |
780
+ (ARRAY_FIELD_EX32(s->regs, AFR, UAF3)) |
781
+ (ARRAY_FIELD_EX32(s->regs, AFR, UAF4)))) {
782
+ filter_pass = true;
783
+ }
784
+
785
+ /*
786
+ * Messages that pass any of the acceptance filters will be stored in
787
+ * the RX FIFO.
788
+ */
789
+ if (ARRAY_FIELD_EX32(s->regs, AFR, UAF1)) {
790
+ uint32_t id_masked = s->regs[R_AFMR1] & frame->can_id;
791
+ uint32_t filter_id_masked = s->regs[R_AFMR1] & s->regs[R_AFIR1];
792
+
793
+ if (filter_id_masked == id_masked) {
794
+ filter_pass = true;
795
+ }
796
+ }
797
+
798
+ if (ARRAY_FIELD_EX32(s->regs, AFR, UAF2)) {
799
+ uint32_t id_masked = s->regs[R_AFMR2] & frame->can_id;
800
+ uint32_t filter_id_masked = s->regs[R_AFMR2] & s->regs[R_AFIR2];
801
+
802
+ if (filter_id_masked == id_masked) {
803
+ filter_pass = true;
804
+ }
805
+ }
806
+
807
+ if (ARRAY_FIELD_EX32(s->regs, AFR, UAF3)) {
808
+ uint32_t id_masked = s->regs[R_AFMR3] & frame->can_id;
809
+ uint32_t filter_id_masked = s->regs[R_AFMR3] & s->regs[R_AFIR3];
810
+
811
+ if (filter_id_masked == id_masked) {
812
+ filter_pass = true;
813
+ }
814
+ }
815
+
816
+ if (ARRAY_FIELD_EX32(s->regs, AFR, UAF4)) {
817
+ uint32_t id_masked = s->regs[R_AFMR4] & frame->can_id;
818
+ uint32_t filter_id_masked = s->regs[R_AFMR4] & s->regs[R_AFIR4];
819
+
820
+ if (filter_id_masked == id_masked) {
821
+ filter_pass = true;
822
+ }
823
+ }
824
+
825
+ if (!filter_pass) {
826
+ trace_xlnx_can_rx_fifo_filter_reject(frame->can_id, frame->can_dlc);
827
+ return;
828
+ }
829
+
830
+ /* Store the message in fifo if it passed through any of the filters. */
831
+ if (filter_pass && frame->can_dlc <= MAX_DLC) {
832
+
833
+ if (fifo32_is_full(&s->rx_fifo)) {
834
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXOFLW, 1);
835
+ } else {
836
+ timestamp = CAN_TIMER_MAX - ptimer_get_count(s->can_timer);
837
+
838
+ fifo32_push(&s->rx_fifo, frame->can_id);
839
+
840
+ fifo32_push(&s->rx_fifo, deposit32(0, R_RXFIFO_DLC_DLC_SHIFT,
841
+ R_RXFIFO_DLC_DLC_LENGTH,
842
+ frame->can_dlc) |
843
+ deposit32(0, R_RXFIFO_DLC_RXT_SHIFT,
844
+ R_RXFIFO_DLC_RXT_LENGTH,
845
+ timestamp));
846
+
847
+ /* First 32 bit of the data. */
848
+ fifo32_push(&s->rx_fifo, deposit32(0, R_TXFIFO_DATA1_DB3_SHIFT,
849
+ R_TXFIFO_DATA1_DB3_LENGTH,
850
+ frame->data[0]) |
851
+ deposit32(0, R_TXFIFO_DATA1_DB2_SHIFT,
852
+ R_TXFIFO_DATA1_DB2_LENGTH,
853
+ frame->data[1]) |
854
+ deposit32(0, R_TXFIFO_DATA1_DB1_SHIFT,
855
+ R_TXFIFO_DATA1_DB1_LENGTH,
856
+ frame->data[2]) |
857
+ deposit32(0, R_TXFIFO_DATA1_DB0_SHIFT,
858
+ R_TXFIFO_DATA1_DB0_LENGTH,
859
+ frame->data[3]));
860
+ /* Last 32 bit of the data. */
861
+ fifo32_push(&s->rx_fifo, deposit32(0, R_TXFIFO_DATA2_DB7_SHIFT,
862
+ R_TXFIFO_DATA2_DB7_LENGTH,
863
+ frame->data[4]) |
864
+ deposit32(0, R_TXFIFO_DATA2_DB6_SHIFT,
865
+ R_TXFIFO_DATA2_DB6_LENGTH,
866
+ frame->data[5]) |
867
+ deposit32(0, R_TXFIFO_DATA2_DB5_SHIFT,
868
+ R_TXFIFO_DATA2_DB5_LENGTH,
869
+ frame->data[6]) |
870
+ deposit32(0, R_TXFIFO_DATA2_DB4_SHIFT,
871
+ R_TXFIFO_DATA2_DB4_LENGTH,
872
+ frame->data[7]));
873
+
874
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXOK, 1);
875
+ trace_xlnx_can_rx_data(frame->can_id, frame->can_dlc,
876
+ frame->data[0], frame->data[1],
877
+ frame->data[2], frame->data[3],
878
+ frame->data[4], frame->data[5],
879
+ frame->data[6], frame->data[7]);
880
+ }
881
+
882
+ can_update_irq(s);
883
+ }
82
+ }
884
+}
83
+}
885
+
84
+
886
+static uint64_t can_rxfifo_pre_read(RegisterInfo *reg, uint64_t val)
85
void arm_debug_excp_handler(CPUState *cs)
887
+{
86
{
888
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
87
/*
889
+
890
+ if (!fifo32_is_empty(&s->rx_fifo)) {
891
+ val = fifo32_pop(&s->rx_fifo);
892
+ } else {
893
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXUFLW, 1);
894
+ }
895
+
896
+ can_update_irq(s);
897
+ return val;
898
+}
899
+
900
+static void can_filter_enable_post_write(RegisterInfo *reg, uint64_t val)
901
+{
902
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
903
+
904
+ if (ARRAY_FIELD_EX32(s->regs, AFR, UAF1) &&
905
+ ARRAY_FIELD_EX32(s->regs, AFR, UAF2) &&
906
+ ARRAY_FIELD_EX32(s->regs, AFR, UAF3) &&
907
+ ARRAY_FIELD_EX32(s->regs, AFR, UAF4)) {
908
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, ACFBSY, 1);
909
+ } else {
910
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, ACFBSY, 0);
911
+ }
912
+}
913
+
914
+static uint64_t can_filter_mask_pre_write(RegisterInfo *reg, uint64_t val)
915
+{
916
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
917
+ uint32_t reg_idx = (reg->access->addr) / 4;
918
+ uint32_t filter_number = (reg_idx - R_AFMR1) / 2;
919
+
920
+ /* modify an acceptance filter, the corresponding UAF bit should be '0'. */
921
+ if (!(s->regs[R_AFR] & (1 << filter_number))) {
922
+ s->regs[reg_idx] = val;
923
+
924
+ trace_xlnx_can_filter_mask_pre_write(filter_number, s->regs[reg_idx]);
925
+ } else {
926
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
927
+
928
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Acceptance filter %d"
929
+ " mask is not set as corresponding UAF bit is not 0.\n",
930
+ path, filter_number + 1);
931
+ }
932
+
933
+ return s->regs[reg_idx];
934
+}
935
+
936
+static uint64_t can_filter_id_pre_write(RegisterInfo *reg, uint64_t val)
937
+{
938
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
939
+ uint32_t reg_idx = (reg->access->addr) / 4;
940
+ uint32_t filter_number = (reg_idx - R_AFIR1) / 2;
941
+
942
+ if (!(s->regs[R_AFR] & (1 << filter_number))) {
943
+ s->regs[reg_idx] = val;
944
+
945
+ trace_xlnx_can_filter_id_pre_write(filter_number, s->regs[reg_idx]);
946
+ } else {
947
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
948
+
949
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Acceptance filter %d"
950
+ " id is not set as corresponding UAF bit is not 0.\n",
951
+ path, filter_number + 1);
952
+ }
953
+
954
+ return s->regs[reg_idx];
955
+}
956
+
957
+static void can_tx_post_write(RegisterInfo *reg, uint64_t val)
958
+{
959
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
960
+
961
+ bool is_txhpb = reg->access->addr > A_TXFIFO_DATA2;
962
+
963
+ bool initiate_transfer = (reg->access->addr == A_TXFIFO_DATA2) ||
964
+ (reg->access->addr == A_TXHPB_DATA2);
965
+
966
+ Fifo32 *f = is_txhpb ? &s->txhpb_fifo : &s->tx_fifo;
967
+
968
+ if (!fifo32_is_full(f)) {
969
+ fifo32_push(f, val);
970
+ } else {
971
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
972
+
973
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: TX FIFO is full.\n", path);
974
+ }
975
+
976
+ /* Initiate the message send if TX register is written. */
977
+ if (initiate_transfer &&
978
+ ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN)) {
979
+ transfer_fifo(s, f);
980
+ }
981
+
982
+ can_update_irq(s);
983
+}
984
+
985
+static const RegisterAccessInfo can_regs_info[] = {
986
+ { .name = "SOFTWARE_RESET_REGISTER",
987
+ .addr = A_SOFTWARE_RESET_REGISTER,
988
+ .rsvd = 0xfffffffc,
989
+ .pre_write = can_srr_pre_write,
990
+ },{ .name = "MODE_SELECT_REGISTER",
991
+ .addr = A_MODE_SELECT_REGISTER,
992
+ .rsvd = 0xfffffff8,
993
+ .pre_write = can_msr_pre_write,
994
+ },{ .name = "ARBITRATION_PHASE_BAUD_RATE_PRESCALER_REGISTER",
995
+ .addr = A_ARBITRATION_PHASE_BAUD_RATE_PRESCALER_REGISTER,
996
+ .rsvd = 0xffffff00,
997
+ .pre_write = can_brpr_pre_write,
998
+ },{ .name = "ARBITRATION_PHASE_BIT_TIMING_REGISTER",
999
+ .addr = A_ARBITRATION_PHASE_BIT_TIMING_REGISTER,
1000
+ .rsvd = 0xfffffe00,
1001
+ .pre_write = can_btr_pre_write,
1002
+ },{ .name = "ERROR_COUNTER_REGISTER",
1003
+ .addr = A_ERROR_COUNTER_REGISTER,
1004
+ .rsvd = 0xffff0000,
1005
+ .ro = 0xffffffff,
1006
+ },{ .name = "ERROR_STATUS_REGISTER",
1007
+ .addr = A_ERROR_STATUS_REGISTER,
1008
+ .rsvd = 0xffffffe0,
1009
+ .w1c = 0x1f,
1010
+ },{ .name = "STATUS_REGISTER", .addr = A_STATUS_REGISTER,
1011
+ .reset = 0x1,
1012
+ .rsvd = 0xffffe000,
1013
+ .ro = 0x1fff,
1014
+ },{ .name = "INTERRUPT_STATUS_REGISTER",
1015
+ .addr = A_INTERRUPT_STATUS_REGISTER,
1016
+ .reset = 0x6000,
1017
+ .rsvd = 0xffff8000,
1018
+ .ro = 0x7fff,
1019
+ },{ .name = "INTERRUPT_ENABLE_REGISTER",
1020
+ .addr = A_INTERRUPT_ENABLE_REGISTER,
1021
+ .rsvd = 0xffff8000,
1022
+ .post_write = can_ier_post_write,
1023
+ },{ .name = "INTERRUPT_CLEAR_REGISTER",
1024
+ .addr = A_INTERRUPT_CLEAR_REGISTER,
1025
+ .rsvd = 0xffff8000,
1026
+ .pre_write = can_icr_pre_write,
1027
+ },{ .name = "TIMESTAMP_REGISTER",
1028
+ .addr = A_TIMESTAMP_REGISTER,
1029
+ .rsvd = 0xfffffffe,
1030
+ .pre_write = can_tcr_pre_write,
1031
+ },{ .name = "WIR", .addr = A_WIR,
1032
+ .reset = 0x3f3f,
1033
+ .rsvd = 0xffff0000,
1034
+ },{ .name = "TXFIFO_ID", .addr = A_TXFIFO_ID,
1035
+ .post_write = can_tx_post_write,
1036
+ },{ .name = "TXFIFO_DLC", .addr = A_TXFIFO_DLC,
1037
+ .rsvd = 0xfffffff,
1038
+ .post_write = can_tx_post_write,
1039
+ },{ .name = "TXFIFO_DATA1", .addr = A_TXFIFO_DATA1,
1040
+ .post_write = can_tx_post_write,
1041
+ },{ .name = "TXFIFO_DATA2", .addr = A_TXFIFO_DATA2,
1042
+ .post_write = can_tx_post_write,
1043
+ },{ .name = "TXHPB_ID", .addr = A_TXHPB_ID,
1044
+ .post_write = can_tx_post_write,
1045
+ },{ .name = "TXHPB_DLC", .addr = A_TXHPB_DLC,
1046
+ .rsvd = 0xfffffff,
1047
+ .post_write = can_tx_post_write,
1048
+ },{ .name = "TXHPB_DATA1", .addr = A_TXHPB_DATA1,
1049
+ .post_write = can_tx_post_write,
1050
+ },{ .name = "TXHPB_DATA2", .addr = A_TXHPB_DATA2,
1051
+ .post_write = can_tx_post_write,
1052
+ },{ .name = "RXFIFO_ID", .addr = A_RXFIFO_ID,
1053
+ .ro = 0xffffffff,
1054
+ .post_read = can_rxfifo_pre_read,
1055
+ },{ .name = "RXFIFO_DLC", .addr = A_RXFIFO_DLC,
1056
+ .rsvd = 0xfff0000,
1057
+ .post_read = can_rxfifo_pre_read,
1058
+ },{ .name = "RXFIFO_DATA1", .addr = A_RXFIFO_DATA1,
1059
+ .post_read = can_rxfifo_pre_read,
1060
+ },{ .name = "RXFIFO_DATA2", .addr = A_RXFIFO_DATA2,
1061
+ .post_read = can_rxfifo_pre_read,
1062
+ },{ .name = "AFR", .addr = A_AFR,
1063
+ .rsvd = 0xfffffff0,
1064
+ .post_write = can_filter_enable_post_write,
1065
+ },{ .name = "AFMR1", .addr = A_AFMR1,
1066
+ .pre_write = can_filter_mask_pre_write,
1067
+ },{ .name = "AFIR1", .addr = A_AFIR1,
1068
+ .pre_write = can_filter_id_pre_write,
1069
+ },{ .name = "AFMR2", .addr = A_AFMR2,
1070
+ .pre_write = can_filter_mask_pre_write,
1071
+ },{ .name = "AFIR2", .addr = A_AFIR2,
1072
+ .pre_write = can_filter_id_pre_write,
1073
+ },{ .name = "AFMR3", .addr = A_AFMR3,
1074
+ .pre_write = can_filter_mask_pre_write,
1075
+ },{ .name = "AFIR3", .addr = A_AFIR3,
1076
+ .pre_write = can_filter_id_pre_write,
1077
+ },{ .name = "AFMR4", .addr = A_AFMR4,
1078
+ .pre_write = can_filter_mask_pre_write,
1079
+ },{ .name = "AFIR4", .addr = A_AFIR4,
1080
+ .pre_write = can_filter_id_pre_write,
1081
+ }
1082
+};
1083
+
1084
+static void xlnx_zynqmp_can_ptimer_cb(void *opaque)
1085
+{
1086
+ /* No action required on the timer rollover. */
1087
+}
1088
+
1089
+static const MemoryRegionOps can_ops = {
1090
+ .read = register_read_memory,
1091
+ .write = register_write_memory,
1092
+ .endianness = DEVICE_LITTLE_ENDIAN,
1093
+ .valid = {
1094
+ .min_access_size = 4,
1095
+ .max_access_size = 4,
1096
+ },
1097
+};
1098
+
1099
+static void xlnx_zynqmp_can_reset_init(Object *obj, ResetType type)
1100
+{
1101
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(obj);
1102
+ unsigned int i;
1103
+
1104
+ for (i = R_RXFIFO_ID; i < ARRAY_SIZE(s->reg_info); ++i) {
1105
+ register_reset(&s->reg_info[i]);
1106
+ }
1107
+
1108
+ ptimer_transaction_begin(s->can_timer);
1109
+ ptimer_set_count(s->can_timer, 0);
1110
+ ptimer_transaction_commit(s->can_timer);
1111
+}
1112
+
1113
+static void xlnx_zynqmp_can_reset_hold(Object *obj)
1114
+{
1115
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(obj);
1116
+ unsigned int i;
1117
+
1118
+ for (i = 0; i < R_RXFIFO_ID; ++i) {
1119
+ register_reset(&s->reg_info[i]);
1120
+ }
1121
+
1122
+ /*
1123
+ * Reset FIFOs when CAN model is reset. This will clear the fifo writes
1124
+ * done by post_write which gets called from register_reset function,
1125
+ * post_write handle will not be able to trigger tx because CAN will be
1126
+ * disabled when software_reset_register is cleared first.
1127
+ */
1128
+ fifo32_reset(&s->rx_fifo);
1129
+ fifo32_reset(&s->tx_fifo);
1130
+ fifo32_reset(&s->txhpb_fifo);
1131
+}
1132
+
1133
+static bool xlnx_zynqmp_can_can_receive(CanBusClientState *client)
1134
+{
1135
+ XlnxZynqMPCANState *s = container_of(client, XlnxZynqMPCANState,
1136
+ bus_client);
1137
+
1138
+ if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, SRST)) {
1139
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
1140
+
1141
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Controller is in reset state.\n",
1142
+ path);
1143
+ return false;
1144
+ }
1145
+
1146
+ if ((ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN)) == 0) {
1147
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
1148
+
1149
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Controller is disabled. Incoming"
1150
+ " messages will be discarded.\n", path);
1151
+ return false;
1152
+ }
1153
+
1154
+ return true;
1155
+}
1156
+
1157
+static ssize_t xlnx_zynqmp_can_receive(CanBusClientState *client,
1158
+ const qemu_can_frame *buf, size_t buf_size) {
1159
+ XlnxZynqMPCANState *s = container_of(client, XlnxZynqMPCANState,
1160
+ bus_client);
1161
+ const qemu_can_frame *frame = buf;
1162
+
1163
+ if (buf_size <= 0) {
1164
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
1165
+
1166
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Error in the data received.\n",
1167
+ path);
1168
+ return 0;
1169
+ }
1170
+
1171
+ if (ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, SNOOP)) {
1172
+ /* Snoop Mode: Just keep the data. no response back. */
1173
+ update_rx_fifo(s, frame);
1174
+ } else if ((ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, SLEEP))) {
1175
+ /*
1176
+ * XlnxZynqMPCAN is in sleep mode. Any data on bus will bring it to wake
1177
+ * up state.
1178
+ */
1179
+ can_exit_sleep_mode(s);
1180
+ update_rx_fifo(s, frame);
1181
+ } else if ((ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, SLEEP)) == 0) {
1182
+ update_rx_fifo(s, frame);
1183
+ } else {
1184
+ /*
1185
+ * XlnxZynqMPCAN will not participate in normal bus communication
1186
+ * and will not receive any messages transmitted by other CAN nodes.
1187
+ */
1188
+ trace_xlnx_can_rx_discard(s->regs[R_STATUS_REGISTER]);
1189
+ }
1190
+
1191
+ return 1;
1192
+}
1193
+
1194
+static CanBusClientInfo can_xilinx_bus_client_info = {
1195
+ .can_receive = xlnx_zynqmp_can_can_receive,
1196
+ .receive = xlnx_zynqmp_can_receive,
1197
+};
1198
+
1199
+static int xlnx_zynqmp_can_connect_to_bus(XlnxZynqMPCANState *s,
1200
+ CanBusState *bus)
1201
+{
1202
+ s->bus_client.info = &can_xilinx_bus_client_info;
1203
+
1204
+ if (can_bus_insert_client(bus, &s->bus_client) < 0) {
1205
+ return -1;
1206
+ }
1207
+ return 0;
1208
+}
1209
+
1210
+static void xlnx_zynqmp_can_realize(DeviceState *dev, Error **errp)
1211
+{
1212
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(dev);
1213
+
1214
+ if (s->canbus) {
1215
+ if (xlnx_zynqmp_can_connect_to_bus(s, s->canbus) < 0) {
1216
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
1217
+
1218
+ error_setg(errp, "%s: xlnx_zynqmp_can_connect_to_bus"
1219
+ " failed.", path);
1220
+ return;
1221
+ }
1222
+ }
1223
+
1224
+ /* Create RX FIFO, TXFIFO, TXHPB storage. */
1225
+ fifo32_create(&s->rx_fifo, RXFIFO_SIZE);
1226
+ fifo32_create(&s->tx_fifo, RXFIFO_SIZE);
1227
+ fifo32_create(&s->txhpb_fifo, CAN_FRAME_SIZE);
1228
+
1229
+ /* Allocate a new timer. */
1230
+ s->can_timer = ptimer_init(xlnx_zynqmp_can_ptimer_cb, s,
1231
+ PTIMER_POLICY_DEFAULT);
1232
+
1233
+ ptimer_transaction_begin(s->can_timer);
1234
+
1235
+ ptimer_set_freq(s->can_timer, s->cfg.ext_clk_freq);
1236
+ ptimer_set_limit(s->can_timer, CAN_TIMER_MAX, 1);
1237
+ ptimer_run(s->can_timer, 0);
1238
+ ptimer_transaction_commit(s->can_timer);
1239
+}
1240
+
1241
+static void xlnx_zynqmp_can_init(Object *obj)
1242
+{
1243
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(obj);
1244
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
1245
+
1246
+ RegisterInfoArray *reg_array;
1247
+
1248
+ memory_region_init(&s->iomem, obj, TYPE_XLNX_ZYNQMP_CAN,
1249
+ XLNX_ZYNQMP_CAN_R_MAX * 4);
1250
+ reg_array = register_init_block32(DEVICE(obj), can_regs_info,
1251
+ ARRAY_SIZE(can_regs_info),
1252
+ s->reg_info, s->regs,
1253
+ &can_ops,
1254
+ XLNX_ZYNQMP_CAN_ERR_DEBUG,
1255
+ XLNX_ZYNQMP_CAN_R_MAX * 4);
1256
+
1257
+ memory_region_add_subregion(&s->iomem, 0x00, &reg_array->mem);
1258
+ sysbus_init_mmio(sbd, &s->iomem);
1259
+ sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->irq);
1260
+}
1261
+
1262
+static const VMStateDescription vmstate_can = {
1263
+ .name = TYPE_XLNX_ZYNQMP_CAN,
1264
+ .version_id = 1,
1265
+ .minimum_version_id = 1,
1266
+ .fields = (VMStateField[]) {
1267
+ VMSTATE_FIFO32(rx_fifo, XlnxZynqMPCANState),
1268
+ VMSTATE_FIFO32(tx_fifo, XlnxZynqMPCANState),
1269
+ VMSTATE_FIFO32(txhpb_fifo, XlnxZynqMPCANState),
1270
+ VMSTATE_UINT32_ARRAY(regs, XlnxZynqMPCANState, XLNX_ZYNQMP_CAN_R_MAX),
1271
+ VMSTATE_PTIMER(can_timer, XlnxZynqMPCANState),
1272
+ VMSTATE_END_OF_LIST(),
1273
+ }
1274
+};
1275
+
1276
+static Property xlnx_zynqmp_can_properties[] = {
1277
+ DEFINE_PROP_UINT32("ext_clk_freq", XlnxZynqMPCANState, cfg.ext_clk_freq,
1278
+ CAN_DEFAULT_CLOCK),
1279
+ DEFINE_PROP_LINK("canbus", XlnxZynqMPCANState, canbus, TYPE_CAN_BUS,
1280
+ CanBusState *),
1281
+ DEFINE_PROP_END_OF_LIST(),
1282
+};
1283
+
1284
+static void xlnx_zynqmp_can_class_init(ObjectClass *klass, void *data)
1285
+{
1286
+ DeviceClass *dc = DEVICE_CLASS(klass);
1287
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
1288
+
1289
+ rc->phases.enter = xlnx_zynqmp_can_reset_init;
1290
+ rc->phases.hold = xlnx_zynqmp_can_reset_hold;
1291
+ dc->realize = xlnx_zynqmp_can_realize;
1292
+ device_class_set_props(dc, xlnx_zynqmp_can_properties);
1293
+ dc->vmsd = &vmstate_can;
1294
+}
1295
+
1296
+static const TypeInfo can_info = {
1297
+ .name = TYPE_XLNX_ZYNQMP_CAN,
1298
+ .parent = TYPE_SYS_BUS_DEVICE,
1299
+ .instance_size = sizeof(XlnxZynqMPCANState),
1300
+ .class_init = xlnx_zynqmp_can_class_init,
1301
+ .instance_init = xlnx_zynqmp_can_init,
1302
+};
1303
+
1304
+static void can_register_types(void)
1305
+{
1306
+ type_register_static(&can_info);
1307
+}
1308
+
1309
+type_init(can_register_types)
1310
diff --git a/hw/Kconfig b/hw/Kconfig
1311
index XXXXXXX..XXXXXXX 100644
1312
--- a/hw/Kconfig
1313
+++ b/hw/Kconfig
1314
@@ -XXX,XX +XXX,XX @@ config XILINX_AXI
1315
config XLNX_ZYNQMP
1316
bool
1317
select REGISTER
1318
+ select CAN_BUS
1319
diff --git a/hw/net/can/meson.build b/hw/net/can/meson.build
1320
index XXXXXXX..XXXXXXX 100644
1321
--- a/hw/net/can/meson.build
1322
+++ b/hw/net/can/meson.build
1323
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_CAN_PCI', if_true: files('can_pcm3680_pci.c'))
1324
softmmu_ss.add(when: 'CONFIG_CAN_PCI', if_true: files('can_mioe3680_pci.c'))
1325
softmmu_ss.add(when: 'CONFIG_CAN_CTUCANFD', if_true: files('ctucan_core.c'))
1326
softmmu_ss.add(when: 'CONFIG_CAN_CTUCANFD_PCI', if_true: files('ctucan_pci.c'))
1327
+softmmu_ss.add(when: 'CONFIG_XLNX_ZYNQMP', if_true: files('xlnx-zynqmp-can.c'))
1328
diff --git a/hw/net/can/trace-events b/hw/net/can/trace-events
1329
new file mode 100644
1330
index XXXXXXX..XXXXXXX
1331
--- /dev/null
1332
+++ b/hw/net/can/trace-events
1333
@@ -XXX,XX +XXX,XX @@
1334
+# xlnx-zynqmp-can.c
1335
+xlnx_can_update_irq(uint32_t isr, uint32_t ier, uint32_t irq) "ISR: 0x%08x IER: 0x%08x IRQ: 0x%08x"
1336
+xlnx_can_reset(uint32_t val) "Resetting controller with value = 0x%08x"
1337
+xlnx_can_rx_fifo_filter_reject(uint32_t id, uint8_t dlc) "Frame: ID: 0x%08x DLC: 0x%02x"
1338
+xlnx_can_filter_id_pre_write(uint8_t filter_num, uint32_t value) "Filter%d ID: 0x%08x"
1339
+xlnx_can_filter_mask_pre_write(uint8_t filter_num, uint32_t value) "Filter%d MASK: 0x%08x"
1340
+xlnx_can_tx_data(uint32_t id, uint8_t dlc, uint8_t db0, uint8_t db1, uint8_t db2, uint8_t db3, uint8_t db4, uint8_t db5, uint8_t db6, uint8_t db7) "Frame: ID: 0x%08x DLC: 0x%02x DATA: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x"
1341
+xlnx_can_rx_data(uint32_t id, uint32_t dlc, uint8_t db0, uint8_t db1, uint8_t db2, uint8_t db3, uint8_t db4, uint8_t db5, uint8_t db6, uint8_t db7) "Frame: ID: 0x%08x DLC: 0x%02x DATA: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x"
1342
+xlnx_can_rx_discard(uint32_t status) "Controller is not enabled for bus communication. Status Register: 0x%08x"
1343
--
88
--
1344
2.20.1
89
2.25.1
1345
1346
diff view generated by jsdifflib
1
From: Vikram Garhwal <fnu.vikram@xilinx.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Connect CAN0 and CAN1 on the ZynqMP.
3
Rename to helper_exception_with_syndrome_el, to emphasize
4
that the target el is a parameter.
4
5
5
Reviewed-by: Francisco Iglesias <francisco.iglesias@xilinx.com>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Vikram Garhwal <fnu.vikram@xilinx.com>
8
Message-id: 20220609202901.1177572-10-richard.henderson@linaro.org
8
Message-id: 1605728926-352690-3-git-send-email-fnu.vikram@xilinx.com
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
10
---
11
include/hw/arm/xlnx-zynqmp.h | 8 ++++++++
11
target/arm/helper.h | 2 +-
12
hw/arm/xlnx-zcu102.c | 20 ++++++++++++++++++++
12
target/arm/translate.h | 6 +++---
13
hw/arm/xlnx-zynqmp.c | 34 ++++++++++++++++++++++++++++++++++
13
target/arm/op_helper.c | 6 +++---
14
3 files changed, 62 insertions(+)
14
target/arm/translate.c | 6 +++---
15
4 files changed, 10 insertions(+), 10 deletions(-)
15
16
16
diff --git a/include/hw/arm/xlnx-zynqmp.h b/include/hw/arm/xlnx-zynqmp.h
17
diff --git a/target/arm/helper.h b/target/arm/helper.h
17
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
18
--- a/include/hw/arm/xlnx-zynqmp.h
19
--- a/target/arm/helper.h
19
+++ b/include/hw/arm/xlnx-zynqmp.h
20
+++ b/target/arm/helper.h
20
@@ -XXX,XX +XXX,XX @@
21
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_2(usad8, TCG_CALL_NO_RWG_SE, i32, i32, i32)
21
#include "hw/intc/arm_gic.h"
22
DEF_HELPER_FLAGS_3(sel_flags, TCG_CALL_NO_RWG_SE,
22
#include "hw/net/cadence_gem.h"
23
i32, i32, i32, i32)
23
#include "hw/char/cadence_uart.h"
24
DEF_HELPER_2(exception_internal, noreturn, env, i32)
24
+#include "hw/net/xlnx-zynqmp-can.h"
25
-DEF_HELPER_4(exception_with_syndrome, noreturn, env, i32, i32, i32)
25
#include "hw/ide/ahci.h"
26
+DEF_HELPER_4(exception_with_syndrome_el, noreturn, env, i32, i32, i32)
26
#include "hw/sd/sdhci.h"
27
DEF_HELPER_2(exception_bkpt_insn, noreturn, env, i32)
27
#include "hw/ssi/xilinx_spips.h"
28
DEF_HELPER_2(exception_pc_alignment, noreturn, env, tl)
28
@@ -XXX,XX +XXX,XX @@
29
DEF_HELPER_1(setend, void, env)
29
#include "hw/cpu/cluster.h"
30
diff --git a/target/arm/translate.h b/target/arm/translate.h
30
#include "target/arm/cpu.h"
31
#include "qom/object.h"
32
+#include "net/can_emu.h"
33
34
#define TYPE_XLNX_ZYNQMP "xlnx,zynqmp"
35
OBJECT_DECLARE_SIMPLE_TYPE(XlnxZynqMPState, XLNX_ZYNQMP)
36
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_SIMPLE_TYPE(XlnxZynqMPState, XLNX_ZYNQMP)
37
#define XLNX_ZYNQMP_NUM_RPU_CPUS 2
38
#define XLNX_ZYNQMP_NUM_GEMS 4
39
#define XLNX_ZYNQMP_NUM_UARTS 2
40
+#define XLNX_ZYNQMP_NUM_CAN 2
41
+#define XLNX_ZYNQMP_CAN_REF_CLK (24 * 1000 * 1000)
42
#define XLNX_ZYNQMP_NUM_SDHCI 2
43
#define XLNX_ZYNQMP_NUM_SPIS 2
44
#define XLNX_ZYNQMP_NUM_GDMA_CH 8
45
@@ -XXX,XX +XXX,XX @@ struct XlnxZynqMPState {
46
47
CadenceGEMState gem[XLNX_ZYNQMP_NUM_GEMS];
48
CadenceUARTState uart[XLNX_ZYNQMP_NUM_UARTS];
49
+ XlnxZynqMPCANState can[XLNX_ZYNQMP_NUM_CAN];
50
SysbusAHCIState sata;
51
SDHCIState sdhci[XLNX_ZYNQMP_NUM_SDHCI];
52
XilinxSPIPS spi[XLNX_ZYNQMP_NUM_SPIS];
53
@@ -XXX,XX +XXX,XX @@ struct XlnxZynqMPState {
54
bool virt;
55
/* Has the RPU subsystem? */
56
bool has_rpu;
57
+
58
+ /* CAN bus. */
59
+ CanBusState *canbus[XLNX_ZYNQMP_NUM_CAN];
60
};
61
62
#endif
63
diff --git a/hw/arm/xlnx-zcu102.c b/hw/arm/xlnx-zcu102.c
64
index XXXXXXX..XXXXXXX 100644
31
index XXXXXXX..XXXXXXX 100644
65
--- a/hw/arm/xlnx-zcu102.c
32
--- a/target/arm/translate.h
66
+++ b/hw/arm/xlnx-zcu102.c
33
+++ b/target/arm/translate.h
67
@@ -XXX,XX +XXX,XX @@
34
@@ -XXX,XX +XXX,XX @@ static inline void gen_ss_advance(DisasContext *s)
68
#include "sysemu/qtest.h"
35
static inline void gen_exception(int excp, uint32_t syndrome,
69
#include "sysemu/device_tree.h"
36
uint32_t target_el)
70
#include "qom/object.h"
37
{
71
+#include "net/can_emu.h"
38
- gen_helper_exception_with_syndrome(cpu_env, tcg_constant_i32(excp),
72
39
- tcg_constant_i32(syndrome),
73
struct XlnxZCU102 {
40
- tcg_constant_i32(target_el));
74
MachineState parent_obj;
41
+ gen_helper_exception_with_syndrome_el(cpu_env, tcg_constant_i32(excp),
75
@@ -XXX,XX +XXX,XX @@ struct XlnxZCU102 {
42
+ tcg_constant_i32(syndrome),
76
bool secure;
43
+ tcg_constant_i32(target_el));
77
bool virt;
78
79
+ CanBusState *canbus[XLNX_ZYNQMP_NUM_CAN];
80
+
81
struct arm_boot_info binfo;
82
};
83
84
@@ -XXX,XX +XXX,XX @@ static void xlnx_zcu102_init(MachineState *machine)
85
object_property_set_bool(OBJECT(&s->soc), "virtualization", s->virt,
86
&error_fatal);
87
88
+ for (i = 0; i < XLNX_ZYNQMP_NUM_CAN; i++) {
89
+ gchar *bus_name = g_strdup_printf("canbus%d", i);
90
+
91
+ object_property_set_link(OBJECT(&s->soc), bus_name,
92
+ OBJECT(s->canbus[i]), &error_fatal);
93
+ g_free(bus_name);
94
+ }
95
+
96
qdev_realize(DEVICE(&s->soc), NULL, &error_fatal);
97
98
/* Create and plug in the SD cards */
99
@@ -XXX,XX +XXX,XX @@ static void xlnx_zcu102_machine_instance_init(Object *obj)
100
s->secure = false;
101
/* Default to virt (EL2) being disabled */
102
s->virt = false;
103
+ object_property_add_link(obj, "xlnx-zcu102.canbus0", TYPE_CAN_BUS,
104
+ (Object **)&s->canbus[0],
105
+ object_property_allow_set_link,
106
+ 0);
107
+
108
+ object_property_add_link(obj, "xlnx-zcu102.canbus1", TYPE_CAN_BUS,
109
+ (Object **)&s->canbus[1],
110
+ object_property_allow_set_link,
111
+ 0);
112
}
44
}
113
45
114
static void xlnx_zcu102_machine_class_init(ObjectClass *oc, void *data)
46
/* Generate an architectural singlestep exception */
115
diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c
47
diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c
116
index XXXXXXX..XXXXXXX 100644
48
index XXXXXXX..XXXXXXX 100644
117
--- a/hw/arm/xlnx-zynqmp.c
49
--- a/target/arm/op_helper.c
118
+++ b/hw/arm/xlnx-zynqmp.c
50
+++ b/target/arm/op_helper.c
119
@@ -XXX,XX +XXX,XX @@ static const int uart_intr[XLNX_ZYNQMP_NUM_UARTS] = {
51
@@ -XXX,XX +XXX,XX @@ void HELPER(yield)(CPUARMState *env)
120
21, 22,
52
* those EXCP values which are special cases for QEMU to interrupt
121
};
53
* execution and not to be used for exceptions which are passed to
122
54
* the guest (those must all have syndrome information and thus should
123
+static const uint64_t can_addr[XLNX_ZYNQMP_NUM_CAN] = {
55
- * use exception_with_syndrome).
124
+ 0xFF060000, 0xFF070000,
56
+ * use exception_with_syndrome*).
125
+};
57
*/
126
+
58
void HELPER(exception_internal)(CPUARMState *env, uint32_t excp)
127
+static const int can_intr[XLNX_ZYNQMP_NUM_CAN] = {
59
{
128
+ 23, 24,
60
@@ -XXX,XX +XXX,XX @@ void HELPER(exception_internal)(CPUARMState *env, uint32_t excp)
129
+};
61
}
130
+
62
131
static const uint64_t sdhci_addr[XLNX_ZYNQMP_NUM_SDHCI] = {
63
/* Raise an exception with the specified syndrome register value */
132
0xFF160000, 0xFF170000,
64
-void HELPER(exception_with_syndrome)(CPUARMState *env, uint32_t excp,
133
};
65
- uint32_t syndrome, uint32_t target_el)
134
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_init(Object *obj)
66
+void HELPER(exception_with_syndrome_el)(CPUARMState *env, uint32_t excp,
135
TYPE_CADENCE_UART);
67
+ uint32_t syndrome, uint32_t target_el)
136
}
68
{
137
69
raise_exception(env, excp, syndrome, target_el);
138
+ for (i = 0; i < XLNX_ZYNQMP_NUM_CAN; i++) {
70
}
139
+ object_initialize_child(obj, "can[*]", &s->can[i],
71
diff --git a/target/arm/translate.c b/target/arm/translate.c
140
+ TYPE_XLNX_ZYNQMP_CAN);
72
index XXXXXXX..XXXXXXX 100644
141
+ }
73
--- a/target/arm/translate.c
142
+
74
+++ b/target/arm/translate.c
143
object_initialize_child(obj, "sata", &s->sata, TYPE_SYSBUS_AHCI);
75
@@ -XXX,XX +XXX,XX @@ static void gen_exception_el(DisasContext *s, int excp, uint32_t syn,
144
76
{
145
for (i = 0; i < XLNX_ZYNQMP_NUM_SDHCI; i++) {
77
gen_set_condexec(s);
146
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
78
gen_set_pc_im(s, s->pc_curr);
147
gic_spi[uart_intr[i]]);
79
- gen_helper_exception_with_syndrome(cpu_env,
148
}
80
- tcg_constant_i32(excp),
149
81
- tcg_constant_i32(syn), tcg_el);
150
+ for (i = 0; i < XLNX_ZYNQMP_NUM_CAN; i++) {
82
+ gen_helper_exception_with_syndrome_el(cpu_env,
151
+ object_property_set_int(OBJECT(&s->can[i]), "ext_clk_freq",
83
+ tcg_constant_i32(excp),
152
+ XLNX_ZYNQMP_CAN_REF_CLK, &error_abort);
84
+ tcg_constant_i32(syn), tcg_el);
153
+
85
s->base.is_jmp = DISAS_NORETURN;
154
+ object_property_set_link(OBJECT(&s->can[i]), "canbus",
86
}
155
+ OBJECT(s->canbus[i]), &error_fatal);
156
+
157
+ sysbus_realize(SYS_BUS_DEVICE(&s->can[i]), &err);
158
+ if (err) {
159
+ error_propagate(errp, err);
160
+ return;
161
+ }
162
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->can[i]), 0, can_addr[i]);
163
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->can[i]), 0,
164
+ gic_spi[can_intr[i]]);
165
+ }
166
+
167
object_property_set_int(OBJECT(&s->sata), "num-ports", SATA_NUM_PORTS,
168
&error_abort);
169
if (!sysbus_realize(SYS_BUS_DEVICE(&s->sata), errp)) {
170
@@ -XXX,XX +XXX,XX @@ static Property xlnx_zynqmp_props[] = {
171
DEFINE_PROP_BOOL("has_rpu", XlnxZynqMPState, has_rpu, false),
172
DEFINE_PROP_LINK("ddr-ram", XlnxZynqMPState, ddr_ram, TYPE_MEMORY_REGION,
173
MemoryRegion *),
174
+ DEFINE_PROP_LINK("canbus0", XlnxZynqMPState, canbus[0], TYPE_CAN_BUS,
175
+ CanBusState *),
176
+ DEFINE_PROP_LINK("canbus1", XlnxZynqMPState, canbus[1], TYPE_CAN_BUS,
177
+ CanBusState *),
178
DEFINE_PROP_END_OF_LIST()
179
};
180
87
181
--
88
--
182
2.20.1
89
2.25.1
183
184
diff view generated by jsdifflib
1
The constant-expander functions like negate, plus_2, etc, are
1
From: Richard Henderson <richard.henderson@linaro.org>
2
generally useful; move them up in translate.c so we can use them in
3
the VFP/Neon decoders as well as in the A32/T32/T16 decoders.
4
2
3
Create a function below gen_exception_insn that takes
4
the target_el as a TCGv_i32, replacing gen_exception_el.
5
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20220609202901.1177572-11-richard.henderson@linaro.org
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20201119215617.29887-9-peter.maydell@linaro.org
8
---
10
---
9
target/arm/translate.c | 46 +++++++++++++++++++++++-------------------
11
target/arm/translate.c | 27 ++++++++++++---------------
10
1 file changed, 25 insertions(+), 21 deletions(-)
12
1 file changed, 12 insertions(+), 15 deletions(-)
11
13
12
diff --git a/target/arm/translate.c b/target/arm/translate.c
14
diff --git a/target/arm/translate.c b/target/arm/translate.c
13
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/translate.c
16
--- a/target/arm/translate.c
15
+++ b/target/arm/translate.c
17
+++ b/target/arm/translate.c
16
@@ -XXX,XX +XXX,XX @@ static void arm_gen_condlabel(DisasContext *s)
18
@@ -XXX,XX +XXX,XX @@ static void gen_exception_internal_insn(DisasContext *s, uint32_t pc, int excp)
19
s->base.is_jmp = DISAS_NORETURN;
20
}
21
22
-void gen_exception_insn(DisasContext *s, uint64_t pc, int excp,
23
- uint32_t syn, uint32_t target_el)
24
+static void gen_exception_insn_el_v(DisasContext *s, uint64_t pc, int excp,
25
+ uint32_t syn, TCGv_i32 tcg_el)
26
{
27
if (s->aarch64) {
28
gen_a64_set_pc_im(pc);
29
@@ -XXX,XX +XXX,XX @@ void gen_exception_insn(DisasContext *s, uint64_t pc, int excp,
30
gen_set_condexec(s);
31
gen_set_pc_im(s, pc);
17
}
32
}
33
- gen_exception(excp, syn, target_el);
34
+ gen_helper_exception_with_syndrome_el(cpu_env, tcg_constant_i32(excp),
35
+ tcg_constant_i32(syn), tcg_el);
36
s->base.is_jmp = DISAS_NORETURN;
18
}
37
}
19
38
20
+/*
39
+void gen_exception_insn(DisasContext *s, uint64_t pc, int excp,
21
+ * Constant expanders for the decoders.
40
+ uint32_t syn, uint32_t target_el)
22
+ */
23
+
24
+static int negate(DisasContext *s, int x)
25
+{
41
+{
26
+ return -x;
42
+ gen_exception_insn_el_v(s, pc, excp, syn, tcg_constant_i32(target_el));
27
+}
43
+}
28
+
44
+
29
+static int plus_2(DisasContext *s, int x)
45
static void gen_exception_bkpt_insn(DisasContext *s, uint32_t syn)
30
+{
46
{
31
+ return x + 2;
47
gen_set_condexec(s);
32
+}
48
@@ -XXX,XX +XXX,XX @@ void unallocated_encoding(DisasContext *s)
33
+
49
default_exception_el(s));
34
+static int times_2(DisasContext *s, int x)
50
}
35
+{
51
36
+ return x * 2;
52
-static void gen_exception_el(DisasContext *s, int excp, uint32_t syn,
37
+}
53
- TCGv_i32 tcg_el)
38
+
39
+static int times_4(DisasContext *s, int x)
40
+{
41
+ return x * 4;
42
+}
43
+
44
/* Flags for the disas_set_da_iss info argument:
45
* lower bits hold the Rt register number, higher bits are flags.
46
*/
47
@@ -XXX,XX +XXX,XX @@ static void arm_skip_unless(DisasContext *s, uint32_t cond)
48
49
50
/*
51
- * Constant expanders for the decoders.
52
+ * Constant expanders used by T16/T32 decode
53
*/
54
55
-static int negate(DisasContext *s, int x)
56
-{
54
-{
57
- return -x;
55
- gen_set_condexec(s);
56
- gen_set_pc_im(s, s->pc_curr);
57
- gen_helper_exception_with_syndrome_el(cpu_env,
58
- tcg_constant_i32(excp),
59
- tcg_constant_i32(syn), tcg_el);
60
- s->base.is_jmp = DISAS_NORETURN;
58
-}
61
-}
59
-
62
-
60
-static int plus_2(DisasContext *s, int x)
63
/* Force a TB lookup after an instruction that changes the CPU state. */
61
-{
64
void gen_lookup_tb(DisasContext *s)
62
- return x + 2;
63
-}
64
-
65
-static int times_2(DisasContext *s, int x)
66
-{
67
- return x * 2;
68
-}
69
-
70
-static int times_4(DisasContext *s, int x)
71
-{
72
- return x * 4;
73
-}
74
-
75
/* Return only the rotation part of T32ExpandImm. */
76
static int t32_expandimm_rot(DisasContext *s, int x)
77
{
65
{
66
@@ -XXX,XX +XXX,XX @@ static bool msr_banked_access_decode(DisasContext *s, int r, int sysm, int rn,
67
tcg_el = tcg_constant_i32(3);
68
}
69
70
- gen_exception_el(s, EXCP_UDEF, syn_uncategorized(), tcg_el);
71
+ gen_exception_insn_el_v(s, s->pc_curr, EXCP_UDEF,
72
+ syn_uncategorized(), tcg_el);
73
tcg_temp_free_i32(tcg_el);
74
return false;
75
}
78
--
76
--
79
2.20.1
77
2.25.1
80
81
diff view generated by jsdifflib
1
From: Alex Chen <alex.chen@huawei.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
We should use printf format specifier "%u" instead of "%d" for
4
argument of type "unsigned int".
5
6
Reported-by: Euler Robot <euler.robot@huawei.com>
7
Signed-off-by: Alex Chen <alex.chen@huawei.com>
8
Message-id: 20201126111109.112238-3-alex.chen@huawei.com
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20220609202901.1177572-12-richard.henderson@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
7
---
12
hw/misc/imx31_ccm.c | 14 +++++++-------
8
target/arm/translate.h | 4 ++--
13
hw/misc/imx_ccm.c | 4 ++--
9
target/arm/translate-a64.c | 36 ++++++++++++++++----------------
14
2 files changed, 9 insertions(+), 9 deletions(-)
10
target/arm/translate-m-nocp.c | 16 +++++++-------
11
target/arm/translate-mve.c | 4 ++--
12
target/arm/translate-vfp.c | 6 +++---
13
target/arm/translate.c | 39 ++++++++++++++++++-----------------
14
6 files changed, 53 insertions(+), 52 deletions(-)
15
15
16
diff --git a/hw/misc/imx31_ccm.c b/hw/misc/imx31_ccm.c
16
diff --git a/target/arm/translate.h b/target/arm/translate.h
17
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/misc/imx31_ccm.c
18
--- a/target/arm/translate.h
19
+++ b/hw/misc/imx31_ccm.c
19
+++ b/target/arm/translate.h
20
@@ -XXX,XX +XXX,XX @@ static const char *imx31_ccm_reg_name(uint32_t reg)
20
@@ -XXX,XX +XXX,XX @@ void arm_jump_cc(DisasCompare *cmp, TCGLabel *label);
21
case IMX31_CCM_PDR2_REG:
21
void arm_gen_test_cc(int cc, TCGLabel *label);
22
return "PDR2";
22
MemOp pow2_align(unsigned i);
23
void unallocated_encoding(DisasContext *s);
24
-void gen_exception_insn(DisasContext *s, uint64_t pc, int excp,
25
- uint32_t syn, uint32_t target_el);
26
+void gen_exception_insn_el(DisasContext *s, uint64_t pc, int excp,
27
+ uint32_t syn, uint32_t target_el);
28
29
/* Return state of Alternate Half-precision flag, caller frees result */
30
static inline TCGv_i32 get_ahp_flag(void)
31
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
32
index XXXXXXX..XXXXXXX 100644
33
--- a/target/arm/translate-a64.c
34
+++ b/target/arm/translate-a64.c
35
@@ -XXX,XX +XXX,XX @@ static bool fp_access_check(DisasContext *s)
36
assert(!s->fp_access_checked);
37
s->fp_access_checked = true;
38
39
- gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
40
- syn_fp_access_trap(1, 0xe, false, 0),
41
- s->fp_excp_el);
42
+ gen_exception_insn_el(s, s->pc_curr, EXCP_UDEF,
43
+ syn_fp_access_trap(1, 0xe, false, 0),
44
+ s->fp_excp_el);
45
return false;
46
}
47
s->fp_access_checked = true;
48
@@ -XXX,XX +XXX,XX @@ bool sve_access_check(DisasContext *s)
49
assert(!s->sve_access_checked);
50
s->sve_access_checked = true;
51
52
- gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
53
- syn_sve_access_trap(), s->sve_excp_el);
54
+ gen_exception_insn_el(s, s->pc_curr, EXCP_UDEF,
55
+ syn_sve_access_trap(), s->sve_excp_el);
56
return false;
57
}
58
s->sve_access_checked = true;
59
@@ -XXX,XX +XXX,XX @@ static void gen_sysreg_undef(DisasContext *s, bool isread,
60
} else {
61
syndrome = syn_uncategorized();
62
}
63
- gen_exception_insn(s, s->pc_curr, EXCP_UDEF, syndrome,
64
- default_exception_el(s));
65
+ gen_exception_insn_el(s, s->pc_curr, EXCP_UDEF, syndrome,
66
+ default_exception_el(s));
67
}
68
69
/* MRS - move from system register
70
@@ -XXX,XX +XXX,XX @@ static void disas_exc(DisasContext *s, uint32_t insn)
71
switch (op2_ll) {
72
case 1: /* SVC */
73
gen_ss_advance(s);
74
- gen_exception_insn(s, s->base.pc_next, EXCP_SWI,
75
- syn_aa64_svc(imm16), default_exception_el(s));
76
+ gen_exception_insn_el(s, s->base.pc_next, EXCP_SWI,
77
+ syn_aa64_svc(imm16), default_exception_el(s));
78
break;
79
case 2: /* HVC */
80
if (s->current_el == 0) {
81
@@ -XXX,XX +XXX,XX @@ static void disas_exc(DisasContext *s, uint32_t insn)
82
gen_a64_set_pc_im(s->pc_curr);
83
gen_helper_pre_hvc(cpu_env);
84
gen_ss_advance(s);
85
- gen_exception_insn(s, s->base.pc_next, EXCP_HVC,
86
- syn_aa64_hvc(imm16), 2);
87
+ gen_exception_insn_el(s, s->base.pc_next, EXCP_HVC,
88
+ syn_aa64_hvc(imm16), 2);
89
break;
90
case 3: /* SMC */
91
if (s->current_el == 0) {
92
@@ -XXX,XX +XXX,XX @@ static void disas_exc(DisasContext *s, uint32_t insn)
93
gen_a64_set_pc_im(s->pc_curr);
94
gen_helper_pre_smc(cpu_env, tcg_constant_i32(syn_aa64_smc(imm16)));
95
gen_ss_advance(s);
96
- gen_exception_insn(s, s->base.pc_next, EXCP_SMC,
97
- syn_aa64_smc(imm16), 3);
98
+ gen_exception_insn_el(s, s->base.pc_next, EXCP_SMC,
99
+ syn_aa64_smc(imm16), 3);
100
break;
101
default:
102
unallocated_encoding(s);
103
@@ -XXX,XX +XXX,XX @@ static void aarch64_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
104
* Illegal execution state. This has priority over BTI
105
* exceptions, but comes after instruction abort exceptions.
106
*/
107
- gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
108
- syn_illegalstate(), default_exception_el(s));
109
+ gen_exception_insn_el(s, s->pc_curr, EXCP_UDEF,
110
+ syn_illegalstate(), default_exception_el(s));
111
return;
112
}
113
114
@@ -XXX,XX +XXX,XX @@ static void aarch64_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
115
if (s->btype != 0
116
&& s->guarded_page
117
&& !btype_destination_ok(insn, s->bt, s->btype)) {
118
- gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
119
- syn_btitrap(s->btype),
120
- default_exception_el(s));
121
+ gen_exception_insn_el(s, s->pc_curr, EXCP_UDEF,
122
+ syn_btitrap(s->btype),
123
+ default_exception_el(s));
124
return;
125
}
126
} else {
127
diff --git a/target/arm/translate-m-nocp.c b/target/arm/translate-m-nocp.c
128
index XXXXXXX..XXXXXXX 100644
129
--- a/target/arm/translate-m-nocp.c
130
+++ b/target/arm/translate-m-nocp.c
131
@@ -XXX,XX +XXX,XX @@ static bool trans_VSCCLRM(DisasContext *s, arg_VSCCLRM *a)
132
tcg_gen_brcondi_i32(TCG_COND_EQ, sfpa, 0, s->condlabel);
133
134
if (s->fp_excp_el != 0) {
135
- gen_exception_insn(s, s->pc_curr, EXCP_NOCP,
136
- syn_uncategorized(), s->fp_excp_el);
137
+ gen_exception_insn_el(s, s->pc_curr, EXCP_NOCP,
138
+ syn_uncategorized(), s->fp_excp_el);
139
return true;
140
}
141
142
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_write(DisasContext *s, int regno,
143
if (!vfp_access_check_m(s, true)) {
144
/*
145
* This was only a conditional exception, so override
146
- * gen_exception_insn()'s default to DISAS_NORETURN
147
+ * gen_exception_insn_el()'s default to DISAS_NORETURN
148
*/
149
s->base.is_jmp = DISAS_NEXT;
150
break;
151
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_read(DisasContext *s, int regno,
152
if (!vfp_access_check_m(s, true)) {
153
/*
154
* This was only a conditional exception, so override
155
- * gen_exception_insn()'s default to DISAS_NORETURN
156
+ * gen_exception_insn_el()'s default to DISAS_NORETURN
157
*/
158
s->base.is_jmp = DISAS_NEXT;
159
break;
160
@@ -XXX,XX +XXX,XX @@ static bool trans_NOCP(DisasContext *s, arg_nocp *a)
161
}
162
163
if (a->cp != 10) {
164
- gen_exception_insn(s, s->pc_curr, EXCP_NOCP,
165
- syn_uncategorized(), default_exception_el(s));
166
+ gen_exception_insn_el(s, s->pc_curr, EXCP_NOCP,
167
+ syn_uncategorized(), default_exception_el(s));
168
return true;
169
}
170
171
if (s->fp_excp_el != 0) {
172
- gen_exception_insn(s, s->pc_curr, EXCP_NOCP,
173
- syn_uncategorized(), s->fp_excp_el);
174
+ gen_exception_insn_el(s, s->pc_curr, EXCP_NOCP,
175
+ syn_uncategorized(), s->fp_excp_el);
176
return true;
177
}
178
179
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
180
index XXXXXXX..XXXXXXX 100644
181
--- a/target/arm/translate-mve.c
182
+++ b/target/arm/translate-mve.c
183
@@ -XXX,XX +XXX,XX @@ bool mve_eci_check(DisasContext *s)
184
return true;
23
default:
185
default:
24
- sprintf(unknown, "[%d ?]", reg);
186
/* Reserved value: INVSTATE UsageFault */
25
+ sprintf(unknown, "[%u ?]", reg);
187
- gen_exception_insn(s, s->pc_curr, EXCP_INVSTATE, syn_uncategorized(),
26
return unknown;
188
- default_exception_el(s));
27
}
189
+ gen_exception_insn_el(s, s->pc_curr, EXCP_INVSTATE, syn_uncategorized(),
28
}
190
+ default_exception_el(s));
29
@@ -XXX,XX +XXX,XX @@ static uint32_t imx31_ccm_get_pll_ref_clk(IMXCCMState *dev)
191
return false;
30
freq = CKIH_FREQ;
192
}
31
}
193
}
32
194
diff --git a/target/arm/translate-vfp.c b/target/arm/translate-vfp.c
33
- DPRINTF("freq = %d\n", freq);
195
index XXXXXXX..XXXXXXX 100644
34
+ DPRINTF("freq = %u\n", freq);
196
--- a/target/arm/translate-vfp.c
35
197
+++ b/target/arm/translate-vfp.c
36
return freq;
198
@@ -XXX,XX +XXX,XX @@ static bool vfp_access_check_a(DisasContext *s, bool ignore_vfp_enabled)
37
}
199
int coproc = arm_dc_feature(s, ARM_FEATURE_V8) ? 0 : 0xa;
38
@@ -XXX,XX +XXX,XX @@ static uint32_t imx31_ccm_get_mpll_clk(IMXCCMState *dev)
200
uint32_t syn = syn_fp_access_trap(1, 0xe, false, coproc);
39
freq = imx_ccm_calc_pll(s->reg[IMX31_CCM_MPCTL_REG],
201
40
imx31_ccm_get_pll_ref_clk(dev));
202
- gen_exception_insn(s, s->pc_curr, EXCP_UDEF, syn, s->fp_excp_el);
41
203
+ gen_exception_insn_el(s, s->pc_curr, EXCP_UDEF, syn, s->fp_excp_el);
42
- DPRINTF("freq = %d\n", freq);
204
return false;
43
+ DPRINTF("freq = %u\n", freq);
205
}
44
206
45
return freq;
207
@@ -XXX,XX +XXX,XX @@ bool vfp_access_check_m(DisasContext *s, bool skip_context_update)
46
}
208
* the encoding space handled by the patterns in m-nocp.decode,
47
@@ -XXX,XX +XXX,XX @@ static uint32_t imx31_ccm_get_mcu_main_clk(IMXCCMState *dev)
209
* and for them we may need to raise NOCP here.
48
freq = imx31_ccm_get_mpll_clk(dev);
210
*/
49
}
211
- gen_exception_insn(s, s->pc_curr, EXCP_NOCP,
50
212
- syn_uncategorized(), s->fp_excp_el);
51
- DPRINTF("freq = %d\n", freq);
213
+ gen_exception_insn_el(s, s->pc_curr, EXCP_NOCP,
52
+ DPRINTF("freq = %u\n", freq);
214
+ syn_uncategorized(), s->fp_excp_el);
53
215
return false;
54
return freq;
216
}
55
}
217
56
@@ -XXX,XX +XXX,XX @@ static uint32_t imx31_ccm_get_hclk_clk(IMXCCMState *dev)
218
diff --git a/target/arm/translate.c b/target/arm/translate.c
57
freq = imx31_ccm_get_mcu_main_clk(dev)
219
index XXXXXXX..XXXXXXX 100644
58
/ (1 + EXTRACT(s->reg[IMX31_CCM_PDR0_REG], MAX));
220
--- a/target/arm/translate.c
59
221
+++ b/target/arm/translate.c
60
- DPRINTF("freq = %d\n", freq);
222
@@ -XXX,XX +XXX,XX @@ static void gen_exception_insn_el_v(DisasContext *s, uint64_t pc, int excp,
61
+ DPRINTF("freq = %u\n", freq);
223
s->base.is_jmp = DISAS_NORETURN;
62
224
}
63
return freq;
225
64
}
226
-void gen_exception_insn(DisasContext *s, uint64_t pc, int excp,
65
@@ -XXX,XX +XXX,XX @@ static uint32_t imx31_ccm_get_ipg_clk(IMXCCMState *dev)
227
- uint32_t syn, uint32_t target_el)
66
freq = imx31_ccm_get_hclk_clk(dev)
228
+void gen_exception_insn_el(DisasContext *s, uint64_t pc, int excp,
67
/ (1 + EXTRACT(s->reg[IMX31_CCM_PDR0_REG], IPG));
229
+ uint32_t syn, uint32_t target_el)
68
230
{
69
- DPRINTF("freq = %d\n", freq);
231
gen_exception_insn_el_v(s, pc, excp, syn, tcg_constant_i32(target_el));
70
+ DPRINTF("freq = %u\n", freq);
232
}
71
233
@@ -XXX,XX +XXX,XX @@ static void gen_exception_bkpt_insn(DisasContext *s, uint32_t syn)
72
return freq;
234
void unallocated_encoding(DisasContext *s)
73
}
235
{
74
@@ -XXX,XX +XXX,XX @@ static uint32_t imx31_ccm_get_clock_frequency(IMXCCMState *dev, IMXClk clock)
236
/* Unallocated and reserved encodings are uncategorized */
75
break;
237
- gen_exception_insn(s, s->pc_curr, EXCP_UDEF, syn_uncategorized(),
76
}
238
- default_exception_el(s));
77
239
+ gen_exception_insn_el(s, s->pc_curr, EXCP_UDEF, syn_uncategorized(),
78
- DPRINTF("Clock = %d) = %d\n", clock, freq);
240
+ default_exception_el(s));
79
+ DPRINTF("Clock = %d) = %u\n", clock, freq);
241
}
80
242
81
return freq;
243
/* Force a TB lookup after an instruction that changes the CPU state. */
82
}
244
@@ -XXX,XX +XXX,XX @@ static bool msr_banked_access_decode(DisasContext *s, int r, int sysm, int rn,
83
diff --git a/hw/misc/imx_ccm.c b/hw/misc/imx_ccm.c
245
84
index XXXXXXX..XXXXXXX 100644
246
undef:
85
--- a/hw/misc/imx_ccm.c
247
/* If we get here then some access check did not pass */
86
+++ b/hw/misc/imx_ccm.c
248
- gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
87
@@ -XXX,XX +XXX,XX @@ uint32_t imx_ccm_get_clock_frequency(IMXCCMState *dev, IMXClk clock)
249
- syn_uncategorized(), exc_target);
88
freq = klass->get_clock_frequency(dev, clock);
250
+ gen_exception_insn_el(s, s->pc_curr, EXCP_UDEF,
89
}
251
+ syn_uncategorized(), exc_target);
90
252
return false;
91
- DPRINTF("(clock = %d) = %d\n", clock, freq);
253
}
92
+ DPRINTF("(clock = %d) = %u\n", clock, freq);
254
93
255
@@ -XXX,XX +XXX,XX @@ static void gen_srs(DisasContext *s,
94
return freq;
256
* For the UNPREDICTABLE cases we choose to UNDEF.
95
}
257
*/
96
@@ -XXX,XX +XXX,XX @@ uint32_t imx_ccm_calc_pll(uint32_t pllreg, uint32_t base_freq)
258
if (s->current_el == 1 && !s->ns && mode == ARM_CPU_MODE_MON) {
97
freq = ((2 * (base_freq >> 10) * (mfi * mfd + mfn)) /
259
- gen_exception_insn(s, s->pc_curr, EXCP_UDEF, syn_uncategorized(), 3);
98
(mfd * pd)) << 10;
260
+ gen_exception_insn_el(s, s->pc_curr, EXCP_UDEF,
99
261
+ syn_uncategorized(), 3);
100
- DPRINTF("(pllreg = 0x%08x, base_freq = %d) = %d\n", pllreg, base_freq,
262
return;
101
+ DPRINTF("(pllreg = 0x%08x, base_freq = %u) = %d\n", pllreg, base_freq,
263
}
102
freq);
264
103
265
@@ -XXX,XX +XXX,XX @@ static bool trans_WLS(DisasContext *s, arg_WLS *a)
104
return freq;
266
* Do the check-and-raise-exception by hand.
267
*/
268
if (s->fp_excp_el) {
269
- gen_exception_insn(s, s->pc_curr, EXCP_NOCP,
270
- syn_uncategorized(), s->fp_excp_el);
271
+ gen_exception_insn_el(s, s->pc_curr, EXCP_NOCP,
272
+ syn_uncategorized(), s->fp_excp_el);
273
return true;
274
}
275
}
276
@@ -XXX,XX +XXX,XX @@ static bool trans_LE(DisasContext *s, arg_LE *a)
277
tmp = load_cpu_field(v7m.ltpsize);
278
tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 4, skipexc);
279
tcg_temp_free_i32(tmp);
280
- gen_exception_insn(s, s->pc_curr, EXCP_INVSTATE, syn_uncategorized(),
281
- default_exception_el(s));
282
+ gen_exception_insn_el(s, s->pc_curr, EXCP_INVSTATE, syn_uncategorized(),
283
+ default_exception_el(s));
284
gen_set_label(skipexc);
285
}
286
287
@@ -XXX,XX +XXX,XX @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
288
* UsageFault exception.
289
*/
290
if (arm_dc_feature(s, ARM_FEATURE_M)) {
291
- gen_exception_insn(s, s->pc_curr, EXCP_INVSTATE, syn_uncategorized(),
292
- default_exception_el(s));
293
+ gen_exception_insn_el(s, s->pc_curr, EXCP_INVSTATE, syn_uncategorized(),
294
+ default_exception_el(s));
295
return;
296
}
297
298
@@ -XXX,XX +XXX,XX @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
299
* Illegal execution state. This has priority over BTI
300
* exceptions, but comes after instruction abort exceptions.
301
*/
302
- gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
303
- syn_illegalstate(), default_exception_el(s));
304
+ gen_exception_insn_el(s, s->pc_curr, EXCP_UDEF,
305
+ syn_illegalstate(), default_exception_el(s));
306
return;
307
}
308
309
@@ -XXX,XX +XXX,XX @@ static void thumb_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
310
* Illegal execution state. This has priority over BTI
311
* exceptions, but comes after instruction abort exceptions.
312
*/
313
- gen_exception_insn(dc, dc->pc_curr, EXCP_UDEF,
314
- syn_illegalstate(), default_exception_el(dc));
315
+ gen_exception_insn_el(dc, dc->pc_curr, EXCP_UDEF,
316
+ syn_illegalstate(), default_exception_el(dc));
317
return;
318
}
319
320
@@ -XXX,XX +XXX,XX @@ static void thumb_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
321
*/
322
tcg_remove_ops_after(dc->insn_eci_rewind);
323
dc->condjmp = 0;
324
- gen_exception_insn(dc, dc->pc_curr, EXCP_INVSTATE, syn_uncategorized(),
325
- default_exception_el(dc));
326
+ gen_exception_insn_el(dc, dc->pc_curr, EXCP_INVSTATE, syn_uncategorized(),
327
+ default_exception_el(dc));
328
}
329
330
arm_post_translate_insn(dc);
105
--
331
--
106
2.20.1
332
2.25.1
107
108
diff view generated by jsdifflib
1
From: Vikram Garhwal <fnu.vikram@xilinx.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
The QTests perform five tests on the Xilinx ZynqMP CAN controller:
3
Create a new wrapper function that passes the default
4
Tests the CAN controller in loopback, sleep and snoop mode.
4
exception target to gen_exception_insn_el.
5
Tests filtering of incoming CAN messages.
6
5
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Francisco Iglesias <francisco.iglesias@xilinx.com>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Signed-off-by: Vikram Garhwal <fnu.vikram@xilinx.com>
8
Message-id: 20220609202901.1177572-13-richard.henderson@linaro.org
10
Message-id: 1605728926-352690-4-git-send-email-fnu.vikram@xilinx.com
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
10
---
13
tests/qtest/xlnx-can-test.c | 360 ++++++++++++++++++++++++++++++++++++
11
target/arm/translate.h | 1 +
14
tests/qtest/meson.build | 1 +
12
target/arm/translate-a64.c | 15 ++++++---------
15
2 files changed, 361 insertions(+)
13
target/arm/translate-m-nocp.c | 3 +--
16
create mode 100644 tests/qtest/xlnx-can-test.c
14
target/arm/translate-mve.c | 3 +--
15
target/arm/translate.c | 29 +++++++++++++----------------
16
5 files changed, 22 insertions(+), 29 deletions(-)
17
17
18
diff --git a/tests/qtest/xlnx-can-test.c b/tests/qtest/xlnx-can-test.c
18
diff --git a/target/arm/translate.h b/target/arm/translate.h
19
new file mode 100644
19
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX
20
--- a/target/arm/translate.h
21
--- /dev/null
21
+++ b/target/arm/translate.h
22
+++ b/tests/qtest/xlnx-can-test.c
22
@@ -XXX,XX +XXX,XX @@ MemOp pow2_align(unsigned i);
23
@@ -XXX,XX +XXX,XX @@
23
void unallocated_encoding(DisasContext *s);
24
+/*
24
void gen_exception_insn_el(DisasContext *s, uint64_t pc, int excp,
25
+ * QTests for the Xilinx ZynqMP CAN controller.
25
uint32_t syn, uint32_t target_el);
26
+ *
26
+void gen_exception_insn(DisasContext *s, uint64_t pc, int excp, uint32_t syn);
27
+ * Copyright (c) 2020 Xilinx Inc.
27
28
+ *
28
/* Return state of Alternate Half-precision flag, caller frees result */
29
+ * Written-by: Vikram Garhwal<fnu.vikram@xilinx.com>
29
static inline TCGv_i32 get_ahp_flag(void)
30
+ *
30
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
31
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
31
index XXXXXXX..XXXXXXX 100644
32
+ * of this software and associated documentation files (the "Software"), to deal
32
--- a/target/arm/translate-a64.c
33
+ * in the Software without restriction, including without limitation the rights
33
+++ b/target/arm/translate-a64.c
34
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
34
@@ -XXX,XX +XXX,XX @@ static void gen_sysreg_undef(DisasContext *s, bool isread,
35
+ * copies of the Software, and to permit persons to whom the Software is
35
} else {
36
+ * furnished to do so, subject to the following conditions:
36
syndrome = syn_uncategorized();
37
+ *
37
}
38
+ * The above copyright notice and this permission notice shall be included in
38
- gen_exception_insn_el(s, s->pc_curr, EXCP_UDEF, syndrome,
39
+ * all copies or substantial portions of the Software.
39
- default_exception_el(s));
40
+ *
40
+ gen_exception_insn(s, s->pc_curr, EXCP_UDEF, syndrome);
41
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
41
}
42
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
42
43
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
43
/* MRS - move from system register
44
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
44
@@ -XXX,XX +XXX,XX @@ static void disas_exc(DisasContext *s, uint32_t insn)
45
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
45
switch (op2_ll) {
46
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
46
case 1: /* SVC */
47
+ * THE SOFTWARE.
47
gen_ss_advance(s);
48
+ */
48
- gen_exception_insn_el(s, s->base.pc_next, EXCP_SWI,
49
+
49
- syn_aa64_svc(imm16), default_exception_el(s));
50
+#include "qemu/osdep.h"
50
+ gen_exception_insn(s, s->base.pc_next, EXCP_SWI,
51
+#include "libqos/libqtest.h"
51
+ syn_aa64_svc(imm16));
52
+
52
break;
53
+/* Base address. */
53
case 2: /* HVC */
54
+#define CAN0_BASE_ADDR 0xFF060000
54
if (s->current_el == 0) {
55
+#define CAN1_BASE_ADDR 0xFF070000
55
@@ -XXX,XX +XXX,XX @@ static void aarch64_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
56
+
56
* Illegal execution state. This has priority over BTI
57
+/* Register addresses. */
57
* exceptions, but comes after instruction abort exceptions.
58
+#define R_SRR_OFFSET 0x00
58
*/
59
+#define R_MSR_OFFSET 0x04
59
- gen_exception_insn_el(s, s->pc_curr, EXCP_UDEF,
60
+#define R_SR_OFFSET 0x18
60
- syn_illegalstate(), default_exception_el(s));
61
+#define R_ISR_OFFSET 0x1C
61
+ gen_exception_insn(s, s->pc_curr, EXCP_UDEF, syn_illegalstate());
62
+#define R_ICR_OFFSET 0x24
62
return;
63
+#define R_TXID_OFFSET 0x30
63
}
64
+#define R_TXDLC_OFFSET 0x34
64
65
+#define R_TXDATA1_OFFSET 0x38
65
@@ -XXX,XX +XXX,XX @@ static void aarch64_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
66
+#define R_TXDATA2_OFFSET 0x3C
66
if (s->btype != 0
67
+#define R_RXID_OFFSET 0x50
67
&& s->guarded_page
68
+#define R_RXDLC_OFFSET 0x54
68
&& !btype_destination_ok(insn, s->bt, s->btype)) {
69
+#define R_RXDATA1_OFFSET 0x58
69
- gen_exception_insn_el(s, s->pc_curr, EXCP_UDEF,
70
+#define R_RXDATA2_OFFSET 0x5C
70
- syn_btitrap(s->btype),
71
+#define R_AFR 0x60
71
- default_exception_el(s));
72
+#define R_AFMR1 0x64
72
+ gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
73
+#define R_AFIR1 0x68
73
+ syn_btitrap(s->btype));
74
+#define R_AFMR2 0x6C
74
return;
75
+#define R_AFIR2 0x70
75
}
76
+#define R_AFMR3 0x74
76
} else {
77
+#define R_AFIR3 0x78
77
diff --git a/target/arm/translate-m-nocp.c b/target/arm/translate-m-nocp.c
78
+#define R_AFMR4 0x7C
78
index XXXXXXX..XXXXXXX 100644
79
+#define R_AFIR4 0x80
79
--- a/target/arm/translate-m-nocp.c
80
+
80
+++ b/target/arm/translate-m-nocp.c
81
+/* CAN modes. */
81
@@ -XXX,XX +XXX,XX @@ static bool trans_NOCP(DisasContext *s, arg_nocp *a)
82
+#define CONFIG_MODE 0x00
82
}
83
+#define NORMAL_MODE 0x00
83
84
+#define LOOPBACK_MODE 0x02
84
if (a->cp != 10) {
85
+#define SNOOP_MODE 0x04
85
- gen_exception_insn_el(s, s->pc_curr, EXCP_NOCP,
86
+#define SLEEP_MODE 0x01
86
- syn_uncategorized(), default_exception_el(s));
87
+#define ENABLE_CAN (1 << 1)
87
+ gen_exception_insn(s, s->pc_curr, EXCP_NOCP, syn_uncategorized());
88
+#define STATUS_NORMAL_MODE (1 << 3)
88
return true;
89
+#define STATUS_LOOPBACK_MODE (1 << 1)
89
}
90
+#define STATUS_SNOOP_MODE (1 << 12)
90
91
+#define STATUS_SLEEP_MODE (1 << 2)
91
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
92
+#define ISR_TXOK (1 << 1)
92
index XXXXXXX..XXXXXXX 100644
93
+#define ISR_RXOK (1 << 4)
93
--- a/target/arm/translate-mve.c
94
+
94
+++ b/target/arm/translate-mve.c
95
+static void match_rx_tx_data(const uint32_t *buf_tx, const uint32_t *buf_rx,
95
@@ -XXX,XX +XXX,XX @@ bool mve_eci_check(DisasContext *s)
96
+ uint8_t can_timestamp)
96
return true;
97
default:
98
/* Reserved value: INVSTATE UsageFault */
99
- gen_exception_insn_el(s, s->pc_curr, EXCP_INVSTATE, syn_uncategorized(),
100
- default_exception_el(s));
101
+ gen_exception_insn(s, s->pc_curr, EXCP_INVSTATE, syn_uncategorized());
102
return false;
103
}
104
}
105
diff --git a/target/arm/translate.c b/target/arm/translate.c
106
index XXXXXXX..XXXXXXX 100644
107
--- a/target/arm/translate.c
108
+++ b/target/arm/translate.c
109
@@ -XXX,XX +XXX,XX @@ void gen_exception_insn_el(DisasContext *s, uint64_t pc, int excp,
110
gen_exception_insn_el_v(s, pc, excp, syn, tcg_constant_i32(target_el));
111
}
112
113
+void gen_exception_insn(DisasContext *s, uint64_t pc, int excp, uint32_t syn)
97
+{
114
+{
98
+ uint16_t size = 0;
115
+ gen_exception_insn_el(s, pc, excp, syn, default_exception_el(s));
99
+ uint8_t len = 4;
100
+
101
+ while (size < len) {
102
+ if (R_RXID_OFFSET + 4 * size == R_RXDLC_OFFSET) {
103
+ g_assert_cmpint(buf_rx[size], ==, buf_tx[size] + can_timestamp);
104
+ } else {
105
+ g_assert_cmpint(buf_rx[size], ==, buf_tx[size]);
106
+ }
107
+
108
+ size++;
109
+ }
110
+}
116
+}
111
+
117
+
112
+static void read_data(QTestState *qts, uint64_t can_base_addr, uint32_t *buf_rx)
118
static void gen_exception_bkpt_insn(DisasContext *s, uint32_t syn)
113
+{
119
{
114
+ uint32_t int_status;
120
gen_set_condexec(s);
115
+
121
@@ -XXX,XX +XXX,XX @@ static void gen_exception_bkpt_insn(DisasContext *s, uint32_t syn)
116
+ /* Read the interrupt on CAN rx. */
122
void unallocated_encoding(DisasContext *s)
117
+ int_status = qtest_readl(qts, can_base_addr + R_ISR_OFFSET) & ISR_RXOK;
123
{
118
+
124
/* Unallocated and reserved encodings are uncategorized */
119
+ g_assert_cmpint(int_status, ==, ISR_RXOK);
125
- gen_exception_insn_el(s, s->pc_curr, EXCP_UDEF, syn_uncategorized(),
120
+
126
- default_exception_el(s));
121
+ /* Read the RX register data for CAN. */
127
+ gen_exception_insn(s, s->pc_curr, EXCP_UDEF, syn_uncategorized());
122
+ buf_rx[0] = qtest_readl(qts, can_base_addr + R_RXID_OFFSET);
128
}
123
+ buf_rx[1] = qtest_readl(qts, can_base_addr + R_RXDLC_OFFSET);
129
124
+ buf_rx[2] = qtest_readl(qts, can_base_addr + R_RXDATA1_OFFSET);
130
/* Force a TB lookup after an instruction that changes the CPU state. */
125
+ buf_rx[3] = qtest_readl(qts, can_base_addr + R_RXDATA2_OFFSET);
131
@@ -XXX,XX +XXX,XX @@ static bool msr_banked_access_decode(DisasContext *s, int r, int sysm, int rn,
126
+
132
* an exception and return false. Otherwise it will return true,
127
+ /* Clear the RX interrupt. */
133
* and set *tgtmode and *regno appropriately.
128
+ qtest_writel(qts, CAN1_BASE_ADDR + R_ICR_OFFSET, ISR_RXOK);
134
*/
129
+}
135
- int exc_target = default_exception_el(s);
130
+
136
-
131
+static void send_data(QTestState *qts, uint64_t can_base_addr,
137
/* These instructions are present only in ARMv8, or in ARMv7 with the
132
+ const uint32_t *buf_tx)
138
* Virtualization Extensions.
133
+{
139
*/
134
+ uint32_t int_status;
140
@@ -XXX,XX +XXX,XX @@ static bool msr_banked_access_decode(DisasContext *s, int r, int sysm, int rn,
135
+
141
136
+ /* Write the TX register data for CAN. */
142
undef:
137
+ qtest_writel(qts, can_base_addr + R_TXID_OFFSET, buf_tx[0]);
143
/* If we get here then some access check did not pass */
138
+ qtest_writel(qts, can_base_addr + R_TXDLC_OFFSET, buf_tx[1]);
144
- gen_exception_insn_el(s, s->pc_curr, EXCP_UDEF,
139
+ qtest_writel(qts, can_base_addr + R_TXDATA1_OFFSET, buf_tx[2]);
145
- syn_uncategorized(), exc_target);
140
+ qtest_writel(qts, can_base_addr + R_TXDATA2_OFFSET, buf_tx[3]);
146
+ gen_exception_insn(s, s->pc_curr, EXCP_UDEF, syn_uncategorized());
141
+
147
return false;
142
+ /* Read the interrupt on CAN for tx. */
148
}
143
+ int_status = qtest_readl(qts, can_base_addr + R_ISR_OFFSET) & ISR_TXOK;
149
144
+
150
@@ -XXX,XX +XXX,XX @@ static bool trans_LE(DisasContext *s, arg_LE *a)
145
+ g_assert_cmpint(int_status, ==, ISR_TXOK);
151
tmp = load_cpu_field(v7m.ltpsize);
146
+
152
tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 4, skipexc);
147
+ /* Clear the interrupt for tx. */
153
tcg_temp_free_i32(tmp);
148
+ qtest_writel(qts, CAN0_BASE_ADDR + R_ICR_OFFSET, ISR_TXOK);
154
- gen_exception_insn_el(s, s->pc_curr, EXCP_INVSTATE, syn_uncategorized(),
149
+}
155
- default_exception_el(s));
150
+
156
+ gen_exception_insn(s, s->pc_curr, EXCP_INVSTATE, syn_uncategorized());
151
+/*
157
gen_set_label(skipexc);
152
+ * This test will be transferring data from CAN0 and CAN1 through canbus. CAN0
158
}
153
+ * initiate the data transfer to can-bus, CAN1 receives the data. Test compares
159
154
+ * the data sent from CAN0 with received on CAN1.
160
@@ -XXX,XX +XXX,XX @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
155
+ */
161
* UsageFault exception.
156
+static void test_can_bus(void)
162
*/
157
+{
163
if (arm_dc_feature(s, ARM_FEATURE_M)) {
158
+ const uint32_t buf_tx[4] = { 0xFF, 0x80000000, 0x12345678, 0x87654321 };
164
- gen_exception_insn_el(s, s->pc_curr, EXCP_INVSTATE, syn_uncategorized(),
159
+ uint32_t buf_rx[4] = { 0x00, 0x00, 0x00, 0x00 };
165
- default_exception_el(s));
160
+ uint32_t status = 0;
166
+ gen_exception_insn(s, s->pc_curr, EXCP_INVSTATE, syn_uncategorized());
161
+ uint8_t can_timestamp = 1;
167
return;
162
+
168
}
163
+ QTestState *qts = qtest_init("-machine xlnx-zcu102"
169
164
+ " -object can-bus,id=canbus0"
170
@@ -XXX,XX +XXX,XX @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
165
+ " -machine xlnx-zcu102.canbus0=canbus0"
171
* Illegal execution state. This has priority over BTI
166
+ " -machine xlnx-zcu102.canbus1=canbus0"
172
* exceptions, but comes after instruction abort exceptions.
167
+ );
173
*/
168
+
174
- gen_exception_insn_el(s, s->pc_curr, EXCP_UDEF,
169
+ /* Configure the CAN0 and CAN1. */
175
- syn_illegalstate(), default_exception_el(s));
170
+ qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
176
+ gen_exception_insn(s, s->pc_curr, EXCP_UDEF, syn_illegalstate());
171
+ qtest_writel(qts, CAN0_BASE_ADDR + R_MSR_OFFSET, NORMAL_MODE);
177
return;
172
+ qtest_writel(qts, CAN1_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
178
}
173
+ qtest_writel(qts, CAN1_BASE_ADDR + R_MSR_OFFSET, NORMAL_MODE);
179
174
+
180
@@ -XXX,XX +XXX,XX @@ static void thumb_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
175
+ /* Check here if CAN0 and CAN1 are in normal mode. */
181
* Illegal execution state. This has priority over BTI
176
+ status = qtest_readl(qts, CAN0_BASE_ADDR + R_SR_OFFSET);
182
* exceptions, but comes after instruction abort exceptions.
177
+ g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
183
*/
178
+
184
- gen_exception_insn_el(dc, dc->pc_curr, EXCP_UDEF,
179
+ status = qtest_readl(qts, CAN1_BASE_ADDR + R_SR_OFFSET);
185
- syn_illegalstate(), default_exception_el(dc));
180
+ g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
186
+ gen_exception_insn(dc, dc->pc_curr, EXCP_UDEF, syn_illegalstate());
181
+
187
return;
182
+ send_data(qts, CAN0_BASE_ADDR, buf_tx);
188
}
183
+
189
184
+ read_data(qts, CAN1_BASE_ADDR, buf_rx);
190
@@ -XXX,XX +XXX,XX @@ static void thumb_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
185
+ match_rx_tx_data(buf_tx, buf_rx, can_timestamp);
191
*/
186
+
192
tcg_remove_ops_after(dc->insn_eci_rewind);
187
+ qtest_quit(qts);
193
dc->condjmp = 0;
188
+}
194
- gen_exception_insn_el(dc, dc->pc_curr, EXCP_INVSTATE, syn_uncategorized(),
189
+
195
- default_exception_el(dc));
190
+/*
196
+ gen_exception_insn(dc, dc->pc_curr, EXCP_INVSTATE,
191
+ * This test is performing loopback mode on CAN0 and CAN1. Data sent from TX of
197
+ syn_uncategorized());
192
+ * each CAN0 and CAN1 are compared with RX register data for respective CAN.
198
}
193
+ */
199
194
+static void test_can_loopback(void)
200
arm_post_translate_insn(dc);
195
+{
196
+ uint32_t buf_tx[4] = { 0xFF, 0x80000000, 0x12345678, 0x87654321 };
197
+ uint32_t buf_rx[4] = { 0x00, 0x00, 0x00, 0x00 };
198
+ uint32_t status = 0;
199
+
200
+ QTestState *qts = qtest_init("-machine xlnx-zcu102"
201
+ " -object can-bus,id=canbus0"
202
+ " -machine xlnx-zcu102.canbus0=canbus0"
203
+ " -machine xlnx-zcu102.canbus1=canbus0"
204
+ );
205
+
206
+ /* Configure the CAN0 in loopback mode. */
207
+ qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, CONFIG_MODE);
208
+ qtest_writel(qts, CAN0_BASE_ADDR + R_MSR_OFFSET, LOOPBACK_MODE);
209
+ qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
210
+
211
+ /* Check here if CAN0 is set in loopback mode. */
212
+ status = qtest_readl(qts, CAN0_BASE_ADDR + R_SR_OFFSET);
213
+
214
+ g_assert_cmpint(status, ==, STATUS_LOOPBACK_MODE);
215
+
216
+ send_data(qts, CAN0_BASE_ADDR, buf_tx);
217
+ read_data(qts, CAN0_BASE_ADDR, buf_rx);
218
+ match_rx_tx_data(buf_tx, buf_rx, 0);
219
+
220
+ /* Configure the CAN1 in loopback mode. */
221
+ qtest_writel(qts, CAN1_BASE_ADDR + R_SRR_OFFSET, CONFIG_MODE);
222
+ qtest_writel(qts, CAN1_BASE_ADDR + R_MSR_OFFSET, LOOPBACK_MODE);
223
+ qtest_writel(qts, CAN1_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
224
+
225
+ /* Check here if CAN1 is set in loopback mode. */
226
+ status = qtest_readl(qts, CAN1_BASE_ADDR + R_SR_OFFSET);
227
+
228
+ g_assert_cmpint(status, ==, STATUS_LOOPBACK_MODE);
229
+
230
+ send_data(qts, CAN1_BASE_ADDR, buf_tx);
231
+ read_data(qts, CAN1_BASE_ADDR, buf_rx);
232
+ match_rx_tx_data(buf_tx, buf_rx, 0);
233
+
234
+ qtest_quit(qts);
235
+}
236
+
237
+/*
238
+ * Enable filters for CAN1. This will filter incoming messages with ID. In this
239
+ * test message will pass through filter 2.
240
+ */
241
+static void test_can_filter(void)
242
+{
243
+ uint32_t buf_tx[4] = { 0x14, 0x80000000, 0x12345678, 0x87654321 };
244
+ uint32_t buf_rx[4] = { 0x00, 0x00, 0x00, 0x00 };
245
+ uint32_t status = 0;
246
+ uint8_t can_timestamp = 1;
247
+
248
+ QTestState *qts = qtest_init("-machine xlnx-zcu102"
249
+ " -object can-bus,id=canbus0"
250
+ " -machine xlnx-zcu102.canbus0=canbus0"
251
+ " -machine xlnx-zcu102.canbus1=canbus0"
252
+ );
253
+
254
+ /* Configure the CAN0 and CAN1. */
255
+ qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
256
+ qtest_writel(qts, CAN0_BASE_ADDR + R_MSR_OFFSET, NORMAL_MODE);
257
+ qtest_writel(qts, CAN1_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
258
+ qtest_writel(qts, CAN1_BASE_ADDR + R_MSR_OFFSET, NORMAL_MODE);
259
+
260
+ /* Check here if CAN0 and CAN1 are in normal mode. */
261
+ status = qtest_readl(qts, CAN0_BASE_ADDR + R_SR_OFFSET);
262
+ g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
263
+
264
+ status = qtest_readl(qts, CAN1_BASE_ADDR + R_SR_OFFSET);
265
+ g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
266
+
267
+ /* Set filter for CAN1 for incoming messages. */
268
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFR, 0x0);
269
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFMR1, 0xF7);
270
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFIR1, 0x121F);
271
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFMR2, 0x5431);
272
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFIR2, 0x14);
273
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFMR3, 0x1234);
274
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFIR3, 0x5431);
275
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFMR4, 0xFFF);
276
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFIR4, 0x1234);
277
+
278
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFR, 0xF);
279
+
280
+ send_data(qts, CAN0_BASE_ADDR, buf_tx);
281
+
282
+ read_data(qts, CAN1_BASE_ADDR, buf_rx);
283
+ match_rx_tx_data(buf_tx, buf_rx, can_timestamp);
284
+
285
+ qtest_quit(qts);
286
+}
287
+
288
+/* Testing sleep mode on CAN0 while CAN1 is in normal mode. */
289
+static void test_can_sleepmode(void)
290
+{
291
+ uint32_t buf_tx[4] = { 0x14, 0x80000000, 0x12345678, 0x87654321 };
292
+ uint32_t buf_rx[4] = { 0x00, 0x00, 0x00, 0x00 };
293
+ uint32_t status = 0;
294
+ uint8_t can_timestamp = 1;
295
+
296
+ QTestState *qts = qtest_init("-machine xlnx-zcu102"
297
+ " -object can-bus,id=canbus0"
298
+ " -machine xlnx-zcu102.canbus0=canbus0"
299
+ " -machine xlnx-zcu102.canbus1=canbus0"
300
+ );
301
+
302
+ /* Configure the CAN0. */
303
+ qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, CONFIG_MODE);
304
+ qtest_writel(qts, CAN0_BASE_ADDR + R_MSR_OFFSET, SLEEP_MODE);
305
+ qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
306
+
307
+ qtest_writel(qts, CAN1_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
308
+ qtest_writel(qts, CAN1_BASE_ADDR + R_MSR_OFFSET, NORMAL_MODE);
309
+
310
+ /* Check here if CAN0 is in SLEEP mode and CAN1 in normal mode. */
311
+ status = qtest_readl(qts, CAN0_BASE_ADDR + R_SR_OFFSET);
312
+ g_assert_cmpint(status, ==, STATUS_SLEEP_MODE);
313
+
314
+ status = qtest_readl(qts, CAN1_BASE_ADDR + R_SR_OFFSET);
315
+ g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
316
+
317
+ send_data(qts, CAN1_BASE_ADDR, buf_tx);
318
+
319
+ /*
320
+ * Once CAN1 sends data on can-bus. CAN0 should exit sleep mode.
321
+ * Check the CAN0 status now. It should exit the sleep mode and receive the
322
+ * incoming data.
323
+ */
324
+ status = qtest_readl(qts, CAN0_BASE_ADDR + R_SR_OFFSET);
325
+ g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
326
+
327
+ read_data(qts, CAN0_BASE_ADDR, buf_rx);
328
+
329
+ match_rx_tx_data(buf_tx, buf_rx, can_timestamp);
330
+
331
+ qtest_quit(qts);
332
+}
333
+
334
+/* Testing Snoop mode on CAN0 while CAN1 is in normal mode. */
335
+static void test_can_snoopmode(void)
336
+{
337
+ uint32_t buf_tx[4] = { 0x14, 0x80000000, 0x12345678, 0x87654321 };
338
+ uint32_t buf_rx[4] = { 0x00, 0x00, 0x00, 0x00 };
339
+ uint32_t status = 0;
340
+ uint8_t can_timestamp = 1;
341
+
342
+ QTestState *qts = qtest_init("-machine xlnx-zcu102"
343
+ " -object can-bus,id=canbus0"
344
+ " -machine xlnx-zcu102.canbus0=canbus0"
345
+ " -machine xlnx-zcu102.canbus1=canbus0"
346
+ );
347
+
348
+ /* Configure the CAN0. */
349
+ qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, CONFIG_MODE);
350
+ qtest_writel(qts, CAN0_BASE_ADDR + R_MSR_OFFSET, SNOOP_MODE);
351
+ qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
352
+
353
+ qtest_writel(qts, CAN1_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
354
+ qtest_writel(qts, CAN1_BASE_ADDR + R_MSR_OFFSET, NORMAL_MODE);
355
+
356
+ /* Check here if CAN0 is in SNOOP mode and CAN1 in normal mode. */
357
+ status = qtest_readl(qts, CAN0_BASE_ADDR + R_SR_OFFSET);
358
+ g_assert_cmpint(status, ==, STATUS_SNOOP_MODE);
359
+
360
+ status = qtest_readl(qts, CAN1_BASE_ADDR + R_SR_OFFSET);
361
+ g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
362
+
363
+ send_data(qts, CAN1_BASE_ADDR, buf_tx);
364
+
365
+ read_data(qts, CAN0_BASE_ADDR, buf_rx);
366
+
367
+ match_rx_tx_data(buf_tx, buf_rx, can_timestamp);
368
+
369
+ qtest_quit(qts);
370
+}
371
+
372
+int main(int argc, char **argv)
373
+{
374
+ g_test_init(&argc, &argv, NULL);
375
+
376
+ qtest_add_func("/net/can/can_bus", test_can_bus);
377
+ qtest_add_func("/net/can/can_loopback", test_can_loopback);
378
+ qtest_add_func("/net/can/can_filter", test_can_filter);
379
+ qtest_add_func("/net/can/can_test_snoopmode", test_can_snoopmode);
380
+ qtest_add_func("/net/can/can_test_sleepmode", test_can_sleepmode);
381
+
382
+ return g_test_run();
383
+}
384
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
385
index XXXXXXX..XXXXXXX 100644
386
--- a/tests/qtest/meson.build
387
+++ b/tests/qtest/meson.build
388
@@ -XXX,XX +XXX,XX @@ qtests_aarch64 = \
389
['arm-cpu-features',
390
'numa-test',
391
'boot-serial-test',
392
+ 'xlnx-can-test',
393
'migration-test']
394
395
qtests_s390x = \
396
--
201
--
397
2.20.1
202
2.25.1
398
399
diff view generated by jsdifflib
1
v8.1M introduces a new TRD flag in the CCR register, which enables
1
From: Richard Henderson <richard.henderson@linaro.org>
2
checking for stack frame integrity signatures on SG instructions.
3
Add the code in the SG insn implementation for the new behaviour.
4
2
3
Move the computation from gen_swstep_exception into a helper.
4
5
This fixes a bug when:
6
- MDSCR_EL1.KDE == 1 to enable debug exceptions within EL_D itself
7
- we singlestep an ERET from EL_D to some lower EL
8
9
Previously we were computing 'same el' based on the EL which
10
executed the ERET instruction, whereas it ought to be computed
11
based on the EL to which ERET returned. This happens naturally
12
with the new helper, which runs after EL has been changed.
13
14
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
16
Message-id: 20220609202901.1177572-14-richard.henderson@linaro.org
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20201119215617.29887-24-peter.maydell@linaro.org
8
---
18
---
9
target/arm/m_helper.c | 86 +++++++++++++++++++++++++++++++++++++++++++
19
target/arm/helper.h | 1 +
10
1 file changed, 86 insertions(+)
20
target/arm/translate.h | 12 +++---------
21
target/arm/debug_helper.c | 16 ++++++++++++++++
22
3 files changed, 20 insertions(+), 9 deletions(-)
11
23
12
diff --git a/target/arm/m_helper.c b/target/arm/m_helper.c
24
diff --git a/target/arm/helper.h b/target/arm/helper.h
13
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/m_helper.c
26
--- a/target/arm/helper.h
15
+++ b/target/arm/m_helper.c
27
+++ b/target/arm/helper.h
16
@@ -XXX,XX +XXX,XX @@ static bool v7m_read_half_insn(ARMCPU *cpu, ARMMMUIdx mmu_idx,
28
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_3(sel_flags, TCG_CALL_NO_RWG_SE,
17
return true;
29
DEF_HELPER_2(exception_internal, noreturn, env, i32)
30
DEF_HELPER_4(exception_with_syndrome_el, noreturn, env, i32, i32, i32)
31
DEF_HELPER_2(exception_bkpt_insn, noreturn, env, i32)
32
+DEF_HELPER_2(exception_swstep, noreturn, env, i32)
33
DEF_HELPER_2(exception_pc_alignment, noreturn, env, tl)
34
DEF_HELPER_1(setend, void, env)
35
DEF_HELPER_2(wfi, void, env, i32)
36
diff --git a/target/arm/translate.h b/target/arm/translate.h
37
index XXXXXXX..XXXXXXX 100644
38
--- a/target/arm/translate.h
39
+++ b/target/arm/translate.h
40
@@ -XXX,XX +XXX,XX @@ static inline void gen_exception(int excp, uint32_t syndrome,
41
/* Generate an architectural singlestep exception */
42
static inline void gen_swstep_exception(DisasContext *s, int isv, int ex)
43
{
44
- bool same_el = (s->debug_target_el == s->current_el);
45
-
46
- /*
47
- * If singlestep is targeting a lower EL than the current one,
48
- * then s->ss_active must be false and we can never get here.
49
- */
50
- assert(s->debug_target_el >= s->current_el);
51
-
52
- gen_exception(EXCP_UDEF, syn_swstep(same_el, isv, ex), s->debug_target_el);
53
+ /* Fill in the same_el field of the syndrome in the helper. */
54
+ uint32_t syn = syn_swstep(false, isv, ex);
55
+ gen_helper_exception_swstep(cpu_env, tcg_constant_i32(syn));
18
}
56
}
19
57
20
+static bool v7m_read_sg_stack_word(ARMCPU *cpu, ARMMMUIdx mmu_idx,
58
/*
21
+ uint32_t addr, uint32_t *spdata)
59
diff --git a/target/arm/debug_helper.c b/target/arm/debug_helper.c
60
index XXXXXXX..XXXXXXX 100644
61
--- a/target/arm/debug_helper.c
62
+++ b/target/arm/debug_helper.c
63
@@ -XXX,XX +XXX,XX @@ void HELPER(exception_bkpt_insn)(CPUARMState *env, uint32_t syndrome)
64
raise_exception(env, EXCP_BKPT, syndrome, debug_el);
65
}
66
67
+void HELPER(exception_swstep)(CPUARMState *env, uint32_t syndrome)
22
+{
68
+{
69
+ int debug_el = arm_debug_target_el(env);
70
+ int cur_el = arm_current_el(env);
71
+
23
+ /*
72
+ /*
24
+ * Read a word of data from the stack for the SG instruction,
73
+ * If singlestep is targeting a lower EL than the current one, then
25
+ * writing the value into *spdata. If the load succeeds, return
74
+ * DisasContext.ss_active must be false and we can never get here.
26
+ * true; otherwise pend an appropriate exception and return false.
27
+ * (We can't use data load helpers here that throw an exception
28
+ * because of the context we're called in, which is halfway through
29
+ * arm_v7m_cpu_do_interrupt().)
30
+ */
75
+ */
31
+ CPUState *cs = CPU(cpu);
76
+ assert(debug_el >= cur_el);
32
+ CPUARMState *env = &cpu->env;
77
+ if (debug_el == cur_el) {
33
+ MemTxAttrs attrs = {};
78
+ syndrome |= 1 << ARM_EL_EC_SHIFT;
34
+ MemTxResult txres;
35
+ target_ulong page_size;
36
+ hwaddr physaddr;
37
+ int prot;
38
+ ARMMMUFaultInfo fi = {};
39
+ ARMCacheAttrs cacheattrs = {};
40
+ uint32_t value;
41
+
42
+ if (get_phys_addr(env, addr, MMU_DATA_LOAD, mmu_idx, &physaddr,
43
+ &attrs, &prot, &page_size, &fi, &cacheattrs)) {
44
+ /* MPU/SAU lookup failed */
45
+ if (fi.type == ARMFault_QEMU_SFault) {
46
+ qemu_log_mask(CPU_LOG_INT,
47
+ "...SecureFault during stack word read\n");
48
+ env->v7m.sfsr |= R_V7M_SFSR_AUVIOL_MASK | R_V7M_SFSR_SFARVALID_MASK;
49
+ env->v7m.sfar = addr;
50
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_SECURE, false);
51
+ } else {
52
+ qemu_log_mask(CPU_LOG_INT,
53
+ "...MemManageFault during stack word read\n");
54
+ env->v7m.cfsr[M_REG_S] |= R_V7M_CFSR_DACCVIOL_MASK |
55
+ R_V7M_CFSR_MMARVALID_MASK;
56
+ env->v7m.mmfar[M_REG_S] = addr;
57
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_MEM, false);
58
+ }
59
+ return false;
60
+ }
79
+ }
61
+ value = address_space_ldl(arm_addressspace(cs, attrs), physaddr,
80
+ raise_exception(env, EXCP_UDEF, syndrome, debug_el);
62
+ attrs, &txres);
63
+ if (txres != MEMTX_OK) {
64
+ /* BusFault trying to read the data */
65
+ qemu_log_mask(CPU_LOG_INT,
66
+ "...BusFault during stack word read\n");
67
+ env->v7m.cfsr[M_REG_NS] |=
68
+ (R_V7M_CFSR_PRECISERR_MASK | R_V7M_CFSR_BFARVALID_MASK);
69
+ env->v7m.bfar = addr;
70
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_BUS, false);
71
+ return false;
72
+ }
73
+
74
+ *spdata = value;
75
+ return true;
76
+}
81
+}
77
+
82
+
78
static bool v7m_handle_execute_nsc(ARMCPU *cpu)
83
#if !defined(CONFIG_USER_ONLY)
79
{
84
80
/*
85
vaddr arm_adjust_watchpoint_address(CPUState *cs, vaddr addr, int len)
81
@@ -XXX,XX +XXX,XX @@ static bool v7m_handle_execute_nsc(ARMCPU *cpu)
82
*/
83
qemu_log_mask(CPU_LOG_INT, "...really an SG instruction at 0x%08" PRIx32
84
", executing it\n", env->regs[15]);
85
+
86
+ if (cpu_isar_feature(aa32_m_sec_state, cpu) &&
87
+ !arm_v7m_is_handler_mode(env)) {
88
+ /*
89
+ * v8.1M exception stack frame integrity check. Note that we
90
+ * must perform the memory access even if CCR_S.TRD is zero
91
+ * and we aren't going to check what the data loaded is.
92
+ */
93
+ uint32_t spdata, sp;
94
+
95
+ /*
96
+ * We know we are currently NS, so the S stack pointers must be
97
+ * in other_ss_{psp,msp}, not in regs[13]/other_sp.
98
+ */
99
+ sp = v7m_using_psp(env) ? env->v7m.other_ss_psp : env->v7m.other_ss_msp;
100
+ if (!v7m_read_sg_stack_word(cpu, mmu_idx, sp, &spdata)) {
101
+ /* Stack access failed and an exception has been pended */
102
+ return false;
103
+ }
104
+
105
+ if (env->v7m.ccr[M_REG_S] & R_V7M_CCR_TRD_MASK) {
106
+ if (((spdata & ~1) == 0xfefa125a) ||
107
+ !(env->v7m.control[M_REG_S] & 1)) {
108
+ goto gen_invep;
109
+ }
110
+ }
111
+ }
112
+
113
env->regs[14] &= ~1;
114
env->v7m.control[M_REG_S] &= ~R_V7M_CONTROL_SFPA_MASK;
115
switch_v7m_security_state(env, true);
116
--
86
--
117
2.20.1
87
2.25.1
118
119
diff view generated by jsdifflib
1
v8.1M defines a new FP system register FPSCR_nzcvqc; this behaves
1
From: Richard Henderson <richard.henderson@linaro.org>
2
like the existing FPSCR, except that it reads and writes only bits
3
[31:27] of the FPSCR (the N, Z, C, V and QC flag bits). (Unlike the
4
FPSCR, the special case for Rt=15 of writing the CPSR.NZCV is not
5
permitted.)
6
2
7
Implement the register. Since we don't yet implement MVE, we handle
3
We no longer need this value during translation,
8
the QC bit as RES0, with todo comments for where we will need to add
4
as it is now handled within the helpers.
9
support later.
10
5
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20220609202901.1177572-15-richard.henderson@linaro.org
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
13
Message-id: 20201119215617.29887-11-peter.maydell@linaro.org
14
---
10
---
15
target/arm/cpu.h | 13 +++++++++++++
11
target/arm/cpu.h | 6 ++----
16
target/arm/translate-vfp.c.inc | 27 +++++++++++++++++++++++++++
12
target/arm/translate.h | 2 --
17
2 files changed, 40 insertions(+)
13
target/arm/helper.c | 12 ++----------
14
target/arm/translate-a64.c | 1 -
15
target/arm/translate.c | 1 -
16
5 files changed, 4 insertions(+), 18 deletions(-)
18
17
19
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
18
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
20
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
21
--- a/target/arm/cpu.h
20
--- a/target/arm/cpu.h
22
+++ b/target/arm/cpu.h
21
+++ b/target/arm/cpu.h
23
@@ -XXX,XX +XXX,XX @@ void vfp_set_fpscr(CPUARMState *env, uint32_t val);
22
@@ -XXX,XX +XXX,XX @@ FIELD(TBFLAG_ANY, BE_DATA, 3, 1)
24
#define FPCR_FZ (1 << 24) /* Flush-to-zero enable bit */
23
FIELD(TBFLAG_ANY, MMUIDX, 4, 4)
25
#define FPCR_DN (1 << 25) /* Default NaN enable bit */
24
/* Target EL if we take a floating-point-disabled exception */
26
#define FPCR_QC (1 << 27) /* Cumulative saturation bit */
25
FIELD(TBFLAG_ANY, FPEXC_EL, 8, 2)
27
+#define FPCR_V (1 << 28) /* FP overflow flag */
26
-/* For A-profile only, target EL for debug exceptions. */
28
+#define FPCR_C (1 << 29) /* FP carry flag */
27
-FIELD(TBFLAG_ANY, DEBUG_TARGET_EL, 10, 2)
29
+#define FPCR_Z (1 << 30) /* FP zero flag */
28
/* Memory operations require alignment: SCTLR_ELx.A or CCR.UNALIGN_TRP */
30
+#define FPCR_N (1 << 31) /* FP negative flag */
29
-FIELD(TBFLAG_ANY, ALIGN_MEM, 12, 1)
31
+
30
-FIELD(TBFLAG_ANY, PSTATE__IL, 13, 1)
32
+#define FPCR_NZCV_MASK (FPCR_N | FPCR_Z | FPCR_C | FPCR_V)
31
+FIELD(TBFLAG_ANY, ALIGN_MEM, 10, 1)
33
+#define FPCR_NZCVQC_MASK (FPCR_NZCV_MASK | FPCR_QC)
32
+FIELD(TBFLAG_ANY, PSTATE__IL, 11, 1)
34
33
35
static inline uint32_t vfp_get_fpsr(CPUARMState *env)
34
/*
35
* Bit usage when in AArch32 state, both A- and M-profile.
36
diff --git a/target/arm/translate.h b/target/arm/translate.h
37
index XXXXXXX..XXXXXXX 100644
38
--- a/target/arm/translate.h
39
+++ b/target/arm/translate.h
40
@@ -XXX,XX +XXX,XX @@ typedef struct DisasContext {
41
*/
42
uint32_t svc_imm;
43
int current_el;
44
- /* Debug target exception level for single-step exceptions */
45
- int debug_target_el;
46
GHashTable *cp_regs;
47
uint64_t features; /* CPU features bits */
48
bool aarch64;
49
diff --git a/target/arm/helper.c b/target/arm/helper.c
50
index XXXXXXX..XXXXXXX 100644
51
--- a/target/arm/helper.c
52
+++ b/target/arm/helper.c
53
@@ -XXX,XX +XXX,XX @@ static CPUARMTBFlags rebuild_hflags_m32(CPUARMState *env, int fp_el,
54
return rebuild_hflags_common_32(env, fp_el, mmu_idx, flags);
55
}
56
57
-static CPUARMTBFlags rebuild_hflags_aprofile(CPUARMState *env)
58
-{
59
- CPUARMTBFlags flags = {};
60
-
61
- DP_TBFLAG_ANY(flags, DEBUG_TARGET_EL, arm_debug_target_el(env));
62
- return flags;
63
-}
64
-
65
static CPUARMTBFlags rebuild_hflags_a32(CPUARMState *env, int fp_el,
66
ARMMMUIdx mmu_idx)
36
{
67
{
37
@@ -XXX,XX +XXX,XX @@ enum arm_cpu_mode {
68
- CPUARMTBFlags flags = rebuild_hflags_aprofile(env);
38
#define ARM_VFP_FPEXC 8
69
+ CPUARMTBFlags flags = {};
39
#define ARM_VFP_FPINST 9
70
int el = arm_current_el(env);
40
#define ARM_VFP_FPINST2 10
71
41
+/* These ones are M-profile only */
72
if (arm_sctlr(env, el) & SCTLR_A) {
42
+#define ARM_VFP_FPSCR_NZCVQC 2
73
@@ -XXX,XX +XXX,XX @@ static CPUARMTBFlags rebuild_hflags_a32(CPUARMState *env, int fp_el,
43
+#define ARM_VFP_VPR 12
74
static CPUARMTBFlags rebuild_hflags_a64(CPUARMState *env, int el, int fp_el,
44
+#define ARM_VFP_P0 13
75
ARMMMUIdx mmu_idx)
45
+#define ARM_VFP_FPCXT_NS 14
76
{
46
+#define ARM_VFP_FPCXT_S 15
77
- CPUARMTBFlags flags = rebuild_hflags_aprofile(env);
47
78
+ CPUARMTBFlags flags = {};
48
/* QEMU-internal value meaning "FPSCR, but we care only about NZCV" */
79
ARMMMUIdx stage1 = stage_1_mmu_idx(mmu_idx);
49
#define QEMU_VFP_FPSCR_NZCV 0xffff
80
uint64_t tcr = regime_tcr(env, mmu_idx)->raw_tcr;
50
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
81
uint64_t sctlr;
82
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
51
index XXXXXXX..XXXXXXX 100644
83
index XXXXXXX..XXXXXXX 100644
52
--- a/target/arm/translate-vfp.c.inc
84
--- a/target/arm/translate-a64.c
53
+++ b/target/arm/translate-vfp.c.inc
85
+++ b/target/arm/translate-a64.c
54
@@ -XXX,XX +XXX,XX @@ static FPSysRegCheckResult fp_sysreg_checks(DisasContext *s, int regno)
86
@@ -XXX,XX +XXX,XX @@ static void aarch64_tr_init_disas_context(DisasContextBase *dcbase,
55
case ARM_VFP_FPSCR:
87
dc->ss_active = EX_TBFLAG_ANY(tb_flags, SS_ACTIVE);
56
case QEMU_VFP_FPSCR_NZCV:
88
dc->pstate_ss = EX_TBFLAG_ANY(tb_flags, PSTATE__SS);
57
break;
89
dc->is_ldex = false;
58
+ case ARM_VFP_FPSCR_NZCVQC:
90
- dc->debug_target_el = EX_TBFLAG_ANY(tb_flags, DEBUG_TARGET_EL);
59
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
91
60
+ return false;
92
/* Bound the number of insns to execute to those left on the page. */
61
+ }
93
bound = -(dc->base.pc_first | TARGET_PAGE_MASK) / 4;
62
+ break;
94
diff --git a/target/arm/translate.c b/target/arm/translate.c
63
default:
95
index XXXXXXX..XXXXXXX 100644
64
return FPSysRegCheckFailed;
96
--- a/target/arm/translate.c
65
}
97
+++ b/target/arm/translate.c
66
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_write(DisasContext *s, int regno,
98
@@ -XXX,XX +XXX,XX @@ static void arm_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
67
tcg_temp_free_i32(tmp);
99
dc->v7m_lspact = EX_TBFLAG_M32(tb_flags, LSPACT);
68
gen_lookup_tb(s);
100
dc->mve_no_pred = EX_TBFLAG_M32(tb_flags, MVE_NO_PRED);
69
break;
101
} else {
70
+ case ARM_VFP_FPSCR_NZCVQC:
102
- dc->debug_target_el = EX_TBFLAG_ANY(tb_flags, DEBUG_TARGET_EL);
71
+ {
103
dc->sctlr_b = EX_TBFLAG_A32(tb_flags, SCTLR__B);
72
+ TCGv_i32 fpscr;
104
dc->hstr_active = EX_TBFLAG_A32(tb_flags, HSTR_ACTIVE);
73
+ tmp = loadfn(s, opaque);
105
dc->ns = EX_TBFLAG_A32(tb_flags, NS);
74
+ /*
75
+ * TODO: when we implement MVE, write the QC bit.
76
+ * For non-MVE, QC is RES0.
77
+ */
78
+ tcg_gen_andi_i32(tmp, tmp, FPCR_NZCV_MASK);
79
+ fpscr = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
80
+ tcg_gen_andi_i32(fpscr, fpscr, ~FPCR_NZCV_MASK);
81
+ tcg_gen_or_i32(fpscr, fpscr, tmp);
82
+ store_cpu_field(fpscr, vfp.xregs[ARM_VFP_FPSCR]);
83
+ tcg_temp_free_i32(tmp);
84
+ break;
85
+ }
86
default:
87
g_assert_not_reached();
88
}
89
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_read(DisasContext *s, int regno,
90
gen_helper_vfp_get_fpscr(tmp, cpu_env);
91
storefn(s, opaque, tmp);
92
break;
93
+ case ARM_VFP_FPSCR_NZCVQC:
94
+ /*
95
+ * TODO: MVE has a QC bit, which we probably won't store
96
+ * in the xregs[] field. For non-MVE, where QC is RES0,
97
+ * we can just fall through to the FPSCR_NZCV case.
98
+ */
99
case QEMU_VFP_FPSCR_NZCV:
100
/*
101
* Read just NZCV; this is a special case to avoid the
102
--
106
--
103
2.20.1
107
2.25.1
104
105
diff view generated by jsdifflib
1
Implement the new-in-v8.1M VLDR/VSTR variants which directly
1
From: Richard Henderson <richard.henderson@linaro.org>
2
read or write FP system registers to memory.
3
2
3
This function is not required by any other translation file.
4
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20220609202901.1177572-16-richard.henderson@linaro.org
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20201119215617.29887-10-peter.maydell@linaro.org
7
---
9
---
8
target/arm/vfp.decode | 14 ++++++
10
target/arm/translate.h | 8 --------
9
target/arm/translate-vfp.c.inc | 91 ++++++++++++++++++++++++++++++++++
11
target/arm/translate.c | 7 +++++++
10
2 files changed, 105 insertions(+)
12
2 files changed, 7 insertions(+), 8 deletions(-)
11
13
12
diff --git a/target/arm/vfp.decode b/target/arm/vfp.decode
14
diff --git a/target/arm/translate.h b/target/arm/translate.h
13
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/vfp.decode
16
--- a/target/arm/translate.h
15
+++ b/target/arm/vfp.decode
17
+++ b/target/arm/translate.h
16
@@ -XXX,XX +XXX,XX @@ VLDR_VSTR_hp ---- 1101 u:1 .0 l:1 rn:4 .... 1001 imm:8 vd=%vd_sp
18
@@ -XXX,XX +XXX,XX @@ static inline void gen_ss_advance(DisasContext *s)
17
VLDR_VSTR_sp ---- 1101 u:1 .0 l:1 rn:4 .... 1010 imm:8 vd=%vd_sp
19
}
18
VLDR_VSTR_dp ---- 1101 u:1 .0 l:1 rn:4 .... 1011 imm:8 vd=%vd_dp
20
}
19
21
20
+# M-profile VLDR/VSTR to sysreg
22
-static inline void gen_exception(int excp, uint32_t syndrome,
21
+%vldr_sysreg 22:1 13:3
23
- uint32_t target_el)
22
+%imm7_0x4 0:7 !function=times_4
24
-{
23
+
25
- gen_helper_exception_with_syndrome_el(cpu_env, tcg_constant_i32(excp),
24
+&vldr_sysreg rn reg imm a w p
26
- tcg_constant_i32(syndrome),
25
+@vldr_sysreg .... ... . a:1 . . . rn:4 ... . ... .. ....... \
27
- tcg_constant_i32(target_el));
26
+ reg=%vldr_sysreg imm=%imm7_0x4 &vldr_sysreg
28
-}
27
+
29
-
28
+# P=0 W=0 is SEE "Related encodings", so split into two patterns
30
/* Generate an architectural singlestep exception */
29
+VLDR_sysreg ---- 110 1 . . w:1 1 .... ... 0 111 11 ....... @vldr_sysreg p=1
31
static inline void gen_swstep_exception(DisasContext *s, int isv, int ex)
30
+VLDR_sysreg ---- 110 0 . . 1 1 .... ... 0 111 11 ....... @vldr_sysreg p=0 w=1
32
{
31
+VSTR_sysreg ---- 110 1 . . w:1 0 .... ... 0 111 11 ....... @vldr_sysreg p=1
33
diff --git a/target/arm/translate.c b/target/arm/translate.c
32
+VSTR_sysreg ---- 110 0 . . 1 0 .... ... 0 111 11 ....... @vldr_sysreg p=0 w=1
33
+
34
# We split the load/store multiple up into two patterns to avoid
35
# overlap with other insns in the "Advanced SIMD load/store and 64-bit move"
36
# grouping:
37
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
38
index XXXXXXX..XXXXXXX 100644
34
index XXXXXXX..XXXXXXX 100644
39
--- a/target/arm/translate-vfp.c.inc
35
--- a/target/arm/translate.c
40
+++ b/target/arm/translate-vfp.c.inc
36
+++ b/target/arm/translate.c
41
@@ -XXX,XX +XXX,XX @@ static bool trans_VMSR_VMRS(DisasContext *s, arg_VMSR_VMRS *a)
37
@@ -XXX,XX +XXX,XX @@ static void gen_exception_internal_insn(DisasContext *s, uint32_t pc, int excp)
42
return true;
38
s->base.is_jmp = DISAS_NORETURN;
43
}
39
}
44
40
45
+static void fp_sysreg_to_memory(DisasContext *s, void *opaque, TCGv_i32 value)
41
+static void gen_exception(int excp, uint32_t syndrome, uint32_t target_el)
46
+{
42
+{
47
+ arg_vldr_sysreg *a = opaque;
43
+ gen_helper_exception_with_syndrome_el(cpu_env, tcg_constant_i32(excp),
48
+ uint32_t offset = a->imm;
44
+ tcg_constant_i32(syndrome),
49
+ TCGv_i32 addr;
45
+ tcg_constant_i32(target_el));
50
+
51
+ if (!a->a) {
52
+ offset = - offset;
53
+ }
54
+
55
+ addr = load_reg(s, a->rn);
56
+ if (a->p) {
57
+ tcg_gen_addi_i32(addr, addr, offset);
58
+ }
59
+
60
+ if (s->v8m_stackcheck && a->rn == 13 && a->w) {
61
+ gen_helper_v8m_stackcheck(cpu_env, addr);
62
+ }
63
+
64
+ gen_aa32_st_i32(s, value, addr, get_mem_index(s),
65
+ MO_UL | MO_ALIGN | s->be_data);
66
+ tcg_temp_free_i32(value);
67
+
68
+ if (a->w) {
69
+ /* writeback */
70
+ if (!a->p) {
71
+ tcg_gen_addi_i32(addr, addr, offset);
72
+ }
73
+ store_reg(s, a->rn, addr);
74
+ } else {
75
+ tcg_temp_free_i32(addr);
76
+ }
77
+}
46
+}
78
+
47
+
79
+static TCGv_i32 memory_to_fp_sysreg(DisasContext *s, void *opaque)
48
static void gen_exception_insn_el_v(DisasContext *s, uint64_t pc, int excp,
80
+{
49
uint32_t syn, TCGv_i32 tcg_el)
81
+ arg_vldr_sysreg *a = opaque;
82
+ uint32_t offset = a->imm;
83
+ TCGv_i32 addr;
84
+ TCGv_i32 value = tcg_temp_new_i32();
85
+
86
+ if (!a->a) {
87
+ offset = - offset;
88
+ }
89
+
90
+ addr = load_reg(s, a->rn);
91
+ if (a->p) {
92
+ tcg_gen_addi_i32(addr, addr, offset);
93
+ }
94
+
95
+ if (s->v8m_stackcheck && a->rn == 13 && a->w) {
96
+ gen_helper_v8m_stackcheck(cpu_env, addr);
97
+ }
98
+
99
+ gen_aa32_ld_i32(s, value, addr, get_mem_index(s),
100
+ MO_UL | MO_ALIGN | s->be_data);
101
+
102
+ if (a->w) {
103
+ /* writeback */
104
+ if (!a->p) {
105
+ tcg_gen_addi_i32(addr, addr, offset);
106
+ }
107
+ store_reg(s, a->rn, addr);
108
+ } else {
109
+ tcg_temp_free_i32(addr);
110
+ }
111
+ return value;
112
+}
113
+
114
+static bool trans_VLDR_sysreg(DisasContext *s, arg_vldr_sysreg *a)
115
+{
116
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
117
+ return false;
118
+ }
119
+ if (a->rn == 15) {
120
+ return false;
121
+ }
122
+ return gen_M_fp_sysreg_write(s, a->reg, memory_to_fp_sysreg, a);
123
+}
124
+
125
+static bool trans_VSTR_sysreg(DisasContext *s, arg_vldr_sysreg *a)
126
+{
127
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
128
+ return false;
129
+ }
130
+ if (a->rn == 15) {
131
+ return false;
132
+ }
133
+ return gen_M_fp_sysreg_read(s, a->reg, fp_sysreg_to_memory, a);
134
+}
135
+
136
static bool trans_VMOV_half(DisasContext *s, arg_VMOV_single *a)
137
{
50
{
138
TCGv_i32 tmp;
139
--
51
--
140
2.20.1
52
2.25.1
141
142
diff view generated by jsdifflib
1
For M-profile before v8.1M, the only valid register for VMSR/VMRS is
1
From: Richard Henderson <richard.henderson@linaro.org>
2
the FPSCR. We have a comment that states this, but the actual logic
3
to forbid accesses for any other register value is missing, so we
4
would end up with A-profile style behaviour. Add the missing check.
5
2
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20220609202901.1177572-17-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: 20201119215617.29887-7-peter.maydell@linaro.org
9
---
7
---
10
target/arm/translate-vfp.c.inc | 5 ++++-
8
target/arm/translate.c | 18 +++++++++---------
11
1 file changed, 4 insertions(+), 1 deletion(-)
9
1 file changed, 9 insertions(+), 9 deletions(-)
12
10
13
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
11
diff --git a/target/arm/translate.c b/target/arm/translate.c
14
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/translate-vfp.c.inc
13
--- a/target/arm/translate.c
16
+++ b/target/arm/translate-vfp.c.inc
14
+++ b/target/arm/translate.c
17
@@ -XXX,XX +XXX,XX @@ static bool trans_VMSR_VMRS(DisasContext *s, arg_VMSR_VMRS *a)
15
@@ -XXX,XX +XXX,XX @@ static void gen_exception_internal_insn(DisasContext *s, uint32_t pc, int excp)
18
* Accesses to R15 are UNPREDICTABLE; we choose to undef.
16
s->base.is_jmp = DISAS_NORETURN;
19
* (FPSCR -> r15 is a special case which writes to the PSR flags.)
17
}
20
*/
18
21
- if (a->rt == 15 && (!a->l || a->reg != ARM_VFP_FPSCR)) {
19
-static void gen_exception(int excp, uint32_t syndrome, uint32_t target_el)
22
+ if (a->reg != ARM_VFP_FPSCR) {
20
+static void gen_exception_el(int excp, uint32_t syndrome, uint32_t target_el)
23
+ return false;
21
{
24
+ }
22
gen_helper_exception_with_syndrome_el(cpu_env, tcg_constant_i32(excp),
25
+ if (a->rt == 15 && !a->l) {
23
tcg_constant_i32(syndrome),
26
return false;
24
@@ -XXX,XX +XXX,XX @@ static void arm_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
25
switch (dc->base.is_jmp) {
26
case DISAS_SWI:
27
gen_ss_advance(dc);
28
- gen_exception(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb),
29
- default_exception_el(dc));
30
+ gen_exception_el(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb),
31
+ default_exception_el(dc));
32
break;
33
case DISAS_HVC:
34
gen_ss_advance(dc);
35
- gen_exception(EXCP_HVC, syn_aa32_hvc(dc->svc_imm), 2);
36
+ gen_exception_el(EXCP_HVC, syn_aa32_hvc(dc->svc_imm), 2);
37
break;
38
case DISAS_SMC:
39
gen_ss_advance(dc);
40
- gen_exception(EXCP_SMC, syn_aa32_smc(), 3);
41
+ gen_exception_el(EXCP_SMC, syn_aa32_smc(), 3);
42
break;
43
case DISAS_NEXT:
44
case DISAS_TOO_MANY:
45
@@ -XXX,XX +XXX,XX @@ static void arm_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
46
gen_helper_yield(cpu_env);
47
break;
48
case DISAS_SWI:
49
- gen_exception(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb),
50
- default_exception_el(dc));
51
+ gen_exception_el(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb),
52
+ default_exception_el(dc));
53
break;
54
case DISAS_HVC:
55
- gen_exception(EXCP_HVC, syn_aa32_hvc(dc->svc_imm), 2);
56
+ gen_exception_el(EXCP_HVC, syn_aa32_hvc(dc->svc_imm), 2);
57
break;
58
case DISAS_SMC:
59
- gen_exception(EXCP_SMC, syn_aa32_smc(), 3);
60
+ gen_exception_el(EXCP_SMC, syn_aa32_smc(), 3);
61
break;
27
}
62
}
28
}
63
}
29
--
64
--
30
2.20.1
65
2.25.1
31
32
diff view generated by jsdifflib
1
In v8.1M the new CLRM instruction allows zeroing an arbitrary set of
1
From: Richard Henderson <richard.henderson@linaro.org>
2
the general-purpose registers and APSR. Implement this.
3
2
4
The encoding is a subset of the LDMIA T2 encoding, using what would
3
Create a new wrapper function that passes the default
5
be Rn=0b1111 (which UNDEFs for LDMIA).
4
exception target to gen_exception_el.
6
5
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20220609202901.1177572-18-richard.henderson@linaro.org
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20201119215617.29887-6-peter.maydell@linaro.org
10
---
10
---
11
target/arm/t32.decode | 6 +++++-
11
target/arm/translate.c | 11 +++++++----
12
target/arm/translate.c | 38 ++++++++++++++++++++++++++++++++++++++
12
1 file changed, 7 insertions(+), 4 deletions(-)
13
2 files changed, 43 insertions(+), 1 deletion(-)
14
13
15
diff --git a/target/arm/t32.decode b/target/arm/t32.decode
16
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/t32.decode
18
+++ b/target/arm/t32.decode
19
@@ -XXX,XX +XXX,XX @@ UXTAB 1111 1010 0101 .... 1111 .... 10.. .... @rrr_rot
20
21
STM_t32 1110 1000 10.0 .... ................ @ldstm i=1 b=0
22
STM_t32 1110 1001 00.0 .... ................ @ldstm i=0 b=1
23
-LDM_t32 1110 1000 10.1 .... ................ @ldstm i=1 b=0
24
+{
25
+ # Rn=15 UNDEFs for LDM; M-profile CLRM uses that encoding
26
+ CLRM 1110 1000 1001 1111 list:16
27
+ LDM_t32 1110 1000 10.1 .... ................ @ldstm i=1 b=0
28
+}
29
LDM_t32 1110 1001 00.1 .... ................ @ldstm i=0 b=1
30
31
&rfe !extern rn w pu
32
diff --git a/target/arm/translate.c b/target/arm/translate.c
14
diff --git a/target/arm/translate.c b/target/arm/translate.c
33
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
34
--- a/target/arm/translate.c
16
--- a/target/arm/translate.c
35
+++ b/target/arm/translate.c
17
+++ b/target/arm/translate.c
36
@@ -XXX,XX +XXX,XX @@ static bool trans_LDM_t16(DisasContext *s, arg_ldst_block *a)
18
@@ -XXX,XX +XXX,XX @@ static void gen_exception_el(int excp, uint32_t syndrome, uint32_t target_el)
37
return do_ldm(s, a, 1);
19
tcg_constant_i32(target_el));
38
}
20
}
39
21
40
+static bool trans_CLRM(DisasContext *s, arg_CLRM *a)
22
+static void gen_exception(DisasContext *s, int excp, uint32_t syndrome)
41
+{
23
+{
42
+ int i;
24
+ gen_exception_el(excp, syndrome, default_exception_el(s));
43
+ TCGv_i32 zero;
44
+
45
+ if (!dc_isar_feature(aa32_m_sec_state, s)) {
46
+ return false;
47
+ }
48
+
49
+ if (extract32(a->list, 13, 1)) {
50
+ return false;
51
+ }
52
+
53
+ if (!a->list) {
54
+ /* UNPREDICTABLE; we choose to UNDEF */
55
+ return false;
56
+ }
57
+
58
+ zero = tcg_const_i32(0);
59
+ for (i = 0; i < 15; i++) {
60
+ if (extract32(a->list, i, 1)) {
61
+ /* Clear R[i] */
62
+ tcg_gen_mov_i32(cpu_R[i], zero);
63
+ }
64
+ }
65
+ if (extract32(a->list, 15, 1)) {
66
+ /*
67
+ * Clear APSR (by calling the MSR helper with the same argument
68
+ * as for "MSR APSR_nzcvqg, Rn": mask = 0b1100, SYSM=0)
69
+ */
70
+ TCGv_i32 maskreg = tcg_const_i32(0xc << 8);
71
+ gen_helper_v7m_msr(cpu_env, maskreg, zero);
72
+ tcg_temp_free_i32(maskreg);
73
+ }
74
+ tcg_temp_free_i32(zero);
75
+ return true;
76
+}
25
+}
77
+
26
+
78
/*
27
static void gen_exception_insn_el_v(DisasContext *s, uint64_t pc, int excp,
79
* Branch, branch with link
28
uint32_t syn, TCGv_i32 tcg_el)
80
*/
29
{
30
@@ -XXX,XX +XXX,XX @@ static void arm_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
31
switch (dc->base.is_jmp) {
32
case DISAS_SWI:
33
gen_ss_advance(dc);
34
- gen_exception_el(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb),
35
- default_exception_el(dc));
36
+ gen_exception(dc, EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb));
37
break;
38
case DISAS_HVC:
39
gen_ss_advance(dc);
40
@@ -XXX,XX +XXX,XX @@ static void arm_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
41
gen_helper_yield(cpu_env);
42
break;
43
case DISAS_SWI:
44
- gen_exception_el(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb),
45
- default_exception_el(dc));
46
+ gen_exception(dc, EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb));
47
break;
48
case DISAS_HVC:
49
gen_exception_el(EXCP_HVC, syn_aa32_hvc(dc->svc_imm), 2);
81
--
50
--
82
2.20.1
51
2.25.1
83
84
diff view generated by jsdifflib
1
Implement the v8.1M VSCCLRM insn, which zeros floating point
1
From: Richard Henderson <richard.henderson@linaro.org>
2
registers if there is an active floating point context.
3
This requires support in write_neon_element32() for the MO_32
4
element size, so add it.
5
2
6
Because we want to use arm_gen_condlabel(), we need to move
3
Split out a common helper function for gen_exception_el
7
the definition of that function up in translate.c so it is
4
and gen_exception_insn_el_v.
8
before the #include of translate-vfp.c.inc.
9
5
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20220609202901.1177572-19-richard.henderson@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20201119215617.29887-5-peter.maydell@linaro.org
13
---
10
---
14
target/arm/cpu.h | 9 ++++
11
target/arm/translate.c | 13 ++++++++-----
15
target/arm/m-nocp.decode | 8 +++-
12
1 file changed, 8 insertions(+), 5 deletions(-)
16
target/arm/translate.c | 21 +++++----
17
target/arm/translate-vfp.c.inc | 84 ++++++++++++++++++++++++++++++++++
18
4 files changed, 111 insertions(+), 11 deletions(-)
19
13
20
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
21
index XXXXXXX..XXXXXXX 100644
22
--- a/target/arm/cpu.h
23
+++ b/target/arm/cpu.h
24
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa32_mprofile(const ARMISARegisters *id)
25
return FIELD_EX32(id->id_pfr1, ID_PFR1, MPROGMOD) != 0;
26
}
27
28
+static inline bool isar_feature_aa32_m_sec_state(const ARMISARegisters *id)
29
+{
30
+ /*
31
+ * Return true if M-profile state handling insns
32
+ * (VSCCLRM, CLRM, FPCTX access insns) are implemented
33
+ */
34
+ return FIELD_EX32(id->id_pfr1, ID_PFR1, SECURITY) >= 3;
35
+}
36
+
37
static inline bool isar_feature_aa32_fp16_arith(const ARMISARegisters *id)
38
{
39
/* Sadly this is encoded differently for A-profile and M-profile */
40
diff --git a/target/arm/m-nocp.decode b/target/arm/m-nocp.decode
41
index XXXXXXX..XXXXXXX 100644
42
--- a/target/arm/m-nocp.decode
43
+++ b/target/arm/m-nocp.decode
44
@@ -XXX,XX +XXX,XX @@
45
# If the coprocessor is not present or disabled then we will generate
46
# the NOCP exception; otherwise we let the insn through to the main decode.
47
48
+%vd_dp 22:1 12:4
49
+%vd_sp 12:4 22:1
50
+
51
&nocp cp
52
53
{
54
# Special cases which do not take an early NOCP: VLLDM and VLSTM
55
VLLDM_VLSTM 1110 1100 001 l:1 rn:4 0000 1010 0000 0000
56
- # TODO: VSCCLRM (new in v8.1M) is similar:
57
- #VSCCLRM 1110 1100 1-01 1111 ---- 1011 ---- ---0
58
+ # VSCCLRM (new in v8.1M) is similar:
59
+ VSCCLRM 1110 1100 1.01 1111 .... 1011 imm:7 0 vd=%vd_dp size=3
60
+ VSCCLRM 1110 1100 1.01 1111 .... 1010 imm:8 vd=%vd_sp size=2
61
62
NOCP 111- 1110 ---- ---- ---- cp:4 ---- ---- &nocp
63
NOCP 111- 110- ---- ---- ---- cp:4 ---- ---- &nocp
64
diff --git a/target/arm/translate.c b/target/arm/translate.c
14
diff --git a/target/arm/translate.c b/target/arm/translate.c
65
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
66
--- a/target/arm/translate.c
16
--- a/target/arm/translate.c
67
+++ b/target/arm/translate.c
17
+++ b/target/arm/translate.c
68
@@ -XXX,XX +XXX,XX @@ void arm_translate_init(void)
18
@@ -XXX,XX +XXX,XX @@ static void gen_exception_internal_insn(DisasContext *s, uint32_t pc, int excp)
69
a64_translate_init();
19
s->base.is_jmp = DISAS_NORETURN;
70
}
20
}
71
21
72
+/* Generate a label used for skipping this instruction */
22
-static void gen_exception_el(int excp, uint32_t syndrome, uint32_t target_el)
73
+static void arm_gen_condlabel(DisasContext *s)
23
+static void gen_exception_el_v(int excp, uint32_t syndrome, TCGv_i32 tcg_el)
74
+{
24
{
75
+ if (!s->condjmp) {
25
gen_helper_exception_with_syndrome_el(cpu_env, tcg_constant_i32(excp),
76
+ s->condlabel = gen_new_label();
26
- tcg_constant_i32(syndrome),
77
+ s->condjmp = 1;
27
- tcg_constant_i32(target_el));
78
+ }
28
+ tcg_constant_i32(syndrome), tcg_el);
79
+}
29
+}
80
+
30
+
81
/* Flags for the disas_set_da_iss info argument:
31
+static void gen_exception_el(int excp, uint32_t syndrome, uint32_t target_el)
82
* lower bits hold the Rt register number, higher bits are flags.
32
+{
83
*/
33
+ gen_exception_el_v(excp, syndrome, tcg_constant_i32(target_el));
84
@@ -XXX,XX +XXX,XX @@ static void write_neon_element64(TCGv_i64 src, int reg, int ele, MemOp memop)
85
long off = neon_element_offset(reg, ele, memop);
86
87
switch (memop) {
88
+ case MO_32:
89
+ tcg_gen_st32_i64(src, cpu_env, off);
90
+ break;
91
case MO_64:
92
tcg_gen_st_i64(src, cpu_env, off);
93
break;
94
@@ -XXX,XX +XXX,XX @@ static void gen_srs(DisasContext *s,
95
s->base.is_jmp = DISAS_UPDATE_EXIT;
96
}
34
}
97
35
98
-/* Generate a label used for skipping this instruction */
36
static void gen_exception(DisasContext *s, int excp, uint32_t syndrome)
99
-static void arm_gen_condlabel(DisasContext *s)
37
@@ -XXX,XX +XXX,XX @@ static void gen_exception_insn_el_v(DisasContext *s, uint64_t pc, int excp,
100
-{
38
gen_set_condexec(s);
101
- if (!s->condjmp) {
39
gen_set_pc_im(s, pc);
102
- s->condlabel = gen_new_label();
40
}
103
- s->condjmp = 1;
41
- gen_helper_exception_with_syndrome_el(cpu_env, tcg_constant_i32(excp),
104
- }
42
- tcg_constant_i32(syn), tcg_el);
105
-}
43
+ gen_exception_el_v(excp, syn, tcg_el);
106
-
44
s->base.is_jmp = DISAS_NORETURN;
107
/* Skip this instruction if the ARM condition is false */
108
static void arm_skip_unless(DisasContext *s, uint32_t cond)
109
{
110
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
111
index XXXXXXX..XXXXXXX 100644
112
--- a/target/arm/translate-vfp.c.inc
113
+++ b/target/arm/translate-vfp.c.inc
114
@@ -XXX,XX +XXX,XX @@ static bool trans_VLLDM_VLSTM(DisasContext *s, arg_VLLDM_VLSTM *a)
115
return true;
116
}
45
}
117
46
118
+static bool trans_VSCCLRM(DisasContext *s, arg_VSCCLRM *a)
119
+{
120
+ int btmreg, topreg;
121
+ TCGv_i64 zero;
122
+ TCGv_i32 aspen, sfpa;
123
+
124
+ if (!dc_isar_feature(aa32_m_sec_state, s)) {
125
+ /* Before v8.1M, fall through in decode to NOCP check */
126
+ return false;
127
+ }
128
+
129
+ /* Explicitly UNDEF because this takes precedence over NOCP */
130
+ if (!arm_dc_feature(s, ARM_FEATURE_M_MAIN) || !s->v8m_secure) {
131
+ unallocated_encoding(s);
132
+ return true;
133
+ }
134
+
135
+ if (!dc_isar_feature(aa32_vfp_simd, s)) {
136
+ /* NOP if we have neither FP nor MVE */
137
+ return true;
138
+ }
139
+
140
+ /*
141
+ * If FPCCR.ASPEN != 0 && CONTROL_S.SFPA == 0 then there is no
142
+ * active floating point context so we must NOP (without doing
143
+ * any lazy state preservation or the NOCP check).
144
+ */
145
+ aspen = load_cpu_field(v7m.fpccr[M_REG_S]);
146
+ sfpa = load_cpu_field(v7m.control[M_REG_S]);
147
+ tcg_gen_andi_i32(aspen, aspen, R_V7M_FPCCR_ASPEN_MASK);
148
+ tcg_gen_xori_i32(aspen, aspen, R_V7M_FPCCR_ASPEN_MASK);
149
+ tcg_gen_andi_i32(sfpa, sfpa, R_V7M_CONTROL_SFPA_MASK);
150
+ tcg_gen_or_i32(sfpa, sfpa, aspen);
151
+ arm_gen_condlabel(s);
152
+ tcg_gen_brcondi_i32(TCG_COND_EQ, sfpa, 0, s->condlabel);
153
+
154
+ if (s->fp_excp_el != 0) {
155
+ gen_exception_insn(s, s->pc_curr, EXCP_NOCP,
156
+ syn_uncategorized(), s->fp_excp_el);
157
+ return true;
158
+ }
159
+
160
+ topreg = a->vd + a->imm - 1;
161
+ btmreg = a->vd;
162
+
163
+ /* Convert to Sreg numbers if the insn specified in Dregs */
164
+ if (a->size == 3) {
165
+ topreg = topreg * 2 + 1;
166
+ btmreg *= 2;
167
+ }
168
+
169
+ if (topreg > 63 || (topreg > 31 && !(topreg & 1))) {
170
+ /* UNPREDICTABLE: we choose to undef */
171
+ unallocated_encoding(s);
172
+ return true;
173
+ }
174
+
175
+ /* Silently ignore requests to clear D16-D31 if they don't exist */
176
+ if (topreg > 31 && !dc_isar_feature(aa32_simd_r32, s)) {
177
+ topreg = 31;
178
+ }
179
+
180
+ if (!vfp_access_check(s)) {
181
+ return true;
182
+ }
183
+
184
+ /* Zero the Sregs from btmreg to topreg inclusive. */
185
+ zero = tcg_const_i64(0);
186
+ if (btmreg & 1) {
187
+ write_neon_element64(zero, btmreg >> 1, 1, MO_32);
188
+ btmreg++;
189
+ }
190
+ for (; btmreg + 1 <= topreg; btmreg += 2) {
191
+ write_neon_element64(zero, btmreg >> 1, 0, MO_64);
192
+ }
193
+ if (btmreg == topreg) {
194
+ write_neon_element64(zero, btmreg >> 1, 0, MO_32);
195
+ btmreg++;
196
+ }
197
+ assert(btmreg == topreg + 1);
198
+ /* TODO: when MVE is implemented, zero VPR here */
199
+ return true;
200
+}
201
+
202
static bool trans_NOCP(DisasContext *s, arg_nocp *a)
203
{
204
/*
205
--
47
--
206
2.20.1
48
2.25.1
207
208
diff view generated by jsdifflib
1
From: Havard Skinnemoen <hskinnemoen@google.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Dump the collected random data after a randomness test failure.
3
With the helper we can use exception_target_el at runtime,
4
instead of default_exception_el at translate time.
5
While we're at it, remove the DisasContext parameter from
6
gen_exception, as it is no longer used.
4
7
5
Note that this relies on the test having called
6
g_test_set_nonfatal_assertions() so we don't abort immediately on the
7
assertion failure.
8
9
Signed-off-by: Havard Skinnemoen <hskinnemoen@google.com>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
[PMM: minor commit message tweak]
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20220609202901.1177572-20-richard.henderson@linaro.org
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
12
---
14
tests/qtest/npcm7xx_rng-test.c | 12 ++++++++++++
13
target/arm/helper.h | 1 +
15
1 file changed, 12 insertions(+)
14
target/arm/op_helper.c | 10 ++++++++++
15
target/arm/translate.c | 18 +++++++++++++-----
16
3 files changed, 24 insertions(+), 5 deletions(-)
16
17
17
diff --git a/tests/qtest/npcm7xx_rng-test.c b/tests/qtest/npcm7xx_rng-test.c
18
diff --git a/target/arm/helper.h b/target/arm/helper.h
18
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
19
--- a/tests/qtest/npcm7xx_rng-test.c
20
--- a/target/arm/helper.h
20
+++ b/tests/qtest/npcm7xx_rng-test.c
21
+++ b/target/arm/helper.h
21
@@ -XXX,XX +XXX,XX @@
22
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_2(usad8, TCG_CALL_NO_RWG_SE, i32, i32, i32)
22
23
DEF_HELPER_FLAGS_3(sel_flags, TCG_CALL_NO_RWG_SE,
23
#include "libqtest-single.h"
24
i32, i32, i32, i32)
24
#include "qemu/bitops.h"
25
DEF_HELPER_2(exception_internal, noreturn, env, i32)
25
+#include "qemu-common.h"
26
+DEF_HELPER_3(exception_with_syndrome, noreturn, env, i32, i32)
26
27
DEF_HELPER_4(exception_with_syndrome_el, noreturn, env, i32, i32, i32)
27
#define RNG_BASE_ADDR 0xf000b000
28
DEF_HELPER_2(exception_bkpt_insn, noreturn, env, i32)
28
29
DEF_HELPER_2(exception_swstep, noreturn, env, i32)
29
@@ -XXX,XX +XXX,XX @@
30
diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c
30
/* Number of bits to collect for randomness tests. */
31
index XXXXXXX..XXXXXXX 100644
31
#define TEST_INPUT_BITS (128)
32
--- a/target/arm/op_helper.c
32
33
+++ b/target/arm/op_helper.c
33
+static void dump_buf_if_failed(const uint8_t *buf, size_t size)
34
@@ -XXX,XX +XXX,XX @@ void HELPER(exception_with_syndrome_el)(CPUARMState *env, uint32_t excp,
35
raise_exception(env, excp, syndrome, target_el);
36
}
37
38
+/*
39
+ * Raise an exception with the specified syndrome register value
40
+ * to the default target el.
41
+ */
42
+void HELPER(exception_with_syndrome)(CPUARMState *env, uint32_t excp,
43
+ uint32_t syndrome)
34
+{
44
+{
35
+ if (g_test_failed()) {
45
+ raise_exception(env, excp, syndrome, exception_target_el(env));
36
+ qemu_hexdump(stderr, "", buf, size);
37
+ }
38
+}
46
+}
39
+
47
+
40
static void rng_writeb(unsigned int offset, uint8_t value)
48
uint32_t HELPER(cpsr_read)(CPUARMState *env)
41
{
49
{
42
writeb(RNG_BASE_ADDR + offset, value);
50
return cpsr_read(env) & ~CPSR_EXEC;
43
@@ -XXX,XX +XXX,XX @@ static void test_continuous_monobit(void)
51
diff --git a/target/arm/translate.c b/target/arm/translate.c
44
}
52
index XXXXXXX..XXXXXXX 100644
45
53
--- a/target/arm/translate.c
46
g_assert_cmpfloat(calc_monobit_p(buf, sizeof(buf)), >, 0.01);
54
+++ b/target/arm/translate.c
47
+ dump_buf_if_failed(buf, sizeof(buf));
55
@@ -XXX,XX +XXX,XX @@ static void gen_exception_el(int excp, uint32_t syndrome, uint32_t target_el)
56
gen_exception_el_v(excp, syndrome, tcg_constant_i32(target_el));
48
}
57
}
49
58
50
/*
59
-static void gen_exception(DisasContext *s, int excp, uint32_t syndrome)
51
@@ -XXX,XX +XXX,XX @@ static void test_continuous_runs(void)
60
+static void gen_exception(int excp, uint32_t syndrome)
52
}
61
{
53
62
- gen_exception_el(excp, syndrome, default_exception_el(s));
54
g_assert_cmpfloat(calc_runs_p(buf.l, sizeof(buf) * BITS_PER_BYTE), >, 0.01);
63
+ gen_helper_exception_with_syndrome(cpu_env, tcg_constant_i32(excp),
55
+ dump_buf_if_failed(buf.c, sizeof(buf));
64
+ tcg_constant_i32(syndrome));
56
}
65
}
57
66
58
/*
67
static void gen_exception_insn_el_v(DisasContext *s, uint64_t pc, int excp,
59
@@ -XXX,XX +XXX,XX @@ static void test_first_byte_monobit(void)
68
@@ -XXX,XX +XXX,XX @@ void gen_exception_insn_el(DisasContext *s, uint64_t pc, int excp,
60
}
69
61
70
void gen_exception_insn(DisasContext *s, uint64_t pc, int excp, uint32_t syn)
62
g_assert_cmpfloat(calc_monobit_p(buf, sizeof(buf)), >, 0.01);
71
{
63
+ dump_buf_if_failed(buf, sizeof(buf));
72
- gen_exception_insn_el(s, pc, excp, syn, default_exception_el(s));
73
+ if (s->aarch64) {
74
+ gen_a64_set_pc_im(pc);
75
+ } else {
76
+ gen_set_condexec(s);
77
+ gen_set_pc_im(s, pc);
78
+ }
79
+ gen_exception(excp, syn);
80
+ s->base.is_jmp = DISAS_NORETURN;
64
}
81
}
65
82
66
/*
83
static void gen_exception_bkpt_insn(DisasContext *s, uint32_t syn)
67
@@ -XXX,XX +XXX,XX @@ static void test_first_byte_runs(void)
84
@@ -XXX,XX +XXX,XX @@ static void arm_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
68
}
85
switch (dc->base.is_jmp) {
69
86
case DISAS_SWI:
70
g_assert_cmpfloat(calc_runs_p(buf.l, sizeof(buf) * BITS_PER_BYTE), >, 0.01);
87
gen_ss_advance(dc);
71
+ dump_buf_if_failed(buf.c, sizeof(buf));
88
- gen_exception(dc, EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb));
72
}
89
+ gen_exception(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb));
73
90
break;
74
int main(int argc, char **argv)
91
case DISAS_HVC:
92
gen_ss_advance(dc);
93
@@ -XXX,XX +XXX,XX @@ static void arm_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
94
gen_helper_yield(cpu_env);
95
break;
96
case DISAS_SWI:
97
- gen_exception(dc, EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb));
98
+ gen_exception(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb));
99
break;
100
case DISAS_HVC:
101
gen_exception_el(EXCP_HVC, syn_aa32_hvc(dc->svc_imm), 2);
75
--
102
--
76
2.20.1
103
2.25.1
77
78
diff view generated by jsdifflib
1
From: Kunkun Jiang <jiangkunkun@huawei.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Accroding to the SMMUv3 spec, the SPAN field of Level1 Stream Table
3
This function is no longer used. At the same time, remove
4
Descriptor is 5 bits([4:0]).
4
DisasContext.secure_routed_to_el3, as it in turn becomes unused.
5
5
6
Fixes: 9bde7f0674f(hw/arm/smmuv3: Implement translate callback)
7
Signed-off-by: Kunkun Jiang <jiangkunkun@huawei.com>
8
Message-id: 20201124023711.1184-1-jiangkunkun@huawei.com
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Acked-by: Eric Auger <eric.auger@redhat.com>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20220609202901.1177572-21-richard.henderson@linaro.org
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
10
---
13
hw/arm/smmuv3-internal.h | 2 +-
11
target/arm/translate.h | 16 ----------------
14
1 file changed, 1 insertion(+), 1 deletion(-)
12
target/arm/translate-a64.c | 5 -----
13
target/arm/translate.c | 5 -----
14
3 files changed, 26 deletions(-)
15
15
16
diff --git a/hw/arm/smmuv3-internal.h b/hw/arm/smmuv3-internal.h
16
diff --git a/target/arm/translate.h b/target/arm/translate.h
17
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/arm/smmuv3-internal.h
18
--- a/target/arm/translate.h
19
+++ b/hw/arm/smmuv3-internal.h
19
+++ b/target/arm/translate.h
20
@@ -XXX,XX +XXX,XX @@ static inline uint64_t l1std_l2ptr(STEDesc *desc)
20
@@ -XXX,XX +XXX,XX @@ typedef struct DisasContext {
21
return hi << 32 | lo;
21
int fp_excp_el; /* FP exception EL or 0 if enabled */
22
int sve_excp_el; /* SVE exception EL or 0 if enabled */
23
int vl; /* current vector length in bytes */
24
- /* Flag indicating that exceptions from secure mode are routed to EL3. */
25
- bool secure_routed_to_el3;
26
bool vfp_enabled; /* FP enabled via FPSCR.EN */
27
int vec_len;
28
int vec_stride;
29
@@ -XXX,XX +XXX,XX @@ static inline int get_mem_index(DisasContext *s)
30
return arm_to_core_mmu_idx(s->mmu_idx);
22
}
31
}
23
32
24
-#define L1STD_SPAN(stm) (extract32((stm)->word[0], 0, 4))
33
-/* Function used to determine the target exception EL when otherwise not known
25
+#define L1STD_SPAN(stm) (extract32((stm)->word[0], 0, 5))
34
- * or default.
26
35
- */
27
#endif
36
-static inline int default_exception_el(DisasContext *s)
37
-{
38
- /* If we are coming from secure EL0 in a system with a 32-bit EL3, then
39
- * there is no secure EL1, so we route exceptions to EL3. Otherwise,
40
- * exceptions can only be routed to ELs above 1, so we target the higher of
41
- * 1 or the current EL.
42
- */
43
- return (s->mmu_idx == ARMMMUIdx_SE10_0 && s->secure_routed_to_el3)
44
- ? 3 : MAX(1, s->current_el);
45
-}
46
-
47
static inline void disas_set_insn_syndrome(DisasContext *s, uint32_t syn)
48
{
49
/* We don't need to save all of the syndrome so we mask and shift
50
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
51
index XXXXXXX..XXXXXXX 100644
52
--- a/target/arm/translate-a64.c
53
+++ b/target/arm/translate-a64.c
54
@@ -XXX,XX +XXX,XX @@ static void aarch64_tr_init_disas_context(DisasContextBase *dcbase,
55
dc->condjmp = 0;
56
57
dc->aarch64 = true;
58
- /* If we are coming from secure EL0 in a system with a 32-bit EL3, then
59
- * there is no secure EL1, so we route exceptions to EL3.
60
- */
61
- dc->secure_routed_to_el3 = arm_feature(env, ARM_FEATURE_EL3) &&
62
- !arm_el_is_aa64(env, 3);
63
dc->thumb = false;
64
dc->sctlr_b = 0;
65
dc->be_data = EX_TBFLAG_ANY(tb_flags, BE_DATA) ? MO_BE : MO_LE;
66
diff --git a/target/arm/translate.c b/target/arm/translate.c
67
index XXXXXXX..XXXXXXX 100644
68
--- a/target/arm/translate.c
69
+++ b/target/arm/translate.c
70
@@ -XXX,XX +XXX,XX @@ static void arm_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
71
dc->condjmp = 0;
72
73
dc->aarch64 = false;
74
- /* If we are coming from secure EL0 in a system with a 32-bit EL3, then
75
- * there is no secure EL1, so we route exceptions to EL3.
76
- */
77
- dc->secure_routed_to_el3 = arm_feature(env, ARM_FEATURE_EL3) &&
78
- !arm_el_is_aa64(env, 3);
79
dc->thumb = EX_TBFLAG_AM32(tb_flags, THUMB);
80
dc->be_data = EX_TBFLAG_ANY(tb_flags, BE_DATA) ? MO_BE : MO_LE;
81
condexec = EX_TBFLAG_AM32(tb_flags, CONDEXEC);
28
--
82
--
29
2.20.1
83
2.25.1
30
31
diff view generated by jsdifflib
Deleted patch
1
From: Vikram Garhwal <fnu.vikram@xilinx.com>
2
1
3
Reviewed-by: Francisco Iglesias <francisco.iglesias@xilinx.com>
4
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
5
Signed-off-by: Vikram Garhwal <fnu.vikram@xilinx.com>
6
Message-id: 1605728926-352690-5-git-send-email-fnu.vikram@xilinx.com
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
---
9
MAINTAINERS | 8 ++++++++
10
1 file changed, 8 insertions(+)
11
12
diff --git a/MAINTAINERS b/MAINTAINERS
13
index XXXXXXX..XXXXXXX 100644
14
--- a/MAINTAINERS
15
+++ b/MAINTAINERS
16
@@ -XXX,XX +XXX,XX @@ F: hw/net/opencores_eth.c
17
18
Devices
19
-------
20
+Xilinx CAN
21
+M: Vikram Garhwal <fnu.vikram@xilinx.com>
22
+M: Francisco Iglesias <francisco.iglesias@xilinx.com>
23
+S: Maintained
24
+F: hw/net/can/xlnx-*
25
+F: include/hw/net/xlnx-*
26
+F: tests/qtest/xlnx-can-test*
27
+
28
EDU
29
M: Jiri Slaby <jslaby@suse.cz>
30
S: Maintained
31
--
32
2.20.1
33
34
diff view generated by jsdifflib
Deleted patch
1
From: Alex Chen <alex.chen@huawei.com>
2
1
3
We should use printf format specifier "%u" instead of "%d" for
4
argument of type "unsigned int".
5
6
Reported-by: Euler Robot <euler.robot@huawei.com>
7
Signed-off-by: Alex Chen <alex.chen@huawei.com>
8
Message-id: 20201126111109.112238-2-alex.chen@huawei.com
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
hw/misc/imx25_ccm.c | 12 ++++++------
13
1 file changed, 6 insertions(+), 6 deletions(-)
14
15
diff --git a/hw/misc/imx25_ccm.c b/hw/misc/imx25_ccm.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/misc/imx25_ccm.c
18
+++ b/hw/misc/imx25_ccm.c
19
@@ -XXX,XX +XXX,XX @@ static const char *imx25_ccm_reg_name(uint32_t reg)
20
case IMX25_CCM_LPIMR1_REG:
21
return "lpimr1";
22
default:
23
- sprintf(unknown, "[%d ?]", reg);
24
+ sprintf(unknown, "[%u ?]", reg);
25
return unknown;
26
}
27
}
28
@@ -XXX,XX +XXX,XX @@ static uint32_t imx25_ccm_get_mpll_clk(IMXCCMState *dev)
29
freq = imx_ccm_calc_pll(s->reg[IMX25_CCM_MPCTL_REG], CKIH_FREQ);
30
}
31
32
- DPRINTF("freq = %d\n", freq);
33
+ DPRINTF("freq = %u\n", freq);
34
35
return freq;
36
}
37
@@ -XXX,XX +XXX,XX @@ static uint32_t imx25_ccm_get_mcu_clk(IMXCCMState *dev)
38
39
freq = freq / (1 + EXTRACT(s->reg[IMX25_CCM_CCTL_REG], ARM_CLK_DIV));
40
41
- DPRINTF("freq = %d\n", freq);
42
+ DPRINTF("freq = %u\n", freq);
43
44
return freq;
45
}
46
@@ -XXX,XX +XXX,XX @@ static uint32_t imx25_ccm_get_ahb_clk(IMXCCMState *dev)
47
freq = imx25_ccm_get_mcu_clk(dev)
48
/ (1 + EXTRACT(s->reg[IMX25_CCM_CCTL_REG], AHB_CLK_DIV));
49
50
- DPRINTF("freq = %d\n", freq);
51
+ DPRINTF("freq = %u\n", freq);
52
53
return freq;
54
}
55
@@ -XXX,XX +XXX,XX @@ static uint32_t imx25_ccm_get_ipg_clk(IMXCCMState *dev)
56
57
freq = imx25_ccm_get_ahb_clk(dev) / 2;
58
59
- DPRINTF("freq = %d\n", freq);
60
+ DPRINTF("freq = %u\n", freq);
61
62
return freq;
63
}
64
@@ -XXX,XX +XXX,XX @@ static uint32_t imx25_ccm_get_clock_frequency(IMXCCMState *dev, IMXClk clock)
65
break;
66
}
67
68
- DPRINTF("Clock = %d) = %d\n", clock, freq);
69
+ DPRINTF("Clock = %d) = %u\n", clock, freq);
70
71
return freq;
72
}
73
--
74
2.20.1
75
76
diff view generated by jsdifflib
1
In commit 077d7449100d824a4 we added code to handle the v8M
1
From: Richard Henderson <richard.henderson@linaro.org>
2
requirement that returns from NMI or HardFault forcibly deactivate
3
those exceptions regardless of what interrupt the guest is trying to
4
deactivate. Unfortunately this broke the handling of the "illegal
5
exception return because the returning exception number is not
6
active" check for those cases. In the pseudocode this test is done
7
on the exception the guest asks to return from, but because our
8
implementation was doing this in armv7m_nvic_complete_irq() after the
9
new "deactivate NMI/HardFault regardless" code we ended up doing the
10
test on the VecInfo for that exception instead, which usually meant
11
failing to raise the illegal exception return fault.
12
2
13
In the case for "configurable exception targeting the opposite
3
Handle the debug vs current el exception test in one place.
14
security state" we detected the illegal-return case but went ahead
4
Leave EXCP_BKPT alone, since that treats debug < current differently.
15
and deactivated the VecInfo anyway, which is wrong because that is
16
the VecInfo for the other security state.
17
5
18
Rearrange the code so that we first identify the illegal return
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
19
cases, then see if we really need to deactivate NMI or HardFault
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
20
instead, and finally do the deactivation.
8
Message-id: 20220609202901.1177572-22-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
target/arm/debug_helper.c | 44 +++++++++++++++++++++------------------
12
1 file changed, 24 insertions(+), 20 deletions(-)
21
13
22
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
diff --git a/target/arm/debug_helper.c b/target/arm/debug_helper.c
23
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
24
Message-id: 20201119215617.29887-25-peter.maydell@linaro.org
25
---
26
hw/intc/armv7m_nvic.c | 59 +++++++++++++++++++++++--------------------
27
1 file changed, 32 insertions(+), 27 deletions(-)
28
29
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
30
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
31
--- a/hw/intc/armv7m_nvic.c
16
--- a/target/arm/debug_helper.c
32
+++ b/hw/intc/armv7m_nvic.c
17
+++ b/target/arm/debug_helper.c
33
@@ -XXX,XX +XXX,XX @@ int armv7m_nvic_complete_irq(void *opaque, int irq, bool secure)
18
@@ -XXX,XX +XXX,XX @@
34
{
19
#include "exec/helper-proto.h"
35
NVICState *s = (NVICState *)opaque;
20
36
VecInfo *vec = NULL;
21
37
- int ret;
22
+/*
38
+ int ret = 0;
23
+ * Raise an exception to the debug target el.
39
24
+ * Modify syndrome to indicate when origin and target EL are the same.
40
assert(irq > ARMV7M_EXCP_RESET && irq < s->num_irq);
25
+ */
41
26
+G_NORETURN static void
42
+ trace_nvic_complete_irq(irq, secure);
27
+raise_exception_debug(CPUARMState *env, uint32_t excp, uint32_t syndrome)
43
+
28
+{
44
+ if (secure && exc_is_banked(irq)) {
29
+ int debug_el = arm_debug_target_el(env);
45
+ vec = &s->sec_vectors[irq];
30
+ int cur_el = arm_current_el(env);
46
+ } else {
47
+ vec = &s->vectors[irq];
48
+ }
49
+
31
+
50
+ /*
32
+ /*
51
+ * Identify illegal exception return cases. We can't immediately
33
+ * If singlestep is targeting a lower EL than the current one, then
52
+ * return at this point because we still need to deactivate
34
+ * DisasContext.ss_active must be false and we can never get here.
53
+ * (either this exception or NMI/HardFault) first.
35
+ * Similarly for watchpoint and breakpoint matches.
54
+ */
36
+ */
55
+ if (!exc_is_banked(irq) && exc_targets_secure(s, irq) != secure) {
37
+ assert(debug_el >= cur_el);
56
+ /*
38
+ syndrome |= (debug_el == cur_el) << ARM_EL_EC_SHIFT;
57
+ * Return from a configurable exception targeting the opposite
39
+ raise_exception(env, excp, syndrome, debug_el);
58
+ * security state from the one we're trying to complete it for.
40
+}
59
+ * Clear vec because it's not really the VecInfo for this
60
+ * (irq, secstate) so we mustn't deactivate it.
61
+ */
62
+ ret = -1;
63
+ vec = NULL;
64
+ } else if (!vec->active) {
65
+ /* Return from an inactive interrupt */
66
+ ret = -1;
67
+ } else {
68
+ /* Legal return, we will return the RETTOBASE bit value to the caller */
69
+ ret = nvic_rettobase(s);
70
+ }
71
+
41
+
72
/*
42
/* See AArch64.GenerateDebugExceptionsFrom() in ARM ARM pseudocode */
73
* For negative priorities, v8M will forcibly deactivate the appropriate
43
static bool aa64_generate_debug_exceptions(CPUARMState *env)
74
* NMI or HardFault regardless of what interrupt we're being asked to
44
{
75
@@ -XXX,XX +XXX,XX @@ int armv7m_nvic_complete_irq(void *opaque, int irq, bool secure)
45
@@ -XXX,XX +XXX,XX @@ void arm_debug_excp_handler(CPUState *cs)
46
if (wp_hit) {
47
if (wp_hit->flags & BP_CPU) {
48
bool wnr = (wp_hit->flags & BP_WATCHPOINT_HIT_WRITE) != 0;
49
- bool same_el = arm_debug_target_el(env) == arm_current_el(env);
50
51
cs->watchpoint_hit = NULL;
52
53
env->exception.fsr = arm_debug_exception_fsr(env);
54
env->exception.vaddress = wp_hit->hitaddr;
55
- raise_exception(env, EXCP_DATA_ABORT,
56
- syn_watchpoint(same_el, 0, wnr),
57
- arm_debug_target_el(env));
58
+ raise_exception_debug(env, EXCP_DATA_ABORT,
59
+ syn_watchpoint(0, 0, wnr));
60
}
61
} else {
62
uint64_t pc = is_a64(env) ? env->pc : env->regs[15];
63
- bool same_el = (arm_debug_target_el(env) == arm_current_el(env));
64
65
/*
66
* (1) GDB breakpoints should be handled first.
67
@@ -XXX,XX +XXX,XX @@ void arm_debug_excp_handler(CPUState *cs)
68
* exception/security level.
69
*/
70
env->exception.vaddress = 0;
71
- raise_exception(env, EXCP_PREFETCH_ABORT,
72
- syn_breakpoint(same_el),
73
- arm_debug_target_el(env));
74
+ raise_exception_debug(env, EXCP_PREFETCH_ABORT, syn_breakpoint(0));
76
}
75
}
77
76
}
78
if (!vec) {
77
79
- if (secure && exc_is_banked(irq)) {
78
@@ -XXX,XX +XXX,XX @@ void HELPER(exception_bkpt_insn)(CPUARMState *env, uint32_t syndrome)
80
- vec = &s->sec_vectors[irq];
79
81
- } else {
80
void HELPER(exception_swstep)(CPUARMState *env, uint32_t syndrome)
82
- vec = &s->vectors[irq];
81
{
83
- }
82
- int debug_el = arm_debug_target_el(env);
84
- }
83
- int cur_el = arm_current_el(env);
85
-
86
- trace_nvic_complete_irq(irq, secure);
87
-
88
- if (!vec->active) {
89
- /* Tell the caller this was an illegal exception return */
90
- return -1;
91
- }
92
-
84
-
93
- /*
85
- /*
94
- * If this is a configurable exception and it is currently
86
- * If singlestep is targeting a lower EL than the current one, then
95
- * targeting the opposite security state from the one we're trying
87
- * DisasContext.ss_active must be false and we can never get here.
96
- * to complete it for, this counts as an illegal exception return.
97
- * We still need to deactivate whatever vector the logic above has
98
- * selected, though, as it might not be the same as the one for the
99
- * requested exception number.
100
- */
88
- */
101
- if (!exc_is_banked(irq) && exc_targets_secure(s, irq) != secure) {
89
- assert(debug_el >= cur_el);
102
- ret = -1;
90
- if (debug_el == cur_el) {
103
- } else {
91
- syndrome |= 1 << ARM_EL_EC_SHIFT;
104
- ret = nvic_rettobase(s);
92
- }
105
+ return ret;
93
- raise_exception(env, EXCP_UDEF, syndrome, debug_el);
106
}
94
+ raise_exception_debug(env, EXCP_UDEF, syndrome);
107
95
}
108
vec->active = 0;
96
97
#if !defined(CONFIG_USER_ONLY)
109
--
98
--
110
2.20.1
99
2.25.1
111
112
diff view generated by jsdifflib
1
Currently M-profile borrows the A-profile code for VMSR and VMRS
1
From: Richard Henderson <richard.henderson@linaro.org>
2
(access to the FP system registers), because all it needs to support
3
is the FPSCR. In v8.1M things become significantly more complicated
4
in two ways:
5
2
6
* there are several new FP system registers; some have side effects
3
This function is no longer used outside debug_helper.c.
7
on read, and one (FPCXT_NS) needs to avoid the usual
8
vfp_access_check() and the "only if FPU implemented" check
9
4
10
* all sysregs are now accessible both by VMRS/VMSR (which
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
reads/writes a general purpose register) and also by VLDR/VSTR
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
12
(which reads/writes them directly to memory)
7
Message-id: 20220609202901.1177572-23-richard.henderson@linaro.org
13
14
Refactor the structure of how we handle VMSR/VMRS to cope with this:
15
16
* keep the M-profile code entirely separate from the A-profile code
17
18
* abstract out the "read or write the general purpose register" part
19
of the code into a loadfn or storefn function pointer, so we can
20
reuse it for VLDR/VSTR.
21
22
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
23
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
24
Message-id: 20201119215617.29887-8-peter.maydell@linaro.org
25
---
9
---
26
target/arm/cpu.h | 3 +
10
target/arm/cpu.h | 21 ---------------------
27
target/arm/translate-vfp.c.inc | 182 ++++++++++++++++++++++++++++++---
11
target/arm/debug_helper.c | 21 +++++++++++++++++++++
28
2 files changed, 171 insertions(+), 14 deletions(-)
12
2 files changed, 21 insertions(+), 21 deletions(-)
29
13
30
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
14
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
31
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
32
--- a/target/arm/cpu.h
16
--- a/target/arm/cpu.h
33
+++ b/target/arm/cpu.h
17
+++ b/target/arm/cpu.h
34
@@ -XXX,XX +XXX,XX @@ enum arm_cpu_mode {
18
@@ -XXX,XX +XXX,XX @@ typedef enum ARMASIdx {
35
#define ARM_VFP_FPINST 9
19
ARMASIdx_TagS = 3,
36
#define ARM_VFP_FPINST2 10
20
} ARMASIdx;
37
21
38
+/* QEMU-internal value meaning "FPSCR, but we care only about NZCV" */
22
-/* Return the Exception Level targeted by debug exceptions. */
39
+#define QEMU_VFP_FPSCR_NZCV 0xffff
23
-static inline int arm_debug_target_el(CPUARMState *env)
24
-{
25
- bool secure = arm_is_secure(env);
26
- bool route_to_el2 = false;
27
-
28
- if (arm_is_el2_enabled(env)) {
29
- route_to_el2 = env->cp15.hcr_el2 & HCR_TGE ||
30
- env->cp15.mdcr_el2 & MDCR_TDE;
31
- }
32
-
33
- if (route_to_el2) {
34
- return 2;
35
- } else if (arm_feature(env, ARM_FEATURE_EL3) &&
36
- !arm_el_is_aa64(env, 3) && secure) {
37
- return 3;
38
- } else {
39
- return 1;
40
- }
41
-}
42
-
43
static inline bool arm_v7m_csselr_razwi(ARMCPU *cpu)
44
{
45
/* If all the CLIDR.Ctypem bits are 0 there are no caches, and
46
diff --git a/target/arm/debug_helper.c b/target/arm/debug_helper.c
47
index XXXXXXX..XXXXXXX 100644
48
--- a/target/arm/debug_helper.c
49
+++ b/target/arm/debug_helper.c
50
@@ -XXX,XX +XXX,XX @@
51
#include "exec/helper-proto.h"
52
53
54
+/* Return the Exception Level targeted by debug exceptions. */
55
+static int arm_debug_target_el(CPUARMState *env)
56
+{
57
+ bool secure = arm_is_secure(env);
58
+ bool route_to_el2 = false;
40
+
59
+
41
/* iwMMXt coprocessor control registers. */
60
+ if (arm_is_el2_enabled(env)) {
42
#define ARM_IWMMXT_wCID 0
61
+ route_to_el2 = env->cp15.hcr_el2 & HCR_TGE ||
43
#define ARM_IWMMXT_wCon 1
62
+ env->cp15.mdcr_el2 & MDCR_TDE;
44
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
45
index XXXXXXX..XXXXXXX 100644
46
--- a/target/arm/translate-vfp.c.inc
47
+++ b/target/arm/translate-vfp.c.inc
48
@@ -XXX,XX +XXX,XX @@ static bool trans_VDUP(DisasContext *s, arg_VDUP *a)
49
return true;
50
}
51
52
+/*
53
+ * M-profile provides two different sets of instructions that can
54
+ * access floating point system registers: VMSR/VMRS (which move
55
+ * to/from a general purpose register) and VLDR/VSTR sysreg (which
56
+ * move directly to/from memory). In some cases there are also side
57
+ * effects which must happen after any write to memory (which could
58
+ * cause an exception). So we implement the common logic for the
59
+ * sysreg access in gen_M_fp_sysreg_write() and gen_M_fp_sysreg_read(),
60
+ * which take pointers to callback functions which will perform the
61
+ * actual "read/write general purpose register" and "read/write
62
+ * memory" operations.
63
+ */
64
+
65
+/*
66
+ * Emit code to store the sysreg to its final destination; frees the
67
+ * TCG temp 'value' it is passed.
68
+ */
69
+typedef void fp_sysreg_storefn(DisasContext *s, void *opaque, TCGv_i32 value);
70
+/*
71
+ * Emit code to load the value to be copied to the sysreg; returns
72
+ * a new TCG temporary
73
+ */
74
+typedef TCGv_i32 fp_sysreg_loadfn(DisasContext *s, void *opaque);
75
+
76
+/* Common decode/access checks for fp sysreg read/write */
77
+typedef enum FPSysRegCheckResult {
78
+ FPSysRegCheckFailed, /* caller should return false */
79
+ FPSysRegCheckDone, /* caller should return true */
80
+ FPSysRegCheckContinue, /* caller should continue generating code */
81
+} FPSysRegCheckResult;
82
+
83
+static FPSysRegCheckResult fp_sysreg_checks(DisasContext *s, int regno)
84
+{
85
+ if (!dc_isar_feature(aa32_fpsp_v2, s)) {
86
+ return FPSysRegCheckFailed;
87
+ }
63
+ }
88
+
64
+
89
+ switch (regno) {
65
+ if (route_to_el2) {
90
+ case ARM_VFP_FPSCR:
66
+ return 2;
91
+ case QEMU_VFP_FPSCR_NZCV:
67
+ } else if (arm_feature(env, ARM_FEATURE_EL3) &&
92
+ break;
68
+ !arm_el_is_aa64(env, 3) && secure) {
93
+ default:
69
+ return 3;
94
+ return FPSysRegCheckFailed;
95
+ }
96
+
97
+ if (!vfp_access_check(s)) {
98
+ return FPSysRegCheckDone;
99
+ }
100
+
101
+ return FPSysRegCheckContinue;
102
+}
103
+
104
+static bool gen_M_fp_sysreg_write(DisasContext *s, int regno,
105
+
106
+ fp_sysreg_loadfn *loadfn,
107
+ void *opaque)
108
+{
109
+ /* Do a write to an M-profile floating point system register */
110
+ TCGv_i32 tmp;
111
+
112
+ switch (fp_sysreg_checks(s, regno)) {
113
+ case FPSysRegCheckFailed:
114
+ return false;
115
+ case FPSysRegCheckDone:
116
+ return true;
117
+ case FPSysRegCheckContinue:
118
+ break;
119
+ }
120
+
121
+ switch (regno) {
122
+ case ARM_VFP_FPSCR:
123
+ tmp = loadfn(s, opaque);
124
+ gen_helper_vfp_set_fpscr(cpu_env, tmp);
125
+ tcg_temp_free_i32(tmp);
126
+ gen_lookup_tb(s);
127
+ break;
128
+ default:
129
+ g_assert_not_reached();
130
+ }
131
+ return true;
132
+}
133
+
134
+static bool gen_M_fp_sysreg_read(DisasContext *s, int regno,
135
+ fp_sysreg_storefn *storefn,
136
+ void *opaque)
137
+{
138
+ /* Do a read from an M-profile floating point system register */
139
+ TCGv_i32 tmp;
140
+
141
+ switch (fp_sysreg_checks(s, regno)) {
142
+ case FPSysRegCheckFailed:
143
+ return false;
144
+ case FPSysRegCheckDone:
145
+ return true;
146
+ case FPSysRegCheckContinue:
147
+ break;
148
+ }
149
+
150
+ switch (regno) {
151
+ case ARM_VFP_FPSCR:
152
+ tmp = tcg_temp_new_i32();
153
+ gen_helper_vfp_get_fpscr(tmp, cpu_env);
154
+ storefn(s, opaque, tmp);
155
+ break;
156
+ case QEMU_VFP_FPSCR_NZCV:
157
+ /*
158
+ * Read just NZCV; this is a special case to avoid the
159
+ * helper call for the "VMRS to CPSR.NZCV" insn.
160
+ */
161
+ tmp = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
162
+ tcg_gen_andi_i32(tmp, tmp, 0xf0000000);
163
+ storefn(s, opaque, tmp);
164
+ break;
165
+ default:
166
+ g_assert_not_reached();
167
+ }
168
+ return true;
169
+}
170
+
171
+static void fp_sysreg_to_gpr(DisasContext *s, void *opaque, TCGv_i32 value)
172
+{
173
+ arg_VMSR_VMRS *a = opaque;
174
+
175
+ if (a->rt == 15) {
176
+ /* Set the 4 flag bits in the CPSR */
177
+ gen_set_nzcv(value);
178
+ tcg_temp_free_i32(value);
179
+ } else {
70
+ } else {
180
+ store_reg(s, a->rt, value);
71
+ return 1;
181
+ }
72
+ }
182
+}
73
+}
183
+
74
+
184
+static TCGv_i32 gpr_to_fp_sysreg(DisasContext *s, void *opaque)
75
/*
185
+{
76
* Raise an exception to the debug target el.
186
+ arg_VMSR_VMRS *a = opaque;
77
* Modify syndrome to indicate when origin and target EL are the same.
187
+
188
+ return load_reg(s, a->rt);
189
+}
190
+
191
+static bool gen_M_VMSR_VMRS(DisasContext *s, arg_VMSR_VMRS *a)
192
+{
193
+ /*
194
+ * Accesses to R15 are UNPREDICTABLE; we choose to undef.
195
+ * FPSCR -> r15 is a special case which writes to the PSR flags;
196
+ * set a->reg to a special value to tell gen_M_fp_sysreg_read()
197
+ * we only care about the top 4 bits of FPSCR there.
198
+ */
199
+ if (a->rt == 15) {
200
+ if (a->l && a->reg == ARM_VFP_FPSCR) {
201
+ a->reg = QEMU_VFP_FPSCR_NZCV;
202
+ } else {
203
+ return false;
204
+ }
205
+ }
206
+
207
+ if (a->l) {
208
+ /* VMRS, move FP system register to gp register */
209
+ return gen_M_fp_sysreg_read(s, a->reg, fp_sysreg_to_gpr, a);
210
+ } else {
211
+ /* VMSR, move gp register to FP system register */
212
+ return gen_M_fp_sysreg_write(s, a->reg, gpr_to_fp_sysreg, a);
213
+ }
214
+}
215
+
216
static bool trans_VMSR_VMRS(DisasContext *s, arg_VMSR_VMRS *a)
217
{
218
TCGv_i32 tmp;
219
bool ignore_vfp_enabled = false;
220
221
- if (!dc_isar_feature(aa32_fpsp_v2, s)) {
222
- return false;
223
+ if (arm_dc_feature(s, ARM_FEATURE_M)) {
224
+ return gen_M_VMSR_VMRS(s, a);
225
}
226
227
- if (arm_dc_feature(s, ARM_FEATURE_M)) {
228
- /*
229
- * The only M-profile VFP vmrs/vmsr sysreg is FPSCR.
230
- * Accesses to R15 are UNPREDICTABLE; we choose to undef.
231
- * (FPSCR -> r15 is a special case which writes to the PSR flags.)
232
- */
233
- if (a->reg != ARM_VFP_FPSCR) {
234
- return false;
235
- }
236
- if (a->rt == 15 && !a->l) {
237
- return false;
238
- }
239
+ if (!dc_isar_feature(aa32_fpsp_v2, s)) {
240
+ return false;
241
}
242
243
switch (a->reg) {
244
--
78
--
245
2.20.1
79
2.25.1
246
247
diff view generated by jsdifflib
1
In arm_cpu_realizefn() we check whether the board code disabled EL3
1
From: Richard Henderson <richard.henderson@linaro.org>
2
via the has_el3 CPU object property, which we create if the CPU
3
starts with the ARM_FEATURE_EL3 feature bit. If it is disabled, then
4
we turn off ARM_FEATURE_EL3 and also zero out the relevant fields in
5
the ID_PFR1 and ID_AA64PFR0 registers.
6
2
7
This codepath was incorrectly being taken for M-profile CPUs, which
3
We were using arm_is_secure and is_a64, which are
8
do not have an EL3 and don't set ARM_FEATURE_EL3, but which may have
4
tests against the current EL, as opposed to
9
the M-profile Security extension and so should have non-zero values
5
arm_el_is_aa64 and arm_is_secure_below_el3, which
10
in the ID_PFR1.Security field.
6
can be applied to a different EL than current.
7
Consolidate the two tests.
11
8
12
Restrict the handling of the feature flag to A/R-profile cores.
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20220609202901.1177572-24-richard.henderson@linaro.org
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
14
target/arm/helper.c | 23 +++++++++--------------
15
1 file changed, 9 insertions(+), 14 deletions(-)
13
16
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
diff --git a/target/arm/helper.c b/target/arm/helper.c
15
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
16
Message-id: 20201119215617.29887-4-peter.maydell@linaro.org
17
---
18
target/arm/cpu.c | 2 +-
19
1 file changed, 1 insertion(+), 1 deletion(-)
20
21
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
22
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
23
--- a/target/arm/cpu.c
19
--- a/target/arm/helper.c
24
+++ b/target/arm/cpu.c
20
+++ b/target/arm/helper.c
25
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
21
@@ -XXX,XX +XXX,XX @@ int fp_exception_el(CPUARMState *env, int cur_el)
22
int fpen = FIELD_EX64(env->cp15.cpacr_el1, CPACR_EL1, FPEN);
23
24
switch (fpen) {
25
+ case 1:
26
+ if (cur_el != 0) {
27
+ break;
28
+ }
29
+ /* fall through */
30
case 0:
31
case 2:
32
- if (cur_el == 0 || cur_el == 1) {
33
- /* Trap to PL1, which might be EL1 or EL3 */
34
- if (arm_is_secure(env) && !arm_el_is_aa64(env, 3)) {
35
- return 3;
36
- }
37
- return 1;
38
- }
39
- if (cur_el == 3 && !is_a64(env)) {
40
- /* Secure PL1 running at EL3 */
41
+ /* Trap from Secure PL0 or PL1 to Secure PL1. */
42
+ if (!arm_el_is_aa64(env, 3)
43
+ && (cur_el == 3 || arm_is_secure_below_el3(env))) {
44
return 3;
45
}
46
- break;
47
- case 1:
48
- if (cur_el == 0) {
49
+ if (cur_el <= 1) {
50
return 1;
51
}
52
break;
53
- case 3:
54
- break;
26
}
55
}
27
}
56
}
28
57
29
- if (!cpu->has_el3) {
30
+ if (!arm_feature(env, ARM_FEATURE_M) && !cpu->has_el3) {
31
/* If the has_el3 CPU property is disabled then we need to disable the
32
* feature.
33
*/
34
--
58
--
35
2.20.1
59
2.25.1
36
37
diff view generated by jsdifflib
1
From: Alex Chen <alex.chen@huawei.com>
1
From: Hao Wu <wuhaotsh@google.com>
2
2
3
We should use printf format specifier "%u" instead of "%d" for
3
Creating 1GB image for a simple qtest is unnecessary
4
argument of type "unsigned int".
4
and could lead to failures. We reduce the image size
5
to 1MB to reduce the test overhead.
5
6
6
Reported-by: Euler Robot <euler.robot@huawei.com>
7
Signed-off-by: Hao Wu <wuhaotsh@google.com>
7
Signed-off-by: Alex Chen <alex.chen@huawei.com>
8
Message-id: 20220609214125.4192212-1-wuhaotsh@google.com
8
Message-id: 20201126111109.112238-4-alex.chen@huawei.com
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
11
---
12
hw/misc/imx6_ccm.c | 20 ++++++++++----------
12
tests/qtest/npcm7xx_sdhci-test.c | 2 +-
13
hw/misc/imx6_src.c | 2 +-
13
1 file changed, 1 insertion(+), 1 deletion(-)
14
2 files changed, 11 insertions(+), 11 deletions(-)
15
14
16
diff --git a/hw/misc/imx6_ccm.c b/hw/misc/imx6_ccm.c
15
diff --git a/tests/qtest/npcm7xx_sdhci-test.c b/tests/qtest/npcm7xx_sdhci-test.c
17
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/misc/imx6_ccm.c
17
--- a/tests/qtest/npcm7xx_sdhci-test.c
19
+++ b/hw/misc/imx6_ccm.c
18
+++ b/tests/qtest/npcm7xx_sdhci-test.c
20
@@ -XXX,XX +XXX,XX @@ static const char *imx6_ccm_reg_name(uint32_t reg)
19
@@ -XXX,XX +XXX,XX @@
21
case CCM_CMEOR:
20
#define NPCM7XX_REG_SIZE 0x100
22
return "CMEOR";
21
#define NPCM7XX_MMC_BA 0xF0842000
23
default:
22
#define NPCM7XX_BLK_SIZE 512
24
- sprintf(unknown, "%d ?", reg);
23
-#define NPCM7XX_TEST_IMAGE_SIZE (1 << 30)
25
+ sprintf(unknown, "%u ?", reg);
24
+#define NPCM7XX_TEST_IMAGE_SIZE (1 << 20)
26
return unknown;
25
27
}
26
char *sd_path;
28
}
27
29
@@ -XXX,XX +XXX,XX @@ static const char *imx6_analog_reg_name(uint32_t reg)
30
case USB_ANALOG_DIGPROG:
31
return "USB_ANALOG_DIGPROG";
32
default:
33
- sprintf(unknown, "%d ?", reg);
34
+ sprintf(unknown, "%u ?", reg);
35
return unknown;
36
}
37
}
38
@@ -XXX,XX +XXX,XX @@ static uint64_t imx6_analog_get_pll2_clk(IMX6CCMState *dev)
39
freq *= 20;
40
}
41
42
- DPRINTF("freq = %d\n", (uint32_t)freq);
43
+ DPRINTF("freq = %u\n", (uint32_t)freq);
44
45
return freq;
46
}
47
@@ -XXX,XX +XXX,XX @@ static uint64_t imx6_analog_get_pll2_pfd0_clk(IMX6CCMState *dev)
48
freq = imx6_analog_get_pll2_clk(dev) * 18
49
/ EXTRACT(dev->analog[CCM_ANALOG_PFD_528], PFD0_FRAC);
50
51
- DPRINTF("freq = %d\n", (uint32_t)freq);
52
+ DPRINTF("freq = %u\n", (uint32_t)freq);
53
54
return freq;
55
}
56
@@ -XXX,XX +XXX,XX @@ static uint64_t imx6_analog_get_pll2_pfd2_clk(IMX6CCMState *dev)
57
freq = imx6_analog_get_pll2_clk(dev) * 18
58
/ EXTRACT(dev->analog[CCM_ANALOG_PFD_528], PFD2_FRAC);
59
60
- DPRINTF("freq = %d\n", (uint32_t)freq);
61
+ DPRINTF("freq = %u\n", (uint32_t)freq);
62
63
return freq;
64
}
65
@@ -XXX,XX +XXX,XX @@ static uint64_t imx6_analog_get_periph_clk(IMX6CCMState *dev)
66
break;
67
}
68
69
- DPRINTF("freq = %d\n", (uint32_t)freq);
70
+ DPRINTF("freq = %u\n", (uint32_t)freq);
71
72
return freq;
73
}
74
@@ -XXX,XX +XXX,XX @@ static uint64_t imx6_ccm_get_ahb_clk(IMX6CCMState *dev)
75
freq = imx6_analog_get_periph_clk(dev)
76
/ (1 + EXTRACT(dev->ccm[CCM_CBCDR], AHB_PODF));
77
78
- DPRINTF("freq = %d\n", (uint32_t)freq);
79
+ DPRINTF("freq = %u\n", (uint32_t)freq);
80
81
return freq;
82
}
83
@@ -XXX,XX +XXX,XX @@ static uint64_t imx6_ccm_get_ipg_clk(IMX6CCMState *dev)
84
freq = imx6_ccm_get_ahb_clk(dev)
85
/ (1 + EXTRACT(dev->ccm[CCM_CBCDR], IPG_PODF));
86
87
- DPRINTF("freq = %d\n", (uint32_t)freq);
88
+ DPRINTF("freq = %u\n", (uint32_t)freq);
89
90
return freq;
91
}
92
@@ -XXX,XX +XXX,XX @@ static uint64_t imx6_ccm_get_per_clk(IMX6CCMState *dev)
93
freq = imx6_ccm_get_ipg_clk(dev)
94
/ (1 + EXTRACT(dev->ccm[CCM_CSCMR1], PERCLK_PODF));
95
96
- DPRINTF("freq = %d\n", (uint32_t)freq);
97
+ DPRINTF("freq = %u\n", (uint32_t)freq);
98
99
return freq;
100
}
101
@@ -XXX,XX +XXX,XX @@ static uint32_t imx6_ccm_get_clock_frequency(IMXCCMState *dev, IMXClk clock)
102
break;
103
}
104
105
- DPRINTF("Clock = %d) = %d\n", clock, freq);
106
+ DPRINTF("Clock = %d) = %u\n", clock, freq);
107
108
return freq;
109
}
110
diff --git a/hw/misc/imx6_src.c b/hw/misc/imx6_src.c
111
index XXXXXXX..XXXXXXX 100644
112
--- a/hw/misc/imx6_src.c
113
+++ b/hw/misc/imx6_src.c
114
@@ -XXX,XX +XXX,XX @@ static const char *imx6_src_reg_name(uint32_t reg)
115
case SRC_GPR10:
116
return "SRC_GPR10";
117
default:
118
- sprintf(unknown, "%d ?", reg);
119
+ sprintf(unknown, "%u ?", reg);
120
return unknown;
121
}
122
}
123
--
28
--
124
2.20.1
29
2.25.1
125
126
diff view generated by jsdifflib
1
In v8.1M the PXN architecture extension adds a new PXN bit to the
1
From: Richard Henderson <richard.henderson@linaro.org>
2
MPU_RLAR registers, which forbids execution of code in the region
3
from a privileged mode.
4
2
5
This is another feature which is just in the generic "in v8.1M" set
3
Because reset always initializes the AA64 version, SCR_EL3,
6
and has no ID register field indicating its presence.
4
test the mode of EL3 instead of the type of the cpreg.
7
5
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20220609214657.1217913-2-richard.henderson@linaro.org
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20201119215617.29887-3-peter.maydell@linaro.org
11
---
10
---
12
target/arm/helper.c | 7 ++++++-
11
target/arm/helper.c | 14 ++++++++------
13
1 file changed, 6 insertions(+), 1 deletion(-)
12
1 file changed, 8 insertions(+), 6 deletions(-)
14
13
15
diff --git a/target/arm/helper.c b/target/arm/helper.c
14
diff --git a/target/arm/helper.c b/target/arm/helper.c
16
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/helper.c
16
--- a/target/arm/helper.c
18
+++ b/target/arm/helper.c
17
+++ b/target/arm/helper.c
19
@@ -XXX,XX +XXX,XX @@ bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address,
18
@@ -XXX,XX +XXX,XX @@ static void scr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
20
} else {
19
uint32_t valid_mask = 0x3fff;
21
uint32_t ap = extract32(env->pmsav8.rbar[secure][matchregion], 1, 2);
20
ARMCPU *cpu = env_archcpu(env);
22
uint32_t xn = extract32(env->pmsav8.rbar[secure][matchregion], 0, 1);
21
23
+ bool pxn = false;
22
- if (ri->state == ARM_CP_STATE_AA64) {
24
+
23
- if (arm_feature(env, ARM_FEATURE_AARCH64) &&
25
+ if (arm_feature(env, ARM_FEATURE_V8_1M)) {
24
- !cpu_isar_feature(aa64_aa32_el1, cpu)) {
26
+ pxn = extract32(env->pmsav8.rlar[secure][matchregion], 4, 1);
25
- value |= SCR_FW | SCR_AW; /* these two bits are RES1. */
27
+ }
26
- }
28
27
- valid_mask &= ~SCR_NET;
29
if (m_is_system_region(env, address)) {
28
+ /*
30
/* System space is always execute never */
29
+ * Because SCR_EL3 is the "real" cpreg and SCR is the alias, reset always
31
@@ -XXX,XX +XXX,XX @@ bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address,
30
+ * passes the reginfo for SCR_EL3, which has type ARM_CP_STATE_AA64.
32
}
31
+ * Instead, choose the format based on the mode of EL3.
33
32
+ */
34
*prot = simple_ap_to_rw_prot(env, mmu_idx, ap);
33
+ if (arm_el_is_aa64(env, 3)) {
35
- if (*prot && !xn) {
34
+ value |= SCR_FW | SCR_AW; /* RES1 */
36
+ if (*prot && !xn && !(pxn && !is_user)) {
35
+ valid_mask &= ~SCR_NET; /* RES0 */
37
*prot |= PAGE_EXEC;
36
38
}
37
if (cpu_isar_feature(aa64_ras, cpu)) {
39
/* We don't need to look the attribute up in the MAIR0/MAIR1
38
valid_mask |= SCR_TERR;
40
--
39
--
41
2.20.1
40
2.25.1
42
43
diff view generated by jsdifflib
1
For v8.1M the architecture mandates that CPUs must provide at
1
From: Richard Henderson <richard.henderson@linaro.org>
2
least the "minimal RAS implementation" from the Reliability,
3
Availability and Serviceability extension. This consists of:
4
* an ESB instruction which is a NOP
5
-- since it is in the HINT space we need only add a comment
6
* an RFSR register which will RAZ/WI
7
* a RAZ/WI AIRCR.IESB bit
8
-- the code which handles writes to AIRCR does not allow setting
9
of RES0 bits, so we already treat this as RAZ/WI; add a comment
10
noting that this is deliberate
11
* minimal implementation of the RAS register block at 0xe0005000
12
-- this will be in a subsequent commit
13
* setting the ID_PFR0.RAS field to 0b0010
14
-- we will do this when we add the Cortex-M55 CPU model
15
2
3
Since DDI0487F.a, the RW bit is RAO/WI. When specifically
4
targeting such a cpu, e.g. cortex-a76, it is legitimate to
5
ignore the bit within the secure monitor.
6
7
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1062
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20220609214657.1217913-3-richard.henderson@linaro.org
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
18
Message-id: 20201119215617.29887-26-peter.maydell@linaro.org
19
---
12
---
20
target/arm/cpu.h | 14 ++++++++++++++
13
target/arm/cpu.h | 5 +++++
21
target/arm/t32.decode | 4 ++++
14
target/arm/helper.c | 4 ++++
22
hw/intc/armv7m_nvic.c | 13 +++++++++++++
15
2 files changed, 9 insertions(+)
23
3 files changed, 31 insertions(+)
24
16
25
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
17
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
26
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
27
--- a/target/arm/cpu.h
19
--- a/target/arm/cpu.h
28
+++ b/target/arm/cpu.h
20
+++ b/target/arm/cpu.h
29
@@ -XXX,XX +XXX,XX @@ FIELD(ID_MMFR4, LSM, 20, 4)
21
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa64_aa32_el1(const ARMISARegisters *id)
30
FIELD(ID_MMFR4, CCIDX, 24, 4)
22
return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, EL1) >= 2;
31
FIELD(ID_MMFR4, EVT, 28, 4)
32
33
+FIELD(ID_PFR0, STATE0, 0, 4)
34
+FIELD(ID_PFR0, STATE1, 4, 4)
35
+FIELD(ID_PFR0, STATE2, 8, 4)
36
+FIELD(ID_PFR0, STATE3, 12, 4)
37
+FIELD(ID_PFR0, CSV2, 16, 4)
38
+FIELD(ID_PFR0, AMU, 20, 4)
39
+FIELD(ID_PFR0, DIT, 24, 4)
40
+FIELD(ID_PFR0, RAS, 28, 4)
41
+
42
FIELD(ID_PFR1, PROGMOD, 0, 4)
43
FIELD(ID_PFR1, SECURITY, 4, 4)
44
FIELD(ID_PFR1, MPROGMOD, 8, 4)
45
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa32_predinv(const ARMISARegisters *id)
46
return FIELD_EX32(id->id_isar6, ID_ISAR6, SPECRES) != 0;
47
}
23
}
48
24
49
+static inline bool isar_feature_aa32_ras(const ARMISARegisters *id)
25
+static inline bool isar_feature_aa64_aa32_el2(const ARMISARegisters *id)
50
+{
26
+{
51
+ return FIELD_EX32(id->id_pfr0, ID_PFR0, RAS) != 0;
27
+ return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, EL2) >= 2;
52
+}
28
+}
53
+
29
+
54
static inline bool isar_feature_aa32_mprofile(const ARMISARegisters *id)
30
static inline bool isar_feature_aa64_ras(const ARMISARegisters *id)
55
{
31
{
56
return FIELD_EX32(id->id_pfr1, ID_PFR1, MPROGMOD) != 0;
32
return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, RAS) != 0;
57
diff --git a/target/arm/t32.decode b/target/arm/t32.decode
33
diff --git a/target/arm/helper.c b/target/arm/helper.c
58
index XXXXXXX..XXXXXXX 100644
34
index XXXXXXX..XXXXXXX 100644
59
--- a/target/arm/t32.decode
35
--- a/target/arm/helper.c
60
+++ b/target/arm/t32.decode
36
+++ b/target/arm/helper.c
61
@@ -XXX,XX +XXX,XX @@ CLZ 1111 1010 1011 ---- 1111 .... 1000 .... @rdm
37
@@ -XXX,XX +XXX,XX @@ static void scr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
62
# SEV 1111 0011 1010 1111 1000 0000 0000 0100
38
value |= SCR_FW | SCR_AW; /* RES1 */
63
# SEVL 1111 0011 1010 1111 1000 0000 0000 0101
39
valid_mask &= ~SCR_NET; /* RES0 */
64
40
65
+ # For M-profile minimal-RAS ESB can be a NOP, which is the
41
+ if (!cpu_isar_feature(aa64_aa32_el1, cpu) &&
66
+ # default behaviour since it is in the hint space.
42
+ !cpu_isar_feature(aa64_aa32_el2, cpu)) {
67
+ # ESB 1111 0011 1010 1111 1000 0000 0001 0000
43
+ value |= SCR_RW; /* RAO/WI */
68
+
44
+ }
69
# The canonical nop ends in 0000 0000, but the whole rest
45
if (cpu_isar_feature(aa64_ras, cpu)) {
70
# of the space is "reserved hint, behaves as nop".
46
valid_mask |= SCR_TERR;
71
NOP 1111 0011 1010 1111 1000 0000 ---- ----
72
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
73
index XXXXXXX..XXXXXXX 100644
74
--- a/hw/intc/armv7m_nvic.c
75
+++ b/hw/intc/armv7m_nvic.c
76
@@ -XXX,XX +XXX,XX @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
77
return 0;
78
}
47
}
79
return cpu->env.v7m.sfar;
80
+ case 0xf04: /* RFSR */
81
+ if (!cpu_isar_feature(aa32_ras, cpu)) {
82
+ goto bad_offset;
83
+ }
84
+ /* We provide minimal-RAS only: RFSR is RAZ/WI */
85
+ return 0;
86
case 0xf34: /* FPCCR */
87
if (!cpu_isar_feature(aa32_vfp_simd, cpu)) {
88
return 0;
89
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
90
R_V7M_AIRCR_PRIGROUP_SHIFT,
91
R_V7M_AIRCR_PRIGROUP_LENGTH);
92
}
93
+ /* AIRCR.IESB is RAZ/WI because we implement only minimal RAS */
94
if (attrs.secure) {
95
/* These bits are only writable by secure */
96
cpu->env.v7m.aircr = value &
97
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
98
}
99
break;
100
}
101
+ case 0xf04: /* RFSR */
102
+ if (!cpu_isar_feature(aa32_ras, cpu)) {
103
+ goto bad_offset;
104
+ }
105
+ /* We provide minimal-RAS only: RFSR is RAZ/WI */
106
+ break;
107
case 0xf34: /* FPCCR */
108
if (cpu_isar_feature(aa32_vfp_simd, cpu)) {
109
/* Not all bits here are banked. */
110
--
48
--
111
2.20.1
49
2.25.1
112
113
diff view generated by jsdifflib
1
For M-profile CPUs, the range from 0xe0000000 to 0xe00fffff is the
1
In two places in gdbstub.c we look at gdbserver_state.init to decide
2
Private Peripheral Bus range, which includes all of the memory mapped
2
whether we're going to do a semihosting syscall via the gdb remote
3
devices and registers that are part of the CPU itself, including the
3
protocol:
4
NVIC, systick timer, and debug and trace components like the Data
4
* when setting up, if the user didn't explicitly select either
5
Watchpoint and Trace unit (DWT). Within this large region, the range
5
native semihosting or gdb semihosting, we autoselect, with the
6
0xe000e000 to 0xe000efff is the System Control Space (NVIC, system
6
intended behaviour "use gdb if gdb is connected"
7
registers, systick) and 0xe002e000 to 0exe002efff is its Non-secure
7
* when the semihosting layer attempts to do a syscall via gdb, we
8
alias.
8
silently ignore it if the gdbstub wasn't actually set up
9
9
10
The architecture is clear that within the SCS unimplemented registers
10
However, if the user's commandline sets up the gdbstub but tells QEMU
11
should be RES0 for privileged accesses and generate BusFault for
11
to start rather than waiting for a GDB to connect (eg using '-s' but
12
unprivileged accesses, and we currently implement this.
12
not '-S'), then we will have gdbserver_state.init true but no actual
13
connection; an attempt to use gdb syscalls will then crash because we
14
try to use gdbserver_state.c_cpu when it hasn't been set up:
13
15
14
It is less clear about how to handle accesses to unimplemented
16
#0 0x00007ffff6803ba8 in qemu_cpu_kick (cpu=0x0) at ../../softmmu/cpus.c:457
15
regions of the wider PPB. Unprivileged accesses should definitely
17
#1 0x00007ffff6c03913 in gdb_do_syscallv (cb=0x7ffff6c19944 <common_semi_cb>,
16
cause BusFaults (R_DQQS), but the behaviour of privileged accesses is
18
fmt=0x7ffff7573b7e "", va=0x7ffff56294c0) at ../../gdbstub.c:2946
17
not given as a general rule. However, the register definitions of
19
#2 0x00007ffff6c19c3a in common_semi_gdb_syscall (cs=0x7ffff83fe060,
18
individual registers for components like the DWT all state that they
20
cb=0x7ffff6c19944 <common_semi_cb>, fmt=0x7ffff7573b75 "isatty,%x")
19
are RES0 if the relevant component is not implemented, so the
21
at ../../semihosting/arm-compat-semi.c:494
20
simplest way to provide that is to provide RAZ/WI for the whole range
22
#3 0x00007ffff6c1a064 in gdb_isattyfn (cs=0x7ffff83fe060, gf=0x7ffff86a3690)
21
for privileged accesses. (The v7M Arm ARM does say that reserved
23
at ../../semihosting/arm-compat-semi.c:636
22
registers should be UNK/SBZP.)
24
#4 0x00007ffff6c1b20f in do_common_semihosting (cs=0x7ffff83fe060)
25
at ../../semihosting/arm-compat-semi.c:967
26
#5 0x00007ffff693a037 in handle_semihosting (cs=0x7ffff83fe060)
27
at ../../target/arm/helper.c:10316
23
28
24
Expand the container MemoryRegion that the NVIC exposes so that
29
You can probably also get into this state via some odd
25
it covers the whole PPB space. This means:
30
corner cases involving connecting a GDB and then telling it
26
* moving the address that the ARMV7M device maps it to down by
31
to detach from all the vCPUs.
27
0xe000 bytes
28
* moving the off and the offsets within the container of all the
29
subregions forward by 0xe000 bytes
30
* adding a new default MemoryRegion that covers the whole container
31
at a lower priority than anything else and which provides the
32
RAZWI/BusFault behaviour
33
32
33
Abstract out the test into a new gdb_attached() function
34
which returns true only if there's actually a GDB connected
35
to the debug stub and attached to at least one vCPU.
36
37
Reported-by: Liviu Ionescu <ilg@livius.net>
34
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
38
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
35
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
39
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
36
Message-id: 20201119215617.29887-2-peter.maydell@linaro.org
40
Reviewed-by: Luc Michel <luc@lmichel.fr>
41
Message-id: 20220526190053.521505-2-peter.maydell@linaro.org
37
---
42
---
38
include/hw/intc/armv7m_nvic.h | 1 +
43
gdbstub.c | 14 +++++++++++---
39
hw/arm/armv7m.c | 2 +-
44
1 file changed, 11 insertions(+), 3 deletions(-)
40
hw/intc/armv7m_nvic.c | 78 ++++++++++++++++++++++++++++++-----
41
3 files changed, 69 insertions(+), 12 deletions(-)
42
45
43
diff --git a/include/hw/intc/armv7m_nvic.h b/include/hw/intc/armv7m_nvic.h
46
diff --git a/gdbstub.c b/gdbstub.c
44
index XXXXXXX..XXXXXXX 100644
47
index XXXXXXX..XXXXXXX 100644
45
--- a/include/hw/intc/armv7m_nvic.h
48
--- a/gdbstub.c
46
+++ b/include/hw/intc/armv7m_nvic.h
49
+++ b/gdbstub.c
47
@@ -XXX,XX +XXX,XX @@ struct NVICState {
50
@@ -XXX,XX +XXX,XX @@ static int get_char(void)
48
MemoryRegion systickmem;
51
}
49
MemoryRegion systick_ns_mem;
52
#endif
50
MemoryRegion container;
51
+ MemoryRegion defaultmem;
52
53
uint32_t num_irq;
54
qemu_irq excpout;
55
diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c
56
index XXXXXXX..XXXXXXX 100644
57
--- a/hw/arm/armv7m.c
58
+++ b/hw/arm/armv7m.c
59
@@ -XXX,XX +XXX,XX @@ static void armv7m_realize(DeviceState *dev, Error **errp)
60
sysbus_connect_irq(sbd, 0,
61
qdev_get_gpio_in(DEVICE(s->cpu), ARM_CPU_IRQ));
62
63
- memory_region_add_subregion(&s->container, 0xe000e000,
64
+ memory_region_add_subregion(&s->container, 0xe0000000,
65
sysbus_mmio_get_region(sbd, 0));
66
67
for (i = 0; i < ARRAY_SIZE(s->bitband); i++) {
68
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
69
index XXXXXXX..XXXXXXX 100644
70
--- a/hw/intc/armv7m_nvic.c
71
+++ b/hw/intc/armv7m_nvic.c
72
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps nvic_systick_ops = {
73
.endianness = DEVICE_NATIVE_ENDIAN,
74
};
75
53
76
+/*
54
+/*
77
+ * Unassigned portions of the PPB space are RAZ/WI for privileged
55
+ * Return true if there is a GDB currently connected to the stub
78
+ * accesses, and fault for non-privileged accesses.
56
+ * and attached to a CPU
79
+ */
57
+ */
80
+static MemTxResult ppb_default_read(void *opaque, hwaddr addr,
58
+static bool gdb_attached(void)
81
+ uint64_t *data, unsigned size,
82
+ MemTxAttrs attrs)
83
+{
59
+{
84
+ qemu_log_mask(LOG_UNIMP, "Read of unassigned area of PPB: offset 0x%x\n",
60
+ return gdbserver_state.init && gdbserver_state.c_cpu;
85
+ (uint32_t)addr);
86
+ if (attrs.user) {
87
+ return MEMTX_ERROR;
88
+ }
89
+ *data = 0;
90
+ return MEMTX_OK;
91
+}
61
+}
92
+
62
+
93
+static MemTxResult ppb_default_write(void *opaque, hwaddr addr,
63
static enum {
94
+ uint64_t value, unsigned size,
64
GDB_SYS_UNKNOWN,
95
+ MemTxAttrs attrs)
65
GDB_SYS_ENABLED,
96
+{
66
@@ -XXX,XX +XXX,XX @@ int use_gdb_syscalls(void)
97
+ qemu_log_mask(LOG_UNIMP, "Write of unassigned area of PPB: offset 0x%x\n",
67
/* -semihosting-config target=auto */
98
+ (uint32_t)addr);
68
/* On the first call check if gdb is connected and remember. */
99
+ if (attrs.user) {
69
if (gdb_syscall_mode == GDB_SYS_UNKNOWN) {
100
+ return MEMTX_ERROR;
70
- gdb_syscall_mode = gdbserver_state.init ?
101
+ }
71
- GDB_SYS_ENABLED : GDB_SYS_DISABLED;
102
+ return MEMTX_OK;
72
+ gdb_syscall_mode = gdb_attached() ? GDB_SYS_ENABLED : GDB_SYS_DISABLED;
103
+}
104
+
105
+static const MemoryRegionOps ppb_default_ops = {
106
+ .read_with_attrs = ppb_default_read,
107
+ .write_with_attrs = ppb_default_write,
108
+ .endianness = DEVICE_NATIVE_ENDIAN,
109
+ .valid.min_access_size = 1,
110
+ .valid.max_access_size = 8,
111
+};
112
+
113
static int nvic_post_load(void *opaque, int version_id)
114
{
115
NVICState *s = opaque;
116
@@ -XXX,XX +XXX,XX @@ static void nvic_systick_trigger(void *opaque, int n, int level)
117
static void armv7m_nvic_realize(DeviceState *dev, Error **errp)
118
{
119
NVICState *s = NVIC(dev);
120
- int regionlen;
121
122
/* The armv7m container object will have set our CPU pointer */
123
if (!s->cpu || !arm_feature(&s->cpu->env, ARM_FEATURE_M)) {
124
@@ -XXX,XX +XXX,XX @@ static void armv7m_nvic_realize(DeviceState *dev, Error **errp)
125
M_REG_S));
126
}
73
}
127
74
return gdb_syscall_mode == GDB_SYS_ENABLED;
128
- /* The NVIC and System Control Space (SCS) starts at 0xe000e000
75
}
129
+ /*
76
@@ -XXX,XX +XXX,XX @@ void gdb_do_syscallv(gdb_syscall_complete_cb cb, const char *fmt, va_list va)
130
+ * This device provides a single sysbus memory region which
77
target_ulong addr;
131
+ * represents the whole of the "System PPB" space. This is the
78
uint64_t i64;
132
+ * range from 0xe0000000 to 0xe00fffff and includes the NVIC,
79
133
+ * the System Control Space (system registers), the systick timer,
80
- if (!gdbserver_state.init) {
134
+ * and for CPUs with the Security extension an NS banked version
81
+ if (!gdb_attached()) {
135
+ * of all of these.
82
return;
136
+ *
137
+ * The default behaviour for unimplemented registers/ranges
138
+ * (for instance the Data Watchpoint and Trace unit at 0xe0001000)
139
+ * is to RAZ/WI for privileged access and BusFault for non-privileged
140
+ * access.
141
+ *
142
+ * The NVIC and System Control Space (SCS) starts at 0xe000e000
143
* and looks like this:
144
* 0x004 - ICTR
145
* 0x010 - 0xff - systick
146
@@ -XXX,XX +XXX,XX @@ static void armv7m_nvic_realize(DeviceState *dev, Error **errp)
147
* generally code determining which banked register to use should
148
* use attrs.secure; code determining actual behaviour of the system
149
* should use env->v7m.secure.
150
+ *
151
+ * The container covers the whole PPB space. Within it the priority
152
+ * of overlapping regions is:
153
+ * - default region (for RAZ/WI and BusFault) : -1
154
+ * - system register regions : 0
155
+ * - systick : 1
156
+ * This is because the systick device is a small block of registers
157
+ * in the middle of the other system control registers.
158
*/
159
- regionlen = arm_feature(&s->cpu->env, ARM_FEATURE_V8) ? 0x21000 : 0x1000;
160
- memory_region_init(&s->container, OBJECT(s), "nvic", regionlen);
161
- /* The system register region goes at the bottom of the priority
162
- * stack as it covers the whole page.
163
- */
164
+ memory_region_init(&s->container, OBJECT(s), "nvic", 0x100000);
165
+ memory_region_init_io(&s->defaultmem, OBJECT(s), &ppb_default_ops, s,
166
+ "nvic-default", 0x100000);
167
+ memory_region_add_subregion_overlap(&s->container, 0, &s->defaultmem, -1);
168
memory_region_init_io(&s->sysregmem, OBJECT(s), &nvic_sysreg_ops, s,
169
"nvic_sysregs", 0x1000);
170
- memory_region_add_subregion(&s->container, 0, &s->sysregmem);
171
+ memory_region_add_subregion(&s->container, 0xe000, &s->sysregmem);
172
173
memory_region_init_io(&s->systickmem, OBJECT(s),
174
&nvic_systick_ops, s,
175
"nvic_systick", 0xe0);
176
177
- memory_region_add_subregion_overlap(&s->container, 0x10,
178
+ memory_region_add_subregion_overlap(&s->container, 0xe010,
179
&s->systickmem, 1);
180
181
if (arm_feature(&s->cpu->env, ARM_FEATURE_V8)) {
182
memory_region_init_io(&s->sysreg_ns_mem, OBJECT(s),
183
&nvic_sysreg_ns_ops, &s->sysregmem,
184
"nvic_sysregs_ns", 0x1000);
185
- memory_region_add_subregion(&s->container, 0x20000, &s->sysreg_ns_mem);
186
+ memory_region_add_subregion(&s->container, 0x2e000, &s->sysreg_ns_mem);
187
memory_region_init_io(&s->systick_ns_mem, OBJECT(s),
188
&nvic_sysreg_ns_ops, &s->systickmem,
189
"nvic_systick_ns", 0xe0);
190
- memory_region_add_subregion_overlap(&s->container, 0x20010,
191
+ memory_region_add_subregion_overlap(&s->container, 0x2e010,
192
&s->systick_ns_mem, 1);
193
}
83
}
194
84
195
--
85
--
196
2.20.1
86
2.25.1
197
87
198
88
diff view generated by jsdifflib
Deleted patch
1
We defined a constant name for the mask of NZCV bits in the FPCR/FPSCR
2
in the previous commit; use it in a couple of places in existing code,
3
where we're masking out everything except NZCV for the "load to Rt=15
4
sets CPSR.NZCV" special case.
5
1
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20201119215617.29887-12-peter.maydell@linaro.org
9
---
10
target/arm/translate-vfp.c.inc | 4 ++--
11
1 file changed, 2 insertions(+), 2 deletions(-)
12
13
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/translate-vfp.c.inc
16
+++ b/target/arm/translate-vfp.c.inc
17
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_read(DisasContext *s, int regno,
18
* helper call for the "VMRS to CPSR.NZCV" insn.
19
*/
20
tmp = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
21
- tcg_gen_andi_i32(tmp, tmp, 0xf0000000);
22
+ tcg_gen_andi_i32(tmp, tmp, FPCR_NZCV_MASK);
23
storefn(s, opaque, tmp);
24
break;
25
default:
26
@@ -XXX,XX +XXX,XX @@ static bool trans_VMSR_VMRS(DisasContext *s, arg_VMSR_VMRS *a)
27
case ARM_VFP_FPSCR:
28
if (a->rt == 15) {
29
tmp = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
30
- tcg_gen_andi_i32(tmp, tmp, 0xf0000000);
31
+ tcg_gen_andi_i32(tmp, tmp, FPCR_NZCV_MASK);
32
} else {
33
tmp = tcg_temp_new_i32();
34
gen_helper_vfp_get_fpscr(tmp, cpu_env);
35
--
36
2.20.1
37
38
diff view generated by jsdifflib
Deleted patch
1
Implement the new-in-v8.1M FPCXT_S floating point system register.
2
This is for saving and restoring the secure floating point context,
3
and it reads and writes bits [27:0] from the FPSCR and the
4
CONTROL.SFPA bit in bit [31].
5
1
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20201119215617.29887-14-peter.maydell@linaro.org
9
---
10
target/arm/translate-vfp.c.inc | 58 ++++++++++++++++++++++++++++++++++
11
1 file changed, 58 insertions(+)
12
13
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/translate-vfp.c.inc
16
+++ b/target/arm/translate-vfp.c.inc
17
@@ -XXX,XX +XXX,XX @@ static FPSysRegCheckResult fp_sysreg_checks(DisasContext *s, int regno)
18
return false;
19
}
20
break;
21
+ case ARM_VFP_FPCXT_S:
22
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
23
+ return false;
24
+ }
25
+ if (!s->v8m_secure) {
26
+ return false;
27
+ }
28
+ break;
29
default:
30
return FPSysRegCheckFailed;
31
}
32
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_write(DisasContext *s, int regno,
33
tcg_temp_free_i32(tmp);
34
break;
35
}
36
+ case ARM_VFP_FPCXT_S:
37
+ {
38
+ TCGv_i32 sfpa, control, fpscr;
39
+ /* Set FPSCR[27:0] and CONTROL.SFPA from value */
40
+ tmp = loadfn(s, opaque);
41
+ sfpa = tcg_temp_new_i32();
42
+ tcg_gen_shri_i32(sfpa, tmp, 31);
43
+ control = load_cpu_field(v7m.control[M_REG_S]);
44
+ tcg_gen_deposit_i32(control, control, sfpa,
45
+ R_V7M_CONTROL_SFPA_SHIFT, 1);
46
+ store_cpu_field(control, v7m.control[M_REG_S]);
47
+ fpscr = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
48
+ tcg_gen_andi_i32(fpscr, fpscr, FPCR_NZCV_MASK);
49
+ tcg_gen_andi_i32(tmp, tmp, ~FPCR_NZCV_MASK);
50
+ tcg_gen_or_i32(fpscr, fpscr, tmp);
51
+ store_cpu_field(fpscr, vfp.xregs[ARM_VFP_FPSCR]);
52
+ tcg_temp_free_i32(tmp);
53
+ tcg_temp_free_i32(sfpa);
54
+ break;
55
+ }
56
default:
57
g_assert_not_reached();
58
}
59
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_read(DisasContext *s, int regno,
60
tcg_gen_andi_i32(tmp, tmp, FPCR_NZCV_MASK);
61
storefn(s, opaque, tmp);
62
break;
63
+ case ARM_VFP_FPCXT_S:
64
+ {
65
+ TCGv_i32 control, sfpa, fpscr;
66
+ /* Bits [27:0] from FPSCR, bit [31] from CONTROL.SFPA */
67
+ tmp = tcg_temp_new_i32();
68
+ sfpa = tcg_temp_new_i32();
69
+ gen_helper_vfp_get_fpscr(tmp, cpu_env);
70
+ tcg_gen_andi_i32(tmp, tmp, ~FPCR_NZCV_MASK);
71
+ control = load_cpu_field(v7m.control[M_REG_S]);
72
+ tcg_gen_andi_i32(sfpa, control, R_V7M_CONTROL_SFPA_MASK);
73
+ tcg_gen_shli_i32(sfpa, sfpa, 31 - R_V7M_CONTROL_SFPA_SHIFT);
74
+ tcg_gen_or_i32(tmp, tmp, sfpa);
75
+ tcg_temp_free_i32(sfpa);
76
+ /*
77
+ * Store result before updating FPSCR etc, in case
78
+ * it is a memory write which causes an exception.
79
+ */
80
+ storefn(s, opaque, tmp);
81
+ /*
82
+ * Now we must reset FPSCR from FPDSCR_NS, and clear
83
+ * CONTROL.SFPA; so we'll end the TB here.
84
+ */
85
+ tcg_gen_andi_i32(control, control, ~R_V7M_CONTROL_SFPA_MASK);
86
+ store_cpu_field(control, v7m.control[M_REG_S]);
87
+ fpscr = load_cpu_field(v7m.fpdscr[M_REG_NS]);
88
+ gen_helper_vfp_set_fpscr(cpu_env, fpscr);
89
+ tcg_temp_free_i32(fpscr);
90
+ gen_lookup_tb(s);
91
+ break;
92
+ }
93
default:
94
g_assert_not_reached();
95
}
96
--
97
2.20.1
98
99
diff view generated by jsdifflib
Deleted patch
1
In v8.0M, on exception entry the registers R0-R3, R12, APSR and EPSR
2
are zeroed for an exception taken to Non-secure state; for an
3
exception taken to Secure state they become UNKNOWN, and we chose to
4
leave them at their previous values.
5
1
6
In v8.1M the behaviour is specified more tightly and these registers
7
are always zeroed regardless of the security state that the exception
8
targets (see rule R_KPZV). Implement this.
9
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20201119215617.29887-17-peter.maydell@linaro.org
13
---
14
target/arm/m_helper.c | 16 ++++++++++++----
15
1 file changed, 12 insertions(+), 4 deletions(-)
16
17
diff --git a/target/arm/m_helper.c b/target/arm/m_helper.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/m_helper.c
20
+++ b/target/arm/m_helper.c
21
@@ -XXX,XX +XXX,XX @@ static void v7m_exception_taken(ARMCPU *cpu, uint32_t lr, bool dotailchain,
22
* Clear registers if necessary to prevent non-secure exception
23
* code being able to see register values from secure code.
24
* Where register values become architecturally UNKNOWN we leave
25
- * them with their previous values.
26
+ * them with their previous values. v8.1M is tighter than v8.0M
27
+ * here and always zeroes the caller-saved registers regardless
28
+ * of the security state the exception is targeting.
29
*/
30
if (arm_feature(env, ARM_FEATURE_M_SECURITY)) {
31
- if (!targets_secure) {
32
+ if (!targets_secure || arm_feature(env, ARM_FEATURE_V8_1M)) {
33
/*
34
* Always clear the caller-saved registers (they have been
35
* pushed to the stack earlier in v7m_push_stack()).
36
@@ -XXX,XX +XXX,XX @@ static void v7m_exception_taken(ARMCPU *cpu, uint32_t lr, bool dotailchain,
37
* v7m_push_callee_stack()).
38
*/
39
int i;
40
+ /*
41
+ * r4..r11 are callee-saves, zero only if background
42
+ * state was Secure (EXCRET.S == 1) and exception
43
+ * targets Non-secure state
44
+ */
45
+ bool zero_callee_saves = !targets_secure &&
46
+ (lr & R_V7M_EXCRET_S_MASK);
47
48
for (i = 0; i < 13; i++) {
49
- /* r4..r11 are callee-saves, zero only if EXCRET.S == 1 */
50
- if (i < 4 || i > 11 || (lr & R_V7M_EXCRET_S_MASK)) {
51
+ if (i < 4 || i > 11 || zero_callee_saves) {
52
env->regs[i] = 0;
53
}
54
}
55
--
56
2.20.1
57
58
diff view generated by jsdifflib
Deleted patch
1
In v8.1M, vector table fetch failures don't set HFSR.FORCED (see rule
2
R_LLRP). (In previous versions of the architecture this was either
3
required or IMPDEF.)
4
1
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20201119215617.29887-18-peter.maydell@linaro.org
8
---
9
target/arm/m_helper.c | 6 +++++-
10
1 file changed, 5 insertions(+), 1 deletion(-)
11
12
diff --git a/target/arm/m_helper.c b/target/arm/m_helper.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/m_helper.c
15
+++ b/target/arm/m_helper.c
16
@@ -XXX,XX +XXX,XX @@ load_fail:
17
* The HardFault is Secure if BFHFNMINS is 0 (meaning that all HFs are
18
* secure); otherwise it targets the same security state as the
19
* underlying exception.
20
+ * In v8.1M HardFaults from vector table fetch fails don't set FORCED.
21
*/
22
if (!(cpu->env.v7m.aircr & R_V7M_AIRCR_BFHFNMINS_MASK)) {
23
exc_secure = true;
24
}
25
- env->v7m.hfsr |= R_V7M_HFSR_VECTTBL_MASK | R_V7M_HFSR_FORCED_MASK;
26
+ env->v7m.hfsr |= R_V7M_HFSR_VECTTBL_MASK;
27
+ if (!arm_feature(env, ARM_FEATURE_V8_1M)) {
28
+ env->v7m.hfsr |= R_V7M_HFSR_FORCED_MASK;
29
+ }
30
armv7m_nvic_set_pending_derived(env->nvic, ARMV7M_EXCP_HARD, exc_secure);
31
return false;
32
}
33
--
34
2.20.1
35
36
diff view generated by jsdifflib
Deleted patch
1
In v8.1M a REVIDR register is defined, which is at address 0xe00ecfc
2
and is a read-only IMPDEF register providing implementation specific
3
minor revision information, like the v8A REVIDR_EL1. Implement this.
4
1
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20201119215617.29887-19-peter.maydell@linaro.org
8
---
9
hw/intc/armv7m_nvic.c | 5 +++++
10
1 file changed, 5 insertions(+)
11
12
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/intc/armv7m_nvic.c
15
+++ b/hw/intc/armv7m_nvic.c
16
@@ -XXX,XX +XXX,XX @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
17
}
18
return val;
19
}
20
+ case 0xcfc:
21
+ if (!arm_feature(&cpu->env, ARM_FEATURE_V8_1M)) {
22
+ goto bad_offset;
23
+ }
24
+ return cpu->revidr;
25
case 0xd00: /* CPUID Base. */
26
return cpu->midr;
27
case 0xd04: /* Interrupt Control State (ICSR) */
28
--
29
2.20.1
30
31
diff view generated by jsdifflib
Deleted patch
1
In v8.1M a new exception return check is added which may cause a NOCP
2
UsageFault (see rule R_XLTP): before we clear s0..s15 and the FPSCR
3
we must check whether access to CP10 from the Security state of the
4
returning exception is disabled; if it is then we must take a fault.
5
1
6
(Note that for our implementation CPPWR is always RAZ/WI and so can
7
never cause CP10 accesses to fail.)
8
9
The other v8.1M change to this register-clearing code is that if MVE
10
is implemented VPR must also be cleared, so add a TODO comment to
11
that effect.
12
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
Message-id: 20201119215617.29887-20-peter.maydell@linaro.org
16
---
17
target/arm/m_helper.c | 22 +++++++++++++++++++++-
18
1 file changed, 21 insertions(+), 1 deletion(-)
19
20
diff --git a/target/arm/m_helper.c b/target/arm/m_helper.c
21
index XXXXXXX..XXXXXXX 100644
22
--- a/target/arm/m_helper.c
23
+++ b/target/arm/m_helper.c
24
@@ -XXX,XX +XXX,XX @@ static void do_v7m_exception_exit(ARMCPU *cpu)
25
v7m_exception_taken(cpu, excret, true, false);
26
return;
27
} else {
28
- /* Clear s0..s15 and FPSCR */
29
+ if (arm_feature(env, ARM_FEATURE_V8_1M)) {
30
+ /* v8.1M adds this NOCP check */
31
+ bool nsacr_pass = exc_secure ||
32
+ extract32(env->v7m.nsacr, 10, 1);
33
+ bool cpacr_pass = v7m_cpacr_pass(env, exc_secure, true);
34
+ if (!nsacr_pass) {
35
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE, true);
36
+ env->v7m.cfsr[M_REG_S] |= R_V7M_CFSR_NOCP_MASK;
37
+ qemu_log_mask(CPU_LOG_INT, "...taking UsageFault on existing "
38
+ "stackframe: NSACR prevents clearing FPU registers\n");
39
+ v7m_exception_taken(cpu, excret, true, false);
40
+ } else if (!cpacr_pass) {
41
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE,
42
+ exc_secure);
43
+ env->v7m.cfsr[exc_secure] |= R_V7M_CFSR_NOCP_MASK;
44
+ qemu_log_mask(CPU_LOG_INT, "...taking UsageFault on existing "
45
+ "stackframe: CPACR prevents clearing FPU registers\n");
46
+ v7m_exception_taken(cpu, excret, true, false);
47
+ }
48
+ }
49
+ /* Clear s0..s15 and FPSCR; TODO also VPR when MVE is implemented */
50
int i;
51
52
for (i = 0; i < 16; i += 2) {
53
--
54
2.20.1
55
56
diff view generated by jsdifflib
1
v8.1M adds new encodings of VLLDM and VLSTM (where bit 7 is set).
1
Currently we mishandle the --semihosting-config option if the
2
The only difference is that:
2
user specifies it on the command line more than once. For
3
* the old T1 encodings UNDEF if the implementation implements 32
3
example with:
4
Dregs (this is currently architecturally impossible for M-profile)
4
--semihosting-config target=gdb --semihosting-config arg=foo,arg=bar
5
* the new T2 encodings have the implementation-defined option to
6
read from memory (discarding the data) or write UNKNOWN values to
7
memory for the stack slots that would be D16-D31
8
5
9
We choose not to make those accesses, so for us the two
6
the function qemu_semihosting_config_options() is called twice, once
10
instructions behave identically assuming they don't UNDEF.
7
for each argument. But that function expects to be called only once,
8
and it always unconditionally sets the semihosting.enabled,
9
semihost_chardev and semihosting.target variables. This means that
10
if any of those options were set anywhere except the last
11
--semihosting-config option on the command line, those settings are
12
ignored. In the example above, 'target=gdb' in the first option is
13
overridden by an implied default 'target=auto' in the second.
14
15
The QemuOptsList machinery has a flag for handling this kind of
16
"option group is setting global state": by setting
17
.merge_lists = true;
18
we make the machinery merge all the --semihosting-config arguments
19
the user passes into a single set of options and call our
20
qemu_semihosting_config_options() just once.
11
21
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
22
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
23
Reviewed-by: Luc Michel <luc@lmichel.fr>
14
Message-id: 20201119215617.29887-21-peter.maydell@linaro.org
24
Message-id: 20220526190053.521505-3-peter.maydell@linaro.org
15
---
25
---
16
target/arm/m-nocp.decode | 2 +-
26
semihosting/config.c | 1 +
17
target/arm/translate-vfp.c.inc | 25 +++++++++++++++++++++++++
27
1 file changed, 1 insertion(+)
18
2 files changed, 26 insertions(+), 1 deletion(-)
19
28
20
diff --git a/target/arm/m-nocp.decode b/target/arm/m-nocp.decode
29
diff --git a/semihosting/config.c b/semihosting/config.c
21
index XXXXXXX..XXXXXXX 100644
30
index XXXXXXX..XXXXXXX 100644
22
--- a/target/arm/m-nocp.decode
31
--- a/semihosting/config.c
23
+++ b/target/arm/m-nocp.decode
32
+++ b/semihosting/config.c
24
@@ -XXX,XX +XXX,XX @@
33
@@ -XXX,XX +XXX,XX @@
25
34
26
{
35
QemuOptsList qemu_semihosting_config_opts = {
27
# Special cases which do not take an early NOCP: VLLDM and VLSTM
36
.name = "semihosting-config",
28
- VLLDM_VLSTM 1110 1100 001 l:1 rn:4 0000 1010 0000 0000
37
+ .merge_lists = true,
29
+ VLLDM_VLSTM 1110 1100 001 l:1 rn:4 0000 1010 op:1 000 0000
38
.implied_opt_name = "enable",
30
# VSCCLRM (new in v8.1M) is similar:
39
.head = QTAILQ_HEAD_INITIALIZER(qemu_semihosting_config_opts.head),
31
VSCCLRM 1110 1100 1.01 1111 .... 1011 imm:7 0 vd=%vd_dp size=3
40
.desc = {
32
VSCCLRM 1110 1100 1.01 1111 .... 1010 imm:8 vd=%vd_sp size=2
33
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
34
index XXXXXXX..XXXXXXX 100644
35
--- a/target/arm/translate-vfp.c.inc
36
+++ b/target/arm/translate-vfp.c.inc
37
@@ -XXX,XX +XXX,XX @@ static bool trans_VLLDM_VLSTM(DisasContext *s, arg_VLLDM_VLSTM *a)
38
!arm_dc_feature(s, ARM_FEATURE_V8)) {
39
return false;
40
}
41
+
42
+ if (a->op) {
43
+ /*
44
+ * T2 encoding ({D0-D31} reglist): v8.1M and up. We choose not
45
+ * to take the IMPDEF option to make memory accesses to the stack
46
+ * slots that correspond to the D16-D31 registers (discarding
47
+ * read data and writing UNKNOWN values), so for us the T2
48
+ * encoding behaves identically to the T1 encoding.
49
+ */
50
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
51
+ return false;
52
+ }
53
+ } else {
54
+ /*
55
+ * T1 encoding ({D0-D15} reglist); undef if we have 32 Dregs.
56
+ * This is currently architecturally impossible, but we add the
57
+ * check to stay in line with the pseudocode. Note that we must
58
+ * emit code for the UNDEF so it takes precedence over the NOCP.
59
+ */
60
+ if (dc_isar_feature(aa32_simd_r32, s)) {
61
+ unallocated_encoding(s);
62
+ return true;
63
+ }
64
+ }
65
+
66
/*
67
* If not secure, UNDEF. We must emit code for this
68
* rather than returning false so that this takes
69
--
41
--
70
2.20.1
42
2.25.1
71
72
diff view generated by jsdifflib