1
The following changes since commit 4c41341af76cfc85b5a6c0f87de4838672ab9f89:
1
The following changes since commit 8f6330a807f2642dc2a3cdf33347aa28a4c00a87:
2
2
3
Merge remote-tracking branch 'remotes/aperard/tags/pull-xen-20201020' into staging (2020-10-20 11:20:36 +0100)
3
Merge tag 'pull-maintainer-updates-060324-1' of https://gitlab.com/stsquad/qemu into staging (2024-03-06 16:56:20 +0000)
4
4
5
are available in the Git repository at:
5
are available in the Git repository at:
6
6
7
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20201020
7
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20240308
8
8
9
for you to fetch changes up to 6358890cb939192f6169fdf7664d903bf9b1d338:
9
for you to fetch changes up to bbf6c6dbead82292a20951eb1204442a6b838de9:
10
10
11
tests/tcg/aarch64: Add bti smoke tests (2020-10-20 16:12:02 +0100)
11
target/arm: Move v7m-related code from cpu32.c into a separate file (2024-03-08 14:45:03 +0000)
12
12
13
----------------------------------------------------------------
13
----------------------------------------------------------------
14
target-arm queue:
14
target-arm queue:
15
* Fix AArch32 SMLAD incorrect setting of Q bit
15
* Implement FEAT_ECV
16
* AArch32 VCVT fixed-point to float is always round-to-nearest
16
* STM32L4x5: Implement GPIO device
17
* strongarm: Fix 'time to transmit a char' unit comment
17
* Fix 32-bit SMOPA
18
* Restrict APEI tables generation to the 'virt' machine
18
* Refactor v7m related code from cpu32.c into its own file
19
* bcm2835: minor code cleanups
19
* hw/rtc/sun4v-rtc: Relicense to GPLv2-or-later
20
* correctly flush TLBs when TBI is enabled
21
* tests/qtest: Add npcm7xx timer test
22
* loads-stores.rst: add footnote that clarifies GETPC usage
23
* Fix reported EL for mte_check_fail
24
* Ignore HCR_EL2.ATA when {E2H,TGE} != 11
25
* microbit_i2c: Fix coredump when dump-vmstate
26
* nseries: Fix loading kernel image on n8x0 machines
27
* Implement v8.1M low-overhead-loops
28
* linux-user: Support AArch64 BTI
29
20
30
----------------------------------------------------------------
21
----------------------------------------------------------------
31
Emanuele Giuseppe Esposito (1):
22
Inès Varhol (3):
32
loads-stores.rst: add footnote that clarifies GETPC usage
23
hw/gpio: Implement STM32L4x5 GPIO
24
hw/arm: Connect STM32L4x5 GPIO to STM32L4x5 SoC
25
tests/qtest: Add STM32L4x5 GPIO QTest testcase
33
26
34
Havard Skinnemoen (1):
27
Peter Maydell (9):
35
tests/qtest: Add npcm7xx timer test
28
target/arm: Move some register related defines to internals.h
29
target/arm: Timer _EL02 registers UNDEF for E2H == 0
30
target/arm: use FIELD macro for CNTHCTL bit definitions
31
target/arm: Don't allow RES0 CNTHCTL_EL2 bits to be written
32
target/arm: Implement new FEAT_ECV trap bits
33
target/arm: Define CNTPCTSS_EL0 and CNTVCTSS_EL0
34
target/arm: Implement FEAT_ECV CNTPOFF_EL2 handling
35
target/arm: Enable FEAT_ECV for 'max' CPU
36
hw/rtc/sun4v-rtc: Relicense to GPLv2-or-later
36
37
37
Peng Liang (1):
38
Richard Henderson (1):
38
microbit_i2c: Fix coredump when dump-vmstate
39
target/arm: Fix 32-bit SMOPA
39
40
40
Peter Maydell (12):
41
Thomas Huth (1):
41
target/arm: Fix SMLAD incorrect setting of Q bit
42
target/arm: Move v7m-related code from cpu32.c into a separate file
42
target/arm: AArch32 VCVT fixed-point to float is always round-to-nearest
43
decodetree: Fix codegen for non-overlapping group inside overlapping group
44
target/arm: Implement v8.1M NOCP handling
45
target/arm: Implement v8.1M conditional-select insns
46
target/arm: Make the t32 insn[25:23]=111 group non-overlapping
47
target/arm: Don't allow BLX imm for M-profile
48
target/arm: Implement v8.1M branch-future insns (as NOPs)
49
target/arm: Implement v8.1M low-overhead-loop instructions
50
target/arm: Fix has_vfp/has_neon ID reg squashing for M-profile
51
target/arm: Allow M-profile CPUs with FP16 to set FPSCR.FP16
52
target/arm: Implement FPSCR.LTPSIZE for M-profile LOB extension
53
43
54
Philippe Mathieu-Daudé (10):
44
MAINTAINERS | 1 +
55
hw/arm/strongarm: Fix 'time to transmit a char' unit comment
45
docs/system/arm/b-l475e-iot01a.rst | 2 +-
56
hw/arm: Restrict APEI tables generation to the 'virt' machine
46
docs/system/arm/emulation.rst | 1 +
57
hw/timer/bcm2835: Introduce BCM2835_SYSTIMER_COUNT definition
47
include/hw/arm/stm32l4x5_soc.h | 2 +
58
hw/timer/bcm2835: Rename variable holding CTRL_STATUS register
48
include/hw/gpio/stm32l4x5_gpio.h | 71 +++++
59
hw/timer/bcm2835: Support the timer COMPARE registers
49
include/hw/misc/stm32l4x5_syscfg.h | 3 +-
60
hw/arm/bcm2835_peripherals: Correctly wire the SYS_timer IRQs
50
include/hw/rtc/sun4v-rtc.h | 2 +-
61
hw/intc/bcm2835_ic: Trace GPU/CPU IRQ handlers
51
target/arm/cpu-features.h | 10 +
62
hw/intc/bcm2836_control: Use IRQ definitions instead of magic numbers
52
target/arm/cpu.h | 129 +--------
63
hw/arm/nseries: Fix loading kernel image on n8x0 machines
53
target/arm/internals.h | 151 ++++++++++
64
linux-user/elfload: Avoid leaking interp_name using GLib memory API
54
hw/arm/stm32l4x5_soc.c | 71 ++++-
55
hw/gpio/stm32l4x5_gpio.c | 477 ++++++++++++++++++++++++++++++++
56
hw/misc/stm32l4x5_syscfg.c | 1 +
57
hw/rtc/sun4v-rtc.c | 2 +-
58
target/arm/helper.c | 189 ++++++++++++-
59
target/arm/tcg/cpu-v7m.c | 290 +++++++++++++++++++
60
target/arm/tcg/cpu32.c | 261 ------------------
61
target/arm/tcg/cpu64.c | 1 +
62
target/arm/tcg/sme_helper.c | 77 +++---
63
tests/qtest/stm32l4x5_gpio-test.c | 551 +++++++++++++++++++++++++++++++++++++
64
tests/tcg/aarch64/sme-smopa-1.c | 47 ++++
65
tests/tcg/aarch64/sme-smopa-2.c | 54 ++++
66
hw/arm/Kconfig | 3 +-
67
hw/gpio/Kconfig | 3 +
68
hw/gpio/meson.build | 1 +
69
hw/gpio/trace-events | 6 +
70
target/arm/meson.build | 3 +
71
target/arm/tcg/meson.build | 3 +
72
target/arm/trace-events | 1 +
73
tests/qtest/meson.build | 3 +-
74
tests/tcg/aarch64/Makefile.target | 2 +-
75
31 files changed, 1962 insertions(+), 456 deletions(-)
76
create mode 100644 include/hw/gpio/stm32l4x5_gpio.h
77
create mode 100644 hw/gpio/stm32l4x5_gpio.c
78
create mode 100644 target/arm/tcg/cpu-v7m.c
79
create mode 100644 tests/qtest/stm32l4x5_gpio-test.c
80
create mode 100644 tests/tcg/aarch64/sme-smopa-1.c
81
create mode 100644 tests/tcg/aarch64/sme-smopa-2.c
65
82
66
Richard Henderson (16):
67
accel/tcg: Add tlb_flush_page_bits_by_mmuidx*
68
target/arm: Use tlb_flush_page_bits_by_mmuidx*
69
target/arm: Remove redundant mmu_idx lookup
70
target/arm: Fix reported EL for mte_check_fail
71
target/arm: Ignore HCR_EL2.ATA when {E2H,TGE} != 11
72
linux-user/aarch64: Reset btype for signals
73
linux-user: Set PAGE_TARGET_1 for TARGET_PROT_BTI
74
include/elf: Add defines related to GNU property notes for AArch64
75
linux-user/elfload: Fix coding style in load_elf_image
76
linux-user/elfload: Adjust iteration over phdr
77
linux-user/elfload: Move PT_INTERP detection to first loop
78
linux-user/elfload: Use Error for load_elf_image
79
linux-user/elfload: Use Error for load_elf_interp
80
linux-user/elfload: Parse NT_GNU_PROPERTY_TYPE_0 notes
81
linux-user/elfload: Parse GNU_PROPERTY_AARCH64_FEATURE_1_AND
82
tests/tcg/aarch64: Add bti smoke tests
83
84
docs/devel/loads-stores.rst | 8 +-
85
default-configs/devices/arm-softmmu.mak | 1 -
86
include/elf.h | 22 ++
87
include/exec/cpu-all.h | 2 +
88
include/exec/exec-all.h | 36 ++
89
include/hw/timer/bcm2835_systmr.h | 17 +-
90
linux-user/qemu.h | 4 +
91
linux-user/syscall_defs.h | 4 +
92
target/arm/cpu.h | 13 +
93
target/arm/helper.h | 13 +
94
target/arm/internals.h | 9 +-
95
target/arm/m-nocp.decode | 10 +-
96
target/arm/t32.decode | 50 ++-
97
accel/tcg/cputlb.c | 275 +++++++++++++++-
98
hw/arm/bcm2835_peripherals.c | 13 +-
99
hw/arm/nseries.c | 1 +
100
hw/arm/strongarm.c | 2 +-
101
hw/i2c/microbit_i2c.c | 1 +
102
hw/intc/bcm2835_ic.c | 4 +-
103
hw/intc/bcm2836_control.c | 8 +-
104
hw/timer/bcm2835_systmr.c | 57 ++--
105
linux-user/aarch64/signal.c | 10 +-
106
linux-user/elfload.c | 326 ++++++++++++++----
107
linux-user/mmap.c | 16 +
108
target/arm/cpu.c | 38 ++-
109
target/arm/helper.c | 55 +++-
110
target/arm/mte_helper.c | 13 +-
111
target/arm/translate-a64.c | 6 +-
112
target/arm/translate.c | 239 +++++++++++++-
113
target/arm/vfp_helper.c | 76 +++--
114
tests/qtest/npcm7xx_timer-test.c | 562 ++++++++++++++++++++++++++++++++
115
tests/tcg/aarch64/bti-1.c | 62 ++++
116
tests/tcg/aarch64/bti-2.c | 108 ++++++
117
tests/tcg/aarch64/bti-crt.inc.c | 51 +++
118
hw/arm/Kconfig | 1 +
119
hw/intc/trace-events | 4 +
120
hw/timer/trace-events | 6 +-
121
scripts/decodetree.py | 2 +-
122
target/arm/translate-vfp.c.inc | 41 ++-
123
tests/qtest/meson.build | 1 +
124
tests/tcg/aarch64/Makefile.target | 10 +
125
tests/tcg/configure.sh | 4 +
126
42 files changed, 1973 insertions(+), 208 deletions(-)
127
create mode 100644 tests/qtest/npcm7xx_timer-test.c
128
create mode 100644 tests/tcg/aarch64/bti-1.c
129
create mode 100644 tests/tcg/aarch64/bti-2.c
130
create mode 100644 tests/tcg/aarch64/bti-crt.inc.c
131
diff view generated by jsdifflib
Deleted patch
1
The SMLAD instruction is supposed to:
2
* signed multiply Rn[15:0] * Rm[15:0]
3
* signed multiply Rn[31:16] * Rm[31:16]
4
* perform a signed addition of the products and Ra
5
* set Rd to the low 32 bits of the theoretical
6
infinite-precision result
7
* set the Q flag if the sign-extension of Rd
8
would differ from the infinite-precision result
9
(ie on overflow)
10
1
11
Our current implementation doesn't quite do this, though: it performs
12
an addition of the products setting Q on overflow, and then it adds
13
Ra, again possibly setting Q. This sometimes incorrectly sets Q when
14
the architecturally mandated only-check-for-overflow-once algorithm
15
does not. For instance:
16
r1 = 0x80008000; r2 = 0x80008000; r3 = 0xffffffff
17
smlad r0, r1, r2, r3
18
This is (-32768 * -32768) + (-32768 * -32768) - 1
19
20
The products are both 0x4000_0000, so when added together as 32-bit
21
signed numbers they overflow (and QEMU sets Q), but because the
22
addition of Ra == -1 brings the total back down to 0x7fff_ffff
23
there is no overflow for the complete operation and setting Q is
24
incorrect.
25
26
Fix this edge case by resorting to 64-bit arithmetic for the
27
case where we need to add three values together.
28
29
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
30
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
31
Message-id: 20201009144712.11187-1-peter.maydell@linaro.org
32
---
33
target/arm/translate.c | 58 ++++++++++++++++++++++++++++++++++--------
34
1 file changed, 48 insertions(+), 10 deletions(-)
35
36
diff --git a/target/arm/translate.c b/target/arm/translate.c
37
index XXXXXXX..XXXXXXX 100644
38
--- a/target/arm/translate.c
39
+++ b/target/arm/translate.c
40
@@ -XXX,XX +XXX,XX @@ static bool op_smlad(DisasContext *s, arg_rrrr *a, bool m_swap, bool sub)
41
gen_smul_dual(t1, t2);
42
43
if (sub) {
44
- /* This subtraction cannot overflow. */
45
+ /*
46
+ * This subtraction cannot overflow, so we can do a simple
47
+ * 32-bit subtraction and then a possible 32-bit saturating
48
+ * addition of Ra.
49
+ */
50
tcg_gen_sub_i32(t1, t1, t2);
51
+ tcg_temp_free_i32(t2);
52
+
53
+ if (a->ra != 15) {
54
+ t2 = load_reg(s, a->ra);
55
+ gen_helper_add_setq(t1, cpu_env, t1, t2);
56
+ tcg_temp_free_i32(t2);
57
+ }
58
+ } else if (a->ra == 15) {
59
+ /* Single saturation-checking addition */
60
+ gen_helper_add_setq(t1, cpu_env, t1, t2);
61
+ tcg_temp_free_i32(t2);
62
} else {
63
/*
64
- * This addition cannot overflow 32 bits; however it may
65
- * overflow considered as a signed operation, in which case
66
- * we must set the Q flag.
67
+ * We need to add the products and Ra together and then
68
+ * determine whether the final result overflowed. Doing
69
+ * this as two separate add-and-check-overflow steps incorrectly
70
+ * sets Q for cases like (-32768 * -32768) + (-32768 * -32768) + -1.
71
+ * Do all the arithmetic at 64-bits and then check for overflow.
72
*/
73
- gen_helper_add_setq(t1, cpu_env, t1, t2);
74
- }
75
- tcg_temp_free_i32(t2);
76
+ TCGv_i64 p64, q64;
77
+ TCGv_i32 t3, qf, one;
78
79
- if (a->ra != 15) {
80
- t2 = load_reg(s, a->ra);
81
- gen_helper_add_setq(t1, cpu_env, t1, t2);
82
+ p64 = tcg_temp_new_i64();
83
+ q64 = tcg_temp_new_i64();
84
+ tcg_gen_ext_i32_i64(p64, t1);
85
+ tcg_gen_ext_i32_i64(q64, t2);
86
+ tcg_gen_add_i64(p64, p64, q64);
87
+ load_reg_var(s, t2, a->ra);
88
+ tcg_gen_ext_i32_i64(q64, t2);
89
+ tcg_gen_add_i64(p64, p64, q64);
90
+ tcg_temp_free_i64(q64);
91
+
92
+ tcg_gen_extr_i64_i32(t1, t2, p64);
93
+ tcg_temp_free_i64(p64);
94
+ /*
95
+ * t1 is the low half of the result which goes into Rd.
96
+ * We have overflow and must set Q if the high half (t2)
97
+ * is different from the sign-extension of t1.
98
+ */
99
+ t3 = tcg_temp_new_i32();
100
+ tcg_gen_sari_i32(t3, t1, 31);
101
+ qf = load_cpu_field(QF);
102
+ one = tcg_const_i32(1);
103
+ tcg_gen_movcond_i32(TCG_COND_NE, qf, t2, t3, one, qf);
104
+ store_cpu_field(qf, QF);
105
+ tcg_temp_free_i32(one);
106
+ tcg_temp_free_i32(t3);
107
tcg_temp_free_i32(t2);
108
}
109
store_reg(s, a->rd, t1);
110
--
111
2.20.1
112
113
diff view generated by jsdifflib
1
From v8.1M, disabled-coprocessor handling changes slightly:
1
cpu.h has a lot of #defines relating to CPU register fields.
2
* coprocessors 8, 9, 14 and 15 are also governed by the
2
Most of these aren't actually used outside target/arm code,
3
cp10 enable bit, like cp11
3
so there's no point in cluttering up the cpu.h file with them.
4
* an extra range of instruction patterns is considered
4
Move some easy ones to internals.h.
5
to be inside the coprocessor space
6
7
We previously marked these up with TODO comments; implement the
8
correct behaviour.
9
10
Unfortunately there is no ID register field which indicates this
11
behaviour. We could in theory test an unrelated ID register which
12
indicates guaranteed-to-be-in-v8.1M behaviour like ID_ISAR0.CmpBranch
13
>= 3 (low-overhead-loops), but it seems better to simply define a new
14
ARM_FEATURE_V8_1M feature flag and use it for this and other
15
new-in-v8.1M behaviour that isn't identifiable from the ID registers.
16
5
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
18
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
19
Message-id: 20201019151301.2046-3-peter.maydell@linaro.org
9
Message-id: 20240301183219.2424889-2-peter.maydell@linaro.org
20
---
10
---
21
target/arm/cpu.h | 1 +
11
target/arm/cpu.h | 128 -----------------------------------------
22
target/arm/m-nocp.decode | 10 ++++++----
12
target/arm/internals.h | 128 +++++++++++++++++++++++++++++++++++++++++
23
target/arm/translate-vfp.c.inc | 17 +++++++++++++++--
13
2 files changed, 128 insertions(+), 128 deletions(-)
24
3 files changed, 22 insertions(+), 6 deletions(-)
25
14
26
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
15
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
27
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
28
--- a/target/arm/cpu.h
17
--- a/target/arm/cpu.h
29
+++ b/target/arm/cpu.h
18
+++ b/target/arm/cpu.h
30
@@ -XXX,XX +XXX,XX @@ enum arm_features {
19
@@ -XXX,XX +XXX,XX @@ typedef struct ARMGenericTimer {
31
ARM_FEATURE_VBAR, /* has cp15 VBAR */
20
uint64_t ctl; /* Timer Control register */
32
ARM_FEATURE_M_SECURITY, /* M profile Security Extension */
21
} ARMGenericTimer;
33
ARM_FEATURE_M_MAIN, /* M profile Main Extension */
22
34
+ ARM_FEATURE_V8_1M, /* M profile extras only in v8.1M and later */
23
-#define VTCR_NSW (1u << 29)
35
};
24
-#define VTCR_NSA (1u << 30)
36
25
-#define VSTCR_SW VTCR_NSW
37
static inline int arm_feature(CPUARMState *env, int feature)
26
-#define VSTCR_SA VTCR_NSA
38
diff --git a/target/arm/m-nocp.decode b/target/arm/m-nocp.decode
27
-
28
/* Define a maximum sized vector register.
29
* For 32-bit, this is a 128-bit NEON/AdvSIMD register.
30
* For 64-bit, this is a 2048-bit SVE register.
31
@@ -XXX,XX +XXX,XX @@ void pmu_init(ARMCPU *cpu);
32
#define SCTLR_SPINTMASK (1ULL << 62) /* FEAT_NMI */
33
#define SCTLR_TIDCP (1ULL << 63) /* FEAT_TIDCP1 */
34
35
-/* Bit definitions for CPACR (AArch32 only) */
36
-FIELD(CPACR, CP10, 20, 2)
37
-FIELD(CPACR, CP11, 22, 2)
38
-FIELD(CPACR, TRCDIS, 28, 1) /* matches CPACR_EL1.TTA */
39
-FIELD(CPACR, D32DIS, 30, 1) /* up to v7; RAZ in v8 */
40
-FIELD(CPACR, ASEDIS, 31, 1)
41
-
42
-/* Bit definitions for CPACR_EL1 (AArch64 only) */
43
-FIELD(CPACR_EL1, ZEN, 16, 2)
44
-FIELD(CPACR_EL1, FPEN, 20, 2)
45
-FIELD(CPACR_EL1, SMEN, 24, 2)
46
-FIELD(CPACR_EL1, TTA, 28, 1) /* matches CPACR.TRCDIS */
47
-
48
-/* Bit definitions for HCPTR (AArch32 only) */
49
-FIELD(HCPTR, TCP10, 10, 1)
50
-FIELD(HCPTR, TCP11, 11, 1)
51
-FIELD(HCPTR, TASE, 15, 1)
52
-FIELD(HCPTR, TTA, 20, 1)
53
-FIELD(HCPTR, TAM, 30, 1) /* matches CPTR_EL2.TAM */
54
-FIELD(HCPTR, TCPAC, 31, 1) /* matches CPTR_EL2.TCPAC */
55
-
56
-/* Bit definitions for CPTR_EL2 (AArch64 only) */
57
-FIELD(CPTR_EL2, TZ, 8, 1) /* !E2H */
58
-FIELD(CPTR_EL2, TFP, 10, 1) /* !E2H, matches HCPTR.TCP10 */
59
-FIELD(CPTR_EL2, TSM, 12, 1) /* !E2H */
60
-FIELD(CPTR_EL2, ZEN, 16, 2) /* E2H */
61
-FIELD(CPTR_EL2, FPEN, 20, 2) /* E2H */
62
-FIELD(CPTR_EL2, SMEN, 24, 2) /* E2H */
63
-FIELD(CPTR_EL2, TTA, 28, 1)
64
-FIELD(CPTR_EL2, TAM, 30, 1) /* matches HCPTR.TAM */
65
-FIELD(CPTR_EL2, TCPAC, 31, 1) /* matches HCPTR.TCPAC */
66
-
67
-/* Bit definitions for CPTR_EL3 (AArch64 only) */
68
-FIELD(CPTR_EL3, EZ, 8, 1)
69
-FIELD(CPTR_EL3, TFP, 10, 1)
70
-FIELD(CPTR_EL3, ESM, 12, 1)
71
-FIELD(CPTR_EL3, TTA, 20, 1)
72
-FIELD(CPTR_EL3, TAM, 30, 1)
73
-FIELD(CPTR_EL3, TCPAC, 31, 1)
74
-
75
-#define MDCR_MTPME (1U << 28)
76
-#define MDCR_TDCC (1U << 27)
77
-#define MDCR_HLP (1U << 26) /* MDCR_EL2 */
78
-#define MDCR_SCCD (1U << 23) /* MDCR_EL3 */
79
-#define MDCR_HCCD (1U << 23) /* MDCR_EL2 */
80
-#define MDCR_EPMAD (1U << 21)
81
-#define MDCR_EDAD (1U << 20)
82
-#define MDCR_TTRF (1U << 19)
83
-#define MDCR_STE (1U << 18) /* MDCR_EL3 */
84
-#define MDCR_SPME (1U << 17) /* MDCR_EL3 */
85
-#define MDCR_HPMD (1U << 17) /* MDCR_EL2 */
86
-#define MDCR_SDD (1U << 16)
87
-#define MDCR_SPD (3U << 14)
88
-#define MDCR_TDRA (1U << 11)
89
-#define MDCR_TDOSA (1U << 10)
90
-#define MDCR_TDA (1U << 9)
91
-#define MDCR_TDE (1U << 8)
92
-#define MDCR_HPME (1U << 7)
93
-#define MDCR_TPM (1U << 6)
94
-#define MDCR_TPMCR (1U << 5)
95
-#define MDCR_HPMN (0x1fU)
96
-
97
-/* Not all of the MDCR_EL3 bits are present in the 32-bit SDCR */
98
-#define SDCR_VALID_MASK (MDCR_MTPME | MDCR_TDCC | MDCR_SCCD | \
99
- MDCR_EPMAD | MDCR_EDAD | MDCR_TTRF | \
100
- MDCR_STE | MDCR_SPME | MDCR_SPD)
101
-
102
#define CPSR_M (0x1fU)
103
#define CPSR_T (1U << 5)
104
#define CPSR_F (1U << 6)
105
@@ -XXX,XX +XXX,XX @@ FIELD(CPTR_EL3, TCPAC, 31, 1)
106
#define XPSR_NZCV CPSR_NZCV
107
#define XPSR_IT CPSR_IT
108
109
-#define TTBCR_N (7U << 0) /* TTBCR.EAE==0 */
110
-#define TTBCR_T0SZ (7U << 0) /* TTBCR.EAE==1 */
111
-#define TTBCR_PD0 (1U << 4)
112
-#define TTBCR_PD1 (1U << 5)
113
-#define TTBCR_EPD0 (1U << 7)
114
-#define TTBCR_IRGN0 (3U << 8)
115
-#define TTBCR_ORGN0 (3U << 10)
116
-#define TTBCR_SH0 (3U << 12)
117
-#define TTBCR_T1SZ (3U << 16)
118
-#define TTBCR_A1 (1U << 22)
119
-#define TTBCR_EPD1 (1U << 23)
120
-#define TTBCR_IRGN1 (3U << 24)
121
-#define TTBCR_ORGN1 (3U << 26)
122
-#define TTBCR_SH1 (1U << 28)
123
-#define TTBCR_EAE (1U << 31)
124
-
125
-FIELD(VTCR, T0SZ, 0, 6)
126
-FIELD(VTCR, SL0, 6, 2)
127
-FIELD(VTCR, IRGN0, 8, 2)
128
-FIELD(VTCR, ORGN0, 10, 2)
129
-FIELD(VTCR, SH0, 12, 2)
130
-FIELD(VTCR, TG0, 14, 2)
131
-FIELD(VTCR, PS, 16, 3)
132
-FIELD(VTCR, VS, 19, 1)
133
-FIELD(VTCR, HA, 21, 1)
134
-FIELD(VTCR, HD, 22, 1)
135
-FIELD(VTCR, HWU59, 25, 1)
136
-FIELD(VTCR, HWU60, 26, 1)
137
-FIELD(VTCR, HWU61, 27, 1)
138
-FIELD(VTCR, HWU62, 28, 1)
139
-FIELD(VTCR, NSW, 29, 1)
140
-FIELD(VTCR, NSA, 30, 1)
141
-FIELD(VTCR, DS, 32, 1)
142
-FIELD(VTCR, SL2, 33, 1)
143
-
144
/* Bit definitions for ARMv8 SPSR (PSTATE) format.
145
* Only these are valid when in AArch64 mode; in
146
* AArch32 mode SPSRs are basically CPSR-format.
147
@@ -XXX,XX +XXX,XX @@ static inline void xpsr_write(CPUARMState *env, uint32_t val, uint32_t mask)
148
#define HCR_TWEDEN (1ULL << 59)
149
#define HCR_TWEDEL MAKE_64BIT_MASK(60, 4)
150
151
-#define HCRX_ENAS0 (1ULL << 0)
152
-#define HCRX_ENALS (1ULL << 1)
153
-#define HCRX_ENASR (1ULL << 2)
154
-#define HCRX_FNXS (1ULL << 3)
155
-#define HCRX_FGTNXS (1ULL << 4)
156
-#define HCRX_SMPME (1ULL << 5)
157
-#define HCRX_TALLINT (1ULL << 6)
158
-#define HCRX_VINMI (1ULL << 7)
159
-#define HCRX_VFNMI (1ULL << 8)
160
-#define HCRX_CMOW (1ULL << 9)
161
-#define HCRX_MCE2 (1ULL << 10)
162
-#define HCRX_MSCEN (1ULL << 11)
163
-
164
-#define HPFAR_NS (1ULL << 63)
165
-
166
#define SCR_NS (1ULL << 0)
167
#define SCR_IRQ (1ULL << 1)
168
#define SCR_FIQ (1ULL << 2)
169
@@ -XXX,XX +XXX,XX @@ static inline void xpsr_write(CPUARMState *env, uint32_t val, uint32_t mask)
170
#define SCR_GPF (1ULL << 48)
171
#define SCR_NSE (1ULL << 62)
172
173
-#define HSTR_TTEE (1 << 16)
174
-#define HSTR_TJDBX (1 << 17)
175
-
176
-#define CNTHCTL_CNTVMASK (1 << 18)
177
-#define CNTHCTL_CNTPMASK (1 << 19)
178
-
179
/* Return the current FPSCR value. */
180
uint32_t vfp_get_fpscr(CPUARMState *env);
181
void vfp_set_fpscr(CPUARMState *env, uint32_t val);
182
diff --git a/target/arm/internals.h b/target/arm/internals.h
39
index XXXXXXX..XXXXXXX 100644
183
index XXXXXXX..XXXXXXX 100644
40
--- a/target/arm/m-nocp.decode
184
--- a/target/arm/internals.h
41
+++ b/target/arm/m-nocp.decode
185
+++ b/target/arm/internals.h
42
@@ -XXX,XX +XXX,XX @@
186
@@ -XXX,XX +XXX,XX @@ FIELD(DBGWCR, WT, 20, 1)
43
# If the coprocessor is not present or disabled then we will generate
187
FIELD(DBGWCR, MASK, 24, 5)
44
# the NOCP exception; otherwise we let the insn through to the main decode.
188
FIELD(DBGWCR, SSCE, 29, 1)
45
189
46
+&nocp cp
190
+#define VTCR_NSW (1u << 29)
47
+
191
+#define VTCR_NSA (1u << 30)
48
{
192
+#define VSTCR_SW VTCR_NSW
49
# Special cases which do not take an early NOCP: VLLDM and VLSTM
193
+#define VSTCR_SA VTCR_NSA
50
VLLDM_VLSTM 1110 1100 001 l:1 rn:4 0000 1010 0000 0000
194
+
51
# TODO: VSCCLRM (new in v8.1M) is similar:
195
+/* Bit definitions for CPACR (AArch32 only) */
52
#VSCCLRM 1110 1100 1-01 1111 ---- 1011 ---- ---0
196
+FIELD(CPACR, CP10, 20, 2)
53
197
+FIELD(CPACR, CP11, 22, 2)
54
- NOCP 111- 1110 ---- ---- ---- cp:4 ---- ----
198
+FIELD(CPACR, TRCDIS, 28, 1) /* matches CPACR_EL1.TTA */
55
- NOCP 111- 110- ---- ---- ---- cp:4 ---- ----
199
+FIELD(CPACR, D32DIS, 30, 1) /* up to v7; RAZ in v8 */
56
- # TODO: From v8.1M onwards we will also want this range to NOCP
200
+FIELD(CPACR, ASEDIS, 31, 1)
57
- #NOCP_8_1 111- 1111 ---- ---- ---- ---- ---- ---- cp=10
201
+
58
+ NOCP 111- 1110 ---- ---- ---- cp:4 ---- ---- &nocp
202
+/* Bit definitions for CPACR_EL1 (AArch64 only) */
59
+ NOCP 111- 110- ---- ---- ---- cp:4 ---- ---- &nocp
203
+FIELD(CPACR_EL1, ZEN, 16, 2)
60
+ # From v8.1M onwards this range will also NOCP:
204
+FIELD(CPACR_EL1, FPEN, 20, 2)
61
+ NOCP_8_1 111- 1111 ---- ---- ---- ---- ---- ---- &nocp cp=10
205
+FIELD(CPACR_EL1, SMEN, 24, 2)
62
}
206
+FIELD(CPACR_EL1, TTA, 28, 1) /* matches CPACR.TRCDIS */
63
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
207
+
64
index XXXXXXX..XXXXXXX 100644
208
+/* Bit definitions for HCPTR (AArch32 only) */
65
--- a/target/arm/translate-vfp.c.inc
209
+FIELD(HCPTR, TCP10, 10, 1)
66
+++ b/target/arm/translate-vfp.c.inc
210
+FIELD(HCPTR, TCP11, 11, 1)
67
@@ -XXX,XX +XXX,XX @@ static bool trans_VLLDM_VLSTM(DisasContext *s, arg_VLLDM_VLSTM *a)
211
+FIELD(HCPTR, TASE, 15, 1)
68
return true;
212
+FIELD(HCPTR, TTA, 20, 1)
69
}
213
+FIELD(HCPTR, TAM, 30, 1) /* matches CPTR_EL2.TAM */
70
214
+FIELD(HCPTR, TCPAC, 31, 1) /* matches CPTR_EL2.TCPAC */
71
-static bool trans_NOCP(DisasContext *s, arg_NOCP *a)
215
+
72
+static bool trans_NOCP(DisasContext *s, arg_nocp *a)
216
+/* Bit definitions for CPTR_EL2 (AArch64 only) */
73
{
217
+FIELD(CPTR_EL2, TZ, 8, 1) /* !E2H */
74
/*
218
+FIELD(CPTR_EL2, TFP, 10, 1) /* !E2H, matches HCPTR.TCP10 */
75
* Handle M-profile early check for disabled coprocessor:
219
+FIELD(CPTR_EL2, TSM, 12, 1) /* !E2H */
76
@@ -XXX,XX +XXX,XX @@ static bool trans_NOCP(DisasContext *s, arg_NOCP *a)
220
+FIELD(CPTR_EL2, ZEN, 16, 2) /* E2H */
77
if (a->cp == 11) {
221
+FIELD(CPTR_EL2, FPEN, 20, 2) /* E2H */
78
a->cp = 10;
222
+FIELD(CPTR_EL2, SMEN, 24, 2) /* E2H */
79
}
223
+FIELD(CPTR_EL2, TTA, 28, 1)
80
- /* TODO: in v8.1M cp 8, 9, 14, 15 also are governed by the cp10 enable */
224
+FIELD(CPTR_EL2, TAM, 30, 1) /* matches HCPTR.TAM */
81
+ if (arm_dc_feature(s, ARM_FEATURE_V8_1M) &&
225
+FIELD(CPTR_EL2, TCPAC, 31, 1) /* matches HCPTR.TCPAC */
82
+ (a->cp == 8 || a->cp == 9 || a->cp == 14 || a->cp == 15)) {
226
+
83
+ /* in v8.1M cp 8, 9, 14, 15 also are governed by the cp10 enable */
227
+/* Bit definitions for CPTR_EL3 (AArch64 only) */
84
+ a->cp = 10;
228
+FIELD(CPTR_EL3, EZ, 8, 1)
85
+ }
229
+FIELD(CPTR_EL3, TFP, 10, 1)
86
230
+FIELD(CPTR_EL3, ESM, 12, 1)
87
if (a->cp != 10) {
231
+FIELD(CPTR_EL3, TTA, 20, 1)
88
gen_exception_insn(s, s->pc_curr, EXCP_NOCP,
232
+FIELD(CPTR_EL3, TAM, 30, 1)
89
@@ -XXX,XX +XXX,XX @@ static bool trans_NOCP(DisasContext *s, arg_NOCP *a)
233
+FIELD(CPTR_EL3, TCPAC, 31, 1)
90
return false;
234
+
91
}
235
+#define MDCR_MTPME (1U << 28)
92
236
+#define MDCR_TDCC (1U << 27)
93
+static bool trans_NOCP_8_1(DisasContext *s, arg_nocp *a)
237
+#define MDCR_HLP (1U << 26) /* MDCR_EL2 */
94
+{
238
+#define MDCR_SCCD (1U << 23) /* MDCR_EL3 */
95
+ /* This range needs a coprocessor check for v8.1M and later only */
239
+#define MDCR_HCCD (1U << 23) /* MDCR_EL2 */
96
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
240
+#define MDCR_EPMAD (1U << 21)
97
+ return false;
241
+#define MDCR_EDAD (1U << 20)
98
+ }
242
+#define MDCR_TTRF (1U << 19)
99
+ return trans_NOCP(s, a);
243
+#define MDCR_STE (1U << 18) /* MDCR_EL3 */
100
+}
244
+#define MDCR_SPME (1U << 17) /* MDCR_EL3 */
101
+
245
+#define MDCR_HPMD (1U << 17) /* MDCR_EL2 */
102
static bool trans_VINS(DisasContext *s, arg_VINS *a)
246
+#define MDCR_SDD (1U << 16)
103
{
247
+#define MDCR_SPD (3U << 14)
104
TCGv_i32 rd, rm;
248
+#define MDCR_TDRA (1U << 11)
249
+#define MDCR_TDOSA (1U << 10)
250
+#define MDCR_TDA (1U << 9)
251
+#define MDCR_TDE (1U << 8)
252
+#define MDCR_HPME (1U << 7)
253
+#define MDCR_TPM (1U << 6)
254
+#define MDCR_TPMCR (1U << 5)
255
+#define MDCR_HPMN (0x1fU)
256
+
257
+/* Not all of the MDCR_EL3 bits are present in the 32-bit SDCR */
258
+#define SDCR_VALID_MASK (MDCR_MTPME | MDCR_TDCC | MDCR_SCCD | \
259
+ MDCR_EPMAD | MDCR_EDAD | MDCR_TTRF | \
260
+ MDCR_STE | MDCR_SPME | MDCR_SPD)
261
+
262
+#define TTBCR_N (7U << 0) /* TTBCR.EAE==0 */
263
+#define TTBCR_T0SZ (7U << 0) /* TTBCR.EAE==1 */
264
+#define TTBCR_PD0 (1U << 4)
265
+#define TTBCR_PD1 (1U << 5)
266
+#define TTBCR_EPD0 (1U << 7)
267
+#define TTBCR_IRGN0 (3U << 8)
268
+#define TTBCR_ORGN0 (3U << 10)
269
+#define TTBCR_SH0 (3U << 12)
270
+#define TTBCR_T1SZ (3U << 16)
271
+#define TTBCR_A1 (1U << 22)
272
+#define TTBCR_EPD1 (1U << 23)
273
+#define TTBCR_IRGN1 (3U << 24)
274
+#define TTBCR_ORGN1 (3U << 26)
275
+#define TTBCR_SH1 (1U << 28)
276
+#define TTBCR_EAE (1U << 31)
277
+
278
+FIELD(VTCR, T0SZ, 0, 6)
279
+FIELD(VTCR, SL0, 6, 2)
280
+FIELD(VTCR, IRGN0, 8, 2)
281
+FIELD(VTCR, ORGN0, 10, 2)
282
+FIELD(VTCR, SH0, 12, 2)
283
+FIELD(VTCR, TG0, 14, 2)
284
+FIELD(VTCR, PS, 16, 3)
285
+FIELD(VTCR, VS, 19, 1)
286
+FIELD(VTCR, HA, 21, 1)
287
+FIELD(VTCR, HD, 22, 1)
288
+FIELD(VTCR, HWU59, 25, 1)
289
+FIELD(VTCR, HWU60, 26, 1)
290
+FIELD(VTCR, HWU61, 27, 1)
291
+FIELD(VTCR, HWU62, 28, 1)
292
+FIELD(VTCR, NSW, 29, 1)
293
+FIELD(VTCR, NSA, 30, 1)
294
+FIELD(VTCR, DS, 32, 1)
295
+FIELD(VTCR, SL2, 33, 1)
296
+
297
+#define HCRX_ENAS0 (1ULL << 0)
298
+#define HCRX_ENALS (1ULL << 1)
299
+#define HCRX_ENASR (1ULL << 2)
300
+#define HCRX_FNXS (1ULL << 3)
301
+#define HCRX_FGTNXS (1ULL << 4)
302
+#define HCRX_SMPME (1ULL << 5)
303
+#define HCRX_TALLINT (1ULL << 6)
304
+#define HCRX_VINMI (1ULL << 7)
305
+#define HCRX_VFNMI (1ULL << 8)
306
+#define HCRX_CMOW (1ULL << 9)
307
+#define HCRX_MCE2 (1ULL << 10)
308
+#define HCRX_MSCEN (1ULL << 11)
309
+
310
+#define HPFAR_NS (1ULL << 63)
311
+
312
+#define HSTR_TTEE (1 << 16)
313
+#define HSTR_TJDBX (1 << 17)
314
+
315
+#define CNTHCTL_CNTVMASK (1 << 18)
316
+#define CNTHCTL_CNTPMASK (1 << 19)
317
+
318
/* We use a few fake FSR values for internal purposes in M profile.
319
* M profile cores don't have A/R format FSRs, but currently our
320
* get_phys_addr() code assumes A/R profile and reports failures via
105
--
321
--
106
2.20.1
322
2.34.1
107
323
108
324
diff view generated by jsdifflib
1
M-profile CPUs with half-precision floating point support should
1
The timer _EL02 registers should UNDEF for invalid accesses from EL2
2
be able to write to FPSCR.FZ16, but an M-profile specific masking
2
or EL3 when HCR_EL2.E2H == 0, not take a cp access trap. We were
3
of the value at the top of vfp_set_fpscr() currently prevents that.
3
delivering the exception to EL2 with the wrong syndrome.
4
This is not yet an active bug because we have no M-profile
5
FP16 CPUs, but needs to be fixed before we can add any.
6
7
The bits that the masking is effectively preventing from being
8
set are the A-profile only short-vector Len and Stride fields,
9
plus the Neon QC bit. Rearrange the order of the function so
10
that those fields are handled earlier and only under a suitable
11
guard; this allows us to drop the M-profile specific masking,
12
making FZ16 writeable.
13
14
This change also makes the QC bit correctly RAZ/WI for older
15
no-Neon A-profile cores.
16
17
This refactoring also paves the way for the low-overhead-branch
18
LTPSIZE field, which uses some of the bits that are used for
19
A-profile Stride and Len.
20
4
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
22
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
23
Message-id: 20201019151301.2046-10-peter.maydell@linaro.org
7
Message-id: 20240301183219.2424889-3-peter.maydell@linaro.org
24
---
8
---
25
target/arm/vfp_helper.c | 47 ++++++++++++++++++++++++-----------------
9
target/arm/helper.c | 2 +-
26
1 file changed, 28 insertions(+), 19 deletions(-)
10
1 file changed, 1 insertion(+), 1 deletion(-)
27
11
28
diff --git a/target/arm/vfp_helper.c b/target/arm/vfp_helper.c
12
diff --git a/target/arm/helper.c b/target/arm/helper.c
29
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
30
--- a/target/arm/vfp_helper.c
14
--- a/target/arm/helper.c
31
+++ b/target/arm/vfp_helper.c
15
+++ b/target/arm/helper.c
32
@@ -XXX,XX +XXX,XX @@ void HELPER(vfp_set_fpscr)(CPUARMState *env, uint32_t val)
16
@@ -XXX,XX +XXX,XX @@ static CPAccessResult e2h_access(CPUARMState *env, const ARMCPRegInfo *ri,
33
val &= ~FPCR_FZ16;
17
return CP_ACCESS_OK;
34
}
18
}
35
19
if (!(arm_hcr_el2_eff(env) & HCR_E2H)) {
36
- if (arm_feature(env, ARM_FEATURE_M)) {
20
- return CP_ACCESS_TRAP;
37
+ vfp_set_fpscr_to_host(env, val);
21
+ return CP_ACCESS_TRAP_UNCATEGORIZED;
38
+
39
+ if (!arm_feature(env, ARM_FEATURE_M)) {
40
/*
41
- * M profile FPSCR is RES0 for the QC, STRIDE, FZ16, LEN bits
42
- * and also for the trapped-exception-handling bits IxE.
43
+ * Short-vector length and stride; on M-profile these bits
44
+ * are used for different purposes.
45
+ * We can't make this conditional be "if MVFR0.FPShVec != 0",
46
+ * because in v7A no-short-vector-support cores still had to
47
+ * allow Stride/Len to be written with the only effect that
48
+ * some insns are required to UNDEF if the guest sets them.
49
+ *
50
+ * TODO: if M-profile MVE implemented, set LTPSIZE.
51
*/
52
- val &= 0xf7c0009f;
53
+ env->vfp.vec_len = extract32(val, 16, 3);
54
+ env->vfp.vec_stride = extract32(val, 20, 2);
55
}
22
}
56
23
return CP_ACCESS_OK;
57
- vfp_set_fpscr_to_host(env, val);
58
+ if (arm_feature(env, ARM_FEATURE_NEON)) {
59
+ /*
60
+ * The bit we set within fpscr_q is arbitrary; the register as a
61
+ * whole being zero/non-zero is what counts.
62
+ * TODO: M-profile MVE also has a QC bit.
63
+ */
64
+ env->vfp.qc[0] = val & FPCR_QC;
65
+ env->vfp.qc[1] = 0;
66
+ env->vfp.qc[2] = 0;
67
+ env->vfp.qc[3] = 0;
68
+ }
69
70
/*
71
* We don't implement trapped exception handling, so the
72
* trap enable bits, IDE|IXE|UFE|OFE|DZE|IOE are all RAZ/WI (not RES0!)
73
*
74
- * If we exclude the exception flags, IOC|DZC|OFC|UFC|IXC|IDC
75
- * (which are stored in fp_status), and the other RES0 bits
76
- * in between, then we clear all of the low 16 bits.
77
+ * The exception flags IOC|DZC|OFC|UFC|IXC|IDC are stored in
78
+ * fp_status; QC, Len and Stride are stored separately earlier.
79
+ * Clear out all of those and the RES0 bits: only NZCV, AHP, DN,
80
+ * FZ, RMode and FZ16 are kept in vfp.xregs[FPSCR].
81
*/
82
env->vfp.xregs[ARM_VFP_FPSCR] = val & 0xf7c80000;
83
- env->vfp.vec_len = (val >> 16) & 7;
84
- env->vfp.vec_stride = (val >> 20) & 3;
85
-
86
- /*
87
- * The bit we set within fpscr_q is arbitrary; the register as a
88
- * whole being zero/non-zero is what counts.
89
- */
90
- env->vfp.qc[0] = val & FPCR_QC;
91
- env->vfp.qc[1] = 0;
92
- env->vfp.qc[2] = 0;
93
- env->vfp.qc[3] = 0;
94
}
24
}
95
96
void vfp_set_fpscr(CPUARMState *env, uint32_t val)
97
--
25
--
98
2.20.1
26
2.34.1
99
100
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
We prefer the FIELD macro over ad-hoc #defines for register bits;
2
switch CNTHCTL to that style before we add any more bits.
2
3
3
Unlike many other bits in HCR_EL2, the description for this
4
bit does not contain the phrase "if ... this field behaves
5
as 0 for all purposes other than", so do not squash the bit
6
in arm_hcr_el2_eff.
7
8
Instead, replicate the E2H+TGE test in the two places that
9
require it.
10
11
Reported-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
12
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
13
Reviewed-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
14
Tested-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
15
Message-id: 20201008162155.161886-4-richard.henderson@linaro.org
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20240301183219.2424889-4-peter.maydell@linaro.org
17
---
8
---
18
target/arm/internals.h | 9 +++++----
9
target/arm/internals.h | 27 +++++++++++++++++++++++++--
19
target/arm/helper.c | 9 +++++----
10
target/arm/helper.c | 9 ++++-----
20
2 files changed, 10 insertions(+), 8 deletions(-)
11
2 files changed, 29 insertions(+), 7 deletions(-)
21
12
22
diff --git a/target/arm/internals.h b/target/arm/internals.h
13
diff --git a/target/arm/internals.h b/target/arm/internals.h
23
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
24
--- a/target/arm/internals.h
15
--- a/target/arm/internals.h
25
+++ b/target/arm/internals.h
16
+++ b/target/arm/internals.h
26
@@ -XXX,XX +XXX,XX @@ static inline bool allocation_tag_access_enabled(CPUARMState *env, int el,
17
@@ -XXX,XX +XXX,XX @@ FIELD(VTCR, SL2, 33, 1)
27
&& !(env->cp15.scr_el3 & SCR_ATA)) {
18
#define HSTR_TTEE (1 << 16)
28
return false;
19
#define HSTR_TJDBX (1 << 17)
29
}
20
30
- if (el < 2
21
-#define CNTHCTL_CNTVMASK (1 << 18)
31
- && arm_feature(env, ARM_FEATURE_EL2)
22
-#define CNTHCTL_CNTPMASK (1 << 19)
32
- && !(arm_hcr_el2_eff(env) & HCR_ATA)) {
23
+/*
33
- return false;
24
+ * Depending on the value of HCR_EL2.E2H, bits 0 and 1
34
+ if (el < 2 && arm_feature(env, ARM_FEATURE_EL2)) {
25
+ * have different bit definitions, and EL1PCTEN might be
35
+ uint64_t hcr = arm_hcr_el2_eff(env);
26
+ * bit 0 or bit 10. We use _E2H1 and _E2H0 suffixes to
36
+ if (!(hcr & HCR_ATA) && (!(hcr & HCR_E2H) || !(hcr & HCR_TGE))) {
27
+ * disambiguate if necessary.
37
+ return false;
28
+ */
38
+ }
29
+FIELD(CNTHCTL, EL0PCTEN_E2H1, 0, 1)
39
}
30
+FIELD(CNTHCTL, EL0VCTEN_E2H1, 1, 1)
40
sctlr &= (el == 0 ? SCTLR_ATA0 : SCTLR_ATA);
31
+FIELD(CNTHCTL, EL1PCTEN_E2H0, 0, 1)
41
return sctlr != 0;
32
+FIELD(CNTHCTL, EL1PCEN_E2H0, 1, 1)
33
+FIELD(CNTHCTL, EVNTEN, 2, 1)
34
+FIELD(CNTHCTL, EVNTDIR, 3, 1)
35
+FIELD(CNTHCTL, EVNTI, 4, 4)
36
+FIELD(CNTHCTL, EL0VTEN, 8, 1)
37
+FIELD(CNTHCTL, EL0PTEN, 9, 1)
38
+FIELD(CNTHCTL, EL1PCTEN_E2H1, 10, 1)
39
+FIELD(CNTHCTL, EL1PTEN, 11, 1)
40
+FIELD(CNTHCTL, ECV, 12, 1)
41
+FIELD(CNTHCTL, EL1TVT, 13, 1)
42
+FIELD(CNTHCTL, EL1TVCT, 14, 1)
43
+FIELD(CNTHCTL, EL1NVPCT, 15, 1)
44
+FIELD(CNTHCTL, EL1NVVCT, 16, 1)
45
+FIELD(CNTHCTL, EVNTIS, 17, 1)
46
+FIELD(CNTHCTL, CNTVMASK, 18, 1)
47
+FIELD(CNTHCTL, CNTPMASK, 19, 1)
48
49
/* We use a few fake FSR values for internal purposes in M profile.
50
* M profile cores don't have A/R format FSRs, but currently our
42
diff --git a/target/arm/helper.c b/target/arm/helper.c
51
diff --git a/target/arm/helper.c b/target/arm/helper.c
43
index XXXXXXX..XXXXXXX 100644
52
index XXXXXXX..XXXXXXX 100644
44
--- a/target/arm/helper.c
53
--- a/target/arm/helper.c
45
+++ b/target/arm/helper.c
54
+++ b/target/arm/helper.c
46
@@ -XXX,XX +XXX,XX @@ static CPAccessResult access_mte(CPUARMState *env, const ARMCPRegInfo *ri,
55
@@ -XXX,XX +XXX,XX @@ static void gt_update_irq(ARMCPU *cpu, int timeridx)
56
* It is RES0 in Secure and NonSecure state.
57
*/
58
if ((ss == ARMSS_Root || ss == ARMSS_Realm) &&
59
- ((timeridx == GTIMER_VIRT && (cnthctl & CNTHCTL_CNTVMASK)) ||
60
- (timeridx == GTIMER_PHYS && (cnthctl & CNTHCTL_CNTPMASK)))) {
61
+ ((timeridx == GTIMER_VIRT && (cnthctl & R_CNTHCTL_CNTVMASK_MASK)) ||
62
+ (timeridx == GTIMER_PHYS && (cnthctl & R_CNTHCTL_CNTPMASK_MASK)))) {
63
irqstate = 0;
64
}
65
66
@@ -XXX,XX +XXX,XX @@ static void gt_cnthctl_write(CPUARMState *env, const ARMCPRegInfo *ri,
47
{
67
{
48
int el = arm_current_el(env);
68
ARMCPU *cpu = env_archcpu(env);
49
69
uint32_t oldval = env->cp15.cnthctl_el2;
50
- if (el < 2 &&
70
-
51
- arm_feature(env, ARM_FEATURE_EL2) &&
71
raw_write(env, ri, value);
52
- !(arm_hcr_el2_eff(env) & HCR_ATA)) {
72
53
- return CP_ACCESS_TRAP_EL2;
73
- if ((oldval ^ value) & CNTHCTL_CNTVMASK) {
54
+ if (el < 2 && arm_feature(env, ARM_FEATURE_EL2)) {
74
+ if ((oldval ^ value) & R_CNTHCTL_CNTVMASK_MASK) {
55
+ uint64_t hcr = arm_hcr_el2_eff(env);
75
gt_update_irq(cpu, GTIMER_VIRT);
56
+ if (!(hcr & HCR_ATA) && (!(hcr & HCR_E2H) || !(hcr & HCR_TGE))) {
76
- } else if ((oldval ^ value) & CNTHCTL_CNTPMASK) {
57
+ return CP_ACCESS_TRAP_EL2;
77
+ } else if ((oldval ^ value) & R_CNTHCTL_CNTPMASK_MASK) {
58
+ }
78
gt_update_irq(cpu, GTIMER_PHYS);
59
}
79
}
60
if (el < 3 &&
80
}
61
arm_feature(env, ARM_FEATURE_EL3) &&
62
--
81
--
63
2.20.1
82
2.34.1
64
83
65
84
diff view generated by jsdifflib
1
For AArch32, unlike the VCVT of integer to float, which honours the
1
Don't allow the guest to write CNTHCTL_EL2 bits which don't exist.
2
rounding mode specified by the FPSCR, VCVT of fixed-point to float is
2
This is not strictly architecturally required, but it is how we've
3
always round-to-nearest. (AArch64 fixed-point-to-float conversions
3
tended to implement registers more recently.
4
always honour the FPCR rounding mode.)
5
4
6
Implement this by providing _round_to_nearest versions of the
5
In particular, bits [19:18] are only present with FEAT_RME,
7
relevant helpers which set the rounding mode temporarily when making
6
and bits [17:12] will only be present with FEAT_ECV.
8
the call to the underlying softfloat function.
9
10
We only need to change the VFP VCVT instructions, because the
11
standard- FPSCR value used by the Neon VCVT is always set to
12
round-to-nearest, so we don't need to do the extra work of saving
13
and restoring the rounding mode.
14
7
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
17
Message-id: 20201013103532.13391-1-peter.maydell@linaro.org
10
Message-id: 20240301183219.2424889-5-peter.maydell@linaro.org
18
---
11
---
19
target/arm/helper.h | 13 +++++++++++++
12
target/arm/helper.c | 18 ++++++++++++++++++
20
target/arm/vfp_helper.c | 23 ++++++++++++++++++++++-
13
1 file changed, 18 insertions(+)
21
target/arm/translate-vfp.c.inc | 24 ++++++++++++------------
22
3 files changed, 47 insertions(+), 13 deletions(-)
23
14
24
diff --git a/target/arm/helper.h b/target/arm/helper.h
15
diff --git a/target/arm/helper.c b/target/arm/helper.c
25
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
26
--- a/target/arm/helper.h
17
--- a/target/arm/helper.c
27
+++ b/target/arm/helper.h
18
+++ b/target/arm/helper.c
28
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_3(vfp_ultoh, f16, i32, i32, ptr)
19
@@ -XXX,XX +XXX,XX @@ static void gt_cnthctl_write(CPUARMState *env, const ARMCPRegInfo *ri,
29
DEF_HELPER_3(vfp_sqtoh, f16, i64, i32, ptr)
20
{
30
DEF_HELPER_3(vfp_uqtoh, f16, i64, i32, ptr)
21
ARMCPU *cpu = env_archcpu(env);
31
22
uint32_t oldval = env->cp15.cnthctl_el2;
32
+DEF_HELPER_3(vfp_shtos_round_to_nearest, f32, i32, i32, ptr)
23
+ uint32_t valid_mask =
33
+DEF_HELPER_3(vfp_sltos_round_to_nearest, f32, i32, i32, ptr)
24
+ R_CNTHCTL_EL0PCTEN_E2H1_MASK |
34
+DEF_HELPER_3(vfp_uhtos_round_to_nearest, f32, i32, i32, ptr)
25
+ R_CNTHCTL_EL0VCTEN_E2H1_MASK |
35
+DEF_HELPER_3(vfp_ultos_round_to_nearest, f32, i32, i32, ptr)
26
+ R_CNTHCTL_EVNTEN_MASK |
36
+DEF_HELPER_3(vfp_shtod_round_to_nearest, f64, i64, i32, ptr)
27
+ R_CNTHCTL_EVNTDIR_MASK |
37
+DEF_HELPER_3(vfp_sltod_round_to_nearest, f64, i64, i32, ptr)
28
+ R_CNTHCTL_EVNTI_MASK |
38
+DEF_HELPER_3(vfp_uhtod_round_to_nearest, f64, i64, i32, ptr)
29
+ R_CNTHCTL_EL0VTEN_MASK |
39
+DEF_HELPER_3(vfp_ultod_round_to_nearest, f64, i64, i32, ptr)
30
+ R_CNTHCTL_EL0PTEN_MASK |
40
+DEF_HELPER_3(vfp_shtoh_round_to_nearest, f16, i32, i32, ptr)
31
+ R_CNTHCTL_EL1PCTEN_E2H1_MASK |
41
+DEF_HELPER_3(vfp_uhtoh_round_to_nearest, f16, i32, i32, ptr)
32
+ R_CNTHCTL_EL1PTEN_MASK;
42
+DEF_HELPER_3(vfp_sltoh_round_to_nearest, f16, i32, i32, ptr)
43
+DEF_HELPER_3(vfp_ultoh_round_to_nearest, f16, i32, i32, ptr)
44
+
33
+
45
DEF_HELPER_FLAGS_2(set_rmode, TCG_CALL_NO_RWG, i32, i32, ptr)
34
+ if (cpu_isar_feature(aa64_rme, cpu)) {
46
35
+ valid_mask |= R_CNTHCTL_CNTVMASK_MASK | R_CNTHCTL_CNTPMASK_MASK;
47
DEF_HELPER_FLAGS_3(vfp_fcvt_f16_to_f32, TCG_CALL_NO_RWG, f32, f16, ptr, i32)
48
diff --git a/target/arm/vfp_helper.c b/target/arm/vfp_helper.c
49
index XXXXXXX..XXXXXXX 100644
50
--- a/target/arm/vfp_helper.c
51
+++ b/target/arm/vfp_helper.c
52
@@ -XXX,XX +XXX,XX @@ float32 VFP_HELPER(fcvts, d)(float64 x, CPUARMState *env)
53
return float64_to_float32(x, &env->vfp.fp_status);
54
}
55
56
-/* VFP3 fixed point conversion. */
57
+/*
58
+ * VFP3 fixed point conversion. The AArch32 versions of fix-to-float
59
+ * must always round-to-nearest; the AArch64 ones honour the FPSCR
60
+ * rounding mode. (For AArch32 Neon the standard-FPSCR is set to
61
+ * round-to-nearest so either helper will work.) AArch32 float-to-fix
62
+ * must round-to-zero.
63
+ */
64
#define VFP_CONV_FIX_FLOAT(name, p, fsz, ftype, isz, itype) \
65
ftype HELPER(vfp_##name##to##p)(uint##isz##_t x, uint32_t shift, \
66
void *fpstp) \
67
{ return itype##_to_##float##fsz##_scalbn(x, -shift, fpstp); }
68
69
+#define VFP_CONV_FIX_FLOAT_ROUND(name, p, fsz, ftype, isz, itype) \
70
+ ftype HELPER(vfp_##name##to##p##_round_to_nearest)(uint##isz##_t x, \
71
+ uint32_t shift, \
72
+ void *fpstp) \
73
+ { \
74
+ ftype ret; \
75
+ float_status *fpst = fpstp; \
76
+ FloatRoundMode oldmode = fpst->float_rounding_mode; \
77
+ fpst->float_rounding_mode = float_round_nearest_even; \
78
+ ret = itype##_to_##float##fsz##_scalbn(x, -shift, fpstp); \
79
+ fpst->float_rounding_mode = oldmode; \
80
+ return ret; \
81
+ }
36
+ }
82
+
37
+
83
#define VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, ftype, isz, itype, ROUND, suff) \
38
+ /* Clear RES0 bits */
84
uint##isz##_t HELPER(vfp_to##name##p##suff)(ftype x, uint32_t shift, \
39
+ value &= valid_mask;
85
void *fpst) \
40
+
86
@@ -XXX,XX +XXX,XX @@ uint##isz##_t HELPER(vfp_to##name##p##suff)(ftype x, uint32_t shift, \
41
raw_write(env, ri, value);
87
42
88
#define VFP_CONV_FIX(name, p, fsz, ftype, isz, itype) \
43
if ((oldval ^ value) & R_CNTHCTL_CNTVMASK_MASK) {
89
VFP_CONV_FIX_FLOAT(name, p, fsz, ftype, isz, itype) \
90
+VFP_CONV_FIX_FLOAT_ROUND(name, p, fsz, ftype, isz, itype) \
91
VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, ftype, isz, itype, \
92
float_round_to_zero, _round_to_zero) \
93
VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, ftype, isz, itype, \
94
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
95
index XXXXXXX..XXXXXXX 100644
96
--- a/target/arm/translate-vfp.c.inc
97
+++ b/target/arm/translate-vfp.c.inc
98
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_fix_hp(DisasContext *s, arg_VCVT_fix_sp *a)
99
/* Switch on op:U:sx bits */
100
switch (a->opc) {
101
case 0:
102
- gen_helper_vfp_shtoh(vd, vd, shift, fpst);
103
+ gen_helper_vfp_shtoh_round_to_nearest(vd, vd, shift, fpst);
104
break;
105
case 1:
106
- gen_helper_vfp_sltoh(vd, vd, shift, fpst);
107
+ gen_helper_vfp_sltoh_round_to_nearest(vd, vd, shift, fpst);
108
break;
109
case 2:
110
- gen_helper_vfp_uhtoh(vd, vd, shift, fpst);
111
+ gen_helper_vfp_uhtoh_round_to_nearest(vd, vd, shift, fpst);
112
break;
113
case 3:
114
- gen_helper_vfp_ultoh(vd, vd, shift, fpst);
115
+ gen_helper_vfp_ultoh_round_to_nearest(vd, vd, shift, fpst);
116
break;
117
case 4:
118
gen_helper_vfp_toshh_round_to_zero(vd, vd, shift, fpst);
119
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_fix_sp(DisasContext *s, arg_VCVT_fix_sp *a)
120
/* Switch on op:U:sx bits */
121
switch (a->opc) {
122
case 0:
123
- gen_helper_vfp_shtos(vd, vd, shift, fpst);
124
+ gen_helper_vfp_shtos_round_to_nearest(vd, vd, shift, fpst);
125
break;
126
case 1:
127
- gen_helper_vfp_sltos(vd, vd, shift, fpst);
128
+ gen_helper_vfp_sltos_round_to_nearest(vd, vd, shift, fpst);
129
break;
130
case 2:
131
- gen_helper_vfp_uhtos(vd, vd, shift, fpst);
132
+ gen_helper_vfp_uhtos_round_to_nearest(vd, vd, shift, fpst);
133
break;
134
case 3:
135
- gen_helper_vfp_ultos(vd, vd, shift, fpst);
136
+ gen_helper_vfp_ultos_round_to_nearest(vd, vd, shift, fpst);
137
break;
138
case 4:
139
gen_helper_vfp_toshs_round_to_zero(vd, vd, shift, fpst);
140
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_fix_dp(DisasContext *s, arg_VCVT_fix_dp *a)
141
/* Switch on op:U:sx bits */
142
switch (a->opc) {
143
case 0:
144
- gen_helper_vfp_shtod(vd, vd, shift, fpst);
145
+ gen_helper_vfp_shtod_round_to_nearest(vd, vd, shift, fpst);
146
break;
147
case 1:
148
- gen_helper_vfp_sltod(vd, vd, shift, fpst);
149
+ gen_helper_vfp_sltod_round_to_nearest(vd, vd, shift, fpst);
150
break;
151
case 2:
152
- gen_helper_vfp_uhtod(vd, vd, shift, fpst);
153
+ gen_helper_vfp_uhtod_round_to_nearest(vd, vd, shift, fpst);
154
break;
155
case 3:
156
- gen_helper_vfp_ultod(vd, vd, shift, fpst);
157
+ gen_helper_vfp_ultod_round_to_nearest(vd, vd, shift, fpst);
158
break;
159
case 4:
160
gen_helper_vfp_toshd_round_to_zero(vd, vd, shift, fpst);
161
--
44
--
162
2.20.1
45
2.34.1
163
164
diff view generated by jsdifflib
Deleted patch
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
1
3
The time to transmit a char is expressed in nanoseconds, not in ticks.
4
5
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Message-id: 20201014213601.205222-1-f4bug@amsat.org
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
hw/arm/strongarm.c | 2 +-
11
1 file changed, 1 insertion(+), 1 deletion(-)
12
13
diff --git a/hw/arm/strongarm.c b/hw/arm/strongarm.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/arm/strongarm.c
16
+++ b/hw/arm/strongarm.c
17
@@ -XXX,XX +XXX,XX @@ struct StrongARMUARTState {
18
uint8_t rx_start;
19
uint8_t rx_len;
20
21
- uint64_t char_transmit_time; /* time to transmit a char in ticks*/
22
+ uint64_t char_transmit_time; /* time to transmit a char in nanoseconds */
23
bool wait_break_end;
24
QEMUTimer *rx_timeout_timer;
25
QEMUTimer *tx_timer;
26
--
27
2.20.1
28
29
diff view generated by jsdifflib
Deleted patch
1
From: Philippe Mathieu-Daudé <philmd@redhat.com>
2
1
3
While APEI is a generic ACPI feature (usable by X86 and ARM64), only
4
the 'virt' machine uses it, by enabling the RAS Virtualization. See
5
commit 2afa8c8519: "hw/arm/virt: Introduce a RAS machine option").
6
7
Restrict the APEI tables generation code to the single user: the virt
8
machine. If another machine wants to use it, it simply has to 'select
9
ACPI_APEI' in its Kconfig.
10
11
Fixes: aa16508f1d ("ACPI: Build related register address fields via hardware error fw_cfg blob")
12
Acked-by: Michael S. Tsirkin <mst@redhat.com>
13
Reviewed-by: Dongjiu Geng <gengdongjiu@huawei.com>
14
Acked-by: Laszlo Ersek <lersek@redhat.com>
15
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
16
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
17
Message-id: 20201008161414.2672569-1-philmd@redhat.com
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
---
20
default-configs/devices/arm-softmmu.mak | 1 -
21
hw/arm/Kconfig | 1 +
22
2 files changed, 1 insertion(+), 1 deletion(-)
23
24
diff --git a/default-configs/devices/arm-softmmu.mak b/default-configs/devices/arm-softmmu.mak
25
index XXXXXXX..XXXXXXX 100644
26
--- a/default-configs/devices/arm-softmmu.mak
27
+++ b/default-configs/devices/arm-softmmu.mak
28
@@ -XXX,XX +XXX,XX @@ CONFIG_FSL_IMX7=y
29
CONFIG_FSL_IMX6UL=y
30
CONFIG_SEMIHOSTING=y
31
CONFIG_ALLWINNER_H3=y
32
-CONFIG_ACPI_APEI=y
33
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
34
index XXXXXXX..XXXXXXX 100644
35
--- a/hw/arm/Kconfig
36
+++ b/hw/arm/Kconfig
37
@@ -XXX,XX +XXX,XX @@ config ARM_VIRT
38
select ACPI_MEMORY_HOTPLUG
39
select ACPI_HW_REDUCED
40
select ACPI_NVDIMM
41
+ select ACPI_APEI
42
43
config CHEETAH
44
bool
45
--
46
2.20.1
47
48
diff view generated by jsdifflib
Deleted patch
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
1
3
Use the BCM2835_SYSTIMER_COUNT definition instead of the
4
magic '4' value.
5
6
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Message-id: 20201010203709.3116542-2-f4bug@amsat.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
include/hw/timer/bcm2835_systmr.h | 4 +++-
13
hw/timer/bcm2835_systmr.c | 3 ++-
14
2 files changed, 5 insertions(+), 2 deletions(-)
15
16
diff --git a/include/hw/timer/bcm2835_systmr.h b/include/hw/timer/bcm2835_systmr.h
17
index XXXXXXX..XXXXXXX 100644
18
--- a/include/hw/timer/bcm2835_systmr.h
19
+++ b/include/hw/timer/bcm2835_systmr.h
20
@@ -XXX,XX +XXX,XX @@
21
#define TYPE_BCM2835_SYSTIMER "bcm2835-sys-timer"
22
OBJECT_DECLARE_SIMPLE_TYPE(BCM2835SystemTimerState, BCM2835_SYSTIMER)
23
24
+#define BCM2835_SYSTIMER_COUNT 4
25
+
26
struct BCM2835SystemTimerState {
27
/*< private >*/
28
SysBusDevice parent_obj;
29
@@ -XXX,XX +XXX,XX @@ struct BCM2835SystemTimerState {
30
31
struct {
32
uint32_t status;
33
- uint32_t compare[4];
34
+ uint32_t compare[BCM2835_SYSTIMER_COUNT];
35
} reg;
36
};
37
38
diff --git a/hw/timer/bcm2835_systmr.c b/hw/timer/bcm2835_systmr.c
39
index XXXXXXX..XXXXXXX 100644
40
--- a/hw/timer/bcm2835_systmr.c
41
+++ b/hw/timer/bcm2835_systmr.c
42
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription bcm2835_systmr_vmstate = {
43
.minimum_version_id = 1,
44
.fields = (VMStateField[]) {
45
VMSTATE_UINT32(reg.status, BCM2835SystemTimerState),
46
- VMSTATE_UINT32_ARRAY(reg.compare, BCM2835SystemTimerState, 4),
47
+ VMSTATE_UINT32_ARRAY(reg.compare, BCM2835SystemTimerState,
48
+ BCM2835_SYSTIMER_COUNT),
49
VMSTATE_END_OF_LIST()
50
}
51
};
52
--
53
2.20.1
54
55
diff view generated by jsdifflib
Deleted patch
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
1
3
The variable holding the CTRL_STATUS register is misnamed
4
'status'. Rename it 'ctrl_status' to make it more obvious
5
this register is also used to control the peripheral.
6
7
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
Message-id: 20201010203709.3116542-3-f4bug@amsat.org
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
13
include/hw/timer/bcm2835_systmr.h | 2 +-
14
hw/timer/bcm2835_systmr.c | 8 ++++----
15
2 files changed, 5 insertions(+), 5 deletions(-)
16
17
diff --git a/include/hw/timer/bcm2835_systmr.h b/include/hw/timer/bcm2835_systmr.h
18
index XXXXXXX..XXXXXXX 100644
19
--- a/include/hw/timer/bcm2835_systmr.h
20
+++ b/include/hw/timer/bcm2835_systmr.h
21
@@ -XXX,XX +XXX,XX @@ struct BCM2835SystemTimerState {
22
qemu_irq irq;
23
24
struct {
25
- uint32_t status;
26
+ uint32_t ctrl_status;
27
uint32_t compare[BCM2835_SYSTIMER_COUNT];
28
} reg;
29
};
30
diff --git a/hw/timer/bcm2835_systmr.c b/hw/timer/bcm2835_systmr.c
31
index XXXXXXX..XXXXXXX 100644
32
--- a/hw/timer/bcm2835_systmr.c
33
+++ b/hw/timer/bcm2835_systmr.c
34
@@ -XXX,XX +XXX,XX @@ REG32(COMPARE3, 0x18)
35
36
static void bcm2835_systmr_update_irq(BCM2835SystemTimerState *s)
37
{
38
- bool enable = !!s->reg.status;
39
+ bool enable = !!s->reg.ctrl_status;
40
41
trace_bcm2835_systmr_irq(enable);
42
qemu_set_irq(s->irq, enable);
43
@@ -XXX,XX +XXX,XX @@ static uint64_t bcm2835_systmr_read(void *opaque, hwaddr offset,
44
45
switch (offset) {
46
case A_CTRL_STATUS:
47
- r = s->reg.status;
48
+ r = s->reg.ctrl_status;
49
break;
50
case A_COMPARE0 ... A_COMPARE3:
51
r = s->reg.compare[(offset - A_COMPARE0) >> 2];
52
@@ -XXX,XX +XXX,XX @@ static void bcm2835_systmr_write(void *opaque, hwaddr offset,
53
trace_bcm2835_systmr_write(offset, value);
54
switch (offset) {
55
case A_CTRL_STATUS:
56
- s->reg.status &= ~value; /* Ack */
57
+ s->reg.ctrl_status &= ~value; /* Ack */
58
bcm2835_systmr_update_irq(s);
59
break;
60
case A_COMPARE0 ... A_COMPARE3:
61
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription bcm2835_systmr_vmstate = {
62
.version_id = 1,
63
.minimum_version_id = 1,
64
.fields = (VMStateField[]) {
65
- VMSTATE_UINT32(reg.status, BCM2835SystemTimerState),
66
+ VMSTATE_UINT32(reg.ctrl_status, BCM2835SystemTimerState),
67
VMSTATE_UINT32_ARRAY(reg.compare, BCM2835SystemTimerState,
68
BCM2835_SYSTIMER_COUNT),
69
VMSTATE_END_OF_LIST()
70
--
71
2.20.1
72
73
diff view generated by jsdifflib
Deleted patch
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
1
3
This peripheral has 1 free-running timer and 4 compare registers.
4
5
Only the free-running timer is implemented. Add support the
6
COMPARE registers (each register is wired to an IRQ).
7
8
Reference: "BCM2835 ARM Peripherals" datasheet [*]
9
chapter 12 "System Timer":
10
11
The System Timer peripheral provides four 32-bit timer channels
12
and a single 64-bit free running counter. Each channel has an
13
output compare register, which is compared against the 32 least
14
significant bits of the free running counter values. When the
15
two values match, the system timer peripheral generates a signal
16
to indicate a match for the appropriate channel. The match signal
17
is then fed into the interrupt controller.
18
19
This peripheral is used since Linux 3.7, commit ee4af5696720
20
("ARM: bcm2835: add system timer").
21
22
[*] https://www.raspberrypi.org/app/uploads/2012/02/BCM2835-ARM-Peripherals.pdf
23
24
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
25
Reviewed-by: Luc Michel <luc@lmichel.fr>
26
Message-id: 20201010203709.3116542-4-f4bug@amsat.org
27
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
28
---
29
include/hw/timer/bcm2835_systmr.h | 11 +++++--
30
hw/timer/bcm2835_systmr.c | 48 ++++++++++++++++++++-----------
31
hw/timer/trace-events | 6 ++--
32
3 files changed, 44 insertions(+), 21 deletions(-)
33
34
diff --git a/include/hw/timer/bcm2835_systmr.h b/include/hw/timer/bcm2835_systmr.h
35
index XXXXXXX..XXXXXXX 100644
36
--- a/include/hw/timer/bcm2835_systmr.h
37
+++ b/include/hw/timer/bcm2835_systmr.h
38
@@ -XXX,XX +XXX,XX @@
39
40
#include "hw/sysbus.h"
41
#include "hw/irq.h"
42
+#include "qemu/timer.h"
43
#include "qom/object.h"
44
45
#define TYPE_BCM2835_SYSTIMER "bcm2835-sys-timer"
46
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_SIMPLE_TYPE(BCM2835SystemTimerState, BCM2835_SYSTIMER)
47
48
#define BCM2835_SYSTIMER_COUNT 4
49
50
+typedef struct {
51
+ unsigned id;
52
+ QEMUTimer timer;
53
+ qemu_irq irq;
54
+ BCM2835SystemTimerState *state;
55
+} BCM2835SystemTimerCompare;
56
+
57
struct BCM2835SystemTimerState {
58
/*< private >*/
59
SysBusDevice parent_obj;
60
61
/*< public >*/
62
MemoryRegion iomem;
63
- qemu_irq irq;
64
-
65
struct {
66
uint32_t ctrl_status;
67
uint32_t compare[BCM2835_SYSTIMER_COUNT];
68
} reg;
69
+ BCM2835SystemTimerCompare tmr[BCM2835_SYSTIMER_COUNT];
70
};
71
72
#endif
73
diff --git a/hw/timer/bcm2835_systmr.c b/hw/timer/bcm2835_systmr.c
74
index XXXXXXX..XXXXXXX 100644
75
--- a/hw/timer/bcm2835_systmr.c
76
+++ b/hw/timer/bcm2835_systmr.c
77
@@ -XXX,XX +XXX,XX @@ REG32(COMPARE1, 0x10)
78
REG32(COMPARE2, 0x14)
79
REG32(COMPARE3, 0x18)
80
81
-static void bcm2835_systmr_update_irq(BCM2835SystemTimerState *s)
82
+static void bcm2835_systmr_timer_expire(void *opaque)
83
{
84
- bool enable = !!s->reg.ctrl_status;
85
+ BCM2835SystemTimerCompare *tmr = opaque;
86
87
- trace_bcm2835_systmr_irq(enable);
88
- qemu_set_irq(s->irq, enable);
89
-}
90
-
91
-static void bcm2835_systmr_update_compare(BCM2835SystemTimerState *s,
92
- unsigned timer_index)
93
-{
94
- /* TODO fow now, since neither Linux nor U-boot use these timers. */
95
- qemu_log_mask(LOG_UNIMP, "COMPARE register %u not implemented\n",
96
- timer_index);
97
+ trace_bcm2835_systmr_timer_expired(tmr->id);
98
+ tmr->state->reg.ctrl_status |= 1 << tmr->id;
99
+ qemu_set_irq(tmr->irq, 1);
100
}
101
102
static uint64_t bcm2835_systmr_read(void *opaque, hwaddr offset,
103
@@ -XXX,XX +XXX,XX @@ static uint64_t bcm2835_systmr_read(void *opaque, hwaddr offset,
104
}
105
106
static void bcm2835_systmr_write(void *opaque, hwaddr offset,
107
- uint64_t value, unsigned size)
108
+ uint64_t value64, unsigned size)
109
{
110
BCM2835SystemTimerState *s = BCM2835_SYSTIMER(opaque);
111
+ int index;
112
+ uint32_t value = value64;
113
+ uint32_t triggers_delay_us;
114
+ uint64_t now;
115
116
trace_bcm2835_systmr_write(offset, value);
117
switch (offset) {
118
case A_CTRL_STATUS:
119
s->reg.ctrl_status &= ~value; /* Ack */
120
- bcm2835_systmr_update_irq(s);
121
+ for (index = 0; index < ARRAY_SIZE(s->tmr); index++) {
122
+ if (extract32(value, index, 1)) {
123
+ trace_bcm2835_systmr_irq_ack(index);
124
+ qemu_set_irq(s->tmr[index].irq, 0);
125
+ }
126
+ }
127
break;
128
case A_COMPARE0 ... A_COMPARE3:
129
- s->reg.compare[(offset - A_COMPARE0) >> 2] = value;
130
- bcm2835_systmr_update_compare(s, (offset - A_COMPARE0) >> 2);
131
+ index = (offset - A_COMPARE0) >> 2;
132
+ s->reg.compare[index] = value;
133
+ now = qemu_clock_get_us(QEMU_CLOCK_VIRTUAL);
134
+ /* Compare lower 32-bits of the free-running counter. */
135
+ triggers_delay_us = value - now;
136
+ trace_bcm2835_systmr_run(index, triggers_delay_us);
137
+ timer_mod(&s->tmr[index].timer, now + triggers_delay_us);
138
break;
139
case A_COUNTER_LOW:
140
case A_COUNTER_HIGH:
141
@@ -XXX,XX +XXX,XX @@ static void bcm2835_systmr_realize(DeviceState *dev, Error **errp)
142
memory_region_init_io(&s->iomem, OBJECT(dev), &bcm2835_systmr_ops,
143
s, "bcm2835-sys-timer", 0x20);
144
sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->iomem);
145
- sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->irq);
146
+
147
+ for (size_t i = 0; i < ARRAY_SIZE(s->tmr); i++) {
148
+ s->tmr[i].id = i;
149
+ s->tmr[i].state = s;
150
+ sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->tmr[i].irq);
151
+ timer_init_us(&s->tmr[i].timer, QEMU_CLOCK_VIRTUAL,
152
+ bcm2835_systmr_timer_expire, &s->tmr[i]);
153
+ }
154
}
155
156
static const VMStateDescription bcm2835_systmr_vmstate = {
157
diff --git a/hw/timer/trace-events b/hw/timer/trace-events
158
index XXXXXXX..XXXXXXX 100644
159
--- a/hw/timer/trace-events
160
+++ b/hw/timer/trace-events
161
@@ -XXX,XX +XXX,XX @@ nrf51_timer_write(uint8_t timer_id, uint64_t addr, uint32_t value, unsigned size
162
nrf51_timer_set_count(uint8_t timer_id, uint8_t counter_id, uint32_t value) "timer %u counter %u count 0x%" PRIx32
163
164
# bcm2835_systmr.c
165
-bcm2835_systmr_irq(bool enable) "timer irq state %u"
166
+bcm2835_systmr_timer_expired(unsigned id) "timer #%u expired"
167
+bcm2835_systmr_irq_ack(unsigned id) "timer #%u acked"
168
bcm2835_systmr_read(uint64_t offset, uint64_t data) "timer read: offset 0x%" PRIx64 " data 0x%" PRIx64
169
-bcm2835_systmr_write(uint64_t offset, uint64_t data) "timer write: offset 0x%" PRIx64 " data 0x%" PRIx64
170
+bcm2835_systmr_write(uint64_t offset, uint32_t data) "timer write: offset 0x%" PRIx64 " data 0x%" PRIx32
171
+bcm2835_systmr_run(unsigned id, uint64_t delay_us) "timer #%u expiring in %"PRIu64" us"
172
173
# avr_timer16.c
174
avr_timer16_read(uint8_t addr, uint8_t value) "timer16 read addr:%u value:%u"
175
--
176
2.20.1
177
178
diff view generated by jsdifflib
Deleted patch
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
1
3
The SYS_timer is not directly wired to the ARM core, but to the
4
SoC (peripheral) interrupt controller.
5
6
Fixes: 0e5bbd74064 ("hw/arm/bcm2835_peripherals: Use the SYS_timer")
7
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
Message-id: 20201010203709.3116542-5-f4bug@amsat.org
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
13
hw/arm/bcm2835_peripherals.c | 13 +++++++++++--
14
1 file changed, 11 insertions(+), 2 deletions(-)
15
16
diff --git a/hw/arm/bcm2835_peripherals.c b/hw/arm/bcm2835_peripherals.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/arm/bcm2835_peripherals.c
19
+++ b/hw/arm/bcm2835_peripherals.c
20
@@ -XXX,XX +XXX,XX @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
21
memory_region_add_subregion(&s->peri_mr, ST_OFFSET,
22
sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->systmr), 0));
23
sysbus_connect_irq(SYS_BUS_DEVICE(&s->systmr), 0,
24
- qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_ARM_IRQ,
25
- INTERRUPT_ARM_TIMER));
26
+ qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ,
27
+ INTERRUPT_TIMER0));
28
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->systmr), 1,
29
+ qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ,
30
+ INTERRUPT_TIMER1));
31
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->systmr), 2,
32
+ qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ,
33
+ INTERRUPT_TIMER2));
34
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->systmr), 3,
35
+ qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ,
36
+ INTERRUPT_TIMER3));
37
38
/* UART0 */
39
qdev_prop_set_chr(DEVICE(&s->uart0), "chardev", serial_hd(0));
40
--
41
2.20.1
42
43
diff view generated by jsdifflib
1
v8.1M's "low-overhead-loop" extension has three instructions
1
The functionality defined by ID_AA64MMFR0_EL1.ECV == 1 is:
2
for looping:
2
* four new trap bits for various counter and timer registers
3
* DLS (start of a do-loop)
3
* the CNTHCTL_EL2.EVNTIS and CNTKCTL_EL1.EVNTIS bits which control
4
* WLS (start of a while-loop)
4
scaling of the event stream. This is a no-op for us, because we don't
5
* LE (end of a loop)
5
implement the event stream (our WFE is a NOP): all we need to do is
6
allow CNTHCTL_EL2.ENVTIS to be read and written.
7
* extensions to PMSCR_EL1.PCT, PMSCR_EL2.PCT, TRFCR_EL1.TS and
8
TRFCR_EL2.TS: these are all no-ops for us, because we don't implement
9
FEAT_SPE or FEAT_TRF.
10
* new registers CNTPCTSS_EL0 and NCTVCTSS_EL0 which are
11
"self-sychronizing" views of the CNTPCT_EL0 and CNTVCT_EL0, meaning
12
that no barriers are needed around their accesses. For us these
13
are just the same as the normal views, because all our sysregs are
14
inherently self-sychronizing.
6
15
7
The loop-start instructions are both simple operations to start a
16
In this commit we implement the trap handling and permit the new
8
loop whose iteration count (if any) is in LR. The loop-end
17
CNTHCTL_EL2 bits to be written.
9
instruction handles "decrement iteration count and jump back to loop
10
start"; it also caches the information about the branch back to the
11
start of the loop to improve performance of the branch on subsequent
12
iterations.
13
14
As with the branch-future instructions, the architecture permits an
15
implementation to discard the LO_BRANCH_INFO cache at any time, and
16
QEMU takes the IMPDEF option to never set it in the first place
17
(equivalent to discarding it immediately), because for us a "real"
18
implementation would be unnecessary complexity.
19
20
(This implementation only provides the simple looping constructs; the
21
vector extension MVE (Helium) adds some extra variants to handle
22
looping across vectors. We'll add those later when we implement
23
MVE.)
24
18
25
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
26
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
20
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
27
Message-id: 20201019151301.2046-8-peter.maydell@linaro.org
21
Message-id: 20240301183219.2424889-6-peter.maydell@linaro.org
28
---
22
---
29
target/arm/t32.decode | 8 ++++
23
target/arm/cpu-features.h | 5 ++++
30
target/arm/translate.c | 93 +++++++++++++++++++++++++++++++++++++++++-
24
target/arm/helper.c | 51 +++++++++++++++++++++++++++++++++++----
31
2 files changed, 99 insertions(+), 2 deletions(-)
25
2 files changed, 51 insertions(+), 5 deletions(-)
32
26
33
diff --git a/target/arm/t32.decode b/target/arm/t32.decode
27
diff --git a/target/arm/cpu-features.h b/target/arm/cpu-features.h
34
index XXXXXXX..XXXXXXX 100644
28
index XXXXXXX..XXXXXXX 100644
35
--- a/target/arm/t32.decode
29
--- a/target/arm/cpu-features.h
36
+++ b/target/arm/t32.decode
30
+++ b/target/arm/cpu-features.h
37
@@ -XXX,XX +XXX,XX @@ BL 1111 0. .......... 11.1 ............ @branch24
31
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa64_fgt(const ARMISARegisters *id)
38
BF 1111 0 boff:4 10 ----- 1110 - ---------- 1 # BF
32
return FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, FGT) != 0;
39
BF 1111 0 boff:4 11 ----- 1110 0 0000000000 1 # BFX, BFLX
40
]
41
+ [
42
+ # LE and WLS immediate
43
+ %lob_imm 1:10 11:1 !function=times_2
44
+
45
+ DLS 1111 0 0000 100 rn:4 1110 0000 0000 0001
46
+ WLS 1111 0 0000 100 rn:4 1100 . .......... 1 imm=%lob_imm
47
+ LE 1111 0 0000 0 f:1 0 1111 1100 . .......... 1 imm=%lob_imm
48
+ ]
49
}
33
}
50
diff --git a/target/arm/translate.c b/target/arm/translate.c
34
51
index XXXXXXX..XXXXXXX 100644
35
+static inline bool isar_feature_aa64_ecv_traps(const ARMISARegisters *id)
52
--- a/target/arm/translate.c
53
+++ b/target/arm/translate.c
54
@@ -XXX,XX +XXX,XX @@ static void gen_goto_tb(DisasContext *s, int n, target_ulong dest)
55
s->base.is_jmp = DISAS_NORETURN;
56
}
57
58
-static inline void gen_jmp (DisasContext *s, uint32_t dest)
59
+/* Jump, specifying which TB number to use if we gen_goto_tb() */
60
+static inline void gen_jmp_tb(DisasContext *s, uint32_t dest, int tbno)
61
{
62
if (unlikely(is_singlestepping(s))) {
63
/* An indirect jump so that we still trigger the debug exception. */
64
gen_set_pc_im(s, dest);
65
s->base.is_jmp = DISAS_JUMP;
66
} else {
67
- gen_goto_tb(s, 0, dest);
68
+ gen_goto_tb(s, tbno, dest);
69
}
70
}
71
72
+static inline void gen_jmp(DisasContext *s, uint32_t dest)
73
+{
36
+{
74
+ gen_jmp_tb(s, dest, 0);
37
+ return FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, ECV) > 0;
75
+}
38
+}
76
+
39
+
77
static inline void gen_mulxy(TCGv_i32 t0, TCGv_i32 t1, int x, int y)
40
static inline bool isar_feature_aa64_vh(const ARMISARegisters *id)
78
{
41
{
79
if (x)
42
return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, VH) != 0;
80
@@ -XXX,XX +XXX,XX @@ static bool trans_BF(DisasContext *s, arg_BF *a)
43
diff --git a/target/arm/helper.c b/target/arm/helper.c
81
return true;
44
index XXXXXXX..XXXXXXX 100644
45
--- a/target/arm/helper.c
46
+++ b/target/arm/helper.c
47
@@ -XXX,XX +XXX,XX @@ static CPAccessResult gt_counter_access(CPUARMState *env, int timeridx,
48
: !extract32(env->cp15.cnthctl_el2, 0, 1))) {
49
return CP_ACCESS_TRAP_EL2;
50
}
51
+ if (has_el2 && timeridx == GTIMER_VIRT) {
52
+ if (FIELD_EX64(env->cp15.cnthctl_el2, CNTHCTL, EL1TVCT)) {
53
+ return CP_ACCESS_TRAP_EL2;
54
+ }
55
+ }
56
break;
57
}
58
return CP_ACCESS_OK;
59
@@ -XXX,XX +XXX,XX @@ static CPAccessResult gt_timer_access(CPUARMState *env, int timeridx,
60
}
61
}
62
}
63
+ if (has_el2 && timeridx == GTIMER_VIRT) {
64
+ if (FIELD_EX64(env->cp15.cnthctl_el2, CNTHCTL, EL1TVT)) {
65
+ return CP_ACCESS_TRAP_EL2;
66
+ }
67
+ }
68
break;
69
}
70
return CP_ACCESS_OK;
71
@@ -XXX,XX +XXX,XX @@ static void gt_cnthctl_write(CPUARMState *env, const ARMCPRegInfo *ri,
72
if (cpu_isar_feature(aa64_rme, cpu)) {
73
valid_mask |= R_CNTHCTL_CNTVMASK_MASK | R_CNTHCTL_CNTPMASK_MASK;
74
}
75
+ if (cpu_isar_feature(aa64_ecv_traps, cpu)) {
76
+ valid_mask |=
77
+ R_CNTHCTL_EL1TVT_MASK |
78
+ R_CNTHCTL_EL1TVCT_MASK |
79
+ R_CNTHCTL_EL1NVPCT_MASK |
80
+ R_CNTHCTL_EL1NVVCT_MASK |
81
+ R_CNTHCTL_EVNTIS_MASK;
82
+ }
83
84
/* Clear RES0 bits */
85
value &= valid_mask;
86
@@ -XXX,XX +XXX,XX @@ static CPAccessResult e2h_access(CPUARMState *env, const ARMCPRegInfo *ri,
87
{
88
if (arm_current_el(env) == 1) {
89
/* This must be a FEAT_NV access */
90
- /* TODO: FEAT_ECV will need to check CNTHCTL_EL2 here */
91
return CP_ACCESS_OK;
92
}
93
if (!(arm_hcr_el2_eff(env) & HCR_E2H)) {
94
@@ -XXX,XX +XXX,XX @@ static CPAccessResult e2h_access(CPUARMState *env, const ARMCPRegInfo *ri,
95
return CP_ACCESS_OK;
82
}
96
}
83
97
84
+static bool trans_DLS(DisasContext *s, arg_DLS *a)
98
+static CPAccessResult access_el1nvpct(CPUARMState *env, const ARMCPRegInfo *ri,
99
+ bool isread)
85
+{
100
+{
86
+ /* M-profile low-overhead loop start */
101
+ if (arm_current_el(env) == 1) {
87
+ TCGv_i32 tmp;
102
+ /* This must be a FEAT_NV access with NVx == 101 */
88
+
103
+ if (FIELD_EX64(env->cp15.cnthctl_el2, CNTHCTL, EL1NVPCT)) {
89
+ if (!dc_isar_feature(aa32_lob, s)) {
104
+ return CP_ACCESS_TRAP_EL2;
90
+ return false;
105
+ }
91
+ }
106
+ }
92
+ if (a->rn == 13 || a->rn == 15) {
107
+ return e2h_access(env, ri, isread);
93
+ /* CONSTRAINED UNPREDICTABLE: we choose to UNDEF */
94
+ return false;
95
+ }
96
+
97
+ /* Not a while loop, no tail predication: just set LR to the count */
98
+ tmp = load_reg(s, a->rn);
99
+ store_reg(s, 14, tmp);
100
+ return true;
101
+}
108
+}
102
+
109
+
103
+static bool trans_WLS(DisasContext *s, arg_WLS *a)
110
+static CPAccessResult access_el1nvvct(CPUARMState *env, const ARMCPRegInfo *ri,
111
+ bool isread)
104
+{
112
+{
105
+ /* M-profile low-overhead while-loop start */
113
+ if (arm_current_el(env) == 1) {
106
+ TCGv_i32 tmp;
114
+ /* This must be a FEAT_NV access with NVx == 101 */
107
+ TCGLabel *nextlabel;
115
+ if (FIELD_EX64(env->cp15.cnthctl_el2, CNTHCTL, EL1NVVCT)) {
108
+
116
+ return CP_ACCESS_TRAP_EL2;
109
+ if (!dc_isar_feature(aa32_lob, s)) {
117
+ }
110
+ return false;
111
+ }
118
+ }
112
+ if (a->rn == 13 || a->rn == 15) {
119
+ return e2h_access(env, ri, isread);
113
+ /* CONSTRAINED UNPREDICTABLE: we choose to UNDEF */
114
+ return false;
115
+ }
116
+ if (s->condexec_mask) {
117
+ /*
118
+ * WLS in an IT block is CONSTRAINED UNPREDICTABLE;
119
+ * we choose to UNDEF, because otherwise our use of
120
+ * gen_goto_tb(1) would clash with the use of TB exit 1
121
+ * in the dc->condjmp condition-failed codepath in
122
+ * arm_tr_tb_stop() and we'd get an assertion.
123
+ */
124
+ return false;
125
+ }
126
+ nextlabel = gen_new_label();
127
+ tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_R[a->rn], 0, nextlabel);
128
+ tmp = load_reg(s, a->rn);
129
+ store_reg(s, 14, tmp);
130
+ gen_jmp_tb(s, s->base.pc_next, 1);
131
+
132
+ gen_set_label(nextlabel);
133
+ gen_jmp(s, read_pc(s) + a->imm);
134
+ return true;
135
+}
120
+}
136
+
121
+
137
+static bool trans_LE(DisasContext *s, arg_LE *a)
122
/* Test if system register redirection is to occur in the current state. */
138
+{
123
static bool redirect_for_e2h(CPUARMState *env)
139
+ /*
140
+ * M-profile low-overhead loop end. The architecture permits an
141
+ * implementation to discard the LO_BRANCH_INFO cache at any time,
142
+ * and we take the IMPDEF option to never set it in the first place
143
+ * (equivalent to always discarding it immediately), because for QEMU
144
+ * a "real" implementation would be complicated and wouldn't execute
145
+ * any faster.
146
+ */
147
+ TCGv_i32 tmp;
148
+
149
+ if (!dc_isar_feature(aa32_lob, s)) {
150
+ return false;
151
+ }
152
+
153
+ if (!a->f) {
154
+ /* Not loop-forever. If LR <= 1 this is the last loop: do nothing. */
155
+ arm_gen_condlabel(s);
156
+ tcg_gen_brcondi_i32(TCG_COND_LEU, cpu_R[14], 1, s->condlabel);
157
+ /* Decrement LR */
158
+ tmp = load_reg(s, 14);
159
+ tcg_gen_addi_i32(tmp, tmp, -1);
160
+ store_reg(s, 14, tmp);
161
+ }
162
+ /* Jump back to the loop start */
163
+ gen_jmp(s, read_pc(s) - a->imm);
164
+ return true;
165
+}
166
+
167
static bool op_tbranch(DisasContext *s, arg_tbranch *a, bool half)
168
{
124
{
169
TCGv_i32 addr, tmp;
125
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo vhe_reginfo[] = {
126
{ .name = "CNTP_CTL_EL02", .state = ARM_CP_STATE_AA64,
127
.opc0 = 3, .opc1 = 5, .crn = 14, .crm = 2, .opc2 = 1,
128
.type = ARM_CP_IO | ARM_CP_ALIAS,
129
- .access = PL2_RW, .accessfn = e2h_access,
130
+ .access = PL2_RW, .accessfn = access_el1nvpct,
131
.nv2_redirect_offset = 0x180 | NV2_REDIR_NO_NV1,
132
.fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_PHYS].ctl),
133
.writefn = gt_phys_ctl_write, .raw_writefn = raw_write },
134
{ .name = "CNTV_CTL_EL02", .state = ARM_CP_STATE_AA64,
135
.opc0 = 3, .opc1 = 5, .crn = 14, .crm = 3, .opc2 = 1,
136
.type = ARM_CP_IO | ARM_CP_ALIAS,
137
- .access = PL2_RW, .accessfn = e2h_access,
138
+ .access = PL2_RW, .accessfn = access_el1nvvct,
139
.nv2_redirect_offset = 0x170 | NV2_REDIR_NO_NV1,
140
.fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_VIRT].ctl),
141
.writefn = gt_virt_ctl_write, .raw_writefn = raw_write },
142
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo vhe_reginfo[] = {
143
.type = ARM_CP_IO | ARM_CP_ALIAS,
144
.fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_PHYS].cval),
145
.nv2_redirect_offset = 0x178 | NV2_REDIR_NO_NV1,
146
- .access = PL2_RW, .accessfn = e2h_access,
147
+ .access = PL2_RW, .accessfn = access_el1nvpct,
148
.writefn = gt_phys_cval_write, .raw_writefn = raw_write },
149
{ .name = "CNTV_CVAL_EL02", .state = ARM_CP_STATE_AA64,
150
.opc0 = 3, .opc1 = 5, .crn = 14, .crm = 3, .opc2 = 2,
151
.type = ARM_CP_IO | ARM_CP_ALIAS,
152
.nv2_redirect_offset = 0x168 | NV2_REDIR_NO_NV1,
153
.fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_VIRT].cval),
154
- .access = PL2_RW, .accessfn = e2h_access,
155
+ .access = PL2_RW, .accessfn = access_el1nvvct,
156
.writefn = gt_virt_cval_write, .raw_writefn = raw_write },
157
#endif
158
};
170
--
159
--
171
2.20.1
160
2.34.1
172
173
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
For FEAT_ECV, new registers CNTPCTSS_EL0 and CNTVCTSS_EL0 are
2
defined, which are "self-synchronized" views of the physical and
3
virtual counts as seen in the CNTPCT_EL0 and CNTVCT_EL0 registers
4
(meaning that no barriers are needed around accesses to them to
5
ensure that reads of them do not occur speculatively and out-of-order
6
with other instructions).
2
7
3
When TBI is enabled in a given regime, 56 bits of the address
8
For QEMU, all our system registers are self-synchronized, so we can
4
are significant and we need to clear out any other matching
9
simply copy the existing implementation of CNTPCT_EL0 and CNTVCT_EL0
5
virtual addresses with differing tags.
10
to the new register encodings.
6
11
7
The other uses of tlb_flush_page (without mmuidx) in this file
12
This means we now implement all the functionality required for
8
are only used by aarch32 mode.
13
ID_AA64MMFR0_EL1.ECV == 0b0001.
9
14
10
Fixes: 38d931687fa1
11
Reported-by: Jordan Frank <jordanfrank@fb.com>
12
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
14
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
15
Message-id: 20201016210754.818257-3-richard.henderson@linaro.org
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
17
Message-id: 20240301183219.2424889-7-peter.maydell@linaro.org
17
---
18
---
18
target/arm/helper.c | 46 ++++++++++++++++++++++++++++++++++++++-------
19
target/arm/helper.c | 43 +++++++++++++++++++++++++++++++++++++++++++
19
1 file changed, 39 insertions(+), 7 deletions(-)
20
1 file changed, 43 insertions(+)
20
21
21
diff --git a/target/arm/helper.c b/target/arm/helper.c
22
diff --git a/target/arm/helper.c b/target/arm/helper.c
22
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
23
--- a/target/arm/helper.c
24
--- a/target/arm/helper.c
24
+++ b/target/arm/helper.c
25
+++ b/target/arm/helper.c
25
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, target_ulong address,
26
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo generic_timer_cp_reginfo[] = {
27
},
28
};
29
30
+/*
31
+ * FEAT_ECV adds extra views of CNTVCT_EL0 and CNTPCT_EL0 which
32
+ * are "self-synchronizing". For QEMU all sysregs are self-synchronizing,
33
+ * so our implementations here are identical to the normal registers.
34
+ */
35
+static const ARMCPRegInfo gen_timer_ecv_cp_reginfo[] = {
36
+ { .name = "CNTVCTSS", .cp = 15, .crm = 14, .opc1 = 9,
37
+ .access = PL0_R, .type = ARM_CP_64BIT | ARM_CP_NO_RAW | ARM_CP_IO,
38
+ .accessfn = gt_vct_access,
39
+ .readfn = gt_virt_cnt_read, .resetfn = arm_cp_reset_ignore,
40
+ },
41
+ { .name = "CNTVCTSS_EL0", .state = ARM_CP_STATE_AA64,
42
+ .opc0 = 3, .opc1 = 3, .crn = 14, .crm = 0, .opc2 = 6,
43
+ .access = PL0_R, .type = ARM_CP_NO_RAW | ARM_CP_IO,
44
+ .accessfn = gt_vct_access, .readfn = gt_virt_cnt_read,
45
+ },
46
+ { .name = "CNTPCTSS", .cp = 15, .crm = 14, .opc1 = 8,
47
+ .access = PL0_R, .type = ARM_CP_64BIT | ARM_CP_NO_RAW | ARM_CP_IO,
48
+ .accessfn = gt_pct_access,
49
+ .readfn = gt_cnt_read, .resetfn = arm_cp_reset_ignore,
50
+ },
51
+ { .name = "CNTPCTSS_EL0", .state = ARM_CP_STATE_AA64,
52
+ .opc0 = 3, .opc1 = 3, .crn = 14, .crm = 0, .opc2 = 5,
53
+ .access = PL0_R, .type = ARM_CP_NO_RAW | ARM_CP_IO,
54
+ .accessfn = gt_pct_access, .readfn = gt_cnt_read,
55
+ },
56
+};
57
+
58
#else
59
60
/*
61
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo generic_timer_cp_reginfo[] = {
62
},
63
};
64
65
+/*
66
+ * CNTVCTSS_EL0 has the same trap conditions as CNTVCT_EL0, so it also
67
+ * is exposed to userspace by Linux.
68
+ */
69
+static const ARMCPRegInfo gen_timer_ecv_cp_reginfo[] = {
70
+ { .name = "CNTVCTSS_EL0", .state = ARM_CP_STATE_AA64,
71
+ .opc0 = 3, .opc1 = 3, .crn = 14, .crm = 0, .opc2 = 6,
72
+ .access = PL0_R, .type = ARM_CP_NO_RAW | ARM_CP_IO,
73
+ .readfn = gt_virt_cnt_read,
74
+ },
75
+};
76
+
26
#endif
77
#endif
27
78
28
static void switch_mode(CPUARMState *env, int mode);
79
static void par_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
29
+static int aa64_va_parameter_tbi(uint64_t tcr, ARMMMUIdx mmu_idx);
80
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
30
81
if (arm_feature(env, ARM_FEATURE_GENERIC_TIMER)) {
31
static int vfp_gdb_get_reg(CPUARMState *env, GByteArray *buf, int reg)
82
define_arm_cp_regs(cpu, generic_timer_cp_reginfo);
32
{
33
@@ -XXX,XX +XXX,XX @@ static int vae1_tlbmask(CPUARMState *env)
34
}
83
}
35
}
84
+ if (cpu_isar_feature(aa64_ecv_traps, cpu)) {
36
85
+ define_arm_cp_regs(cpu, gen_timer_ecv_cp_reginfo);
37
+/* Return 56 if TBI is enabled, 64 otherwise. */
38
+static int tlbbits_for_regime(CPUARMState *env, ARMMMUIdx mmu_idx,
39
+ uint64_t addr)
40
+{
41
+ uint64_t tcr = regime_tcr(env, mmu_idx)->raw_tcr;
42
+ int tbi = aa64_va_parameter_tbi(tcr, mmu_idx);
43
+ int select = extract64(addr, 55, 1);
44
+
45
+ return (tbi >> select) & 1 ? 56 : 64;
46
+}
47
+
48
+static int vae1_tlbbits(CPUARMState *env, uint64_t addr)
49
+{
50
+ ARMMMUIdx mmu_idx;
51
+
52
+ /* Only the regime of the mmu_idx below is significant. */
53
+ if (arm_is_secure_below_el3(env)) {
54
+ mmu_idx = ARMMMUIdx_SE10_0;
55
+ } else if ((env->cp15.hcr_el2 & (HCR_E2H | HCR_TGE))
56
+ == (HCR_E2H | HCR_TGE)) {
57
+ mmu_idx = ARMMMUIdx_E20_0;
58
+ } else {
59
+ mmu_idx = ARMMMUIdx_E10_0;
60
+ }
86
+ }
61
+ return tlbbits_for_regime(env, mmu_idx, addr);
87
if (arm_feature(env, ARM_FEATURE_VAPA)) {
62
+}
88
ARMCPRegInfo vapa_cp_reginfo[] = {
63
+
89
{ .name = "PAR", .cp = 15, .crn = 7, .crm = 4, .opc1 = 0, .opc2 = 0,
64
static void tlbi_aa64_vmalle1is_write(CPUARMState *env, const ARMCPRegInfo *ri,
65
uint64_t value)
66
{
67
@@ -XXX,XX +XXX,XX @@ static void tlbi_aa64_vae1is_write(CPUARMState *env, const ARMCPRegInfo *ri,
68
CPUState *cs = env_cpu(env);
69
int mask = vae1_tlbmask(env);
70
uint64_t pageaddr = sextract64(value << 12, 0, 56);
71
+ int bits = vae1_tlbbits(env, pageaddr);
72
73
- tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr, mask);
74
+ tlb_flush_page_bits_by_mmuidx_all_cpus_synced(cs, pageaddr, mask, bits);
75
}
76
77
static void tlbi_aa64_vae1_write(CPUARMState *env, const ARMCPRegInfo *ri,
78
@@ -XXX,XX +XXX,XX @@ static void tlbi_aa64_vae1_write(CPUARMState *env, const ARMCPRegInfo *ri,
79
CPUState *cs = env_cpu(env);
80
int mask = vae1_tlbmask(env);
81
uint64_t pageaddr = sextract64(value << 12, 0, 56);
82
+ int bits = vae1_tlbbits(env, pageaddr);
83
84
if (tlb_force_broadcast(env)) {
85
- tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr, mask);
86
+ tlb_flush_page_bits_by_mmuidx_all_cpus_synced(cs, pageaddr, mask, bits);
87
} else {
88
- tlb_flush_page_by_mmuidx(cs, pageaddr, mask);
89
+ tlb_flush_page_bits_by_mmuidx(cs, pageaddr, mask, bits);
90
}
91
}
92
93
@@ -XXX,XX +XXX,XX @@ static void tlbi_aa64_vae2is_write(CPUARMState *env, const ARMCPRegInfo *ri,
94
{
95
CPUState *cs = env_cpu(env);
96
uint64_t pageaddr = sextract64(value << 12, 0, 56);
97
+ int bits = tlbbits_for_regime(env, ARMMMUIdx_E2, pageaddr);
98
99
- tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr,
100
- ARMMMUIdxBit_E2);
101
+ tlb_flush_page_bits_by_mmuidx_all_cpus_synced(cs, pageaddr,
102
+ ARMMMUIdxBit_E2, bits);
103
}
104
105
static void tlbi_aa64_vae3is_write(CPUARMState *env, const ARMCPRegInfo *ri,
106
@@ -XXX,XX +XXX,XX @@ static void tlbi_aa64_vae3is_write(CPUARMState *env, const ARMCPRegInfo *ri,
107
{
108
CPUState *cs = env_cpu(env);
109
uint64_t pageaddr = sextract64(value << 12, 0, 56);
110
+ int bits = tlbbits_for_regime(env, ARMMMUIdx_SE3, pageaddr);
111
112
- tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr,
113
- ARMMMUIdxBit_SE3);
114
+ tlb_flush_page_bits_by_mmuidx_all_cpus_synced(cs, pageaddr,
115
+ ARMMMUIdxBit_SE3, bits);
116
}
117
118
static CPAccessResult aa64_zva_access(CPUARMState *env, const ARMCPRegInfo *ri,
119
--
90
--
120
2.20.1
91
2.34.1
121
122
diff view generated by jsdifflib
1
v8.1M implements a new 'branch future' feature, which is a
1
When ID_AA64MMFR0_EL1.ECV is 0b0010, a new register CNTPOFF_EL2 is
2
set of instructions that request the CPU to perform a branch
2
implemented. This is similar to the existing CNTVOFF_EL2, except
3
"in the future", when it reaches a particular execution address.
3
that it controls a hypervisor-adjustable offset made to the physical
4
In hardware, the expected implementation is that the information
4
counter and timer.
5
about the branch location and destination is cached and then
6
acted upon when execution reaches the specified address.
7
However the architecture permits an implementation to discard
8
this cached information at any point, and so guest code must
9
always include a normal branch insn at the branch point as
10
a fallback. In particular, an implementation is specifically
11
permitted to treat all BF insns as NOPs (which is equivalent
12
to discarding the cached information immediately).
13
5
14
For QEMU, implementing this caching of branch information
6
Implement the handling for this register, which includes control/trap
15
would be complicated and would not improve the speed of
7
bits in SCR_EL3 and CNTHCTL_EL2.
16
execution at all, so we make the IMPDEF choice to implement
17
all BF insns as NOPs.
18
8
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
20
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Message-id: 20240301183219.2424889-8-peter.maydell@linaro.org
21
Message-id: 20201019151301.2046-7-peter.maydell@linaro.org
22
---
12
---
23
target/arm/cpu.h | 6 ++++++
13
target/arm/cpu-features.h | 5 +++
24
target/arm/t32.decode | 13 ++++++++++++-
14
target/arm/cpu.h | 1 +
25
target/arm/translate.c | 20 ++++++++++++++++++++
15
target/arm/helper.c | 68 +++++++++++++++++++++++++++++++++++++--
26
3 files changed, 38 insertions(+), 1 deletion(-)
16
target/arm/trace-events | 1 +
17
4 files changed, 73 insertions(+), 2 deletions(-)
27
18
19
diff --git a/target/arm/cpu-features.h b/target/arm/cpu-features.h
20
index XXXXXXX..XXXXXXX 100644
21
--- a/target/arm/cpu-features.h
22
+++ b/target/arm/cpu-features.h
23
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa64_ecv_traps(const ARMISARegisters *id)
24
return FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, ECV) > 0;
25
}
26
27
+static inline bool isar_feature_aa64_ecv(const ARMISARegisters *id)
28
+{
29
+ return FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, ECV) > 1;
30
+}
31
+
32
static inline bool isar_feature_aa64_vh(const ARMISARegisters *id)
33
{
34
return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, VH) != 0;
28
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
35
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
29
index XXXXXXX..XXXXXXX 100644
36
index XXXXXXX..XXXXXXX 100644
30
--- a/target/arm/cpu.h
37
--- a/target/arm/cpu.h
31
+++ b/target/arm/cpu.h
38
+++ b/target/arm/cpu.h
32
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa32_arm_div(const ARMISARegisters *id)
39
@@ -XXX,XX +XXX,XX @@ typedef struct CPUArchState {
33
return FIELD_EX32(id->id_isar0, ID_ISAR0, DIVIDE) > 1;
40
uint64_t c14_cntkctl; /* Timer Control register */
41
uint64_t cnthctl_el2; /* Counter/Timer Hyp Control register */
42
uint64_t cntvoff_el2; /* Counter Virtual Offset register */
43
+ uint64_t cntpoff_el2; /* Counter Physical Offset register */
44
ARMGenericTimer c14_timer[NUM_GTIMERS];
45
uint32_t c15_cpar; /* XScale Coprocessor Access Register */
46
uint32_t c15_ticonfig; /* TI925T configuration byte. */
47
diff --git a/target/arm/helper.c b/target/arm/helper.c
48
index XXXXXXX..XXXXXXX 100644
49
--- a/target/arm/helper.c
50
+++ b/target/arm/helper.c
51
@@ -XXX,XX +XXX,XX @@ static void scr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
52
if (cpu_isar_feature(aa64_rme, cpu)) {
53
valid_mask |= SCR_NSE | SCR_GPF;
54
}
55
+ if (cpu_isar_feature(aa64_ecv, cpu)) {
56
+ valid_mask |= SCR_ECVEN;
57
+ }
58
} else {
59
valid_mask &= ~(SCR_RW | SCR_ST);
60
if (cpu_isar_feature(aa32_ras, cpu)) {
61
@@ -XXX,XX +XXX,XX @@ void gt_rme_post_el_change(ARMCPU *cpu, void *ignored)
62
gt_update_irq(cpu, GTIMER_PHYS);
34
}
63
}
35
64
36
+static inline bool isar_feature_aa32_lob(const ARMISARegisters *id)
65
+static uint64_t gt_phys_raw_cnt_offset(CPUARMState *env)
37
+{
66
+{
38
+ /* (M-profile) low-overhead loops and branch future */
67
+ if ((env->cp15.scr_el3 & SCR_ECVEN) &&
39
+ return FIELD_EX32(id->id_isar0, ID_ISAR0, CMPBRANCH) >= 3;
68
+ FIELD_EX64(env->cp15.cnthctl_el2, CNTHCTL, ECV) &&
69
+ arm_is_el2_enabled(env) &&
70
+ (arm_hcr_el2_eff(env) & (HCR_E2H | HCR_TGE)) != (HCR_E2H | HCR_TGE)) {
71
+ return env->cp15.cntpoff_el2;
72
+ }
73
+ return 0;
40
+}
74
+}
41
+
75
+
42
static inline bool isar_feature_aa32_jazelle(const ARMISARegisters *id)
76
+static uint64_t gt_phys_cnt_offset(CPUARMState *env)
43
{
44
return FIELD_EX32(id->id_isar1, ID_ISAR1, JAZELLE) != 0;
45
diff --git a/target/arm/t32.decode b/target/arm/t32.decode
46
index XXXXXXX..XXXXXXX 100644
47
--- a/target/arm/t32.decode
48
+++ b/target/arm/t32.decode
49
@@ -XXX,XX +XXX,XX @@ MRC 1110 1110 ... 1 .... .... .... ... 1 .... @mcr
50
51
B 1111 0. .......... 10.1 ............ @branch24
52
BL 1111 0. .......... 11.1 ............ @branch24
53
-BLX_i 1111 0. .......... 11.0 ............ @branch24
54
+{
77
+{
55
+ # BLX_i is non-M-profile only
78
+ if (arm_current_el(env) >= 2) {
56
+ BLX_i 1111 0. .......... 11.0 ............ @branch24
79
+ return 0;
57
+ # M-profile only: loop and branch insns
58
+ [
59
+ # All these BF insns have boff != 0b0000; we NOP them all
60
+ BF 1111 0 boff:4 ------- 1100 - ---------- 1 # BFL
61
+ BF 1111 0 boff:4 0 ------ 1110 - ---------- 1 # BFCSEL
62
+ BF 1111 0 boff:4 10 ----- 1110 - ---------- 1 # BF
63
+ BF 1111 0 boff:4 11 ----- 1110 0 0000000000 1 # BFX, BFLX
64
+ ]
65
+}
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 bool trans_BLX_suffix(DisasContext *s, arg_BLX_suffix *a)
71
return true;
72
}
73
74
+static bool trans_BF(DisasContext *s, arg_BF *a)
75
+{
76
+ /*
77
+ * M-profile branch future insns. The architecture permits an
78
+ * implementation to implement these as NOPs (equivalent to
79
+ * discarding the LO_BRANCH_INFO cache immediately), and we
80
+ * take that IMPDEF option because for QEMU a "real" implementation
81
+ * would be complicated and wouldn't execute any faster.
82
+ */
83
+ if (!dc_isar_feature(aa32_lob, s)) {
84
+ return false;
85
+ }
80
+ }
86
+ if (a->boff == 0) {
81
+ return gt_phys_raw_cnt_offset(env);
87
+ /* SEE "Related encodings" (loop insns) */
88
+ return false;
89
+ }
90
+ /* Handle as NOP */
91
+ return true;
92
+}
82
+}
93
+
83
+
94
static bool op_tbranch(DisasContext *s, arg_tbranch *a, bool half)
84
static void gt_recalc_timer(ARMCPU *cpu, int timeridx)
95
{
85
{
96
TCGv_i32 addr, tmp;
86
ARMGenericTimer *gt = &cpu->env.cp15.c14_timer[timeridx];
87
@@ -XXX,XX +XXX,XX @@ static void gt_recalc_timer(ARMCPU *cpu, int timeridx)
88
* reset timer to when ISTATUS next has to change
89
*/
90
uint64_t offset = timeridx == GTIMER_VIRT ?
91
- cpu->env.cp15.cntvoff_el2 : 0;
92
+ cpu->env.cp15.cntvoff_el2 : gt_phys_raw_cnt_offset(&cpu->env);
93
uint64_t count = gt_get_countervalue(&cpu->env);
94
/* Note that this must be unsigned 64 bit arithmetic: */
95
int istatus = count - offset >= gt->cval;
96
@@ -XXX,XX +XXX,XX @@ static void gt_timer_reset(CPUARMState *env, const ARMCPRegInfo *ri,
97
98
static uint64_t gt_cnt_read(CPUARMState *env, const ARMCPRegInfo *ri)
99
{
100
- return gt_get_countervalue(env);
101
+ return gt_get_countervalue(env) - gt_phys_cnt_offset(env);
102
}
103
104
static uint64_t gt_virt_cnt_offset(CPUARMState *env)
105
@@ -XXX,XX +XXX,XX @@ static uint64_t gt_tval_read(CPUARMState *env, const ARMCPRegInfo *ri,
106
case GTIMER_HYPVIRT:
107
offset = gt_virt_cnt_offset(env);
108
break;
109
+ case GTIMER_PHYS:
110
+ offset = gt_phys_cnt_offset(env);
111
+ break;
112
}
113
114
return (uint32_t)(env->cp15.c14_timer[timeridx].cval -
115
@@ -XXX,XX +XXX,XX @@ static void gt_tval_write(CPUARMState *env, const ARMCPRegInfo *ri,
116
case GTIMER_HYPVIRT:
117
offset = gt_virt_cnt_offset(env);
118
break;
119
+ case GTIMER_PHYS:
120
+ offset = gt_phys_cnt_offset(env);
121
+ break;
122
}
123
124
trace_arm_gt_tval_write(timeridx, value);
125
@@ -XXX,XX +XXX,XX @@ static void gt_cnthctl_write(CPUARMState *env, const ARMCPRegInfo *ri,
126
R_CNTHCTL_EL1NVVCT_MASK |
127
R_CNTHCTL_EVNTIS_MASK;
128
}
129
+ if (cpu_isar_feature(aa64_ecv, cpu)) {
130
+ valid_mask |= R_CNTHCTL_ECV_MASK;
131
+ }
132
133
/* Clear RES0 bits */
134
value &= valid_mask;
135
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo gen_timer_ecv_cp_reginfo[] = {
136
},
137
};
138
139
+static CPAccessResult gt_cntpoff_access(CPUARMState *env,
140
+ const ARMCPRegInfo *ri,
141
+ bool isread)
142
+{
143
+ if (arm_current_el(env) == 2 && !(env->cp15.scr_el3 & SCR_ECVEN)) {
144
+ return CP_ACCESS_TRAP_EL3;
145
+ }
146
+ return CP_ACCESS_OK;
147
+}
148
+
149
+static void gt_cntpoff_write(CPUARMState *env, const ARMCPRegInfo *ri,
150
+ uint64_t value)
151
+{
152
+ ARMCPU *cpu = env_archcpu(env);
153
+
154
+ trace_arm_gt_cntpoff_write(value);
155
+ raw_write(env, ri, value);
156
+ gt_recalc_timer(cpu, GTIMER_PHYS);
157
+}
158
+
159
+static const ARMCPRegInfo gen_timer_cntpoff_reginfo = {
160
+ .name = "CNTPOFF_EL2", .state = ARM_CP_STATE_AA64,
161
+ .opc0 = 3, .opc1 = 4, .crn = 14, .crm = 0, .opc2 = 6,
162
+ .access = PL2_RW, .type = ARM_CP_IO, .resetvalue = 0,
163
+ .accessfn = gt_cntpoff_access, .writefn = gt_cntpoff_write,
164
+ .nv2_redirect_offset = 0x1a8,
165
+ .fieldoffset = offsetof(CPUARMState, cp15.cntpoff_el2),
166
+};
167
#else
168
169
/*
170
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
171
if (cpu_isar_feature(aa64_ecv_traps, cpu)) {
172
define_arm_cp_regs(cpu, gen_timer_ecv_cp_reginfo);
173
}
174
+#ifndef CONFIG_USER_ONLY
175
+ if (cpu_isar_feature(aa64_ecv, cpu)) {
176
+ define_one_arm_cp_reg(cpu, &gen_timer_cntpoff_reginfo);
177
+ }
178
+#endif
179
if (arm_feature(env, ARM_FEATURE_VAPA)) {
180
ARMCPRegInfo vapa_cp_reginfo[] = {
181
{ .name = "PAR", .cp = 15, .crn = 7, .crm = 4, .opc1 = 0, .opc2 = 0,
182
diff --git a/target/arm/trace-events b/target/arm/trace-events
183
index XXXXXXX..XXXXXXX 100644
184
--- a/target/arm/trace-events
185
+++ b/target/arm/trace-events
186
@@ -XXX,XX +XXX,XX @@ arm_gt_tval_write(int timer, uint64_t value) "gt_tval_write: timer %d value 0x%"
187
arm_gt_ctl_write(int timer, uint64_t value) "gt_ctl_write: timer %d value 0x%" PRIx64
188
arm_gt_imask_toggle(int timer) "gt_ctl_write: timer %d IMASK toggle"
189
arm_gt_cntvoff_write(uint64_t value) "gt_cntvoff_write: value 0x%" PRIx64
190
+arm_gt_cntpoff_write(uint64_t value) "gt_cntpoff_write: value 0x%" PRIx64
191
arm_gt_update_irq(int timer, int irqstate) "gt_update_irq: timer %d irqstate %d"
192
193
# kvm.c
97
--
194
--
98
2.20.1
195
2.34.1
99
100
diff view generated by jsdifflib
1
If the M-profile low-overhead-branch extension is implemented, FPSCR
1
Enable all FEAT_ECV features on the 'max' CPU.
2
bits [18:16] are a new field LTPSIZE. If MVE is not implemented
3
(currently always true for us) then this field always reads as 4 and
4
ignores writes.
5
6
These bits used to be the vector-length field for the old
7
short-vector extension, so we need to take care that they are not
8
misinterpreted as setting vec_len. We do this with a rearrangement
9
of the vfp_set_fpscr() code that deals with vec_len, vec_stride
10
and also the QC bit; this obviates the need for the M-profile
11
only masking step that we used to have at the start of the function.
12
13
We provide a new field in CPUState for LTPSIZE, even though this
14
will always be 4, in preparation for MVE, so we don't have to
15
come back later and split it out of the vfp.xregs[FPSCR] value.
16
(This state struct field will be saved and restored as part of
17
the FPSCR value via the vmstate_fpscr in machine.c.)
18
2
19
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
20
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
21
Message-id: 20201019151301.2046-11-peter.maydell@linaro.org
6
Message-id: 20240301183219.2424889-9-peter.maydell@linaro.org
22
---
7
---
23
target/arm/cpu.h | 1 +
8
docs/system/arm/emulation.rst | 1 +
24
target/arm/cpu.c | 9 +++++++++
9
target/arm/tcg/cpu64.c | 1 +
25
target/arm/vfp_helper.c | 6 ++++++
10
2 files changed, 2 insertions(+)
26
3 files changed, 16 insertions(+)
27
11
28
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
12
diff --git a/docs/system/arm/emulation.rst b/docs/system/arm/emulation.rst
29
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
30
--- a/target/arm/cpu.h
14
--- a/docs/system/arm/emulation.rst
31
+++ b/target/arm/cpu.h
15
+++ b/docs/system/arm/emulation.rst
32
@@ -XXX,XX +XXX,XX @@ typedef struct CPUARMState {
16
@@ -XXX,XX +XXX,XX @@ the following architecture extensions:
33
uint32_t fpdscr[M_REG_NUM_BANKS];
17
- FEAT_DotProd (Advanced SIMD dot product instructions)
34
uint32_t cpacr[M_REG_NUM_BANKS];
18
- FEAT_DoubleFault (Double Fault Extension)
35
uint32_t nsacr;
19
- FEAT_E0PD (Preventing EL0 access to halves of address maps)
36
+ int ltpsize;
20
+- FEAT_ECV (Enhanced Counter Virtualization)
37
} v7m;
21
- FEAT_EPAC (Enhanced pointer authentication)
38
22
- FEAT_ETS (Enhanced Translation Synchronization)
39
/* Information associated with an exception about to be taken:
23
- FEAT_EVT (Enhanced Virtualization Traps)
40
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
24
diff --git a/target/arm/tcg/cpu64.c b/target/arm/tcg/cpu64.c
41
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
42
--- a/target/arm/cpu.c
26
--- a/target/arm/tcg/cpu64.c
43
+++ b/target/arm/cpu.c
27
+++ b/target/arm/tcg/cpu64.c
44
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_reset(DeviceState *dev)
28
@@ -XXX,XX +XXX,XX @@ void aarch64_max_tcg_initfn(Object *obj)
45
uint8_t *rom;
29
t = FIELD_DP64(t, ID_AA64MMFR0, TGRAN64_2, 2); /* 64k stage2 supported */
46
uint32_t vecbase;
30
t = FIELD_DP64(t, ID_AA64MMFR0, TGRAN4_2, 2); /* 4k stage2 supported */
47
31
t = FIELD_DP64(t, ID_AA64MMFR0, FGT, 1); /* FEAT_FGT */
48
+ if (cpu_isar_feature(aa32_lob, cpu)) {
32
+ t = FIELD_DP64(t, ID_AA64MMFR0, ECV, 2); /* FEAT_ECV */
49
+ /*
33
cpu->isar.id_aa64mmfr0 = t;
50
+ * LTPSIZE is constant 4 if MVE not implemented, and resets
34
51
+ * to an UNKNOWN value if MVE is implemented. We choose to
35
t = cpu->isar.id_aa64mmfr1;
52
+ * always reset to 4.
53
+ */
54
+ env->v7m.ltpsize = 4;
55
+ }
56
+
57
if (arm_feature(env, ARM_FEATURE_M_SECURITY)) {
58
env->v7m.secure = true;
59
} else {
60
diff --git a/target/arm/vfp_helper.c b/target/arm/vfp_helper.c
61
index XXXXXXX..XXXXXXX 100644
62
--- a/target/arm/vfp_helper.c
63
+++ b/target/arm/vfp_helper.c
64
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(vfp_get_fpscr)(CPUARMState *env)
65
| (env->vfp.vec_len << 16)
66
| (env->vfp.vec_stride << 20);
67
68
+ /*
69
+ * M-profile LTPSIZE overlaps A-profile Stride; whichever of the
70
+ * two is not applicable to this CPU will always be zero.
71
+ */
72
+ fpscr |= env->v7m.ltpsize << 16;
73
+
74
fpscr |= vfp_get_fpscr_from_host(env);
75
76
i = env->vfp.qc[0] | env->vfp.qc[1] | env->vfp.qc[2] | env->vfp.qc[3];
77
--
36
--
78
2.20.1
37
2.34.1
79
38
80
39
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Inès Varhol <ines.varhol@telecom-paris.fr>
2
2
3
On ARM, the Top Byte Ignore feature means that only 56 bits of
3
Features supported :
4
the address are significant in the virtual address. We are
4
- the 8 STM32L4x5 GPIOs are initialized with their reset values
5
required to give the entire 64-bit address to FAR_ELx on fault,
5
(except IDR, see below)
6
which means that we do not "clean" the top byte early in TCG.
6
- input mode : setting a pin in input mode "externally" (using input
7
irqs) results in an out irq (transmitted to SYSCFG)
8
- output mode : setting a bit in ODR sets the corresponding out irq
9
(if this line is configured in output mode)
10
- pull-up, pull-down
11
- push-pull, open-drain
7
12
8
This new interface allows us to flush all 256 possible aliases
13
Difference with the real GPIOs :
9
for a given page, currently missed by tlb_flush_page*.
14
- Alternate Function and Analog mode aren't implemented :
15
pins in AF/Analog behave like pins in input mode
16
- floating pins stay at their last value
17
- register IDR reset values differ from the real one :
18
values are coherent with the other registers reset values
19
and the fact that AF/Analog modes aren't implemented
20
- setting I/O output speed isn't supported
21
- locking port bits isn't supported
22
- ADC function isn't supported
23
- GPIOH has 16 pins instead of 2 pins
24
- writing to registers LCKR, AFRL, AFRH and ASCR is ineffective
10
25
11
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
26
Signed-off-by: Arnaud Minier <arnaud.minier@telecom-paris.fr>
12
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
27
Signed-off-by: Inès Varhol <ines.varhol@telecom-paris.fr>
13
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
28
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
14
Message-id: 20201016210754.818257-2-richard.henderson@linaro.org
29
Acked-by: Alistair Francis <alistair.francis@wdc.com>
30
Message-id: 20240305210444.310665-2-ines.varhol@telecom-paris.fr
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
31
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
---
32
---
17
include/exec/exec-all.h | 36 ++++++
33
MAINTAINERS | 1 +
18
accel/tcg/cputlb.c | 275 ++++++++++++++++++++++++++++++++++++++--
34
docs/system/arm/b-l475e-iot01a.rst | 2 +-
19
2 files changed, 302 insertions(+), 9 deletions(-)
35
include/hw/gpio/stm32l4x5_gpio.h | 70 +++++
36
hw/gpio/stm32l4x5_gpio.c | 477 +++++++++++++++++++++++++++++
37
hw/gpio/Kconfig | 3 +
38
hw/gpio/meson.build | 1 +
39
hw/gpio/trace-events | 6 +
40
7 files changed, 559 insertions(+), 1 deletion(-)
41
create mode 100644 include/hw/gpio/stm32l4x5_gpio.h
42
create mode 100644 hw/gpio/stm32l4x5_gpio.c
20
43
21
diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
44
diff --git a/MAINTAINERS b/MAINTAINERS
22
index XXXXXXX..XXXXXXX 100644
45
index XXXXXXX..XXXXXXX 100644
23
--- a/include/exec/exec-all.h
46
--- a/MAINTAINERS
24
+++ b/include/exec/exec-all.h
47
+++ b/MAINTAINERS
25
@@ -XXX,XX +XXX,XX @@ void tlb_flush_by_mmuidx_all_cpus(CPUState *cpu, uint16_t idxmap);
48
@@ -XXX,XX +XXX,XX @@ F: hw/arm/stm32l4x5_soc.c
26
* depend on when the guests translation ends the TB.
49
F: hw/misc/stm32l4x5_exti.c
27
*/
50
F: hw/misc/stm32l4x5_syscfg.c
28
void tlb_flush_by_mmuidx_all_cpus_synced(CPUState *cpu, uint16_t idxmap);
51
F: hw/misc/stm32l4x5_rcc.c
29
+
52
+F: hw/gpio/stm32l4x5_gpio.c
30
+/**
53
F: include/hw/*/stm32l4x5_*.h
31
+ * tlb_flush_page_bits_by_mmuidx
54
32
+ * @cpu: CPU whose TLB should be flushed
55
B-L475E-IOT01A IoT Node
33
+ * @addr: virtual address of page to be flushed
56
diff --git a/docs/system/arm/b-l475e-iot01a.rst b/docs/system/arm/b-l475e-iot01a.rst
34
+ * @idxmap: bitmap of mmu indexes to flush
57
index XXXXXXX..XXXXXXX 100644
35
+ * @bits: number of significant bits in address
58
--- a/docs/system/arm/b-l475e-iot01a.rst
59
+++ b/docs/system/arm/b-l475e-iot01a.rst
60
@@ -XXX,XX +XXX,XX @@ Currently B-L475E-IOT01A machine's only supports the following devices:
61
- STM32L4x5 EXTI (Extended interrupts and events controller)
62
- STM32L4x5 SYSCFG (System configuration controller)
63
- STM32L4x5 RCC (Reset and clock control)
64
+- STM32L4x5 GPIOs (General-purpose I/Os)
65
66
Missing devices
67
"""""""""""""""
68
@@ -XXX,XX +XXX,XX @@ Missing devices
69
The B-L475E-IOT01A does *not* support the following devices:
70
71
- Serial ports (UART)
72
-- General-purpose I/Os (GPIO)
73
- Analog to Digital Converter (ADC)
74
- SPI controller
75
- Timer controller (TIMER)
76
diff --git a/include/hw/gpio/stm32l4x5_gpio.h b/include/hw/gpio/stm32l4x5_gpio.h
77
new file mode 100644
78
index XXXXXXX..XXXXXXX
79
--- /dev/null
80
+++ b/include/hw/gpio/stm32l4x5_gpio.h
81
@@ -XXX,XX +XXX,XX @@
82
+/*
83
+ * STM32L4x5 GPIO (General Purpose Input/Ouput)
36
+ *
84
+ *
37
+ * Similar to tlb_flush_page_mask, but with a bitmap of indexes.
85
+ * Copyright (c) 2024 Arnaud Minier <arnaud.minier@telecom-paris.fr>
86
+ * Copyright (c) 2024 Inès Varhol <ines.varhol@telecom-paris.fr>
87
+ *
88
+ * SPDX-License-Identifier: GPL-2.0-or-later
89
+ *
90
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
91
+ * See the COPYING file in the top-level directory.
38
+ */
92
+ */
39
+void tlb_flush_page_bits_by_mmuidx(CPUState *cpu, target_ulong addr,
93
+
40
+ uint16_t idxmap, unsigned bits);
94
+/*
41
+
95
+ * The reference used is the STMicroElectronics RM0351 Reference manual
42
+/* Similarly, with broadcast and syncing. */
96
+ * for STM32L4x5 and STM32L4x6 advanced Arm ® -based 32-bit MCUs.
43
+void tlb_flush_page_bits_by_mmuidx_all_cpus(CPUState *cpu, target_ulong addr,
97
+ * https://www.st.com/en/microcontrollers-microprocessors/stm32l4x5/documentation.html
44
+ uint16_t idxmap, unsigned bits);
98
+ */
45
+void tlb_flush_page_bits_by_mmuidx_all_cpus_synced
99
+
46
+ (CPUState *cpu, target_ulong addr, uint16_t idxmap, unsigned bits);
100
+#ifndef HW_STM32L4X5_GPIO_H
47
+
101
+#define HW_STM32L4X5_GPIO_H
48
/**
102
+
49
* tlb_set_page_with_attrs:
103
+#include "hw/sysbus.h"
50
* @cpu: CPU to add this TLB entry for
104
+#include "qom/object.h"
51
@@ -XXX,XX +XXX,XX @@ static inline void tlb_flush_by_mmuidx_all_cpus_synced(CPUState *cpu,
105
+
52
uint16_t idxmap)
106
+#define TYPE_STM32L4X5_GPIO "stm32l4x5-gpio"
53
{
107
+OBJECT_DECLARE_SIMPLE_TYPE(Stm32l4x5GpioState, STM32L4X5_GPIO)
54
}
108
+
55
+static inline void tlb_flush_page_bits_by_mmuidx(CPUState *cpu,
109
+#define GPIO_NUM_PINS 16
56
+ target_ulong addr,
110
+
57
+ uint16_t idxmap,
111
+struct Stm32l4x5GpioState {
58
+ unsigned bits)
112
+ SysBusDevice parent_obj;
59
+{
113
+
60
+}
114
+ MemoryRegion mmio;
61
+static inline void tlb_flush_page_bits_by_mmuidx_all_cpus(CPUState *cpu,
115
+
62
+ target_ulong addr,
116
+ /* GPIO registers */
63
+ uint16_t idxmap,
117
+ uint32_t moder;
64
+ unsigned bits)
118
+ uint32_t otyper;
65
+{
119
+ uint32_t ospeedr;
66
+}
120
+ uint32_t pupdr;
67
+static inline void
121
+ uint32_t idr;
68
+tlb_flush_page_bits_by_mmuidx_all_cpus_synced(CPUState *cpu, target_ulong addr,
122
+ uint32_t odr;
69
+ uint16_t idxmap, unsigned bits)
123
+ uint32_t lckr;
70
+{
124
+ uint32_t afrl;
71
+}
125
+ uint32_t afrh;
72
#endif
126
+ uint32_t ascr;
73
/**
127
+
74
* probe_access:
128
+ /* GPIO registers reset values */
75
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
129
+ uint32_t moder_reset;
76
index XXXXXXX..XXXXXXX 100644
130
+ uint32_t ospeedr_reset;
77
--- a/accel/tcg/cputlb.c
131
+ uint32_t pupdr_reset;
78
+++ b/accel/tcg/cputlb.c
79
@@ -XXX,XX +XXX,XX @@ void tlb_flush_all_cpus_synced(CPUState *src_cpu)
80
tlb_flush_by_mmuidx_all_cpus_synced(src_cpu, ALL_MMUIDX_BITS);
81
}
82
83
+static bool tlb_hit_page_mask_anyprot(CPUTLBEntry *tlb_entry,
84
+ target_ulong page, target_ulong mask)
85
+{
86
+ page &= mask;
87
+ mask &= TARGET_PAGE_MASK | TLB_INVALID_MASK;
88
+
89
+ return (page == (tlb_entry->addr_read & mask) ||
90
+ page == (tlb_addr_write(tlb_entry) & mask) ||
91
+ page == (tlb_entry->addr_code & mask));
92
+}
93
+
94
static inline bool tlb_hit_page_anyprot(CPUTLBEntry *tlb_entry,
95
target_ulong page)
96
{
97
- return tlb_hit_page(tlb_entry->addr_read, page) ||
98
- tlb_hit_page(tlb_addr_write(tlb_entry), page) ||
99
- tlb_hit_page(tlb_entry->addr_code, page);
100
+ return tlb_hit_page_mask_anyprot(tlb_entry, page, -1);
101
}
102
103
/**
104
@@ -XXX,XX +XXX,XX @@ static inline bool tlb_entry_is_empty(const CPUTLBEntry *te)
105
}
106
107
/* Called with tlb_c.lock held */
108
-static inline bool tlb_flush_entry_locked(CPUTLBEntry *tlb_entry,
109
- target_ulong page)
110
+static bool tlb_flush_entry_mask_locked(CPUTLBEntry *tlb_entry,
111
+ target_ulong page,
112
+ target_ulong mask)
113
{
114
- if (tlb_hit_page_anyprot(tlb_entry, page)) {
115
+ if (tlb_hit_page_mask_anyprot(tlb_entry, page, mask)) {
116
memset(tlb_entry, -1, sizeof(*tlb_entry));
117
return true;
118
}
119
return false;
120
}
121
122
+static inline bool tlb_flush_entry_locked(CPUTLBEntry *tlb_entry,
123
+ target_ulong page)
124
+{
125
+ return tlb_flush_entry_mask_locked(tlb_entry, page, -1);
126
+}
127
+
128
/* Called with tlb_c.lock held */
129
-static inline void tlb_flush_vtlb_page_locked(CPUArchState *env, int mmu_idx,
130
- target_ulong page)
131
+static void tlb_flush_vtlb_page_mask_locked(CPUArchState *env, int mmu_idx,
132
+ target_ulong page,
133
+ target_ulong mask)
134
{
135
CPUTLBDesc *d = &env_tlb(env)->d[mmu_idx];
136
int k;
137
138
assert_cpu_is_self(env_cpu(env));
139
for (k = 0; k < CPU_VTLB_SIZE; k++) {
140
- if (tlb_flush_entry_locked(&d->vtable[k], page)) {
141
+ if (tlb_flush_entry_mask_locked(&d->vtable[k], page, mask)) {
142
tlb_n_used_entries_dec(env, mmu_idx);
143
}
144
}
145
}
146
147
+static inline void tlb_flush_vtlb_page_locked(CPUArchState *env, int mmu_idx,
148
+ target_ulong page)
149
+{
150
+ tlb_flush_vtlb_page_mask_locked(env, mmu_idx, page, -1);
151
+}
152
+
153
static void tlb_flush_page_locked(CPUArchState *env, int midx,
154
target_ulong page)
155
{
156
@@ -XXX,XX +XXX,XX @@ void tlb_flush_page_all_cpus_synced(CPUState *src, target_ulong addr)
157
tlb_flush_page_by_mmuidx_all_cpus_synced(src, addr, ALL_MMUIDX_BITS);
158
}
159
160
+static void tlb_flush_page_bits_locked(CPUArchState *env, int midx,
161
+ target_ulong page, unsigned bits)
162
+{
163
+ CPUTLBDesc *d = &env_tlb(env)->d[midx];
164
+ CPUTLBDescFast *f = &env_tlb(env)->f[midx];
165
+ target_ulong mask = MAKE_64BIT_MASK(0, bits);
166
+
132
+
167
+ /*
133
+ /*
168
+ * If @bits is smaller than the tlb size, there may be multiple entries
134
+ * External driving of pins.
169
+ * within the TLB; otherwise all addresses that match under @mask hit
135
+ * The pins can be set externally through the device
170
+ * the same TLB entry.
136
+ * anonymous input GPIOs lines under certain conditions.
171
+ *
137
+ * The pin must not be in push-pull output mode,
172
+ * TODO: Perhaps allow bits to be a few bits less than the size.
138
+ * and can't be set high in open-drain mode.
173
+ * For now, just flush the entire TLB.
139
+ * Pins driven externally and configured to
140
+ * output mode will in general be "disconnected"
141
+ * (see `get_gpio_pinmask_to_disconnect()`)
174
+ */
142
+ */
175
+ if (mask < f->mask) {
143
+ uint16_t disconnected_pins;
176
+ tlb_debug("forcing full flush midx %d ("
144
+ uint16_t pins_connected_high;
177
+ TARGET_FMT_lx "/" TARGET_FMT_lx ")\n",
145
+
178
+ midx, page, mask);
146
+ char *name;
179
+ tlb_flush_one_mmuidx_locked(env, midx, get_clock_realtime());
147
+ Clock *clk;
180
+ return;
148
+ qemu_irq pin[GPIO_NUM_PINS];
181
+ }
149
+};
182
+
150
+
183
+ /* Check if we need to flush due to large pages. */
151
+#endif
184
+ if ((page & d->large_page_mask) == d->large_page_addr) {
152
diff --git a/hw/gpio/stm32l4x5_gpio.c b/hw/gpio/stm32l4x5_gpio.c
185
+ tlb_debug("forcing full flush midx %d ("
153
new file mode 100644
186
+ TARGET_FMT_lx "/" TARGET_FMT_lx ")\n",
154
index XXXXXXX..XXXXXXX
187
+ midx, d->large_page_addr, d->large_page_mask);
155
--- /dev/null
188
+ tlb_flush_one_mmuidx_locked(env, midx, get_clock_realtime());
156
+++ b/hw/gpio/stm32l4x5_gpio.c
189
+ return;
157
@@ -XXX,XX +XXX,XX @@
190
+ }
158
+/*
191
+
159
+ * STM32L4x5 GPIO (General Purpose Input/Ouput)
192
+ if (tlb_flush_entry_mask_locked(tlb_entry(env, midx, page), page, mask)) {
160
+ *
193
+ tlb_n_used_entries_dec(env, midx);
161
+ * Copyright (c) 2024 Arnaud Minier <arnaud.minier@telecom-paris.fr>
194
+ }
162
+ * Copyright (c) 2024 Inès Varhol <ines.varhol@telecom-paris.fr>
195
+ tlb_flush_vtlb_page_mask_locked(env, midx, page, mask);
163
+ *
196
+}
164
+ * SPDX-License-Identifier: GPL-2.0-or-later
197
+
165
+ *
198
+typedef struct {
166
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
199
+ target_ulong addr;
167
+ * See the COPYING file in the top-level directory.
200
+ uint16_t idxmap;
168
+ */
201
+ uint16_t bits;
169
+
202
+} TLBFlushPageBitsByMMUIdxData;
170
+/*
203
+
171
+ * The reference used is the STMicroElectronics RM0351 Reference manual
204
+static void
172
+ * for STM32L4x5 and STM32L4x6 advanced Arm ® -based 32-bit MCUs.
205
+tlb_flush_page_bits_by_mmuidx_async_0(CPUState *cpu,
173
+ * https://www.st.com/en/microcontrollers-microprocessors/stm32l4x5/documentation.html
206
+ TLBFlushPageBitsByMMUIdxData d)
174
+ */
207
+{
175
+
208
+ CPUArchState *env = cpu->env_ptr;
176
+#include "qemu/osdep.h"
209
+ int mmu_idx;
177
+#include "qemu/log.h"
210
+
178
+#include "hw/gpio/stm32l4x5_gpio.h"
211
+ assert_cpu_is_self(cpu);
179
+#include "hw/irq.h"
212
+
180
+#include "hw/qdev-clock.h"
213
+ tlb_debug("page addr:" TARGET_FMT_lx "/%u mmu_map:0x%x\n",
181
+#include "hw/qdev-properties.h"
214
+ d.addr, d.bits, d.idxmap);
182
+#include "qapi/visitor.h"
215
+
183
+#include "qapi/error.h"
216
+ qemu_spin_lock(&env_tlb(env)->c.lock);
184
+#include "migration/vmstate.h"
217
+ for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) {
185
+#include "trace.h"
218
+ if ((d.idxmap >> mmu_idx) & 1) {
186
+
219
+ tlb_flush_page_bits_locked(env, mmu_idx, d.addr, d.bits);
187
+#define GPIO_MODER 0x00
188
+#define GPIO_OTYPER 0x04
189
+#define GPIO_OSPEEDR 0x08
190
+#define GPIO_PUPDR 0x0C
191
+#define GPIO_IDR 0x10
192
+#define GPIO_ODR 0x14
193
+#define GPIO_BSRR 0x18
194
+#define GPIO_LCKR 0x1C
195
+#define GPIO_AFRL 0x20
196
+#define GPIO_AFRH 0x24
197
+#define GPIO_BRR 0x28
198
+#define GPIO_ASCR 0x2C
199
+
200
+/* 0b11111111_11111111_00000000_00000000 */
201
+#define RESERVED_BITS_MASK 0xFFFF0000
202
+
203
+static void update_gpio_idr(Stm32l4x5GpioState *s);
204
+
205
+static bool is_pull_up(Stm32l4x5GpioState *s, unsigned pin)
206
+{
207
+ return extract32(s->pupdr, 2 * pin, 2) == 1;
208
+}
209
+
210
+static bool is_pull_down(Stm32l4x5GpioState *s, unsigned pin)
211
+{
212
+ return extract32(s->pupdr, 2 * pin, 2) == 2;
213
+}
214
+
215
+static bool is_output(Stm32l4x5GpioState *s, unsigned pin)
216
+{
217
+ return extract32(s->moder, 2 * pin, 2) == 1;
218
+}
219
+
220
+static bool is_open_drain(Stm32l4x5GpioState *s, unsigned pin)
221
+{
222
+ return extract32(s->otyper, pin, 1) == 1;
223
+}
224
+
225
+static bool is_push_pull(Stm32l4x5GpioState *s, unsigned pin)
226
+{
227
+ return extract32(s->otyper, pin, 1) == 0;
228
+}
229
+
230
+static void stm32l4x5_gpio_reset_hold(Object *obj)
231
+{
232
+ Stm32l4x5GpioState *s = STM32L4X5_GPIO(obj);
233
+
234
+ s->moder = s->moder_reset;
235
+ s->otyper = 0x00000000;
236
+ s->ospeedr = s->ospeedr_reset;
237
+ s->pupdr = s->pupdr_reset;
238
+ s->idr = 0x00000000;
239
+ s->odr = 0x00000000;
240
+ s->lckr = 0x00000000;
241
+ s->afrl = 0x00000000;
242
+ s->afrh = 0x00000000;
243
+ s->ascr = 0x00000000;
244
+
245
+ s->disconnected_pins = 0xFFFF;
246
+ s->pins_connected_high = 0x0000;
247
+ update_gpio_idr(s);
248
+}
249
+
250
+static void stm32l4x5_gpio_set(void *opaque, int line, int level)
251
+{
252
+ Stm32l4x5GpioState *s = opaque;
253
+ /*
254
+ * The pin isn't set if line is configured in output mode
255
+ * except if level is 0 and the output is open-drain.
256
+ * This way there will be no short-circuit prone situations.
257
+ */
258
+ if (is_output(s, line) && !(is_open_drain(s, line) && (level == 0))) {
259
+ qemu_log_mask(LOG_GUEST_ERROR, "Line %d can't be driven externally\n",
260
+ line);
261
+ return;
262
+ }
263
+
264
+ s->disconnected_pins &= ~(1 << line);
265
+ if (level) {
266
+ s->pins_connected_high |= (1 << line);
267
+ } else {
268
+ s->pins_connected_high &= ~(1 << line);
269
+ }
270
+ trace_stm32l4x5_gpio_pins(s->name, s->disconnected_pins,
271
+ s->pins_connected_high);
272
+ update_gpio_idr(s);
273
+}
274
+
275
+
276
+static void update_gpio_idr(Stm32l4x5GpioState *s)
277
+{
278
+ uint32_t new_idr_mask = 0;
279
+ uint32_t new_idr = s->odr;
280
+ uint32_t old_idr = s->idr;
281
+ int new_pin_state, old_pin_state;
282
+
283
+ for (int i = 0; i < GPIO_NUM_PINS; i++) {
284
+ if (is_output(s, i)) {
285
+ if (is_push_pull(s, i)) {
286
+ new_idr_mask |= (1 << i);
287
+ } else if (!(s->odr & (1 << i))) {
288
+ /* open-drain ODR 0 */
289
+ new_idr_mask |= (1 << i);
290
+ /* open-drain ODR 1 */
291
+ } else if (!(s->disconnected_pins & (1 << i)) &&
292
+ !(s->pins_connected_high & (1 << i))) {
293
+ /* open-drain ODR 1 with pin connected low */
294
+ new_idr_mask |= (1 << i);
295
+ new_idr &= ~(1 << i);
296
+ /* open-drain ODR 1 with unactive pin */
297
+ } else if (is_pull_up(s, i)) {
298
+ new_idr_mask |= (1 << i);
299
+ } else if (is_pull_down(s, i)) {
300
+ new_idr_mask |= (1 << i);
301
+ new_idr &= ~(1 << i);
302
+ }
303
+ /*
304
+ * The only case left is for open-drain ODR 1
305
+ * with unactive pin without pull-up or pull-down :
306
+ * the value is floating.
307
+ */
308
+ /* input or analog mode with connected pin */
309
+ } else if (!(s->disconnected_pins & (1 << i))) {
310
+ if (s->pins_connected_high & (1 << i)) {
311
+ /* pin high */
312
+ new_idr_mask |= (1 << i);
313
+ new_idr |= (1 << i);
314
+ } else {
315
+ /* pin low */
316
+ new_idr_mask |= (1 << i);
317
+ new_idr &= ~(1 << i);
318
+ }
319
+ /* input or analog mode with disconnected pin */
320
+ } else {
321
+ if (is_pull_up(s, i)) {
322
+ /* pull-up */
323
+ new_idr_mask |= (1 << i);
324
+ new_idr |= (1 << i);
325
+ } else if (is_pull_down(s, i)) {
326
+ /* pull-down */
327
+ new_idr_mask |= (1 << i);
328
+ new_idr &= ~(1 << i);
329
+ }
330
+ /*
331
+ * The only case left is for a disconnected pin
332
+ * without pull-up or pull-down :
333
+ * the value is floating.
334
+ */
220
+ }
335
+ }
221
+ }
336
+ }
222
+ qemu_spin_unlock(&env_tlb(env)->c.lock);
337
+
223
+
338
+ s->idr = (old_idr & ~new_idr_mask) | (new_idr & new_idr_mask);
224
+ tb_flush_jmp_cache(cpu, d.addr);
339
+ trace_stm32l4x5_gpio_update_idr(s->name, old_idr, s->idr);
225
+}
340
+
226
+
341
+ for (int i = 0; i < GPIO_NUM_PINS; i++) {
227
+static bool encode_pbm_to_runon(run_on_cpu_data *out,
342
+ if (new_idr_mask & (1 << i)) {
228
+ TLBFlushPageBitsByMMUIdxData d)
343
+ new_pin_state = (new_idr & (1 << i)) > 0;
229
+{
344
+ old_pin_state = (old_idr & (1 << i)) > 0;
230
+ /* We need 6 bits to hold to hold @bits up to 63. */
345
+ if (new_pin_state > old_pin_state) {
231
+ if (d.idxmap <= MAKE_64BIT_MASK(0, TARGET_PAGE_BITS - 6)) {
346
+ qemu_irq_raise(s->pin[i]);
232
+ *out = RUN_ON_CPU_TARGET_PTR(d.addr | (d.idxmap << 6) | d.bits);
347
+ } else if (new_pin_state < old_pin_state) {
233
+ return true;
348
+ qemu_irq_lower(s->pin[i]);
234
+ }
235
+ return false;
236
+}
237
+
238
+static TLBFlushPageBitsByMMUIdxData
239
+decode_runon_to_pbm(run_on_cpu_data data)
240
+{
241
+ target_ulong addr_map_bits = (target_ulong) data.target_ptr;
242
+ return (TLBFlushPageBitsByMMUIdxData){
243
+ .addr = addr_map_bits & TARGET_PAGE_MASK,
244
+ .idxmap = (addr_map_bits & ~TARGET_PAGE_MASK) >> 6,
245
+ .bits = addr_map_bits & 0x3f
246
+ };
247
+}
248
+
249
+static void tlb_flush_page_bits_by_mmuidx_async_1(CPUState *cpu,
250
+ run_on_cpu_data runon)
251
+{
252
+ tlb_flush_page_bits_by_mmuidx_async_0(cpu, decode_runon_to_pbm(runon));
253
+}
254
+
255
+static void tlb_flush_page_bits_by_mmuidx_async_2(CPUState *cpu,
256
+ run_on_cpu_data data)
257
+{
258
+ TLBFlushPageBitsByMMUIdxData *d = data.host_ptr;
259
+ tlb_flush_page_bits_by_mmuidx_async_0(cpu, *d);
260
+ g_free(d);
261
+}
262
+
263
+void tlb_flush_page_bits_by_mmuidx(CPUState *cpu, target_ulong addr,
264
+ uint16_t idxmap, unsigned bits)
265
+{
266
+ TLBFlushPageBitsByMMUIdxData d;
267
+ run_on_cpu_data runon;
268
+
269
+ /* If all bits are significant, this devolves to tlb_flush_page. */
270
+ if (bits >= TARGET_LONG_BITS) {
271
+ tlb_flush_page_by_mmuidx(cpu, addr, idxmap);
272
+ return;
273
+ }
274
+ /* If no page bits are significant, this devolves to tlb_flush. */
275
+ if (bits < TARGET_PAGE_BITS) {
276
+ tlb_flush_by_mmuidx(cpu, idxmap);
277
+ return;
278
+ }
279
+
280
+ /* This should already be page aligned */
281
+ d.addr = addr & TARGET_PAGE_MASK;
282
+ d.idxmap = idxmap;
283
+ d.bits = bits;
284
+
285
+ if (qemu_cpu_is_self(cpu)) {
286
+ tlb_flush_page_bits_by_mmuidx_async_0(cpu, d);
287
+ } else if (encode_pbm_to_runon(&runon, d)) {
288
+ async_run_on_cpu(cpu, tlb_flush_page_bits_by_mmuidx_async_1, runon);
289
+ } else {
290
+ TLBFlushPageBitsByMMUIdxData *p
291
+ = g_new(TLBFlushPageBitsByMMUIdxData, 1);
292
+
293
+ /* Otherwise allocate a structure, freed by the worker. */
294
+ *p = d;
295
+ async_run_on_cpu(cpu, tlb_flush_page_bits_by_mmuidx_async_2,
296
+ RUN_ON_CPU_HOST_PTR(p));
297
+ }
298
+}
299
+
300
+void tlb_flush_page_bits_by_mmuidx_all_cpus(CPUState *src_cpu,
301
+ target_ulong addr,
302
+ uint16_t idxmap,
303
+ unsigned bits)
304
+{
305
+ TLBFlushPageBitsByMMUIdxData d;
306
+ run_on_cpu_data runon;
307
+
308
+ /* If all bits are significant, this devolves to tlb_flush_page. */
309
+ if (bits >= TARGET_LONG_BITS) {
310
+ tlb_flush_page_by_mmuidx_all_cpus(src_cpu, addr, idxmap);
311
+ return;
312
+ }
313
+ /* If no page bits are significant, this devolves to tlb_flush. */
314
+ if (bits < TARGET_PAGE_BITS) {
315
+ tlb_flush_by_mmuidx_all_cpus(src_cpu, idxmap);
316
+ return;
317
+ }
318
+
319
+ /* This should already be page aligned */
320
+ d.addr = addr & TARGET_PAGE_MASK;
321
+ d.idxmap = idxmap;
322
+ d.bits = bits;
323
+
324
+ if (encode_pbm_to_runon(&runon, d)) {
325
+ flush_all_helper(src_cpu, tlb_flush_page_bits_by_mmuidx_async_1, runon);
326
+ } else {
327
+ CPUState *dst_cpu;
328
+ TLBFlushPageBitsByMMUIdxData *p;
329
+
330
+ /* Allocate a separate data block for each destination cpu. */
331
+ CPU_FOREACH(dst_cpu) {
332
+ if (dst_cpu != src_cpu) {
333
+ p = g_new(TLBFlushPageBitsByMMUIdxData, 1);
334
+ *p = d;
335
+ async_run_on_cpu(dst_cpu,
336
+ tlb_flush_page_bits_by_mmuidx_async_2,
337
+ RUN_ON_CPU_HOST_PTR(p));
338
+ }
349
+ }
339
+ }
350
+ }
340
+ }
351
+ }
341
+
352
+}
342
+ tlb_flush_page_bits_by_mmuidx_async_0(src_cpu, d);
353
+
343
+}
354
+/*
344
+
355
+ * Return mask of pins that are both configured in output
345
+void tlb_flush_page_bits_by_mmuidx_all_cpus_synced(CPUState *src_cpu,
356
+ * mode and externally driven (except pins in open-drain
346
+ target_ulong addr,
357
+ * mode externally set to 0).
347
+ uint16_t idxmap,
358
+ */
348
+ unsigned bits)
359
+static uint32_t get_gpio_pinmask_to_disconnect(Stm32l4x5GpioState *s)
349
+{
360
+{
350
+ TLBFlushPageBitsByMMUIdxData d;
361
+ uint32_t pins_to_disconnect = 0;
351
+ run_on_cpu_data runon;
362
+ for (int i = 0; i < GPIO_NUM_PINS; i++) {
352
+
363
+ /* for each connected pin in output mode */
353
+ /* If all bits are significant, this devolves to tlb_flush_page. */
364
+ if (!(s->disconnected_pins & (1 << i)) && is_output(s, i)) {
354
+ if (bits >= TARGET_LONG_BITS) {
365
+ /* if either push-pull or high level */
355
+ tlb_flush_page_by_mmuidx_all_cpus_synced(src_cpu, addr, idxmap);
366
+ if (is_push_pull(s, i) || s->pins_connected_high & (1 << i)) {
356
+ return;
367
+ pins_to_disconnect |= (1 << i);
357
+ }
368
+ qemu_log_mask(LOG_GUEST_ERROR,
358
+ /* If no page bits are significant, this devolves to tlb_flush. */
369
+ "Line %d can't be driven externally\n",
359
+ if (bits < TARGET_PAGE_BITS) {
370
+ i);
360
+ tlb_flush_by_mmuidx_all_cpus_synced(src_cpu, idxmap);
361
+ return;
362
+ }
363
+
364
+ /* This should already be page aligned */
365
+ d.addr = addr & TARGET_PAGE_MASK;
366
+ d.idxmap = idxmap;
367
+ d.bits = bits;
368
+
369
+ if (encode_pbm_to_runon(&runon, d)) {
370
+ flush_all_helper(src_cpu, tlb_flush_page_bits_by_mmuidx_async_1, runon);
371
+ async_safe_run_on_cpu(src_cpu, tlb_flush_page_bits_by_mmuidx_async_1,
372
+ runon);
373
+ } else {
374
+ CPUState *dst_cpu;
375
+ TLBFlushPageBitsByMMUIdxData *p;
376
+
377
+ /* Allocate a separate data block for each destination cpu. */
378
+ CPU_FOREACH(dst_cpu) {
379
+ if (dst_cpu != src_cpu) {
380
+ p = g_new(TLBFlushPageBitsByMMUIdxData, 1);
381
+ *p = d;
382
+ async_run_on_cpu(dst_cpu, tlb_flush_page_bits_by_mmuidx_async_2,
383
+ RUN_ON_CPU_HOST_PTR(p));
384
+ }
371
+ }
385
+ }
372
+ }
386
+
373
+ }
387
+ p = g_new(TLBFlushPageBitsByMMUIdxData, 1);
374
+ return pins_to_disconnect;
388
+ *p = d;
375
+}
389
+ async_safe_run_on_cpu(src_cpu, tlb_flush_page_bits_by_mmuidx_async_2,
376
+
390
+ RUN_ON_CPU_HOST_PTR(p));
377
+/*
391
+ }
378
+ * Set field `disconnected_pins` and call `update_gpio_idr()`
392
+}
379
+ */
393
+
380
+static void disconnect_gpio_pins(Stm32l4x5GpioState *s, uint16_t lines)
394
/* update the TLBs so that writes to code in the virtual page 'addr'
381
+{
395
can be detected */
382
+ s->disconnected_pins |= lines;
396
void tlb_protect_code(ram_addr_t ram_addr)
383
+ trace_stm32l4x5_gpio_pins(s->name, s->disconnected_pins,
384
+ s->pins_connected_high);
385
+ update_gpio_idr(s);
386
+}
387
+
388
+static void disconnected_pins_set(Object *obj, Visitor *v,
389
+ const char *name, void *opaque, Error **errp)
390
+{
391
+ Stm32l4x5GpioState *s = STM32L4X5_GPIO(obj);
392
+ uint16_t value;
393
+ if (!visit_type_uint16(v, name, &value, errp)) {
394
+ return;
395
+ }
396
+ disconnect_gpio_pins(s, value);
397
+}
398
+
399
+static void disconnected_pins_get(Object *obj, Visitor *v,
400
+ const char *name, void *opaque, Error **errp)
401
+{
402
+ visit_type_uint16(v, name, (uint16_t *)opaque, errp);
403
+}
404
+
405
+static void clock_freq_get(Object *obj, Visitor *v,
406
+ const char *name, void *opaque, Error **errp)
407
+{
408
+ Stm32l4x5GpioState *s = STM32L4X5_GPIO(obj);
409
+ uint32_t clock_freq_hz = clock_get_hz(s->clk);
410
+ visit_type_uint32(v, name, &clock_freq_hz, errp);
411
+}
412
+
413
+static void stm32l4x5_gpio_write(void *opaque, hwaddr addr,
414
+ uint64_t val64, unsigned int size)
415
+{
416
+ Stm32l4x5GpioState *s = opaque;
417
+
418
+ uint32_t value = val64;
419
+ trace_stm32l4x5_gpio_write(s->name, addr, val64);
420
+
421
+ switch (addr) {
422
+ case GPIO_MODER:
423
+ s->moder = value;
424
+ disconnect_gpio_pins(s, get_gpio_pinmask_to_disconnect(s));
425
+ qemu_log_mask(LOG_UNIMP,
426
+ "%s: Analog and AF modes aren't supported\n\
427
+ Analog and AF mode behave like input mode\n",
428
+ __func__);
429
+ return;
430
+ case GPIO_OTYPER:
431
+ s->otyper = value & ~RESERVED_BITS_MASK;
432
+ disconnect_gpio_pins(s, get_gpio_pinmask_to_disconnect(s));
433
+ return;
434
+ case GPIO_OSPEEDR:
435
+ qemu_log_mask(LOG_UNIMP,
436
+ "%s: Changing I/O output speed isn't supported\n\
437
+ I/O speed is already maximal\n",
438
+ __func__);
439
+ s->ospeedr = value;
440
+ return;
441
+ case GPIO_PUPDR:
442
+ s->pupdr = value;
443
+ update_gpio_idr(s);
444
+ return;
445
+ case GPIO_IDR:
446
+ qemu_log_mask(LOG_UNIMP,
447
+ "%s: GPIO->IDR is read-only\n",
448
+ __func__);
449
+ return;
450
+ case GPIO_ODR:
451
+ s->odr = value & ~RESERVED_BITS_MASK;
452
+ update_gpio_idr(s);
453
+ return;
454
+ case GPIO_BSRR: {
455
+ uint32_t bits_to_reset = (value & RESERVED_BITS_MASK) >> GPIO_NUM_PINS;
456
+ uint32_t bits_to_set = value & ~RESERVED_BITS_MASK;
457
+ /* If both BSx and BRx are set, BSx has priority.*/
458
+ s->odr &= ~bits_to_reset;
459
+ s->odr |= bits_to_set;
460
+ update_gpio_idr(s);
461
+ return;
462
+ }
463
+ case GPIO_LCKR:
464
+ qemu_log_mask(LOG_UNIMP,
465
+ "%s: Locking port bits configuration isn't supported\n",
466
+ __func__);
467
+ s->lckr = value & ~RESERVED_BITS_MASK;
468
+ return;
469
+ case GPIO_AFRL:
470
+ qemu_log_mask(LOG_UNIMP,
471
+ "%s: Alternate functions aren't supported\n",
472
+ __func__);
473
+ s->afrl = value;
474
+ return;
475
+ case GPIO_AFRH:
476
+ qemu_log_mask(LOG_UNIMP,
477
+ "%s: Alternate functions aren't supported\n",
478
+ __func__);
479
+ s->afrh = value;
480
+ return;
481
+ case GPIO_BRR: {
482
+ uint32_t bits_to_reset = value & ~RESERVED_BITS_MASK;
483
+ s->odr &= ~bits_to_reset;
484
+ update_gpio_idr(s);
485
+ return;
486
+ }
487
+ case GPIO_ASCR:
488
+ qemu_log_mask(LOG_UNIMP,
489
+ "%s: ADC function isn't supported\n",
490
+ __func__);
491
+ s->ascr = value & ~RESERVED_BITS_MASK;
492
+ return;
493
+ default:
494
+ qemu_log_mask(LOG_GUEST_ERROR,
495
+ "%s: Bad offset 0x%" HWADDR_PRIx "\n", __func__, addr);
496
+ }
497
+}
498
+
499
+static uint64_t stm32l4x5_gpio_read(void *opaque, hwaddr addr,
500
+ unsigned int size)
501
+{
502
+ Stm32l4x5GpioState *s = opaque;
503
+
504
+ trace_stm32l4x5_gpio_read(s->name, addr);
505
+
506
+ switch (addr) {
507
+ case GPIO_MODER:
508
+ return s->moder;
509
+ case GPIO_OTYPER:
510
+ return s->otyper;
511
+ case GPIO_OSPEEDR:
512
+ return s->ospeedr;
513
+ case GPIO_PUPDR:
514
+ return s->pupdr;
515
+ case GPIO_IDR:
516
+ return s->idr;
517
+ case GPIO_ODR:
518
+ return s->odr;
519
+ case GPIO_BSRR:
520
+ return 0;
521
+ case GPIO_LCKR:
522
+ return s->lckr;
523
+ case GPIO_AFRL:
524
+ return s->afrl;
525
+ case GPIO_AFRH:
526
+ return s->afrh;
527
+ case GPIO_BRR:
528
+ return 0;
529
+ case GPIO_ASCR:
530
+ return s->ascr;
531
+ default:
532
+ qemu_log_mask(LOG_GUEST_ERROR,
533
+ "%s: Bad offset 0x%" HWADDR_PRIx "\n", __func__, addr);
534
+ return 0;
535
+ }
536
+}
537
+
538
+static const MemoryRegionOps stm32l4x5_gpio_ops = {
539
+ .read = stm32l4x5_gpio_read,
540
+ .write = stm32l4x5_gpio_write,
541
+ .endianness = DEVICE_NATIVE_ENDIAN,
542
+ .impl = {
543
+ .min_access_size = 4,
544
+ .max_access_size = 4,
545
+ .unaligned = false,
546
+ },
547
+ .valid = {
548
+ .min_access_size = 4,
549
+ .max_access_size = 4,
550
+ .unaligned = false,
551
+ },
552
+};
553
+
554
+static void stm32l4x5_gpio_init(Object *obj)
555
+{
556
+ Stm32l4x5GpioState *s = STM32L4X5_GPIO(obj);
557
+
558
+ memory_region_init_io(&s->mmio, obj, &stm32l4x5_gpio_ops, s,
559
+ TYPE_STM32L4X5_GPIO, 0x400);
560
+
561
+ sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio);
562
+
563
+ qdev_init_gpio_out(DEVICE(obj), s->pin, GPIO_NUM_PINS);
564
+ qdev_init_gpio_in(DEVICE(obj), stm32l4x5_gpio_set, GPIO_NUM_PINS);
565
+
566
+ s->clk = qdev_init_clock_in(DEVICE(s), "clk", NULL, s, 0);
567
+
568
+ object_property_add(obj, "disconnected-pins", "uint16",
569
+ disconnected_pins_get, disconnected_pins_set,
570
+ NULL, &s->disconnected_pins);
571
+ object_property_add(obj, "clock-freq-hz", "uint32",
572
+ clock_freq_get, NULL, NULL, NULL);
573
+}
574
+
575
+static void stm32l4x5_gpio_realize(DeviceState *dev, Error **errp)
576
+{
577
+ Stm32l4x5GpioState *s = STM32L4X5_GPIO(dev);
578
+ if (!clock_has_source(s->clk)) {
579
+ error_setg(errp, "GPIO: clk input must be connected");
580
+ return;
581
+ }
582
+}
583
+
584
+static const VMStateDescription vmstate_stm32l4x5_gpio = {
585
+ .name = TYPE_STM32L4X5_GPIO,
586
+ .version_id = 1,
587
+ .minimum_version_id = 1,
588
+ .fields = (VMStateField[]){
589
+ VMSTATE_UINT32(moder, Stm32l4x5GpioState),
590
+ VMSTATE_UINT32(otyper, Stm32l4x5GpioState),
591
+ VMSTATE_UINT32(ospeedr, Stm32l4x5GpioState),
592
+ VMSTATE_UINT32(pupdr, Stm32l4x5GpioState),
593
+ VMSTATE_UINT32(idr, Stm32l4x5GpioState),
594
+ VMSTATE_UINT32(odr, Stm32l4x5GpioState),
595
+ VMSTATE_UINT32(lckr, Stm32l4x5GpioState),
596
+ VMSTATE_UINT32(afrl, Stm32l4x5GpioState),
597
+ VMSTATE_UINT32(afrh, Stm32l4x5GpioState),
598
+ VMSTATE_UINT32(ascr, Stm32l4x5GpioState),
599
+ VMSTATE_UINT16(disconnected_pins, Stm32l4x5GpioState),
600
+ VMSTATE_UINT16(pins_connected_high, Stm32l4x5GpioState),
601
+ VMSTATE_END_OF_LIST()
602
+ }
603
+};
604
+
605
+static Property stm32l4x5_gpio_properties[] = {
606
+ DEFINE_PROP_STRING("name", Stm32l4x5GpioState, name),
607
+ DEFINE_PROP_UINT32("mode-reset", Stm32l4x5GpioState, moder_reset, 0),
608
+ DEFINE_PROP_UINT32("ospeed-reset", Stm32l4x5GpioState, ospeedr_reset, 0),
609
+ DEFINE_PROP_UINT32("pupd-reset", Stm32l4x5GpioState, pupdr_reset, 0),
610
+ DEFINE_PROP_END_OF_LIST(),
611
+};
612
+
613
+static void stm32l4x5_gpio_class_init(ObjectClass *klass, void *data)
614
+{
615
+ DeviceClass *dc = DEVICE_CLASS(klass);
616
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
617
+
618
+ device_class_set_props(dc, stm32l4x5_gpio_properties);
619
+ dc->vmsd = &vmstate_stm32l4x5_gpio;
620
+ dc->realize = stm32l4x5_gpio_realize;
621
+ rc->phases.hold = stm32l4x5_gpio_reset_hold;
622
+}
623
+
624
+static const TypeInfo stm32l4x5_gpio_types[] = {
625
+ {
626
+ .name = TYPE_STM32L4X5_GPIO,
627
+ .parent = TYPE_SYS_BUS_DEVICE,
628
+ .instance_size = sizeof(Stm32l4x5GpioState),
629
+ .instance_init = stm32l4x5_gpio_init,
630
+ .class_init = stm32l4x5_gpio_class_init,
631
+ },
632
+};
633
+
634
+DEFINE_TYPES(stm32l4x5_gpio_types)
635
diff --git a/hw/gpio/Kconfig b/hw/gpio/Kconfig
636
index XXXXXXX..XXXXXXX 100644
637
--- a/hw/gpio/Kconfig
638
+++ b/hw/gpio/Kconfig
639
@@ -XXX,XX +XXX,XX @@ config GPIO_PWR
640
641
config SIFIVE_GPIO
642
bool
643
+
644
+config STM32L4X5_GPIO
645
+ bool
646
diff --git a/hw/gpio/meson.build b/hw/gpio/meson.build
647
index XXXXXXX..XXXXXXX 100644
648
--- a/hw/gpio/meson.build
649
+++ b/hw/gpio/meson.build
650
@@ -XXX,XX +XXX,XX @@ system_ss.add(when: 'CONFIG_RASPI', if_true: files(
651
'bcm2835_gpio.c',
652
'bcm2838_gpio.c'
653
))
654
+system_ss.add(when: 'CONFIG_STM32L4X5_SOC', if_true: files('stm32l4x5_gpio.c'))
655
system_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files('aspeed_gpio.c'))
656
system_ss.add(when: 'CONFIG_SIFIVE_GPIO', if_true: files('sifive_gpio.c'))
657
diff --git a/hw/gpio/trace-events b/hw/gpio/trace-events
658
index XXXXXXX..XXXXXXX 100644
659
--- a/hw/gpio/trace-events
660
+++ b/hw/gpio/trace-events
661
@@ -XXX,XX +XXX,XX @@ sifive_gpio_update_output_irq(int64_t line, int64_t value) "line %" PRIi64 " val
662
# aspeed_gpio.c
663
aspeed_gpio_read(uint64_t offset, uint64_t value) "offset: 0x%" PRIx64 " value 0x%" PRIx64
664
aspeed_gpio_write(uint64_t offset, uint64_t value) "offset: 0x%" PRIx64 " value 0x%" PRIx64
665
+
666
+# stm32l4x5_gpio.c
667
+stm32l4x5_gpio_read(char *gpio, uint64_t addr) "GPIO%s addr: 0x%" PRIx64 " "
668
+stm32l4x5_gpio_write(char *gpio, uint64_t addr, uint64_t data) "GPIO%s addr: 0x%" PRIx64 " val: 0x%" PRIx64 ""
669
+stm32l4x5_gpio_update_idr(char *gpio, uint32_t old_idr, uint32_t new_idr) "GPIO%s from: 0x%x to: 0x%x"
670
+stm32l4x5_gpio_pins(char *gpio, uint16_t disconnected, uint16_t high) "GPIO%s disconnected pins: 0x%x levels: 0x%x"
397
--
671
--
398
2.20.1
672
2.34.1
399
673
400
674
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Inès Varhol <ines.varhol@telecom-paris.fr>
2
2
3
This is generic support, with the code disabled for all targets.
3
Signed-off-by: Arnaud Minier <arnaud.minier@telecom-paris.fr>
4
4
Signed-off-by: Inès Varhol <ines.varhol@telecom-paris.fr>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
6
Message-id: 20201016184207.786698-11-richard.henderson@linaro.org
6
Acked-by: Alistair Francis <alistair.francis@wdc.com>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Message-id: 20240305210444.310665-3-ines.varhol@telecom-paris.fr
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
9
---
10
linux-user/qemu.h | 4 ++
10
include/hw/arm/stm32l4x5_soc.h | 2 +
11
linux-user/elfload.c | 157 +++++++++++++++++++++++++++++++++++++++++++
11
include/hw/gpio/stm32l4x5_gpio.h | 1 +
12
2 files changed, 161 insertions(+)
12
include/hw/misc/stm32l4x5_syscfg.h | 3 +-
13
13
hw/arm/stm32l4x5_soc.c | 71 +++++++++++++++++++++++-------
14
diff --git a/linux-user/qemu.h b/linux-user/qemu.h
14
hw/misc/stm32l4x5_syscfg.c | 1 +
15
index XXXXXXX..XXXXXXX 100644
15
hw/arm/Kconfig | 3 +-
16
--- a/linux-user/qemu.h
16
6 files changed, 63 insertions(+), 18 deletions(-)
17
+++ b/linux-user/qemu.h
17
18
@@ -XXX,XX +XXX,XX @@ struct image_info {
18
diff --git a/include/hw/arm/stm32l4x5_soc.h b/include/hw/arm/stm32l4x5_soc.h
19
abi_ulong interpreter_loadmap_addr;
19
index XXXXXXX..XXXXXXX 100644
20
abi_ulong interpreter_pt_dynamic_addr;
20
--- a/include/hw/arm/stm32l4x5_soc.h
21
struct image_info *other_info;
21
+++ b/include/hw/arm/stm32l4x5_soc.h
22
+
22
@@ -XXX,XX +XXX,XX @@
23
+ /* For target-specific processing of NT_GNU_PROPERTY_TYPE_0. */
23
#include "hw/misc/stm32l4x5_syscfg.h"
24
+ uint32_t note_flags;
24
#include "hw/misc/stm32l4x5_exti.h"
25
+
25
#include "hw/misc/stm32l4x5_rcc.h"
26
#ifdef TARGET_MIPS
26
+#include "hw/gpio/stm32l4x5_gpio.h"
27
int fp_abi;
27
#include "qom/object.h"
28
int interp_fp_abi;
28
29
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
29
#define TYPE_STM32L4X5_SOC "stm32l4x5-soc"
30
index XXXXXXX..XXXXXXX 100644
30
@@ -XXX,XX +XXX,XX @@ struct Stm32l4x5SocState {
31
--- a/linux-user/elfload.c
31
OrIRQState exti_or_gates[NUM_EXTI_OR_GATES];
32
+++ b/linux-user/elfload.c
32
Stm32l4x5SyscfgState syscfg;
33
@@ -XXX,XX +XXX,XX @@ static void elf_core_copy_regs(target_elf_gregset_t *regs,
33
Stm32l4x5RccState rcc;
34
34
+ Stm32l4x5GpioState gpio[NUM_GPIOS];
35
#include "elf.h"
35
36
36
MemoryRegion sram1;
37
+static bool arch_parse_elf_property(uint32_t pr_type, uint32_t pr_datasz,
37
MemoryRegion sram2;
38
+ const uint32_t *data,
38
diff --git a/include/hw/gpio/stm32l4x5_gpio.h b/include/hw/gpio/stm32l4x5_gpio.h
39
+ struct image_info *info,
39
index XXXXXXX..XXXXXXX 100644
40
+ Error **errp)
40
--- a/include/hw/gpio/stm32l4x5_gpio.h
41
+{
41
+++ b/include/hw/gpio/stm32l4x5_gpio.h
42
+ g_assert_not_reached();
42
@@ -XXX,XX +XXX,XX @@
43
+}
43
#define TYPE_STM32L4X5_GPIO "stm32l4x5-gpio"
44
+#define ARCH_USE_GNU_PROPERTY 0
44
OBJECT_DECLARE_SIMPLE_TYPE(Stm32l4x5GpioState, STM32L4X5_GPIO)
45
+
45
46
struct exec
46
+#define NUM_GPIOS 8
47
#define GPIO_NUM_PINS 16
48
49
struct Stm32l4x5GpioState {
50
diff --git a/include/hw/misc/stm32l4x5_syscfg.h b/include/hw/misc/stm32l4x5_syscfg.h
51
index XXXXXXX..XXXXXXX 100644
52
--- a/include/hw/misc/stm32l4x5_syscfg.h
53
+++ b/include/hw/misc/stm32l4x5_syscfg.h
54
@@ -XXX,XX +XXX,XX @@
55
56
#include "hw/sysbus.h"
57
#include "qom/object.h"
58
+#include "hw/gpio/stm32l4x5_gpio.h"
59
60
#define TYPE_STM32L4X5_SYSCFG "stm32l4x5-syscfg"
61
OBJECT_DECLARE_SIMPLE_TYPE(Stm32l4x5SyscfgState, STM32L4X5_SYSCFG)
62
63
-#define NUM_GPIOS 8
64
-#define GPIO_NUM_PINS 16
65
#define SYSCFG_NUM_EXTICR 4
66
67
struct Stm32l4x5SyscfgState {
68
diff --git a/hw/arm/stm32l4x5_soc.c b/hw/arm/stm32l4x5_soc.c
69
index XXXXXXX..XXXXXXX 100644
70
--- a/hw/arm/stm32l4x5_soc.c
71
+++ b/hw/arm/stm32l4x5_soc.c
72
@@ -XXX,XX +XXX,XX @@
73
#include "sysemu/sysemu.h"
74
#include "hw/or-irq.h"
75
#include "hw/arm/stm32l4x5_soc.h"
76
+#include "hw/gpio/stm32l4x5_gpio.h"
77
#include "hw/qdev-clock.h"
78
#include "hw/misc/unimp.h"
79
80
@@ -XXX,XX +XXX,XX @@ static const int exti_or_gate1_lines_in[EXTI_OR_GATE1_NUM_LINES_IN] = {
81
16, 35, 36, 37, 38,
82
};
83
84
+static const struct {
85
+ uint32_t addr;
86
+ uint32_t moder_reset;
87
+ uint32_t ospeedr_reset;
88
+ uint32_t pupdr_reset;
89
+} stm32l4x5_gpio_cfg[NUM_GPIOS] = {
90
+ { 0x48000000, 0xABFFFFFF, 0x0C000000, 0x64000000 },
91
+ { 0x48000400, 0xFFFFFEBF, 0x00000000, 0x00000100 },
92
+ { 0x48000800, 0xFFFFFFFF, 0x00000000, 0x00000000 },
93
+ { 0x48000C00, 0xFFFFFFFF, 0x00000000, 0x00000000 },
94
+ { 0x48001000, 0xFFFFFFFF, 0x00000000, 0x00000000 },
95
+ { 0x48001400, 0xFFFFFFFF, 0x00000000, 0x00000000 },
96
+ { 0x48001800, 0xFFFFFFFF, 0x00000000, 0x00000000 },
97
+ { 0x48001C00, 0x0000000F, 0x00000000, 0x00000000 },
98
+};
99
+
100
static void stm32l4x5_soc_initfn(Object *obj)
47
{
101
{
48
unsigned int a_info; /* Use macros N_MAGIC, etc for access */
102
Stm32l4x5SocState *s = STM32L4X5_SOC(obj);
49
@@ -XXX,XX +XXX,XX @@ void probe_guest_base(const char *image_name, abi_ulong guest_loaddr,
103
@@ -XXX,XX +XXX,XX @@ static void stm32l4x5_soc_initfn(Object *obj)
50
"@ 0x%" PRIx64 "\n", (uint64_t)guest_base);
104
}
105
object_initialize_child(obj, "syscfg", &s->syscfg, TYPE_STM32L4X5_SYSCFG);
106
object_initialize_child(obj, "rcc", &s->rcc, TYPE_STM32L4X5_RCC);
107
+
108
+ for (unsigned i = 0; i < NUM_GPIOS; i++) {
109
+ g_autofree char *name = g_strdup_printf("gpio%c", 'a' + i);
110
+ object_initialize_child(obj, name, &s->gpio[i], TYPE_STM32L4X5_GPIO);
111
+ }
51
}
112
}
52
113
53
+enum {
114
static void stm32l4x5_soc_realize(DeviceState *dev_soc, Error **errp)
54
+ /* The string "GNU\0" as a magic number. */
115
@@ -XXX,XX +XXX,XX @@ static void stm32l4x5_soc_realize(DeviceState *dev_soc, Error **errp)
55
+ GNU0_MAGIC = const_le32('G' | 'N' << 8 | 'U' << 16),
116
Stm32l4x5SocState *s = STM32L4X5_SOC(dev_soc);
56
+ NOTE_DATA_SZ = 1 * KiB,
117
const Stm32l4x5SocClass *sc = STM32L4X5_SOC_GET_CLASS(dev_soc);
57
+ NOTE_NAME_SZ = 4,
118
MemoryRegion *system_memory = get_system_memory();
58
+ ELF_GNU_PROPERTY_ALIGN = ELF_CLASS == ELFCLASS32 ? 4 : 8,
119
- DeviceState *armv7m;
59
+};
120
+ DeviceState *armv7m, *dev;
60
+
121
SysBusDevice *busdev;
61
+/*
122
+ uint32_t pin_index;
62
+ * Process a single gnu_property entry.
123
63
+ * Return false for error.
124
if (!memory_region_init_rom(&s->flash, OBJECT(dev_soc), "flash",
64
+ */
125
sc->flash_size, errp)) {
65
+static bool parse_elf_property(const uint32_t *data, int *off, int datasz,
126
@@ -XXX,XX +XXX,XX @@ static void stm32l4x5_soc_realize(DeviceState *dev_soc, Error **errp)
66
+ struct image_info *info, bool have_prev_type,
127
return;
67
+ uint32_t *prev_type, Error **errp)
128
}
68
+{
129
69
+ uint32_t pr_type, pr_datasz, step;
130
+ /* GPIOs */
70
+
131
+ for (unsigned i = 0; i < NUM_GPIOS; i++) {
71
+ if (*off > datasz || !QEMU_IS_ALIGNED(*off, ELF_GNU_PROPERTY_ALIGN)) {
132
+ g_autofree char *name = g_strdup_printf("%c", 'A' + i);
72
+ goto error_data;
133
+ dev = DEVICE(&s->gpio[i]);
134
+ qdev_prop_set_string(dev, "name", name);
135
+ qdev_prop_set_uint32(dev, "mode-reset",
136
+ stm32l4x5_gpio_cfg[i].moder_reset);
137
+ qdev_prop_set_uint32(dev, "ospeed-reset",
138
+ stm32l4x5_gpio_cfg[i].ospeedr_reset);
139
+ qdev_prop_set_uint32(dev, "pupd-reset",
140
+ stm32l4x5_gpio_cfg[i].pupdr_reset);
141
+ busdev = SYS_BUS_DEVICE(&s->gpio[i]);
142
+ g_free(name);
143
+ name = g_strdup_printf("gpio%c-out", 'a' + i);
144
+ qdev_connect_clock_in(DEVICE(&s->gpio[i]), "clk",
145
+ qdev_get_clock_out(DEVICE(&(s->rcc)), name));
146
+ if (!sysbus_realize(busdev, errp)) {
147
+ return;
148
+ }
149
+ sysbus_mmio_map(busdev, 0, stm32l4x5_gpio_cfg[i].addr);
73
+ }
150
+ }
74
+ datasz -= *off;
151
+
75
+ data += *off / sizeof(uint32_t);
152
/* System configuration controller */
76
+
153
busdev = SYS_BUS_DEVICE(&s->syscfg);
77
+ if (datasz < 2 * sizeof(uint32_t)) {
154
if (!sysbus_realize(busdev, errp)) {
78
+ goto error_data;
155
return;
79
+ }
156
}
80
+ pr_type = data[0];
157
sysbus_mmio_map(busdev, 0, SYSCFG_ADDR);
81
+ pr_datasz = data[1];
158
- /*
82
+ data += 2;
159
- * TODO: when the GPIO device is implemented, connect it
83
+ datasz -= 2 * sizeof(uint32_t);
160
- * to SYCFG using `qdev_connect_gpio_out`, NUM_GPIOS and
84
+ step = ROUND_UP(pr_datasz, ELF_GNU_PROPERTY_ALIGN);
161
- * GPIO_NUM_PINS.
85
+ if (step > datasz) {
162
- */
86
+ goto error_data;
163
+
87
+ }
164
+ for (unsigned i = 0; i < NUM_GPIOS; i++) {
88
+
165
+ for (unsigned j = 0; j < GPIO_NUM_PINS; j++) {
89
+ /* Properties are supposed to be unique and sorted on pr_type. */
166
+ pin_index = GPIO_NUM_PINS * i + j;
90
+ if (have_prev_type && pr_type <= *prev_type) {
167
+ qdev_connect_gpio_out(DEVICE(&s->gpio[i]), j,
91
+ if (pr_type == *prev_type) {
168
+ qdev_get_gpio_in(DEVICE(&s->syscfg),
92
+ error_setg(errp, "Duplicate property in PT_GNU_PROPERTY");
169
+ pin_index));
93
+ } else {
94
+ error_setg(errp, "Unsorted property in PT_GNU_PROPERTY");
95
+ }
96
+ return false;
97
+ }
98
+ *prev_type = pr_type;
99
+
100
+ if (!arch_parse_elf_property(pr_type, pr_datasz, data, info, errp)) {
101
+ return false;
102
+ }
103
+
104
+ *off += 2 * sizeof(uint32_t) + step;
105
+ return true;
106
+
107
+ error_data:
108
+ error_setg(errp, "Ill-formed property in PT_GNU_PROPERTY");
109
+ return false;
110
+}
111
+
112
+/* Process NT_GNU_PROPERTY_TYPE_0. */
113
+static bool parse_elf_properties(int image_fd,
114
+ struct image_info *info,
115
+ const struct elf_phdr *phdr,
116
+ char bprm_buf[BPRM_BUF_SIZE],
117
+ Error **errp)
118
+{
119
+ union {
120
+ struct elf_note nhdr;
121
+ uint32_t data[NOTE_DATA_SZ / sizeof(uint32_t)];
122
+ } note;
123
+
124
+ int n, off, datasz;
125
+ bool have_prev_type;
126
+ uint32_t prev_type;
127
+
128
+ /* Unless the arch requires properties, ignore them. */
129
+ if (!ARCH_USE_GNU_PROPERTY) {
130
+ return true;
131
+ }
132
+
133
+ /* If the properties are crazy large, that's too bad. */
134
+ n = phdr->p_filesz;
135
+ if (n > sizeof(note)) {
136
+ error_setg(errp, "PT_GNU_PROPERTY too large");
137
+ return false;
138
+ }
139
+ if (n < sizeof(note.nhdr)) {
140
+ error_setg(errp, "PT_GNU_PROPERTY too small");
141
+ return false;
142
+ }
143
+
144
+ if (phdr->p_offset + n <= BPRM_BUF_SIZE) {
145
+ memcpy(&note, bprm_buf + phdr->p_offset, n);
146
+ } else {
147
+ ssize_t len = pread(image_fd, &note, n, phdr->p_offset);
148
+ if (len != n) {
149
+ error_setg_errno(errp, errno, "Error reading file header");
150
+ return false;
151
+ }
170
+ }
152
+ }
171
+ }
153
+
172
154
+ /*
173
/* EXTI device */
155
+ * The contents of a valid PT_GNU_PROPERTY is a sequence
174
busdev = SYS_BUS_DEVICE(&s->exti);
156
+ * of uint32_t -- swap them all now.
175
@@ -XXX,XX +XXX,XX @@ static void stm32l4x5_soc_realize(DeviceState *dev_soc, Error **errp)
157
+ */
158
+#ifdef BSWAP_NEEDED
159
+ for (int i = 0; i < n / 4; i++) {
160
+ bswap32s(note.data + i);
161
+ }
162
+#endif
163
+
164
+ /*
165
+ * Note that nhdr is 3 words, and that the "name" described by namesz
166
+ * immediately follows nhdr and is thus at the 4th word. Further, all
167
+ * of the inputs to the kernel's round_up are multiples of 4.
168
+ */
169
+ if (note.nhdr.n_type != NT_GNU_PROPERTY_TYPE_0 ||
170
+ note.nhdr.n_namesz != NOTE_NAME_SZ ||
171
+ note.data[3] != GNU0_MAGIC) {
172
+ error_setg(errp, "Invalid note in PT_GNU_PROPERTY");
173
+ return false;
174
+ }
175
+ off = sizeof(note.nhdr) + NOTE_NAME_SZ;
176
+
177
+ datasz = note.nhdr.n_descsz + off;
178
+ if (datasz > n) {
179
+ error_setg(errp, "Invalid note size in PT_GNU_PROPERTY");
180
+ return false;
181
+ }
182
+
183
+ have_prev_type = false;
184
+ prev_type = 0;
185
+ while (1) {
186
+ if (off == datasz) {
187
+ return true; /* end, exit ok */
188
+ }
189
+ if (!parse_elf_property(note.data, &off, datasz, info,
190
+ have_prev_type, &prev_type, errp)) {
191
+ return false;
192
+ }
193
+ have_prev_type = true;
194
+ }
195
+}
196
+
197
/* Load an ELF image into the address space.
198
199
IMAGE_NAME is the filename of the image, to use in error messages.
200
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
201
goto exit_errmsg;
202
}
203
*pinterp_name = g_steal_pointer(&interp_name);
204
+ } else if (eppnt->p_type == PT_GNU_PROPERTY) {
205
+ if (!parse_elf_properties(image_fd, info, eppnt, bprm_buf, &err)) {
206
+ goto exit_errmsg;
207
+ }
208
}
176
}
209
}
177
}
210
178
179
- for (unsigned i = 0; i < 16; i++) {
180
+ for (unsigned i = 0; i < GPIO_NUM_PINS; i++) {
181
qdev_connect_gpio_out(DEVICE(&s->syscfg), i,
182
qdev_get_gpio_in(DEVICE(&s->exti), i));
183
}
184
@@ -XXX,XX +XXX,XX @@ static void stm32l4x5_soc_realize(DeviceState *dev_soc, Error **errp)
185
/* RESERVED: 0x40024400, 0x7FDBC00 */
186
187
/* AHB2 BUS */
188
- create_unimplemented_device("GPIOA", 0x48000000, 0x400);
189
- create_unimplemented_device("GPIOB", 0x48000400, 0x400);
190
- create_unimplemented_device("GPIOC", 0x48000800, 0x400);
191
- create_unimplemented_device("GPIOD", 0x48000C00, 0x400);
192
- create_unimplemented_device("GPIOE", 0x48001000, 0x400);
193
- create_unimplemented_device("GPIOF", 0x48001400, 0x400);
194
- create_unimplemented_device("GPIOG", 0x48001800, 0x400);
195
- create_unimplemented_device("GPIOH", 0x48001C00, 0x400);
196
/* RESERVED: 0x48002000, 0x7FDBC00 */
197
create_unimplemented_device("OTG_FS", 0x50000000, 0x40000);
198
create_unimplemented_device("ADC", 0x50040000, 0x400);
199
diff --git a/hw/misc/stm32l4x5_syscfg.c b/hw/misc/stm32l4x5_syscfg.c
200
index XXXXXXX..XXXXXXX 100644
201
--- a/hw/misc/stm32l4x5_syscfg.c
202
+++ b/hw/misc/stm32l4x5_syscfg.c
203
@@ -XXX,XX +XXX,XX @@
204
#include "hw/irq.h"
205
#include "migration/vmstate.h"
206
#include "hw/misc/stm32l4x5_syscfg.h"
207
+#include "hw/gpio/stm32l4x5_gpio.h"
208
209
#define SYSCFG_MEMRMP 0x00
210
#define SYSCFG_CFGR1 0x04
211
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
212
index XXXXXXX..XXXXXXX 100644
213
--- a/hw/arm/Kconfig
214
+++ b/hw/arm/Kconfig
215
@@ -XXX,XX +XXX,XX @@ config STM32L4X5_SOC
216
bool
217
select ARM_V7M
218
select OR_IRQ
219
- select STM32L4X5_SYSCFG
220
select STM32L4X5_EXTI
221
+ select STM32L4X5_SYSCFG
222
select STM32L4X5_RCC
223
+ select STM32L4X5_GPIO
224
225
config XLNX_ZYNQMP_ARM
226
bool
211
--
227
--
212
2.20.1
228
2.34.1
213
229
214
230
diff view generated by jsdifflib
1
From: Havard Skinnemoen <hskinnemoen@google.com>
1
From: Inès Varhol <ines.varhol@telecom-paris.fr>
2
2
3
This test exercises the various modes of the npcm7xx timer. In
3
The testcase contains :
4
particular, it triggers the bug found by the fuzzer, as reported here:
4
- `test_idr_reset_value()` :
5
Checks the reset values of MODER, OTYPER, PUPDR, ODR and IDR.
6
- `test_gpio_output_mode()` :
7
Checks that writing a bit in register ODR results in the corresponding
8
pin rising or lowering, if this pin is configured in output mode.
9
- `test_gpio_input_mode()` :
10
Checks that a input pin set high or low externally results
11
in the pin rising and lowering.
12
- `test_pull_up_pull_down()` :
13
Checks that a floating pin in pull-up/down mode is actually high/down.
14
- `test_push_pull()` :
15
Checks that a pin set externally is disconnected when configured in
16
push-pull output mode, and can't be set externally while in this mode.
17
- `test_open_drain()` :
18
Checks that a pin set externally high is disconnected when configured
19
in open-drain output mode, and can't be set high while in this mode.
20
- `test_bsrr_brr()` :
21
Checks that writing to BSRR and BRR has the desired result in ODR.
22
- `test_clock_enable()` :
23
Checks that GPIO clock is at the right frequency after enabling it.
5
24
6
https://lists.gnu.org/archive/html/qemu-devel/2020-09/msg02992.html
25
Acked-by: Thomas Huth <thuth@redhat.com>
7
26
Signed-off-by: Arnaud Minier <arnaud.minier@telecom-paris.fr>
8
It also found several other bugs, especially related to interrupt
27
Signed-off-by: Inès Varhol <ines.varhol@telecom-paris.fr>
9
handling.
28
Message-id: 20240305210444.310665-4-ines.varhol@telecom-paris.fr
10
11
The test exercises all the timers in all the timer modules, which
12
expands to 180 test cases in total.
13
14
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
15
Signed-off-by: Havard Skinnemoen <hskinnemoen@google.com>
16
Message-id: 20201008232154.94221-2-hskinnemoen@google.com
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
29
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
---
30
---
19
tests/qtest/npcm7xx_timer-test.c | 562 +++++++++++++++++++++++++++++++
31
tests/qtest/stm32l4x5_gpio-test.c | 551 ++++++++++++++++++++++++++++++
20
tests/qtest/meson.build | 1 +
32
tests/qtest/meson.build | 3 +-
21
2 files changed, 563 insertions(+)
33
2 files changed, 553 insertions(+), 1 deletion(-)
22
create mode 100644 tests/qtest/npcm7xx_timer-test.c
34
create mode 100644 tests/qtest/stm32l4x5_gpio-test.c
23
35
24
diff --git a/tests/qtest/npcm7xx_timer-test.c b/tests/qtest/npcm7xx_timer-test.c
36
diff --git a/tests/qtest/stm32l4x5_gpio-test.c b/tests/qtest/stm32l4x5_gpio-test.c
25
new file mode 100644
37
new file mode 100644
26
index XXXXXXX..XXXXXXX
38
index XXXXXXX..XXXXXXX
27
--- /dev/null
39
--- /dev/null
28
+++ b/tests/qtest/npcm7xx_timer-test.c
40
+++ b/tests/qtest/stm32l4x5_gpio-test.c
29
@@ -XXX,XX +XXX,XX @@
41
@@ -XXX,XX +XXX,XX @@
30
+/*
42
+/*
31
+ * QTest testcase for the Nuvoton NPCM7xx Timer
43
+ * QTest testcase for STM32L4x5_GPIO
32
+ *
44
+ *
33
+ * Copyright 2020 Google LLC
45
+ * Copyright (c) 2024 Arnaud Minier <arnaud.minier@telecom-paris.fr>
46
+ * Copyright (c) 2024 Inès Varhol <ines.varhol@telecom-paris.fr>
34
+ *
47
+ *
35
+ * This program is free software; you can redistribute it and/or modify it
48
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
36
+ * under the terms of the GNU General Public License as published by the
49
+ * See the COPYING file in the top-level directory.
37
+ * Free Software Foundation; either version 2 of the License, or
38
+ * (at your option) any later version.
39
+ *
40
+ * This program is distributed in the hope that it will be useful, but WITHOUT
41
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
42
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
43
+ * for more details.
44
+ */
50
+ */
45
+
51
+
46
+#include "qemu/osdep.h"
52
+#include "qemu/osdep.h"
47
+#include "qemu/timer.h"
48
+#include "libqtest-single.h"
53
+#include "libqtest-single.h"
49
+
54
+
50
+#define TIM_REF_HZ (25000000)
55
+#define GPIO_BASE_ADDR 0x48000000
51
+
56
+#define GPIO_SIZE 0x400
52
+/* Bits in TCSRx */
57
+#define NUM_GPIOS 8
53
+#define CEN BIT(30)
58
+#define NUM_GPIO_PINS 16
54
+#define IE BIT(29)
59
+
55
+#define MODE_ONESHOT (0 << 27)
60
+#define GPIO_A 0x48000000
56
+#define MODE_PERIODIC (1 << 27)
61
+#define GPIO_B 0x48000400
57
+#define CRST BIT(26)
62
+#define GPIO_C 0x48000800
58
+#define CACT BIT(25)
63
+#define GPIO_D 0x48000C00
59
+#define PRESCALE(x) (x)
64
+#define GPIO_E 0x48001000
60
+
65
+#define GPIO_F 0x48001400
61
+/* Registers shared between all timers in a module. */
66
+#define GPIO_G 0x48001800
62
+#define TISR 0x18
67
+#define GPIO_H 0x48001C00
63
+#define WTCR 0x1c
68
+
64
+# define WTCLK(x) ((x) << 10)
69
+#define MODER 0x00
65
+
70
+#define OTYPER 0x04
66
+/* Power-on default; used to re-initialize timers before each test. */
71
+#define PUPDR 0x0C
67
+#define TCSR_DEFAULT PRESCALE(5)
72
+#define IDR 0x10
68
+
73
+#define ODR 0x14
69
+/* Register offsets for a timer within a timer block. */
74
+#define BSRR 0x18
70
+typedef struct Timer {
75
+#define BRR 0x28
71
+ unsigned int tcsr_offset;
76
+
72
+ unsigned int ticr_offset;
77
+#define MODER_INPUT 0
73
+ unsigned int tdr_offset;
78
+#define MODER_OUTPUT 1
74
+} Timer;
79
+
75
+
80
+#define PUPDR_NONE 0
76
+/* A timer block containing 5 timers. */
81
+#define PUPDR_PULLUP 1
77
+typedef struct TimerBlock {
82
+#define PUPDR_PULLDOWN 2
78
+ int irq_base;
83
+
79
+ uint64_t base_addr;
84
+#define OTYPER_PUSH_PULL 0
80
+} TimerBlock;
85
+#define OTYPER_OPEN_DRAIN 1
81
+
86
+
82
+/* Testdata for testing a particular timer within a timer block. */
87
+const uint32_t moder_reset[NUM_GPIOS] = {
83
+typedef struct TestData {
88
+ 0xABFFFFFF,
84
+ const TimerBlock *tim;
89
+ 0xFFFFFEBF,
85
+ const Timer *timer;
90
+ 0xFFFFFFFF,
86
+} TestData;
91
+ 0xFFFFFFFF,
87
+
92
+ 0xFFFFFFFF,
88
+const TimerBlock timer_block[] = {
93
+ 0xFFFFFFFF,
89
+ {
94
+ 0xFFFFFFFF,
90
+ .irq_base = 32,
95
+ 0x0000000F
91
+ .base_addr = 0xf0008000,
92
+ },
93
+ {
94
+ .irq_base = 37,
95
+ .base_addr = 0xf0009000,
96
+ },
97
+ {
98
+ .irq_base = 42,
99
+ .base_addr = 0xf000a000,
100
+ },
101
+};
96
+};
102
+
97
+
103
+const Timer timer[] = {
98
+const uint32_t pupdr_reset[NUM_GPIOS] = {
104
+ {
99
+ 0x64000000,
105
+ .tcsr_offset = 0x00,
100
+ 0x00000100,
106
+ .ticr_offset = 0x08,
101
+ 0x00000000,
107
+ .tdr_offset = 0x10,
102
+ 0x00000000,
108
+ }, {
103
+ 0x00000000,
109
+ .tcsr_offset = 0x04,
104
+ 0x00000000,
110
+ .ticr_offset = 0x0c,
105
+ 0x00000000,
111
+ .tdr_offset = 0x14,
106
+ 0x00000000
112
+ }, {
113
+ .tcsr_offset = 0x20,
114
+ .ticr_offset = 0x28,
115
+ .tdr_offset = 0x30,
116
+ }, {
117
+ .tcsr_offset = 0x24,
118
+ .ticr_offset = 0x2c,
119
+ .tdr_offset = 0x34,
120
+ }, {
121
+ .tcsr_offset = 0x40,
122
+ .ticr_offset = 0x48,
123
+ .tdr_offset = 0x50,
124
+ },
125
+};
107
+};
126
+
108
+
127
+/* Returns the index of the timer block. */
109
+const uint32_t idr_reset[NUM_GPIOS] = {
128
+static int tim_index(const TimerBlock *tim)
110
+ 0x0000A000,
129
+{
111
+ 0x00000010,
130
+ ptrdiff_t diff = tim - timer_block;
112
+ 0x00000000,
131
+
113
+ 0x00000000,
132
+ g_assert(diff >= 0 && diff < ARRAY_SIZE(timer_block));
114
+ 0x00000000,
133
+
115
+ 0x00000000,
134
+ return diff;
116
+ 0x00000000,
135
+}
117
+ 0x00000000
136
+
118
+};
137
+/* Returns the index of a timer within a timer block. */
119
+
138
+static int timer_index(const Timer *t)
120
+static uint32_t gpio_readl(unsigned int gpio, unsigned int offset)
139
+{
121
+{
140
+ ptrdiff_t diff = t - timer;
122
+ return readl(gpio + offset);
141
+
123
+}
142
+ g_assert(diff >= 0 && diff < ARRAY_SIZE(timer));
124
+
143
+
125
+static void gpio_writel(unsigned int gpio, unsigned int offset, uint32_t value)
144
+ return diff;
126
+{
145
+}
127
+ writel(gpio + offset, value);
146
+
128
+}
147
+/* Returns the irq line for a given timer. */
129
+
148
+static int tim_timer_irq(const TestData *td)
130
+static void gpio_set_bit(unsigned int gpio, unsigned int reg,
149
+{
131
+ unsigned int pin, uint32_t value)
150
+ return td->tim->irq_base + timer_index(td->timer);
132
+{
151
+}
133
+ uint32_t mask = 0xFFFFFFFF & ~(0x1 << pin);
152
+
134
+ gpio_writel(gpio, reg, (gpio_readl(gpio, reg) & mask) | value << pin);
153
+/* Register read/write accessors. */
135
+}
154
+
136
+
155
+static void tim_write(const TestData *td,
137
+static void gpio_set_2bits(unsigned int gpio, unsigned int reg,
156
+ unsigned int offset, uint32_t value)
138
+ unsigned int pin, uint32_t value)
157
+{
139
+{
158
+ writel(td->tim->base_addr + offset, value);
140
+ uint32_t offset = 2 * pin;
159
+}
141
+ uint32_t mask = 0xFFFFFFFF & ~(0x3 << offset);
160
+
142
+ gpio_writel(gpio, reg, (gpio_readl(gpio, reg) & mask) | value << offset);
161
+static uint32_t tim_read(const TestData *td, unsigned int offset)
143
+}
162
+{
144
+
163
+ return readl(td->tim->base_addr + offset);
145
+static unsigned int get_gpio_id(uint32_t gpio_addr)
164
+}
146
+{
165
+
147
+ return (gpio_addr - GPIO_BASE_ADDR) / GPIO_SIZE;
166
+static void tim_write_tcsr(const TestData *td, uint32_t value)
148
+}
167
+{
149
+
168
+ tim_write(td, td->timer->tcsr_offset, value);
150
+static void gpio_set_irq(unsigned int gpio, int num, int level)
169
+}
151
+{
170
+
152
+ g_autofree char *name = g_strdup_printf("/machine/soc/gpio%c",
171
+static uint32_t tim_read_tcsr(const TestData *td)
153
+ get_gpio_id(gpio) + 'a');
172
+{
154
+ qtest_set_irq_in(global_qtest, name, NULL, num, level);
173
+ return tim_read(td, td->timer->tcsr_offset);
155
+}
174
+}
156
+
175
+
157
+static void disconnect_all_pins(unsigned int gpio)
176
+static void tim_write_ticr(const TestData *td, uint32_t value)
158
+{
177
+{
159
+ g_autofree char *path = g_strdup_printf("/machine/soc/gpio%c",
178
+ tim_write(td, td->timer->ticr_offset, value);
160
+ get_gpio_id(gpio) + 'a');
179
+}
161
+ QDict *r;
180
+
162
+
181
+static uint32_t tim_read_ticr(const TestData *td)
163
+ r = qtest_qmp(global_qtest, "{ 'execute': 'qom-set', 'arguments': "
182
+{
164
+ "{ 'path': %s, 'property': 'disconnected-pins', 'value': %d } }",
183
+ return tim_read(td, td->timer->ticr_offset);
165
+ path, 0xFFFF);
184
+}
166
+ g_assert_false(qdict_haskey(r, "error"));
185
+
167
+ qobject_unref(r);
186
+static uint32_t tim_read_tdr(const TestData *td)
168
+}
187
+{
169
+
188
+ return tim_read(td, td->timer->tdr_offset);
170
+static uint32_t get_disconnected_pins(unsigned int gpio)
189
+}
171
+{
190
+
172
+ g_autofree char *path = g_strdup_printf("/machine/soc/gpio%c",
191
+/* Returns the number of nanoseconds to count the given number of cycles. */
173
+ get_gpio_id(gpio) + 'a');
192
+static int64_t tim_calculate_step(uint32_t count, uint32_t prescale)
174
+ uint32_t disconnected_pins = 0;
193
+{
175
+ QDict *r;
194
+ return (1000000000LL / TIM_REF_HZ) * count * (prescale + 1);
176
+
195
+}
177
+ r = qtest_qmp(global_qtest, "{ 'execute': 'qom-get', 'arguments':"
196
+
178
+ " { 'path': %s, 'property': 'disconnected-pins'} }", path);
197
+/* Returns a bitmask corresponding to the timer under test. */
179
+ g_assert_false(qdict_haskey(r, "error"));
198
+static uint32_t tim_timer_bit(const TestData *td)
180
+ disconnected_pins = qdict_get_int(r, "return");
199
+{
181
+ qobject_unref(r);
200
+ return BIT(timer_index(td->timer));
182
+ return disconnected_pins;
201
+}
183
+}
202
+
184
+
203
+/* Resets all timers to power-on defaults. */
185
+static uint32_t reset(uint32_t gpio, unsigned int offset)
204
+static void tim_reset(const TestData *td)
186
+{
205
+{
187
+ switch (offset) {
206
+ int i, j;
188
+ case MODER:
207
+
189
+ return moder_reset[get_gpio_id(gpio)];
208
+ /* Reset all the timers, in case a previous test left a timer running. */
190
+ case PUPDR:
209
+ for (i = 0; i < ARRAY_SIZE(timer_block); i++) {
191
+ return pupdr_reset[get_gpio_id(gpio)];
210
+ for (j = 0; j < ARRAY_SIZE(timer); j++) {
192
+ case IDR:
211
+ writel(timer_block[i].base_addr + timer[j].tcsr_offset,
193
+ return idr_reset[get_gpio_id(gpio)];
212
+ CRST | TCSR_DEFAULT);
213
+ }
214
+ writel(timer_block[i].base_addr + TISR, -1);
215
+ }
194
+ }
216
+}
195
+ return 0x0;
217
+
196
+}
218
+/* Verifies the reset state of a timer. */
197
+
219
+static void test_reset(gconstpointer test_data)
198
+static void system_reset(void)
220
+{
199
+{
221
+ const TestData *td = test_data;
200
+ QDict *r;
222
+
201
+ r = qtest_qmp(global_qtest, "{'execute': 'system_reset'}");
223
+ tim_reset(td);
202
+ g_assert_false(qdict_haskey(r, "error"));
224
+
203
+ qobject_unref(r);
225
+ g_assert_cmphex(tim_read_tcsr(td), ==, TCSR_DEFAULT);
204
+}
226
+ g_assert_cmphex(tim_read_ticr(td), ==, 0);
205
+
227
+ g_assert_cmphex(tim_read_tdr(td), ==, 0);
206
+static void test_idr_reset_value(void)
228
+ g_assert_cmphex(tim_read(td, TISR), ==, 0);
207
+{
229
+ g_assert_cmphex(tim_read(td, WTCR), ==, WTCLK(1));
208
+ /*
230
+}
209
+ * Checks that the values in MODER, OTYPER, PUPDR and ODR
231
+
210
+ * after reset are correct, and that the value in IDR is
232
+/* Verifies that CRST wins if both CEN and CRST are set. */
211
+ * coherent.
233
+static void test_reset_overrides_enable(gconstpointer test_data)
212
+ * Since AF and analog modes aren't implemented, IDR reset
234
+{
213
+ * values aren't the same as with a real board.
235
+ const TestData *td = test_data;
214
+ *
236
+
215
+ * Register IDR contains the actual values of all GPIO pins.
237
+ tim_reset(td);
216
+ * Its value depends on the pins' configuration
238
+
217
+ * (intput/output/analog : register MODER, push-pull/open-drain :
239
+ /* CRST should force CEN to 0 */
218
+ * register OTYPER, pull-up/pull-down/none : register PUPDR)
240
+ tim_write_tcsr(td, CEN | CRST | TCSR_DEFAULT);
219
+ * and on the values stored in register ODR
241
+
220
+ * (in case the pin is in output mode).
242
+ g_assert_cmphex(tim_read_tcsr(td), ==, TCSR_DEFAULT);
221
+ */
243
+ g_assert_cmphex(tim_read_tdr(td), ==, 0);
222
+
244
+ g_assert_cmphex(tim_read(td, TISR), ==, 0);
223
+ gpio_writel(GPIO_A, MODER, 0xDEADBEEF);
245
+}
224
+ gpio_writel(GPIO_A, ODR, 0xDEADBEEF);
246
+
225
+ gpio_writel(GPIO_A, OTYPER, 0xDEADBEEF);
247
+/* Verifies the behavior when CEN is set and then cleared. */
226
+ gpio_writel(GPIO_A, PUPDR, 0xDEADBEEF);
248
+static void test_oneshot_enable_then_disable(gconstpointer test_data)
227
+
249
+{
228
+ gpio_writel(GPIO_B, MODER, 0xDEADBEEF);
250
+ const TestData *td = test_data;
229
+ gpio_writel(GPIO_B, ODR, 0xDEADBEEF);
251
+
230
+ gpio_writel(GPIO_B, OTYPER, 0xDEADBEEF);
252
+ tim_reset(td);
231
+ gpio_writel(GPIO_B, PUPDR, 0xDEADBEEF);
253
+
232
+
254
+ /* Enable the timer with zero initial count, then disable it again. */
233
+ gpio_writel(GPIO_C, MODER, 0xDEADBEEF);
255
+ tim_write_tcsr(td, CEN | TCSR_DEFAULT);
234
+ gpio_writel(GPIO_C, ODR, 0xDEADBEEF);
256
+ tim_write_tcsr(td, TCSR_DEFAULT);
235
+ gpio_writel(GPIO_C, OTYPER, 0xDEADBEEF);
257
+
236
+ gpio_writel(GPIO_C, PUPDR, 0xDEADBEEF);
258
+ g_assert_cmphex(tim_read_tcsr(td), ==, TCSR_DEFAULT);
237
+
259
+ g_assert_cmphex(tim_read_tdr(td), ==, 0);
238
+ gpio_writel(GPIO_H, MODER, 0xDEADBEEF);
260
+ /* Timer interrupt flag should be set, but interrupts are not enabled. */
239
+ gpio_writel(GPIO_H, ODR, 0xDEADBEEF);
261
+ g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td));
240
+ gpio_writel(GPIO_H, OTYPER, 0xDEADBEEF);
262
+ g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
241
+ gpio_writel(GPIO_H, PUPDR, 0xDEADBEEF);
263
+}
242
+
264
+
243
+ system_reset();
265
+/* Verifies that a one-shot timer fires when expected with prescaler 5. */
244
+
266
+static void test_oneshot_ps5(gconstpointer test_data)
245
+ uint32_t moder = gpio_readl(GPIO_A, MODER);
267
+{
246
+ uint32_t odr = gpio_readl(GPIO_A, ODR);
268
+ const TestData *td = test_data;
247
+ uint32_t otyper = gpio_readl(GPIO_A, OTYPER);
269
+ unsigned int count = 256;
248
+ uint32_t pupdr = gpio_readl(GPIO_A, PUPDR);
270
+ unsigned int ps = 5;
249
+ uint32_t idr = gpio_readl(GPIO_A, IDR);
271
+
250
+ /* 15: AF, 14: AF, 13: AF, 12: Analog ... */
272
+ tim_reset(td);
251
+ /* here AF is the same as Analog and Input mode */
273
+
252
+ g_assert_cmphex(moder, ==, reset(GPIO_A, MODER));
274
+ tim_write_ticr(td, count);
253
+ g_assert_cmphex(odr, ==, reset(GPIO_A, ODR));
275
+ tim_write_tcsr(td, CEN | PRESCALE(ps));
254
+ g_assert_cmphex(otyper, ==, reset(GPIO_A, OTYPER));
276
+ g_assert_cmphex(tim_read_tcsr(td), ==, CEN | CACT | PRESCALE(ps));
255
+ /* 15: pull-up, 14: pull-down, 13: pull-up, 12: neither ... */
277
+ g_assert_cmpuint(tim_read_tdr(td), ==, count);
256
+ g_assert_cmphex(pupdr, ==, reset(GPIO_A, PUPDR));
278
+
257
+ /* 15 : 1, 14: 0, 13: 1, 12 : reset value ... */
279
+ clock_step(tim_calculate_step(count, ps) - 1);
258
+ g_assert_cmphex(idr, ==, reset(GPIO_A, IDR));
280
+
259
+
281
+ g_assert_cmphex(tim_read_tcsr(td), ==, CEN | CACT | PRESCALE(ps));
260
+ moder = gpio_readl(GPIO_B, MODER);
282
+ g_assert_cmpuint(tim_read_tdr(td), <, count);
261
+ odr = gpio_readl(GPIO_B, ODR);
283
+ g_assert_cmphex(tim_read(td, TISR), ==, 0);
262
+ otyper = gpio_readl(GPIO_B, OTYPER);
284
+
263
+ pupdr = gpio_readl(GPIO_B, PUPDR);
285
+ clock_step(1);
264
+ idr = gpio_readl(GPIO_B, IDR);
286
+
265
+ /* ... 5: Analog, 4: AF, 3: AF, 2: Analog ... */
287
+ g_assert_cmphex(tim_read_tcsr(td), ==, PRESCALE(ps));
266
+ /* here AF is the same as Analog and Input mode */
288
+ g_assert_cmpuint(tim_read_tdr(td), ==, count);
267
+ g_assert_cmphex(moder, ==, reset(GPIO_B, MODER));
289
+ g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td));
268
+ g_assert_cmphex(odr, ==, reset(GPIO_B, ODR));
290
+ g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
269
+ g_assert_cmphex(otyper, ==, reset(GPIO_B, OTYPER));
291
+
270
+ /* ... 5: neither, 4: pull-up, 3: neither ... */
292
+ /* Clear the interrupt flag. */
271
+ g_assert_cmphex(pupdr, ==, reset(GPIO_B, PUPDR));
293
+ tim_write(td, TISR, tim_timer_bit(td));
272
+ /* ... 5 : reset value, 4 : 1, 3 : reset value ... */
294
+ g_assert_cmphex(tim_read(td, TISR), ==, 0);
273
+ g_assert_cmphex(idr, ==, reset(GPIO_B, IDR));
295
+ g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
274
+
296
+
275
+ moder = gpio_readl(GPIO_C, MODER);
297
+ /* Verify that this isn't a periodic timer. */
276
+ odr = gpio_readl(GPIO_C, ODR);
298
+ clock_step(2 * tim_calculate_step(count, ps));
277
+ otyper = gpio_readl(GPIO_C, OTYPER);
299
+ g_assert_cmphex(tim_read(td, TISR), ==, 0);
278
+ pupdr = gpio_readl(GPIO_C, PUPDR);
300
+ g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
279
+ idr = gpio_readl(GPIO_C, IDR);
301
+}
280
+ /* Analog, same as Input mode*/
302
+
281
+ g_assert_cmphex(moder, ==, reset(GPIO_C, MODER));
303
+/* Verifies that a one-shot timer fires when expected with prescaler 0. */
282
+ g_assert_cmphex(odr, ==, reset(GPIO_C, ODR));
304
+static void test_oneshot_ps0(gconstpointer test_data)
283
+ g_assert_cmphex(otyper, ==, reset(GPIO_C, OTYPER));
305
+{
284
+ /* no pull-up or pull-down */
306
+ const TestData *td = test_data;
285
+ g_assert_cmphex(pupdr, ==, reset(GPIO_C, PUPDR));
307
+ unsigned int count = 1;
286
+ /* reset value */
308
+ unsigned int ps = 0;
287
+ g_assert_cmphex(idr, ==, reset(GPIO_C, IDR));
309
+
288
+
310
+ tim_reset(td);
289
+ moder = gpio_readl(GPIO_H, MODER);
311
+
290
+ odr = gpio_readl(GPIO_H, ODR);
312
+ tim_write_ticr(td, count);
291
+ otyper = gpio_readl(GPIO_H, OTYPER);
313
+ tim_write_tcsr(td, CEN | PRESCALE(ps));
292
+ pupdr = gpio_readl(GPIO_H, PUPDR);
314
+ g_assert_cmphex(tim_read_tcsr(td), ==, CEN | CACT | PRESCALE(ps));
293
+ idr = gpio_readl(GPIO_H, IDR);
315
+ g_assert_cmpuint(tim_read_tdr(td), ==, count);
294
+ /* Analog, same as Input mode */
316
+
295
+ g_assert_cmphex(moder, ==, reset(GPIO_H, MODER));
317
+ clock_step(tim_calculate_step(count, ps) - 1);
296
+ g_assert_cmphex(odr, ==, reset(GPIO_H, ODR));
318
+
297
+ g_assert_cmphex(otyper, ==, reset(GPIO_H, OTYPER));
319
+ g_assert_cmphex(tim_read_tcsr(td), ==, CEN | CACT | PRESCALE(ps));
298
+ /* no pull-up or pull-down */
320
+ g_assert_cmpuint(tim_read_tdr(td), <, count);
299
+ g_assert_cmphex(pupdr, ==, reset(GPIO_H, PUPDR));
321
+ g_assert_cmphex(tim_read(td, TISR), ==, 0);
300
+ /* reset value */
322
+
301
+ g_assert_cmphex(idr, ==, reset(GPIO_H, IDR));
323
+ clock_step(1);
302
+}
324
+
303
+
325
+ g_assert_cmphex(tim_read_tcsr(td), ==, PRESCALE(ps));
304
+static void test_gpio_output_mode(const void *data)
326
+ g_assert_cmpuint(tim_read_tdr(td), ==, count);
305
+{
327
+ g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td));
306
+ /*
328
+ g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
307
+ * Checks that setting a bit in ODR sets the corresponding
329
+}
308
+ * GPIO line high : it should set the right bit in IDR
330
+
309
+ * and send an irq to syscfg.
331
+/* Verifies that a one-shot timer fires when expected with highest prescaler. */
310
+ * Additionally, it checks that values written to ODR
332
+static void test_oneshot_ps255(gconstpointer test_data)
311
+ * when not in output mode are stored and not discarded.
333
+{
312
+ */
334
+ const TestData *td = test_data;
313
+ unsigned int pin = ((uint64_t)data) & 0xF;
335
+ unsigned int count = (1U << 24) - 1;
314
+ uint32_t gpio = ((uint64_t)data) >> 32;
336
+ unsigned int ps = 255;
315
+ unsigned int gpio_id = get_gpio_id(gpio);
337
+
316
+
338
+ tim_reset(td);
317
+ qtest_irq_intercept_in(global_qtest, "/machine/soc/syscfg");
339
+
318
+
340
+ tim_write_ticr(td, count);
319
+ /* Set a bit in ODR and check nothing happens */
341
+ tim_write_tcsr(td, CEN | PRESCALE(ps));
320
+ gpio_set_bit(gpio, ODR, pin, 1);
342
+ g_assert_cmphex(tim_read_tcsr(td), ==, CEN | CACT | PRESCALE(ps));
321
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR));
343
+ g_assert_cmpuint(tim_read_tdr(td), ==, count);
322
+ g_assert_false(get_irq(gpio_id * NUM_GPIO_PINS + pin));
344
+
323
+
345
+ clock_step(tim_calculate_step(count, ps) - 1);
324
+ /* Configure the relevant line as output and check the pin is high */
346
+
325
+ gpio_set_2bits(gpio, MODER, pin, MODER_OUTPUT);
347
+ g_assert_cmphex(tim_read_tcsr(td), ==, CEN | CACT | PRESCALE(ps));
326
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) | (1 << pin));
348
+ g_assert_cmpuint(tim_read_tdr(td), <, count);
327
+ g_assert_true(get_irq(gpio_id * NUM_GPIO_PINS + pin));
349
+ g_assert_cmphex(tim_read(td, TISR), ==, 0);
328
+
350
+
329
+ /* Reset the bit in ODR and check the pin is low */
351
+ clock_step(1);
330
+ gpio_set_bit(gpio, ODR, pin, 0);
352
+
331
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) & ~(1 << pin));
353
+ g_assert_cmphex(tim_read_tcsr(td), ==, PRESCALE(ps));
332
+ g_assert_false(get_irq(gpio_id * NUM_GPIO_PINS + pin));
354
+ g_assert_cmpuint(tim_read_tdr(td), ==, count);
333
+
355
+ g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td));
334
+ /* Clean the test */
356
+ g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
335
+ gpio_writel(gpio, ODR, reset(gpio, ODR));
357
+}
336
+ gpio_writel(gpio, MODER, reset(gpio, MODER));
358
+
337
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR));
359
+/* Verifies that a oneshot timer fires an interrupt when expected. */
338
+ g_assert_false(get_irq(gpio_id * NUM_GPIO_PINS + pin));
360
+static void test_oneshot_interrupt(gconstpointer test_data)
339
+}
361
+{
340
+
362
+ const TestData *td = test_data;
341
+static void test_gpio_input_mode(const void *data)
363
+ unsigned int count = 256;
342
+{
364
+ unsigned int ps = 7;
343
+ /*
365
+
344
+ * Test that setting a line high/low externally sets the
366
+ tim_reset(td);
345
+ * corresponding GPIO line high/low : it should set the
367
+
346
+ * right bit in IDR and send an irq to syscfg.
368
+ tim_write_ticr(td, count);
347
+ */
369
+ tim_write_tcsr(td, IE | CEN | MODE_ONESHOT | PRESCALE(ps));
348
+ unsigned int pin = ((uint64_t)data) & 0xF;
370
+
349
+ uint32_t gpio = ((uint64_t)data) >> 32;
371
+ clock_step_next();
350
+ unsigned int gpio_id = get_gpio_id(gpio);
372
+
351
+
373
+ g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td));
352
+ qtest_irq_intercept_in(global_qtest, "/machine/soc/syscfg");
374
+ g_assert_true(qtest_get_irq(global_qtest, tim_timer_irq(td)));
353
+
375
+}
354
+ /* Configure a line as input, raise it, and check that the pin is high */
376
+
355
+ gpio_set_2bits(gpio, MODER, pin, MODER_INPUT);
377
+/*
356
+ gpio_set_irq(gpio, pin, 1);
378
+ * Verifies that the timer can be paused and later resumed, and it still fires
357
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) | (1 << pin));
379
+ * at the right moment.
358
+ g_assert_true(get_irq(gpio_id * NUM_GPIO_PINS + pin));
380
+ */
359
+
381
+static void test_pause_resume(gconstpointer test_data)
360
+ /* Lower the line and check that the pin is low */
382
+{
361
+ gpio_set_irq(gpio, pin, 0);
383
+ const TestData *td = test_data;
362
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) & ~(1 << pin));
384
+ unsigned int count = 256;
363
+ g_assert_false(get_irq(gpio_id * NUM_GPIO_PINS + pin));
385
+ unsigned int ps = 1;
364
+
386
+
365
+ /* Clean the test */
387
+ tim_reset(td);
366
+ gpio_writel(gpio, MODER, reset(gpio, MODER));
388
+
367
+ disconnect_all_pins(gpio);
389
+ tim_write_ticr(td, count);
368
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR));
390
+ tim_write_tcsr(td, IE | CEN | MODE_ONESHOT | PRESCALE(ps));
369
+}
391
+
370
+
392
+ /* Pause the timer halfway to expiration. */
371
+static void test_pull_up_pull_down(const void *data)
393
+ clock_step(tim_calculate_step(count / 2, ps));
372
+{
394
+ tim_write_tcsr(td, IE | MODE_ONESHOT | PRESCALE(ps));
373
+ /*
395
+ g_assert_cmpuint(tim_read_tdr(td), ==, count / 2);
374
+ * Test that a floating pin with pull-up sets the pin
396
+
375
+ * high and vice-versa.
397
+ /* Counter should not advance during the following step. */
376
+ */
398
+ clock_step(2 * tim_calculate_step(count, ps));
377
+ unsigned int pin = ((uint64_t)data) & 0xF;
399
+ g_assert_cmpuint(tim_read_tdr(td), ==, count / 2);
378
+ uint32_t gpio = ((uint64_t)data) >> 32;
400
+ g_assert_cmphex(tim_read(td, TISR), ==, 0);
379
+ unsigned int gpio_id = get_gpio_id(gpio);
401
+ g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
380
+
402
+
381
+ qtest_irq_intercept_in(global_qtest, "/machine/soc/syscfg");
403
+ /* Resume the timer and run _almost_ to expiration. */
382
+
404
+ tim_write_tcsr(td, IE | CEN | MODE_ONESHOT | PRESCALE(ps));
383
+ /* Configure a line as input with pull-up, check the line is set high */
405
+ clock_step(tim_calculate_step(count / 2, ps) - 1);
384
+ gpio_set_2bits(gpio, MODER, pin, MODER_INPUT);
406
+ g_assert_cmpuint(tim_read_tdr(td), <, count);
385
+ gpio_set_2bits(gpio, PUPDR, pin, PUPDR_PULLUP);
407
+ g_assert_cmphex(tim_read(td, TISR), ==, 0);
386
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) | (1 << pin));
408
+ g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
387
+ g_assert_true(get_irq(gpio_id * NUM_GPIO_PINS + pin));
409
+
388
+
410
+ /* Now, run the rest of the way and verify that the interrupt fires. */
389
+ /* Configure the line with pull-down, check the line is low */
411
+ clock_step(1);
390
+ gpio_set_2bits(gpio, PUPDR, pin, PUPDR_PULLDOWN);
412
+ g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td));
391
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) & ~(1 << pin));
413
+ g_assert_true(qtest_get_irq(global_qtest, tim_timer_irq(td)));
392
+ g_assert_false(get_irq(gpio_id * NUM_GPIO_PINS + pin));
414
+}
393
+
415
+
394
+ /* Clean the test */
416
+/* Verifies that the prescaler can be changed while the timer is runnin. */
395
+ gpio_writel(gpio, MODER, reset(gpio, MODER));
417
+static void test_prescaler_change(gconstpointer test_data)
396
+ gpio_writel(gpio, PUPDR, reset(gpio, PUPDR));
418
+{
397
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR));
419
+ const TestData *td = test_data;
398
+}
420
+ unsigned int count = 256;
399
+
421
+ unsigned int ps = 5;
400
+static void test_push_pull(const void *data)
422
+
401
+{
423
+ tim_reset(td);
402
+ /*
424
+
403
+ * Test that configuring a line in push-pull output mode
425
+ tim_write_ticr(td, count);
404
+ * disconnects the pin, that the pin can't be set or reset
426
+ tim_write_tcsr(td, CEN | MODE_ONESHOT | PRESCALE(ps));
405
+ * externally afterwards.
427
+
406
+ */
428
+ /* Run a quarter of the way, and change the prescaler. */
407
+ unsigned int pin = ((uint64_t)data) & 0xF;
429
+ clock_step(tim_calculate_step(count / 4, ps));
408
+ uint32_t gpio = ((uint64_t)data) >> 32;
430
+ g_assert_cmpuint(tim_read_tdr(td), ==, 3 * count / 4);
409
+ uint32_t gpio2 = GPIO_BASE_ADDR + (GPIO_H - gpio);
431
+ ps = 2;
410
+
432
+ tim_write_tcsr(td, CEN | MODE_ONESHOT | PRESCALE(ps));
411
+ qtest_irq_intercept_in(global_qtest, "/machine/soc/syscfg");
433
+ /* The counter must not change. */
412
+
434
+ g_assert_cmpuint(tim_read_tdr(td), ==, 3 * count / 4);
413
+ /* Setting a line high externally, configuring it in push-pull output */
435
+
414
+ /* And checking the pin was disconnected */
436
+ /* Run another quarter of the way, and change the prescaler again. */
415
+ gpio_set_irq(gpio, pin, 1);
437
+ clock_step(tim_calculate_step(count / 4, ps));
416
+ gpio_set_2bits(gpio, MODER, pin, MODER_OUTPUT);
438
+ g_assert_cmpuint(tim_read_tdr(td), ==, count / 2);
417
+ g_assert_cmphex(get_disconnected_pins(gpio), ==, 0xFFFF);
439
+ ps = 8;
418
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) & ~(1 << pin));
440
+ tim_write_tcsr(td, CEN | MODE_ONESHOT | PRESCALE(ps));
419
+
441
+ /* The counter must not change. */
420
+ /* Setting a line low externally, configuring it in push-pull output */
442
+ g_assert_cmpuint(tim_read_tdr(td), ==, count / 2);
421
+ /* And checking the pin was disconnected */
443
+
422
+ gpio_set_irq(gpio2, pin, 0);
444
+ /* Run another quarter of the way, and change the prescaler again. */
423
+ gpio_set_bit(gpio2, ODR, pin, 1);
445
+ clock_step(tim_calculate_step(count / 4, ps));
424
+ gpio_set_2bits(gpio2, MODER, pin, MODER_OUTPUT);
446
+ g_assert_cmpuint(tim_read_tdr(td), ==, count / 4);
425
+ g_assert_cmphex(get_disconnected_pins(gpio2), ==, 0xFFFF);
447
+ ps = 0;
426
+ g_assert_cmphex(gpio_readl(gpio2, IDR), ==, reset(gpio2, IDR) | (1 << pin));
448
+ tim_write_tcsr(td, CEN | MODE_ONESHOT | PRESCALE(ps));
427
+
449
+ /* The counter must not change. */
428
+ /* Trying to set a push-pull output pin, checking it doesn't work */
450
+ g_assert_cmpuint(tim_read_tdr(td), ==, count / 4);
429
+ gpio_set_irq(gpio, pin, 1);
451
+
430
+ g_assert_cmphex(get_disconnected_pins(gpio), ==, 0xFFFF);
452
+ /* Run almost to expiration, and verify the timer didn't fire yet. */
431
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) & ~(1 << pin));
453
+ clock_step(tim_calculate_step(count / 4, ps) - 1);
432
+
454
+ g_assert_cmpuint(tim_read_tdr(td), <, count);
433
+ /* Trying to reset a push-pull output pin, checking it doesn't work */
455
+ g_assert_cmphex(tim_read(td, TISR), ==, 0);
434
+ gpio_set_irq(gpio2, pin, 0);
456
+
435
+ g_assert_cmphex(get_disconnected_pins(gpio2), ==, 0xFFFF);
457
+ /* Now, run the rest of the way and verify that the timer fires. */
436
+ g_assert_cmphex(gpio_readl(gpio2, IDR), ==, reset(gpio2, IDR) | (1 << pin));
458
+ clock_step(1);
437
+
459
+ g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td));
438
+ /* Clean the test */
460
+}
439
+ gpio_writel(gpio, MODER, reset(gpio, MODER));
461
+
440
+ gpio_writel(gpio2, ODR, reset(gpio2, ODR));
462
+/* Verifies that a periodic timer automatically restarts after expiration. */
441
+ gpio_writel(gpio2, MODER, reset(gpio2, MODER));
463
+static void test_periodic_no_interrupt(gconstpointer test_data)
442
+}
464
+{
443
+
465
+ const TestData *td = test_data;
444
+static void test_open_drain(const void *data)
466
+ unsigned int count = 2;
445
+{
467
+ unsigned int ps = 3;
446
+ /*
468
+ int i;
447
+ * Test that configuring a line in open-drain output mode
469
+
448
+ * disconnects a pin set high externally and that the pin
470
+ tim_reset(td);
449
+ * can't be set high externally while configured in open-drain.
471
+
450
+ *
472
+ tim_write_ticr(td, count);
451
+ * However a pin set low externally shouldn't be disconnected,
473
+ tim_write_tcsr(td, CEN | MODE_PERIODIC | PRESCALE(ps));
452
+ * and it can be set low externally when in open-drain mode.
474
+
453
+ */
475
+ for (i = 0; i < 4; i++) {
454
+ unsigned int pin = ((uint64_t)data) & 0xF;
476
+ clock_step_next();
455
+ uint32_t gpio = ((uint64_t)data) >> 32;
477
+
456
+ uint32_t gpio2 = GPIO_BASE_ADDR + (GPIO_H - gpio);
478
+ g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td));
457
+
479
+ g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
458
+ qtest_irq_intercept_in(global_qtest, "/machine/soc/syscfg");
480
+
459
+
481
+ tim_write(td, TISR, tim_timer_bit(td));
460
+ /* Setting a line high externally, configuring it in open-drain output */
482
+
461
+ /* And checking the pin was disconnected */
483
+ g_assert_cmphex(tim_read(td, TISR), ==, 0);
462
+ gpio_set_irq(gpio, pin, 1);
484
+ g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
463
+ gpio_set_bit(gpio, OTYPER, pin, OTYPER_OPEN_DRAIN);
485
+ }
464
+ gpio_set_2bits(gpio, MODER, pin, MODER_OUTPUT);
486
+}
465
+ g_assert_cmphex(get_disconnected_pins(gpio), ==, 0xFFFF);
487
+
466
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) & ~(1 << pin));
488
+/* Verifies that a periodict timer fires an interrupt every time it expires. */
467
+
489
+static void test_periodic_interrupt(gconstpointer test_data)
468
+ /* Setting a line low externally, configuring it in open-drain output */
490
+{
469
+ /* And checking the pin wasn't disconnected */
491
+ const TestData *td = test_data;
470
+ gpio_set_irq(gpio2, pin, 0);
492
+ unsigned int count = 65535;
471
+ gpio_set_bit(gpio2, ODR, pin, 1);
493
+ unsigned int ps = 2;
472
+ gpio_set_bit(gpio2, OTYPER, pin, OTYPER_OPEN_DRAIN);
494
+ int i;
473
+ gpio_set_2bits(gpio2, MODER, pin, MODER_OUTPUT);
495
+
474
+ g_assert_cmphex(get_disconnected_pins(gpio2), ==, 0xFFFF & ~(1 << pin));
496
+ tim_reset(td);
475
+ g_assert_cmphex(gpio_readl(gpio2, IDR), ==,
497
+
476
+ reset(gpio2, IDR) & ~(1 << pin));
498
+ tim_write_ticr(td, count);
477
+
499
+ tim_write_tcsr(td, CEN | IE | MODE_PERIODIC | PRESCALE(ps));
478
+ /* Trying to set a open-drain output pin, checking it doesn't work */
500
+
479
+ gpio_set_irq(gpio, pin, 1);
501
+ for (i = 0; i < 4; i++) {
480
+ g_assert_cmphex(get_disconnected_pins(gpio), ==, 0xFFFF);
502
+ clock_step_next();
481
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) & ~(1 << pin));
503
+
482
+
504
+ g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td));
483
+ /* Trying to reset a open-drain output pin, checking it works */
505
+ g_assert_true(qtest_get_irq(global_qtest, tim_timer_irq(td)));
484
+ gpio_set_bit(gpio, ODR, pin, 1);
506
+
485
+ gpio_set_irq(gpio, pin, 0);
507
+ tim_write(td, TISR, tim_timer_bit(td));
486
+ g_assert_cmphex(get_disconnected_pins(gpio2), ==, 0xFFFF & ~(1 << pin));
508
+
487
+ g_assert_cmphex(gpio_readl(gpio2, IDR), ==,
509
+ g_assert_cmphex(tim_read(td, TISR), ==, 0);
488
+ reset(gpio2, IDR) & ~(1 << pin));
510
+ g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
489
+
511
+ }
490
+ /* Clean the test */
512
+}
491
+ disconnect_all_pins(gpio2);
513
+
492
+ gpio_writel(gpio2, OTYPER, reset(gpio2, OTYPER));
514
+/*
493
+ gpio_writel(gpio2, ODR, reset(gpio2, ODR));
515
+ * Verifies that the timer behaves correctly when disabled right before and
494
+ gpio_writel(gpio2, MODER, reset(gpio2, MODER));
516
+ * exactly when it's supposed to expire.
495
+ g_assert_cmphex(gpio_readl(gpio2, IDR), ==, reset(gpio2, IDR));
517
+ */
496
+ disconnect_all_pins(gpio);
518
+static void test_disable_on_expiration(gconstpointer test_data)
497
+ gpio_writel(gpio, OTYPER, reset(gpio, OTYPER));
519
+{
498
+ gpio_writel(gpio, ODR, reset(gpio, ODR));
520
+ const TestData *td = test_data;
499
+ gpio_writel(gpio, MODER, reset(gpio, MODER));
521
+ unsigned int count = 8;
500
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR));
522
+ unsigned int ps = 255;
501
+}
523
+
502
+
524
+ tim_reset(td);
503
+static void test_bsrr_brr(const void *data)
525
+
504
+{
526
+ tim_write_ticr(td, count);
505
+ /*
527
+ tim_write_tcsr(td, CEN | MODE_ONESHOT | PRESCALE(ps));
506
+ * Test that writing a '1' in BSS and BSRR
528
+
507
+ * has the desired effect on ODR.
529
+ clock_step(tim_calculate_step(count, ps) - 1);
508
+ * In BSRR, BSx has priority over BRx.
530
+
509
+ */
531
+ tim_write_tcsr(td, MODE_ONESHOT | PRESCALE(ps));
510
+ unsigned int pin = ((uint64_t)data) & 0xF;
532
+ tim_write_tcsr(td, CEN | MODE_ONESHOT | PRESCALE(ps));
511
+ uint32_t gpio = ((uint64_t)data) >> 32;
533
+ clock_step(1);
512
+
534
+ tim_write_tcsr(td, MODE_ONESHOT | PRESCALE(ps));
513
+ gpio_writel(gpio, BSRR, (1 << pin));
535
+ g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td));
514
+ g_assert_cmphex(gpio_readl(gpio, ODR), ==, reset(gpio, ODR) | (1 << pin));
536
+}
515
+
537
+
516
+ gpio_writel(gpio, BSRR, (1 << (pin + NUM_GPIO_PINS)));
538
+/*
517
+ g_assert_cmphex(gpio_readl(gpio, ODR), ==, reset(gpio, ODR));
539
+ * Constructs a name that includes the timer block, timer and testcase name,
518
+
540
+ * and adds the test to the test suite.
519
+ gpio_writel(gpio, BSRR, (1 << pin));
541
+ */
520
+ g_assert_cmphex(gpio_readl(gpio, ODR), ==, reset(gpio, ODR) | (1 << pin));
542
+static void tim_add_test(const char *name, const TestData *td, GTestDataFunc fn)
521
+
543
+{
522
+ gpio_writel(gpio, BRR, (1 << pin));
544
+ g_autofree char *full_name;
523
+ g_assert_cmphex(gpio_readl(gpio, ODR), ==, reset(gpio, ODR));
545
+
524
+
546
+ full_name = g_strdup_printf("npcm7xx_timer/tim[%d]/timer[%d]/%s",
525
+ /* BSx should have priority over BRx */
547
+ tim_index(td->tim), timer_index(td->timer),
526
+ gpio_writel(gpio, BSRR, (1 << pin) | (1 << (pin + NUM_GPIO_PINS)));
548
+ name);
527
+ g_assert_cmphex(gpio_readl(gpio, ODR), ==, reset(gpio, ODR) | (1 << pin));
549
+ qtest_add_data_func(full_name, td, fn);
528
+
550
+}
529
+ gpio_writel(gpio, BRR, (1 << pin));
551
+
530
+ g_assert_cmphex(gpio_readl(gpio, ODR), ==, reset(gpio, ODR));
552
+/* Convenience macro for adding a test with a predictable function name. */
531
+
553
+#define add_test(name, td) tim_add_test(#name, td, test_##name)
532
+ gpio_writel(gpio, ODR, reset(gpio, ODR));
533
+}
554
+
534
+
555
+int main(int argc, char **argv)
535
+int main(int argc, char **argv)
556
+{
536
+{
557
+ TestData testdata[ARRAY_SIZE(timer_block) * ARRAY_SIZE(timer)];
558
+ int ret;
537
+ int ret;
559
+ int i, j;
560
+
538
+
561
+ g_test_init(&argc, &argv, NULL);
539
+ g_test_init(&argc, &argv, NULL);
562
+ g_test_set_nonfatal_assertions();
540
+ g_test_set_nonfatal_assertions();
563
+
541
+ qtest_add_func("stm32l4x5/gpio/test_idr_reset_value",
564
+ for (i = 0; i < ARRAY_SIZE(timer_block); i++) {
542
+ test_idr_reset_value);
565
+ for (j = 0; j < ARRAY_SIZE(timer); j++) {
543
+ /*
566
+ TestData *td = &testdata[i * ARRAY_SIZE(timer) + j];
544
+ * The inputs for the tests (gpio and pin) can be changed,
567
+ td->tim = &timer_block[i];
545
+ * but the tests don't work for pins that are high at reset
568
+ td->timer = &timer[j];
546
+ * (GPIOA15, GPIO13 and GPIOB5).
569
+
547
+ * Specifically, rising the pin then checking `get_irq()`
570
+ add_test(reset, td);
548
+ * is problematic since the pin was already high.
571
+ add_test(reset_overrides_enable, td);
549
+ */
572
+ add_test(oneshot_enable_then_disable, td);
550
+ qtest_add_data_func("stm32l4x5/gpio/test_gpioc5_output_mode",
573
+ add_test(oneshot_ps5, td);
551
+ (void *)((uint64_t)GPIO_C << 32 | 5),
574
+ add_test(oneshot_ps0, td);
552
+ test_gpio_output_mode);
575
+ add_test(oneshot_ps255, td);
553
+ qtest_add_data_func("stm32l4x5/gpio/test_gpioh3_output_mode",
576
+ add_test(oneshot_interrupt, td);
554
+ (void *)((uint64_t)GPIO_H << 32 | 3),
577
+ add_test(pause_resume, td);
555
+ test_gpio_output_mode);
578
+ add_test(prescaler_change, td);
556
+ qtest_add_data_func("stm32l4x5/gpio/test_gpio_input_mode1",
579
+ add_test(periodic_no_interrupt, td);
557
+ (void *)((uint64_t)GPIO_D << 32 | 6),
580
+ add_test(periodic_interrupt, td);
558
+ test_gpio_input_mode);
581
+ add_test(disable_on_expiration, td);
559
+ qtest_add_data_func("stm32l4x5/gpio/test_gpio_input_mode2",
582
+ }
560
+ (void *)((uint64_t)GPIO_C << 32 | 10),
583
+ }
561
+ test_gpio_input_mode);
584
+
562
+ qtest_add_data_func("stm32l4x5/gpio/test_gpio_pull_up_pull_down1",
585
+ qtest_start("-machine npcm750-evb");
563
+ (void *)((uint64_t)GPIO_B << 32 | 5),
586
+ qtest_irq_intercept_in(global_qtest, "/machine/soc/a9mpcore/gic");
564
+ test_pull_up_pull_down);
565
+ qtest_add_data_func("stm32l4x5/gpio/test_gpio_pull_up_pull_down2",
566
+ (void *)((uint64_t)GPIO_F << 32 | 1),
567
+ test_pull_up_pull_down);
568
+ qtest_add_data_func("stm32l4x5/gpio/test_gpio_push_pull1",
569
+ (void *)((uint64_t)GPIO_G << 32 | 6),
570
+ test_push_pull);
571
+ qtest_add_data_func("stm32l4x5/gpio/test_gpio_push_pull2",
572
+ (void *)((uint64_t)GPIO_H << 32 | 3),
573
+ test_push_pull);
574
+ qtest_add_data_func("stm32l4x5/gpio/test_gpio_open_drain1",
575
+ (void *)((uint64_t)GPIO_C << 32 | 4),
576
+ test_open_drain);
577
+ qtest_add_data_func("stm32l4x5/gpio/test_gpio_open_drain2",
578
+ (void *)((uint64_t)GPIO_E << 32 | 11),
579
+ test_open_drain);
580
+ qtest_add_data_func("stm32l4x5/gpio/test_bsrr_brr1",
581
+ (void *)((uint64_t)GPIO_A << 32 | 12),
582
+ test_bsrr_brr);
583
+ qtest_add_data_func("stm32l4x5/gpio/test_bsrr_brr2",
584
+ (void *)((uint64_t)GPIO_D << 32 | 0),
585
+ test_bsrr_brr);
586
+
587
+ qtest_start("-machine b-l475e-iot01a");
587
+ ret = g_test_run();
588
+ ret = g_test_run();
588
+ qtest_end();
589
+ qtest_end();
589
+
590
+
590
+ return ret;
591
+ return ret;
591
+}
592
+}
592
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
593
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
593
index XXXXXXX..XXXXXXX 100644
594
index XXXXXXX..XXXXXXX 100644
594
--- a/tests/qtest/meson.build
595
--- a/tests/qtest/meson.build
595
+++ b/tests/qtest/meson.build
596
+++ b/tests/qtest/meson.build
596
@@ -XXX,XX +XXX,XX @@ qtests_arm = \
597
@@ -XXX,XX +XXX,XX @@ qtests_aspeed = \
597
['arm-cpu-features',
598
qtests_stm32l4x5 = \
598
'microbit-test',
599
['stm32l4x5_exti-test',
599
'm25p80-test',
600
'stm32l4x5_syscfg-test',
600
+ 'npcm7xx_timer-test',
601
- 'stm32l4x5_rcc-test']
601
'test-arm-mptimer',
602
+ 'stm32l4x5_rcc-test',
602
'boot-serial-test',
603
+ 'stm32l4x5_gpio-test']
603
'hexloader-test']
604
605
qtests_arm = \
606
(config_all_devices.has_key('CONFIG_MPS2') ? ['sse-timer-test'] : []) + \
604
--
607
--
605
2.20.1
608
2.34.1
606
609
607
610
diff view generated by jsdifflib
Deleted patch
1
From: Emanuele Giuseppe Esposito <e.emanuelegiuseppe@gmail.com>
2
1
3
Current documentation is not too clear on the GETPC usage.
4
In particular, when used outside the top level helper function
5
it causes unexpected behavior.
6
7
Signed-off-by: Emanuele Giuseppe Esposito <e.emanuelegiuseppe@gmail.com>
8
Message-id: 20201015095147.1691-1-e.emanuelegiuseppe@gmail.com
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
docs/devel/loads-stores.rst | 8 +++++++-
13
1 file changed, 7 insertions(+), 1 deletion(-)
14
15
diff --git a/docs/devel/loads-stores.rst b/docs/devel/loads-stores.rst
16
index XXXXXXX..XXXXXXX 100644
17
--- a/docs/devel/loads-stores.rst
18
+++ b/docs/devel/loads-stores.rst
19
@@ -XXX,XX +XXX,XX @@ guest CPU state in case of a guest CPU exception. This is passed
20
to ``cpu_restore_state()``. Therefore the value should either be 0,
21
to indicate that the guest CPU state is already synchronized, or
22
the result of ``GETPC()`` from the top level ``HELPER(foo)``
23
-function, which is a return address into the generated code.
24
+function, which is a return address into the generated code [#gpc]_.
25
+
26
+.. [#gpc] Note that ``GETPC()`` should be used with great care: calling
27
+ it in other functions that are *not* the top level
28
+ ``HELPER(foo)`` will cause unexpected behavior. Instead, the
29
+ value of ``GETPC()`` should be read from the helper and passed
30
+ if needed to the functions that the helper calls.
31
32
Function names follow the pattern:
33
34
--
35
2.20.1
36
37
diff view generated by jsdifflib
Deleted patch
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
1
3
Add trace events for GPU and CPU IRQs.
4
5
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
6
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Message-id: 20201017180731.1165871-2-f4bug@amsat.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
hw/intc/bcm2835_ic.c | 4 +++-
11
hw/intc/trace-events | 4 ++++
12
2 files changed, 7 insertions(+), 1 deletion(-)
13
14
diff --git a/hw/intc/bcm2835_ic.c b/hw/intc/bcm2835_ic.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/intc/bcm2835_ic.c
17
+++ b/hw/intc/bcm2835_ic.c
18
@@ -XXX,XX +XXX,XX @@
19
#include "migration/vmstate.h"
20
#include "qemu/log.h"
21
#include "qemu/module.h"
22
+#include "trace.h"
23
24
#define GPU_IRQS 64
25
#define ARM_IRQS 8
26
@@ -XXX,XX +XXX,XX @@ static void bcm2835_ic_update(BCM2835ICState *s)
27
set = (s->gpu_irq_level & s->gpu_irq_enable)
28
|| (s->arm_irq_level & s->arm_irq_enable);
29
qemu_set_irq(s->irq, set);
30
-
31
}
32
33
static void bcm2835_ic_set_gpu_irq(void *opaque, int irq, int level)
34
@@ -XXX,XX +XXX,XX @@ static void bcm2835_ic_set_gpu_irq(void *opaque, int irq, int level)
35
BCM2835ICState *s = opaque;
36
37
assert(irq >= 0 && irq < 64);
38
+ trace_bcm2835_ic_set_gpu_irq(irq, level);
39
s->gpu_irq_level = deposit64(s->gpu_irq_level, irq, 1, level != 0);
40
bcm2835_ic_update(s);
41
}
42
@@ -XXX,XX +XXX,XX @@ static void bcm2835_ic_set_arm_irq(void *opaque, int irq, int level)
43
BCM2835ICState *s = opaque;
44
45
assert(irq >= 0 && irq < 8);
46
+ trace_bcm2835_ic_set_cpu_irq(irq, level);
47
s->arm_irq_level = deposit32(s->arm_irq_level, irq, 1, level != 0);
48
bcm2835_ic_update(s);
49
}
50
diff --git a/hw/intc/trace-events b/hw/intc/trace-events
51
index XXXXXXX..XXXXXXX 100644
52
--- a/hw/intc/trace-events
53
+++ b/hw/intc/trace-events
54
@@ -XXX,XX +XXX,XX @@ nvic_sysreg_write(uint64_t addr, uint32_t value, unsigned size) "NVIC sysreg wri
55
heathrow_write(uint64_t addr, unsigned int n, uint64_t value) "0x%"PRIx64" %u: 0x%"PRIx64
56
heathrow_read(uint64_t addr, unsigned int n, uint64_t value) "0x%"PRIx64" %u: 0x%"PRIx64
57
heathrow_set_irq(int num, int level) "set_irq: num=0x%02x level=%d"
58
+
59
+# bcm2835_ic.c
60
+bcm2835_ic_set_gpu_irq(int irq, int level) "GPU irq #%d level %d"
61
+bcm2835_ic_set_cpu_irq(int irq, int level) "CPU irq #%d level %d"
62
--
63
2.20.1
64
65
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
The note test requires gcc 10 for -mbranch-protection=standard.
3
While the 8-bit input elements are sequential in the input vector,
4
The mmap test uses PROT_BTI and does not require special compiler support.
4
the 32-bit output elements are not sequential in the output matrix.
5
5
Do not attempt to compute 2 32-bit outputs at the same time.
6
Acked-by: Alex Bennée <alex.bennee@linaro.org>
6
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Cc: qemu-stable@nongnu.org
8
Fixes: 23a5e3859f5 ("target/arm: Implement SME integer outer product")
9
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2083
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20201016184207.786698-13-richard.henderson@linaro.org
11
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
12
Message-id: 20240305163931.242795-1-richard.henderson@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
14
---
12
tests/tcg/aarch64/bti-1.c | 62 +++++++++++++++++
15
target/arm/tcg/sme_helper.c | 77 ++++++++++++++++++-------------
13
tests/tcg/aarch64/bti-2.c | 108 ++++++++++++++++++++++++++++++
16
tests/tcg/aarch64/sme-smopa-1.c | 47 +++++++++++++++++++
14
tests/tcg/aarch64/bti-crt.inc.c | 51 ++++++++++++++
17
tests/tcg/aarch64/sme-smopa-2.c | 54 ++++++++++++++++++++++
15
tests/tcg/aarch64/Makefile.target | 10 +++
18
tests/tcg/aarch64/Makefile.target | 2 +-
16
tests/tcg/configure.sh | 4 ++
19
4 files changed, 147 insertions(+), 33 deletions(-)
17
5 files changed, 235 insertions(+)
20
create mode 100644 tests/tcg/aarch64/sme-smopa-1.c
18
create mode 100644 tests/tcg/aarch64/bti-1.c
21
create mode 100644 tests/tcg/aarch64/sme-smopa-2.c
19
create mode 100644 tests/tcg/aarch64/bti-2.c
22
20
create mode 100644 tests/tcg/aarch64/bti-crt.inc.c
23
diff --git a/target/arm/tcg/sme_helper.c b/target/arm/tcg/sme_helper.c
21
24
index XXXXXXX..XXXXXXX 100644
22
diff --git a/tests/tcg/aarch64/bti-1.c b/tests/tcg/aarch64/bti-1.c
25
--- a/target/arm/tcg/sme_helper.c
26
+++ b/target/arm/tcg/sme_helper.c
27
@@ -XXX,XX +XXX,XX @@ void HELPER(sme_bfmopa)(void *vza, void *vzn, void *vzm, void *vpn,
28
}
29
}
30
31
-typedef uint64_t IMOPFn(uint64_t, uint64_t, uint64_t, uint8_t, bool);
32
+typedef uint32_t IMOPFn32(uint32_t, uint32_t, uint32_t, uint8_t, bool);
33
+static inline void do_imopa_s(uint32_t *za, uint32_t *zn, uint32_t *zm,
34
+ uint8_t *pn, uint8_t *pm,
35
+ uint32_t desc, IMOPFn32 *fn)
36
+{
37
+ intptr_t row, col, oprsz = simd_oprsz(desc) / 4;
38
+ bool neg = simd_data(desc);
39
40
-static inline void do_imopa(uint64_t *za, uint64_t *zn, uint64_t *zm,
41
- uint8_t *pn, uint8_t *pm,
42
- uint32_t desc, IMOPFn *fn)
43
+ for (row = 0; row < oprsz; ++row) {
44
+ uint8_t pa = (pn[H1(row >> 1)] >> ((row & 1) * 4)) & 0xf;
45
+ uint32_t *za_row = &za[tile_vslice_index(row)];
46
+ uint32_t n = zn[H4(row)];
47
+
48
+ for (col = 0; col < oprsz; ++col) {
49
+ uint8_t pb = pm[H1(col >> 1)] >> ((col & 1) * 4);
50
+ uint32_t *a = &za_row[H4(col)];
51
+
52
+ *a = fn(n, zm[H4(col)], *a, pa & pb, neg);
53
+ }
54
+ }
55
+}
56
+
57
+typedef uint64_t IMOPFn64(uint64_t, uint64_t, uint64_t, uint8_t, bool);
58
+static inline void do_imopa_d(uint64_t *za, uint64_t *zn, uint64_t *zm,
59
+ uint8_t *pn, uint8_t *pm,
60
+ uint32_t desc, IMOPFn64 *fn)
61
{
62
intptr_t row, col, oprsz = simd_oprsz(desc) / 8;
63
bool neg = simd_data(desc);
64
@@ -XXX,XX +XXX,XX @@ static inline void do_imopa(uint64_t *za, uint64_t *zn, uint64_t *zm,
65
}
66
67
#define DEF_IMOP_32(NAME, NTYPE, MTYPE) \
68
-static uint64_t NAME(uint64_t n, uint64_t m, uint64_t a, uint8_t p, bool neg) \
69
+static uint32_t NAME(uint32_t n, uint32_t m, uint32_t a, uint8_t p, bool neg) \
70
{ \
71
- uint32_t sum0 = 0, sum1 = 0; \
72
+ uint32_t sum = 0; \
73
/* Apply P to N as a mask, making the inactive elements 0. */ \
74
n &= expand_pred_b(p); \
75
- sum0 += (NTYPE)(n >> 0) * (MTYPE)(m >> 0); \
76
- sum0 += (NTYPE)(n >> 8) * (MTYPE)(m >> 8); \
77
- sum0 += (NTYPE)(n >> 16) * (MTYPE)(m >> 16); \
78
- sum0 += (NTYPE)(n >> 24) * (MTYPE)(m >> 24); \
79
- sum1 += (NTYPE)(n >> 32) * (MTYPE)(m >> 32); \
80
- sum1 += (NTYPE)(n >> 40) * (MTYPE)(m >> 40); \
81
- sum1 += (NTYPE)(n >> 48) * (MTYPE)(m >> 48); \
82
- sum1 += (NTYPE)(n >> 56) * (MTYPE)(m >> 56); \
83
- if (neg) { \
84
- sum0 = (uint32_t)a - sum0, sum1 = (uint32_t)(a >> 32) - sum1; \
85
- } else { \
86
- sum0 = (uint32_t)a + sum0, sum1 = (uint32_t)(a >> 32) + sum1; \
87
- } \
88
- return ((uint64_t)sum1 << 32) | sum0; \
89
+ sum += (NTYPE)(n >> 0) * (MTYPE)(m >> 0); \
90
+ sum += (NTYPE)(n >> 8) * (MTYPE)(m >> 8); \
91
+ sum += (NTYPE)(n >> 16) * (MTYPE)(m >> 16); \
92
+ sum += (NTYPE)(n >> 24) * (MTYPE)(m >> 24); \
93
+ return neg ? a - sum : a + sum; \
94
}
95
96
#define DEF_IMOP_64(NAME, NTYPE, MTYPE) \
97
@@ -XXX,XX +XXX,XX @@ DEF_IMOP_64(umopa_d, uint16_t, uint16_t)
98
DEF_IMOP_64(sumopa_d, int16_t, uint16_t)
99
DEF_IMOP_64(usmopa_d, uint16_t, int16_t)
100
101
-#define DEF_IMOPH(NAME) \
102
- void HELPER(sme_##NAME)(void *vza, void *vzn, void *vzm, void *vpn, \
103
- void *vpm, uint32_t desc) \
104
- { do_imopa(vza, vzn, vzm, vpn, vpm, desc, NAME); }
105
+#define DEF_IMOPH(NAME, S) \
106
+ void HELPER(sme_##NAME##_##S)(void *vza, void *vzn, void *vzm, \
107
+ void *vpn, void *vpm, uint32_t desc) \
108
+ { do_imopa_##S(vza, vzn, vzm, vpn, vpm, desc, NAME##_##S); }
109
110
-DEF_IMOPH(smopa_s)
111
-DEF_IMOPH(umopa_s)
112
-DEF_IMOPH(sumopa_s)
113
-DEF_IMOPH(usmopa_s)
114
-DEF_IMOPH(smopa_d)
115
-DEF_IMOPH(umopa_d)
116
-DEF_IMOPH(sumopa_d)
117
-DEF_IMOPH(usmopa_d)
118
+DEF_IMOPH(smopa, s)
119
+DEF_IMOPH(umopa, s)
120
+DEF_IMOPH(sumopa, s)
121
+DEF_IMOPH(usmopa, s)
122
+
123
+DEF_IMOPH(smopa, d)
124
+DEF_IMOPH(umopa, d)
125
+DEF_IMOPH(sumopa, d)
126
+DEF_IMOPH(usmopa, d)
127
diff --git a/tests/tcg/aarch64/sme-smopa-1.c b/tests/tcg/aarch64/sme-smopa-1.c
23
new file mode 100644
128
new file mode 100644
24
index XXXXXXX..XXXXXXX
129
index XXXXXXX..XXXXXXX
25
--- /dev/null
130
--- /dev/null
26
+++ b/tests/tcg/aarch64/bti-1.c
131
+++ b/tests/tcg/aarch64/sme-smopa-1.c
27
@@ -XXX,XX +XXX,XX @@
132
@@ -XXX,XX +XXX,XX @@
28
+/*
133
+#include <stdio.h>
29
+ * Branch target identification, basic notskip cases.
134
+#include <string.h>
30
+ */
31
+
32
+#include "bti-crt.inc.c"
33
+
34
+static void skip2_sigill(int sig, siginfo_t *info, ucontext_t *uc)
35
+{
36
+ uc->uc_mcontext.pc += 8;
37
+ uc->uc_mcontext.pstate = 1;
38
+}
39
+
40
+#define NOP "nop"
41
+#define BTI_N "hint #32"
42
+#define BTI_C "hint #34"
43
+#define BTI_J "hint #36"
44
+#define BTI_JC "hint #38"
45
+
46
+#define BTYPE_1(DEST) \
47
+ asm("mov %0,#1; adr x16, 1f; br x16; 1: " DEST "; mov %0,#0" \
48
+ : "=r"(skipped) : : "x16")
49
+
50
+#define BTYPE_2(DEST) \
51
+ asm("mov %0,#1; adr x16, 1f; blr x16; 1: " DEST "; mov %0,#0" \
52
+ : "=r"(skipped) : : "x16", "x30")
53
+
54
+#define BTYPE_3(DEST) \
55
+ asm("mov %0,#1; adr x15, 1f; br x15; 1: " DEST "; mov %0,#0" \
56
+ : "=r"(skipped) : : "x15")
57
+
58
+#define TEST(WHICH, DEST, EXPECT) \
59
+ do { WHICH(DEST); fail += skipped ^ EXPECT; } while (0)
60
+
61
+
135
+
62
+int main()
136
+int main()
63
+{
137
+{
64
+ int fail = 0;
138
+ static const int cmp[4][4] = {
65
+ int skipped;
139
+ { 110, 134, 158, 182 },
66
+
140
+ { 390, 478, 566, 654 },
67
+ /* Signal-like with SA_SIGINFO. */
141
+ { 670, 822, 974, 1126 },
68
+ signal_info(SIGILL, skip2_sigill);
142
+ { 950, 1166, 1382, 1598 }
69
+
143
+ };
70
+ TEST(BTYPE_1, NOP, 1);
144
+ int dst[4][4];
71
+ TEST(BTYPE_1, BTI_N, 1);
145
+ int *tmp = &dst[0][0];
72
+ TEST(BTYPE_1, BTI_C, 0);
146
+
73
+ TEST(BTYPE_1, BTI_J, 0);
147
+ asm volatile(
74
+ TEST(BTYPE_1, BTI_JC, 0);
148
+ ".arch armv8-r+sme\n\t"
75
+
149
+ "smstart\n\t"
76
+ TEST(BTYPE_2, NOP, 1);
150
+ "index z0.b, #0, #1\n\t"
77
+ TEST(BTYPE_2, BTI_N, 1);
151
+ "movprfx z1, z0\n\t"
78
+ TEST(BTYPE_2, BTI_C, 0);
152
+ "add z1.b, z1.b, #16\n\t"
79
+ TEST(BTYPE_2, BTI_J, 1);
153
+ "ptrue p0.b\n\t"
80
+ TEST(BTYPE_2, BTI_JC, 0);
154
+ "smopa za0.s, p0/m, p0/m, z0.b, z1.b\n\t"
81
+
155
+ "ptrue p0.s, vl4\n\t"
82
+ TEST(BTYPE_3, NOP, 1);
156
+ "mov w12, #0\n\t"
83
+ TEST(BTYPE_3, BTI_N, 1);
157
+ "st1w { za0h.s[w12, #0] }, p0, [%0]\n\t"
84
+ TEST(BTYPE_3, BTI_C, 1);
158
+ "add %0, %0, #16\n\t"
85
+ TEST(BTYPE_3, BTI_J, 0);
159
+ "st1w { za0h.s[w12, #1] }, p0, [%0]\n\t"
86
+ TEST(BTYPE_3, BTI_JC, 0);
160
+ "add %0, %0, #16\n\t"
87
+
161
+ "st1w { za0h.s[w12, #2] }, p0, [%0]\n\t"
88
+ return fail;
162
+ "add %0, %0, #16\n\t"
163
+ "st1w { za0h.s[w12, #3] }, p0, [%0]\n\t"
164
+ "smstop"
165
+ : "+r"(tmp) : : "memory");
166
+
167
+ if (memcmp(cmp, dst, sizeof(dst)) == 0) {
168
+ return 0;
169
+ }
170
+
171
+ /* See above for correct results. */
172
+ for (int i = 0; i < 4; ++i) {
173
+ for (int j = 0; j < 4; ++j) {
174
+ printf("%6d", dst[i][j]);
175
+ }
176
+ printf("\n");
177
+ }
178
+ return 1;
89
+}
179
+}
90
diff --git a/tests/tcg/aarch64/bti-2.c b/tests/tcg/aarch64/bti-2.c
180
diff --git a/tests/tcg/aarch64/sme-smopa-2.c b/tests/tcg/aarch64/sme-smopa-2.c
91
new file mode 100644
181
new file mode 100644
92
index XXXXXXX..XXXXXXX
182
index XXXXXXX..XXXXXXX
93
--- /dev/null
183
--- /dev/null
94
+++ b/tests/tcg/aarch64/bti-2.c
184
+++ b/tests/tcg/aarch64/sme-smopa-2.c
95
@@ -XXX,XX +XXX,XX @@
185
@@ -XXX,XX +XXX,XX @@
96
+/*
97
+ * Branch target identification, basic notskip cases.
98
+ */
99
+
100
+#include <stdio.h>
186
+#include <stdio.h>
101
+#include <signal.h>
102
+#include <string.h>
187
+#include <string.h>
103
+#include <unistd.h>
104
+#include <sys/mman.h>
105
+
106
+#ifndef PROT_BTI
107
+#define PROT_BTI 0x10
108
+#endif
109
+
110
+static void skip2_sigill(int sig, siginfo_t *info, void *vuc)
111
+{
112
+ ucontext_t *uc = vuc;
113
+ uc->uc_mcontext.pc += 8;
114
+ uc->uc_mcontext.pstate = 1;
115
+}
116
+
117
+#define NOP "nop"
118
+#define BTI_N "hint #32"
119
+#define BTI_C "hint #34"
120
+#define BTI_J "hint #36"
121
+#define BTI_JC "hint #38"
122
+
123
+#define BTYPE_1(DEST) \
124
+ "mov x1, #1\n\t" \
125
+ "adr x16, 1f\n\t" \
126
+ "br x16\n" \
127
+"1: " DEST "\n\t" \
128
+ "mov x1, #0"
129
+
130
+#define BTYPE_2(DEST) \
131
+ "mov x1, #1\n\t" \
132
+ "adr x16, 1f\n\t" \
133
+ "blr x16\n" \
134
+"1: " DEST "\n\t" \
135
+ "mov x1, #0"
136
+
137
+#define BTYPE_3(DEST) \
138
+ "mov x1, #1\n\t" \
139
+ "adr x15, 1f\n\t" \
140
+ "br x15\n" \
141
+"1: " DEST "\n\t" \
142
+ "mov x1, #0"
143
+
144
+#define TEST(WHICH, DEST, EXPECT) \
145
+ WHICH(DEST) "\n" \
146
+ ".if " #EXPECT "\n\t" \
147
+ "eor x1, x1," #EXPECT "\n" \
148
+ ".endif\n\t" \
149
+ "add x0, x0, x1\n\t"
150
+
151
+extern char test_begin[], test_end[];
152
+
153
+asm("\n"
154
+"test_begin:\n\t"
155
+ BTI_C "\n\t"
156
+ "mov x2, x30\n\t"
157
+ "mov x0, #0\n\t"
158
+
159
+ TEST(BTYPE_1, NOP, 1)
160
+ TEST(BTYPE_1, BTI_N, 1)
161
+ TEST(BTYPE_1, BTI_C, 0)
162
+ TEST(BTYPE_1, BTI_J, 0)
163
+ TEST(BTYPE_1, BTI_JC, 0)
164
+
165
+ TEST(BTYPE_2, NOP, 1)
166
+ TEST(BTYPE_2, BTI_N, 1)
167
+ TEST(BTYPE_2, BTI_C, 0)
168
+ TEST(BTYPE_2, BTI_J, 1)
169
+ TEST(BTYPE_2, BTI_JC, 0)
170
+
171
+ TEST(BTYPE_3, NOP, 1)
172
+ TEST(BTYPE_3, BTI_N, 1)
173
+ TEST(BTYPE_3, BTI_C, 1)
174
+ TEST(BTYPE_3, BTI_J, 0)
175
+ TEST(BTYPE_3, BTI_JC, 0)
176
+
177
+ "ret x2\n"
178
+"test_end:"
179
+);
180
+
188
+
181
+int main()
189
+int main()
182
+{
190
+{
183
+ struct sigaction sa;
191
+ static const long cmp[4][4] = {
184
+
192
+ { 110, 134, 158, 182 },
185
+ void *p = mmap(0, getpagesize(),
193
+ { 390, 478, 566, 654 },
186
+ PROT_EXEC | PROT_READ | PROT_WRITE | PROT_BTI,
194
+ { 670, 822, 974, 1126 },
187
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
195
+ { 950, 1166, 1382, 1598 }
188
+ if (p == MAP_FAILED) {
196
+ };
189
+ perror("mmap");
197
+ long dst[4][4];
190
+ return 1;
198
+ long *tmp = &dst[0][0];
191
+ }
199
+ long svl;
192
+
200
+
193
+ memset(&sa, 0, sizeof(sa));
201
+ /* Validate that we have a wide enough vector for 4 elements. */
194
+ sa.sa_sigaction = skip2_sigill;
202
+ asm(".arch armv8-r+sme-i64\n\trdsvl %0, #1" : "=r"(svl));
195
+ sa.sa_flags = SA_SIGINFO;
203
+ if (svl < 32) {
196
+ if (sigaction(SIGILL, &sa, NULL) < 0) {
204
+ return 0;
197
+ perror("sigaction");
205
+ }
198
+ return 1;
206
+
199
+ }
207
+ asm volatile(
200
+
208
+ "smstart\n\t"
201
+ memcpy(p, test_begin, test_end - test_begin);
209
+ "index z0.h, #0, #1\n\t"
202
+ return ((int (*)(void))p)();
210
+ "movprfx z1, z0\n\t"
203
+}
211
+ "add z1.h, z1.h, #16\n\t"
204
diff --git a/tests/tcg/aarch64/bti-crt.inc.c b/tests/tcg/aarch64/bti-crt.inc.c
212
+ "ptrue p0.b\n\t"
205
new file mode 100644
213
+ "smopa za0.d, p0/m, p0/m, z0.h, z1.h\n\t"
206
index XXXXXXX..XXXXXXX
214
+ "ptrue p0.d, vl4\n\t"
207
--- /dev/null
215
+ "mov w12, #0\n\t"
208
+++ b/tests/tcg/aarch64/bti-crt.inc.c
216
+ "st1d { za0h.d[w12, #0] }, p0, [%0]\n\t"
209
@@ -XXX,XX +XXX,XX @@
217
+ "add %0, %0, #32\n\t"
210
+/*
218
+ "st1d { za0h.d[w12, #1] }, p0, [%0]\n\t"
211
+ * Minimal user-environment for testing BTI.
219
+ "mov w12, #2\n\t"
212
+ *
220
+ "add %0, %0, #32\n\t"
213
+ * Normal libc is not (yet) built with BTI support enabled,
221
+ "st1d { za0h.d[w12, #0] }, p0, [%0]\n\t"
214
+ * and so could generate a BTI TRAP before ever reaching main.
222
+ "add %0, %0, #32\n\t"
215
+ */
223
+ "st1d { za0h.d[w12, #1] }, p0, [%0]\n\t"
216
+
224
+ "smstop"
217
+#include <stdlib.h>
225
+ : "+r"(tmp) : : "memory");
218
+#include <signal.h>
226
+
219
+#include <ucontext.h>
227
+ if (memcmp(cmp, dst, sizeof(dst)) == 0) {
220
+#include <asm/unistd.h>
228
+ return 0;
221
+
229
+ }
222
+int main(void);
230
+
223
+
231
+ /* See above for correct results. */
224
+void _start(void)
232
+ for (int i = 0; i < 4; ++i) {
225
+{
233
+ for (int j = 0; j < 4; ++j) {
226
+ exit(main());
234
+ printf("%6ld", dst[i][j]);
227
+}
235
+ }
228
+
236
+ printf("\n");
229
+void exit(int ret)
237
+ }
230
+{
238
+ return 1;
231
+ register int x0 __asm__("x0") = ret;
232
+ register int x8 __asm__("x8") = __NR_exit;
233
+
234
+ asm volatile("svc #0" : : "r"(x0), "r"(x8));
235
+ __builtin_unreachable();
236
+}
237
+
238
+/*
239
+ * Irritatingly, the user API struct sigaction does not match the
240
+ * kernel API struct sigaction. So for simplicity, isolate the
241
+ * kernel ABI here, and make this act like signal.
242
+ */
243
+void signal_info(int sig, void (*fn)(int, siginfo_t *, ucontext_t *))
244
+{
245
+ struct kernel_sigaction {
246
+ void (*handler)(int, siginfo_t *, ucontext_t *);
247
+ unsigned long flags;
248
+ unsigned long restorer;
249
+ unsigned long mask;
250
+ } sa = { fn, SA_SIGINFO, 0, 0 };
251
+
252
+ register int x0 __asm__("x0") = sig;
253
+ register void *x1 __asm__("x1") = &sa;
254
+ register void *x2 __asm__("x2") = 0;
255
+ register int x3 __asm__("x3") = sizeof(unsigned long);
256
+ register int x8 __asm__("x8") = __NR_rt_sigaction;
257
+
258
+ asm volatile("svc #0"
259
+ : : "r"(x0), "r"(x1), "r"(x2), "r"(x3), "r"(x8) : "memory");
260
+}
239
+}
261
diff --git a/tests/tcg/aarch64/Makefile.target b/tests/tcg/aarch64/Makefile.target
240
diff --git a/tests/tcg/aarch64/Makefile.target b/tests/tcg/aarch64/Makefile.target
262
index XXXXXXX..XXXXXXX 100644
241
index XXXXXXX..XXXXXXX 100644
263
--- a/tests/tcg/aarch64/Makefile.target
242
--- a/tests/tcg/aarch64/Makefile.target
264
+++ b/tests/tcg/aarch64/Makefile.target
243
+++ b/tests/tcg/aarch64/Makefile.target
265
@@ -XXX,XX +XXX,XX @@ run-pauth-%: QEMU_OPTS += -cpu max
244
@@ -XXX,XX +XXX,XX @@ endif
266
run-plugin-pauth-%: QEMU_OPTS += -cpu max
245
246
# SME Tests
247
ifneq ($(CROSS_AS_HAS_ARMV9_SME),)
248
-AARCH64_TESTS += sme-outprod1
249
+AARCH64_TESTS += sme-outprod1 sme-smopa-1 sme-smopa-2
267
endif
250
endif
268
251
269
+# BTI Tests
252
# System Registers Tests
270
+# bti-1 tests the elf notes, so we require special compiler support.
271
+ifneq ($(DOCKER_IMAGE)$(CROSS_CC_HAS_ARMV8_BTI),)
272
+AARCH64_TESTS += bti-1
273
+bti-1: CFLAGS += -mbranch-protection=standard
274
+bti-1: LDFLAGS += -nostdlib
275
+endif
276
+# bti-2 tests PROT_BTI, so no special compiler support required.
277
+AARCH64_TESTS += bti-2
278
+
279
# Semihosting smoke test for linux-user
280
AARCH64_TESTS += semihosting
281
run-semihosting: semihosting
282
diff --git a/tests/tcg/configure.sh b/tests/tcg/configure.sh
283
index XXXXXXX..XXXXXXX 100755
284
--- a/tests/tcg/configure.sh
285
+++ b/tests/tcg/configure.sh
286
@@ -XXX,XX +XXX,XX @@ for target in $target_list; do
287
-march=armv8.3-a -o $TMPE $TMPC; then
288
echo "CROSS_CC_HAS_ARMV8_3=y" >> $config_target_mak
289
fi
290
+ if do_compiler "$target_compiler" $target_compiler_cflags \
291
+ -mbranch-protection=standard -o $TMPE $TMPC; then
292
+ echo "CROSS_CC_HAS_ARMV8_BTI=y" >> $config_target_mak
293
+ fi
294
;;
295
esac
296
297
--
253
--
298
2.20.1
254
2.34.1
299
255
300
256
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
The sun4v RTC device model added under commit a0e893039cf2ce0 in 2016
2
was unfortunately added with a license of GPL-v3-or-later, which is
3
not compatible with other QEMU code which has a GPL-v2-only license.
2
4
3
This is a bit clearer than open-coding some of this
5
Relicense the code in the .c and the .h file to GPL-v2-or-later,
4
with a bare c string.
6
to make it compatible with the rest of QEMU.
5
7
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Cc: qemu-stable@nongnu.org
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Message-id: 20201016184207.786698-9-richard.henderson@linaro.org
10
Signed-off-by: Paolo Bonzini (for Red Hat) <pbonzini@redhat.com>
11
Signed-off-by: Artyom Tarasenko <atar4qemu@gmail.com>
12
Signed-off-by: Markus Armbruster <armbru@redhat.com>
13
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
14
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
15
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
16
Acked-by: Alex Bennée <alex.bennee@linaro.org>
17
Message-id: 20240223161300.938542-1-peter.maydell@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
19
---
11
linux-user/elfload.c | 37 ++++++++++++++++++++-----------------
20
include/hw/rtc/sun4v-rtc.h | 2 +-
12
1 file changed, 20 insertions(+), 17 deletions(-)
21
hw/rtc/sun4v-rtc.c | 2 +-
22
2 files changed, 2 insertions(+), 2 deletions(-)
13
23
14
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
24
diff --git a/include/hw/rtc/sun4v-rtc.h b/include/hw/rtc/sun4v-rtc.h
15
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
16
--- a/linux-user/elfload.c
26
--- a/include/hw/rtc/sun4v-rtc.h
17
+++ b/linux-user/elfload.c
27
+++ b/include/hw/rtc/sun4v-rtc.h
18
@@ -XXX,XX +XXX,XX @@
28
@@ -XXX,XX +XXX,XX @@
19
#include "qemu/guest-random.h"
29
*
20
#include "qemu/units.h"
30
* Copyright (c) 2016 Artyom Tarasenko
21
#include "qemu/selfmap.h"
31
*
22
+#include "qapi/error.h"
32
- * This code is licensed under the GNU GPL v3 or (at your option) any later
23
33
+ * This code is licensed under the GNU GPL v2 or (at your option) any later
24
#ifdef _ARCH_PPC64
34
* version.
25
#undef ARCH_DLINFO
35
*/
26
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
36
27
struct elf_phdr *phdr;
37
diff --git a/hw/rtc/sun4v-rtc.c b/hw/rtc/sun4v-rtc.c
28
abi_ulong load_addr, load_bias, loaddr, hiaddr, error;
38
index XXXXXXX..XXXXXXX 100644
29
int i, retval;
39
--- a/hw/rtc/sun4v-rtc.c
30
- const char *errmsg;
40
+++ b/hw/rtc/sun4v-rtc.c
31
+ Error *err = NULL;
41
@@ -XXX,XX +XXX,XX @@
32
42
*
33
/* First of all, some simple consistency checks */
43
* Copyright (c) 2016 Artyom Tarasenko
34
- errmsg = "Invalid ELF image for this architecture";
44
*
35
if (!elf_check_ident(ehdr)) {
45
- * This code is licensed under the GNU GPL v3 or (at your option) any later
36
+ error_setg(&err, "Invalid ELF image for this architecture");
46
+ * This code is licensed under the GNU GPL v2 or (at your option) any later
37
goto exit_errmsg;
47
* version.
38
}
48
*/
39
bswap_ehdr(ehdr);
40
if (!elf_check_ehdr(ehdr)) {
41
+ error_setg(&err, "Invalid ELF image for this architecture");
42
goto exit_errmsg;
43
}
44
45
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
46
g_autofree char *interp_name = NULL;
47
48
if (*pinterp_name) {
49
- errmsg = "Multiple PT_INTERP entries";
50
+ error_setg(&err, "Multiple PT_INTERP entries");
51
goto exit_errmsg;
52
}
53
+
54
interp_name = g_malloc(eppnt->p_filesz);
55
- if (!interp_name) {
56
- goto exit_perror;
57
- }
58
59
if (eppnt->p_offset + eppnt->p_filesz <= BPRM_BUF_SIZE) {
60
memcpy(interp_name, bprm_buf + eppnt->p_offset,
61
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
62
retval = pread(image_fd, interp_name, eppnt->p_filesz,
63
eppnt->p_offset);
64
if (retval != eppnt->p_filesz) {
65
- goto exit_perror;
66
+ goto exit_read;
67
}
68
}
69
if (interp_name[eppnt->p_filesz - 1] != 0) {
70
- errmsg = "Invalid PT_INTERP entry";
71
+ error_setg(&err, "Invalid PT_INTERP entry");
72
goto exit_errmsg;
73
}
74
*pinterp_name = g_steal_pointer(&interp_name);
75
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
76
(ehdr->e_type == ET_EXEC ? MAP_FIXED : 0),
77
-1, 0);
78
if (load_addr == -1) {
79
- goto exit_perror;
80
+ goto exit_mmap;
81
}
82
load_bias = load_addr - loaddr;
83
84
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
85
image_fd, eppnt->p_offset - vaddr_po);
86
87
if (error == -1) {
88
- goto exit_perror;
89
+ goto exit_mmap;
90
}
91
}
92
93
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
94
} else if (eppnt->p_type == PT_MIPS_ABIFLAGS) {
95
Mips_elf_abiflags_v0 abiflags;
96
if (eppnt->p_filesz < sizeof(Mips_elf_abiflags_v0)) {
97
- errmsg = "Invalid PT_MIPS_ABIFLAGS entry";
98
+ error_setg(&err, "Invalid PT_MIPS_ABIFLAGS entry");
99
goto exit_errmsg;
100
}
101
if (eppnt->p_offset + eppnt->p_filesz <= BPRM_BUF_SIZE) {
102
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
103
retval = pread(image_fd, &abiflags, sizeof(Mips_elf_abiflags_v0),
104
eppnt->p_offset);
105
if (retval != sizeof(Mips_elf_abiflags_v0)) {
106
- goto exit_perror;
107
+ goto exit_read;
108
}
109
}
110
bswap_mips_abiflags(&abiflags);
111
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
112
113
exit_read:
114
if (retval >= 0) {
115
- errmsg = "Incomplete read of file header";
116
- goto exit_errmsg;
117
+ error_setg(&err, "Incomplete read of file header");
118
+ } else {
119
+ error_setg_errno(&err, errno, "Error reading file header");
120
}
121
- exit_perror:
122
- errmsg = strerror(errno);
123
+ goto exit_errmsg;
124
+ exit_mmap:
125
+ error_setg_errno(&err, errno, "Error mapping file");
126
+ goto exit_errmsg;
127
exit_errmsg:
128
- fprintf(stderr, "%s: %s\n", image_name, errmsg);
129
+ error_reportf_err(err, "%s: ", image_name);
130
exit(-1);
131
}
132
49
133
--
50
--
134
2.20.1
51
2.34.1
135
52
136
53
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
From: Thomas Huth <thuth@redhat.com>
2
2
3
The IRQ values are defined few lines earlier, use them instead of
3
Move the code to a separate file so that we do not have to compile
4
the magic numbers.
4
it anymore if CONFIG_ARM_V7M is not set.
5
5
6
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Signed-off-by: Thomas Huth <thuth@redhat.com>
7
Message-id: 20201017180731.1165871-3-f4bug@amsat.org
7
Message-id: 20240308141051.536599-2-thuth@redhat.com
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
10
---
11
hw/intc/bcm2836_control.c | 8 ++++----
11
target/arm/tcg/cpu-v7m.c | 290 +++++++++++++++++++++++++++++++++++++
12
1 file changed, 4 insertions(+), 4 deletions(-)
12
target/arm/tcg/cpu32.c | 261 ---------------------------------
13
target/arm/meson.build | 3 +
14
target/arm/tcg/meson.build | 3 +
15
4 files changed, 296 insertions(+), 261 deletions(-)
16
create mode 100644 target/arm/tcg/cpu-v7m.c
13
17
14
diff --git a/hw/intc/bcm2836_control.c b/hw/intc/bcm2836_control.c
18
diff --git a/target/arm/tcg/cpu-v7m.c b/target/arm/tcg/cpu-v7m.c
19
new file mode 100644
20
index XXXXXXX..XXXXXXX
21
--- /dev/null
22
+++ b/target/arm/tcg/cpu-v7m.c
23
@@ -XXX,XX +XXX,XX @@
24
+/*
25
+ * QEMU ARMv7-M TCG-only CPUs.
26
+ *
27
+ * Copyright (c) 2012 SUSE LINUX Products GmbH
28
+ *
29
+ * This code is licensed under the GNU GPL v2 or later.
30
+ *
31
+ * SPDX-License-Identifier: GPL-2.0-or-later
32
+ */
33
+
34
+#include "qemu/osdep.h"
35
+#include "cpu.h"
36
+#include "hw/core/tcg-cpu-ops.h"
37
+#include "internals.h"
38
+
39
+#if !defined(CONFIG_USER_ONLY)
40
+
41
+#include "hw/intc/armv7m_nvic.h"
42
+
43
+static bool arm_v7m_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
44
+{
45
+ CPUClass *cc = CPU_GET_CLASS(cs);
46
+ ARMCPU *cpu = ARM_CPU(cs);
47
+ CPUARMState *env = &cpu->env;
48
+ bool ret = false;
49
+
50
+ /*
51
+ * ARMv7-M interrupt masking works differently than -A or -R.
52
+ * There is no FIQ/IRQ distinction. Instead of I and F bits
53
+ * masking FIQ and IRQ interrupts, an exception is taken only
54
+ * if it is higher priority than the current execution priority
55
+ * (which depends on state like BASEPRI, FAULTMASK and the
56
+ * currently active exception).
57
+ */
58
+ if (interrupt_request & CPU_INTERRUPT_HARD
59
+ && (armv7m_nvic_can_take_pending_exception(env->nvic))) {
60
+ cs->exception_index = EXCP_IRQ;
61
+ cc->tcg_ops->do_interrupt(cs);
62
+ ret = true;
63
+ }
64
+ return ret;
65
+}
66
+
67
+#endif /* !CONFIG_USER_ONLY */
68
+
69
+static void cortex_m0_initfn(Object *obj)
70
+{
71
+ ARMCPU *cpu = ARM_CPU(obj);
72
+ set_feature(&cpu->env, ARM_FEATURE_V6);
73
+ set_feature(&cpu->env, ARM_FEATURE_M);
74
+
75
+ cpu->midr = 0x410cc200;
76
+
77
+ /*
78
+ * These ID register values are not guest visible, because
79
+ * we do not implement the Main Extension. They must be set
80
+ * to values corresponding to the Cortex-M0's implemented
81
+ * features, because QEMU generally controls its emulation
82
+ * by looking at ID register fields. We use the same values as
83
+ * for the M3.
84
+ */
85
+ cpu->isar.id_pfr0 = 0x00000030;
86
+ cpu->isar.id_pfr1 = 0x00000200;
87
+ cpu->isar.id_dfr0 = 0x00100000;
88
+ cpu->id_afr0 = 0x00000000;
89
+ cpu->isar.id_mmfr0 = 0x00000030;
90
+ cpu->isar.id_mmfr1 = 0x00000000;
91
+ cpu->isar.id_mmfr2 = 0x00000000;
92
+ cpu->isar.id_mmfr3 = 0x00000000;
93
+ cpu->isar.id_isar0 = 0x01141110;
94
+ cpu->isar.id_isar1 = 0x02111000;
95
+ cpu->isar.id_isar2 = 0x21112231;
96
+ cpu->isar.id_isar3 = 0x01111110;
97
+ cpu->isar.id_isar4 = 0x01310102;
98
+ cpu->isar.id_isar5 = 0x00000000;
99
+ cpu->isar.id_isar6 = 0x00000000;
100
+}
101
+
102
+static void cortex_m3_initfn(Object *obj)
103
+{
104
+ ARMCPU *cpu = ARM_CPU(obj);
105
+ set_feature(&cpu->env, ARM_FEATURE_V7);
106
+ set_feature(&cpu->env, ARM_FEATURE_M);
107
+ set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
108
+ cpu->midr = 0x410fc231;
109
+ cpu->pmsav7_dregion = 8;
110
+ cpu->isar.id_pfr0 = 0x00000030;
111
+ cpu->isar.id_pfr1 = 0x00000200;
112
+ cpu->isar.id_dfr0 = 0x00100000;
113
+ cpu->id_afr0 = 0x00000000;
114
+ cpu->isar.id_mmfr0 = 0x00000030;
115
+ cpu->isar.id_mmfr1 = 0x00000000;
116
+ cpu->isar.id_mmfr2 = 0x00000000;
117
+ cpu->isar.id_mmfr3 = 0x00000000;
118
+ cpu->isar.id_isar0 = 0x01141110;
119
+ cpu->isar.id_isar1 = 0x02111000;
120
+ cpu->isar.id_isar2 = 0x21112231;
121
+ cpu->isar.id_isar3 = 0x01111110;
122
+ cpu->isar.id_isar4 = 0x01310102;
123
+ cpu->isar.id_isar5 = 0x00000000;
124
+ cpu->isar.id_isar6 = 0x00000000;
125
+}
126
+
127
+static void cortex_m4_initfn(Object *obj)
128
+{
129
+ ARMCPU *cpu = ARM_CPU(obj);
130
+
131
+ set_feature(&cpu->env, ARM_FEATURE_V7);
132
+ set_feature(&cpu->env, ARM_FEATURE_M);
133
+ set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
134
+ set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP);
135
+ cpu->midr = 0x410fc240; /* r0p0 */
136
+ cpu->pmsav7_dregion = 8;
137
+ cpu->isar.mvfr0 = 0x10110021;
138
+ cpu->isar.mvfr1 = 0x11000011;
139
+ cpu->isar.mvfr2 = 0x00000000;
140
+ cpu->isar.id_pfr0 = 0x00000030;
141
+ cpu->isar.id_pfr1 = 0x00000200;
142
+ cpu->isar.id_dfr0 = 0x00100000;
143
+ cpu->id_afr0 = 0x00000000;
144
+ cpu->isar.id_mmfr0 = 0x00000030;
145
+ cpu->isar.id_mmfr1 = 0x00000000;
146
+ cpu->isar.id_mmfr2 = 0x00000000;
147
+ cpu->isar.id_mmfr3 = 0x00000000;
148
+ cpu->isar.id_isar0 = 0x01141110;
149
+ cpu->isar.id_isar1 = 0x02111000;
150
+ cpu->isar.id_isar2 = 0x21112231;
151
+ cpu->isar.id_isar3 = 0x01111110;
152
+ cpu->isar.id_isar4 = 0x01310102;
153
+ cpu->isar.id_isar5 = 0x00000000;
154
+ cpu->isar.id_isar6 = 0x00000000;
155
+}
156
+
157
+static void cortex_m7_initfn(Object *obj)
158
+{
159
+ ARMCPU *cpu = ARM_CPU(obj);
160
+
161
+ set_feature(&cpu->env, ARM_FEATURE_V7);
162
+ set_feature(&cpu->env, ARM_FEATURE_M);
163
+ set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
164
+ set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP);
165
+ cpu->midr = 0x411fc272; /* r1p2 */
166
+ cpu->pmsav7_dregion = 8;
167
+ cpu->isar.mvfr0 = 0x10110221;
168
+ cpu->isar.mvfr1 = 0x12000011;
169
+ cpu->isar.mvfr2 = 0x00000040;
170
+ cpu->isar.id_pfr0 = 0x00000030;
171
+ cpu->isar.id_pfr1 = 0x00000200;
172
+ cpu->isar.id_dfr0 = 0x00100000;
173
+ cpu->id_afr0 = 0x00000000;
174
+ cpu->isar.id_mmfr0 = 0x00100030;
175
+ cpu->isar.id_mmfr1 = 0x00000000;
176
+ cpu->isar.id_mmfr2 = 0x01000000;
177
+ cpu->isar.id_mmfr3 = 0x00000000;
178
+ cpu->isar.id_isar0 = 0x01101110;
179
+ cpu->isar.id_isar1 = 0x02112000;
180
+ cpu->isar.id_isar2 = 0x20232231;
181
+ cpu->isar.id_isar3 = 0x01111131;
182
+ cpu->isar.id_isar4 = 0x01310132;
183
+ cpu->isar.id_isar5 = 0x00000000;
184
+ cpu->isar.id_isar6 = 0x00000000;
185
+}
186
+
187
+static void cortex_m33_initfn(Object *obj)
188
+{
189
+ ARMCPU *cpu = ARM_CPU(obj);
190
+
191
+ set_feature(&cpu->env, ARM_FEATURE_V8);
192
+ set_feature(&cpu->env, ARM_FEATURE_M);
193
+ set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
194
+ set_feature(&cpu->env, ARM_FEATURE_M_SECURITY);
195
+ set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP);
196
+ cpu->midr = 0x410fd213; /* r0p3 */
197
+ cpu->pmsav7_dregion = 16;
198
+ cpu->sau_sregion = 8;
199
+ cpu->isar.mvfr0 = 0x10110021;
200
+ cpu->isar.mvfr1 = 0x11000011;
201
+ cpu->isar.mvfr2 = 0x00000040;
202
+ cpu->isar.id_pfr0 = 0x00000030;
203
+ cpu->isar.id_pfr1 = 0x00000210;
204
+ cpu->isar.id_dfr0 = 0x00200000;
205
+ cpu->id_afr0 = 0x00000000;
206
+ cpu->isar.id_mmfr0 = 0x00101F40;
207
+ cpu->isar.id_mmfr1 = 0x00000000;
208
+ cpu->isar.id_mmfr2 = 0x01000000;
209
+ cpu->isar.id_mmfr3 = 0x00000000;
210
+ cpu->isar.id_isar0 = 0x01101110;
211
+ cpu->isar.id_isar1 = 0x02212000;
212
+ cpu->isar.id_isar2 = 0x20232232;
213
+ cpu->isar.id_isar3 = 0x01111131;
214
+ cpu->isar.id_isar4 = 0x01310132;
215
+ cpu->isar.id_isar5 = 0x00000000;
216
+ cpu->isar.id_isar6 = 0x00000000;
217
+ cpu->clidr = 0x00000000;
218
+ cpu->ctr = 0x8000c000;
219
+}
220
+
221
+static void cortex_m55_initfn(Object *obj)
222
+{
223
+ ARMCPU *cpu = ARM_CPU(obj);
224
+
225
+ set_feature(&cpu->env, ARM_FEATURE_V8);
226
+ set_feature(&cpu->env, ARM_FEATURE_V8_1M);
227
+ set_feature(&cpu->env, ARM_FEATURE_M);
228
+ set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
229
+ set_feature(&cpu->env, ARM_FEATURE_M_SECURITY);
230
+ set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP);
231
+ cpu->midr = 0x410fd221; /* r0p1 */
232
+ cpu->revidr = 0;
233
+ cpu->pmsav7_dregion = 16;
234
+ cpu->sau_sregion = 8;
235
+ /* These are the MVFR* values for the FPU + full MVE configuration */
236
+ cpu->isar.mvfr0 = 0x10110221;
237
+ cpu->isar.mvfr1 = 0x12100211;
238
+ cpu->isar.mvfr2 = 0x00000040;
239
+ cpu->isar.id_pfr0 = 0x20000030;
240
+ cpu->isar.id_pfr1 = 0x00000230;
241
+ cpu->isar.id_dfr0 = 0x10200000;
242
+ cpu->id_afr0 = 0x00000000;
243
+ cpu->isar.id_mmfr0 = 0x00111040;
244
+ cpu->isar.id_mmfr1 = 0x00000000;
245
+ cpu->isar.id_mmfr2 = 0x01000000;
246
+ cpu->isar.id_mmfr3 = 0x00000011;
247
+ cpu->isar.id_isar0 = 0x01103110;
248
+ cpu->isar.id_isar1 = 0x02212000;
249
+ cpu->isar.id_isar2 = 0x20232232;
250
+ cpu->isar.id_isar3 = 0x01111131;
251
+ cpu->isar.id_isar4 = 0x01310132;
252
+ cpu->isar.id_isar5 = 0x00000000;
253
+ cpu->isar.id_isar6 = 0x00000000;
254
+ cpu->clidr = 0x00000000; /* caches not implemented */
255
+ cpu->ctr = 0x8303c003;
256
+}
257
+
258
+static const TCGCPUOps arm_v7m_tcg_ops = {
259
+ .initialize = arm_translate_init,
260
+ .synchronize_from_tb = arm_cpu_synchronize_from_tb,
261
+ .debug_excp_handler = arm_debug_excp_handler,
262
+ .restore_state_to_opc = arm_restore_state_to_opc,
263
+
264
+#ifdef CONFIG_USER_ONLY
265
+ .record_sigsegv = arm_cpu_record_sigsegv,
266
+ .record_sigbus = arm_cpu_record_sigbus,
267
+#else
268
+ .tlb_fill = arm_cpu_tlb_fill,
269
+ .cpu_exec_interrupt = arm_v7m_cpu_exec_interrupt,
270
+ .do_interrupt = arm_v7m_cpu_do_interrupt,
271
+ .do_transaction_failed = arm_cpu_do_transaction_failed,
272
+ .do_unaligned_access = arm_cpu_do_unaligned_access,
273
+ .adjust_watchpoint_address = arm_adjust_watchpoint_address,
274
+ .debug_check_watchpoint = arm_debug_check_watchpoint,
275
+ .debug_check_breakpoint = arm_debug_check_breakpoint,
276
+#endif /* !CONFIG_USER_ONLY */
277
+};
278
+
279
+static void arm_v7m_class_init(ObjectClass *oc, void *data)
280
+{
281
+ ARMCPUClass *acc = ARM_CPU_CLASS(oc);
282
+ CPUClass *cc = CPU_CLASS(oc);
283
+
284
+ acc->info = data;
285
+ cc->tcg_ops = &arm_v7m_tcg_ops;
286
+ cc->gdb_core_xml_file = "arm-m-profile.xml";
287
+}
288
+
289
+static const ARMCPUInfo arm_v7m_cpus[] = {
290
+ { .name = "cortex-m0", .initfn = cortex_m0_initfn,
291
+ .class_init = arm_v7m_class_init },
292
+ { .name = "cortex-m3", .initfn = cortex_m3_initfn,
293
+ .class_init = arm_v7m_class_init },
294
+ { .name = "cortex-m4", .initfn = cortex_m4_initfn,
295
+ .class_init = arm_v7m_class_init },
296
+ { .name = "cortex-m7", .initfn = cortex_m7_initfn,
297
+ .class_init = arm_v7m_class_init },
298
+ { .name = "cortex-m33", .initfn = cortex_m33_initfn,
299
+ .class_init = arm_v7m_class_init },
300
+ { .name = "cortex-m55", .initfn = cortex_m55_initfn,
301
+ .class_init = arm_v7m_class_init },
302
+};
303
+
304
+static void arm_v7m_cpu_register_types(void)
305
+{
306
+ size_t i;
307
+
308
+ for (i = 0; i < ARRAY_SIZE(arm_v7m_cpus); ++i) {
309
+ arm_cpu_register(&arm_v7m_cpus[i]);
310
+ }
311
+}
312
+
313
+type_init(arm_v7m_cpu_register_types)
314
diff --git a/target/arm/tcg/cpu32.c b/target/arm/tcg/cpu32.c
15
index XXXXXXX..XXXXXXX 100644
315
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/intc/bcm2836_control.c
316
--- a/target/arm/tcg/cpu32.c
17
+++ b/hw/intc/bcm2836_control.c
317
+++ b/target/arm/tcg/cpu32.c
18
@@ -XXX,XX +XXX,XX @@ static void bcm2836_control_set_local_irq(void *opaque, int core, int local_irq,
318
@@ -XXX,XX +XXX,XX @@
19
319
#include "hw/boards.h"
20
static void bcm2836_control_set_local_irq0(void *opaque, int core, int level)
320
#endif
321
#include "cpregs.h"
322
-#if !defined(CONFIG_USER_ONLY) && defined(CONFIG_TCG)
323
-#include "hw/intc/armv7m_nvic.h"
324
-#endif
325
326
327
/* Share AArch32 -cpu max features with AArch64. */
328
@@ -XXX,XX +XXX,XX @@ void aa32_max_features(ARMCPU *cpu)
329
/* CPU models. These are not needed for the AArch64 linux-user build. */
330
#if !defined(CONFIG_USER_ONLY) || !defined(TARGET_AARCH64)
331
332
-#if !defined(CONFIG_USER_ONLY)
333
-static bool arm_v7m_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
334
-{
335
- CPUClass *cc = CPU_GET_CLASS(cs);
336
- ARMCPU *cpu = ARM_CPU(cs);
337
- CPUARMState *env = &cpu->env;
338
- bool ret = false;
339
-
340
- /*
341
- * ARMv7-M interrupt masking works differently than -A or -R.
342
- * There is no FIQ/IRQ distinction. Instead of I and F bits
343
- * masking FIQ and IRQ interrupts, an exception is taken only
344
- * if it is higher priority than the current execution priority
345
- * (which depends on state like BASEPRI, FAULTMASK and the
346
- * currently active exception).
347
- */
348
- if (interrupt_request & CPU_INTERRUPT_HARD
349
- && (armv7m_nvic_can_take_pending_exception(env->nvic))) {
350
- cs->exception_index = EXCP_IRQ;
351
- cc->tcg_ops->do_interrupt(cs);
352
- ret = true;
353
- }
354
- return ret;
355
-}
356
-#endif /* !CONFIG_USER_ONLY */
357
-
358
static void arm926_initfn(Object *obj)
21
{
359
{
22
- bcm2836_control_set_local_irq(opaque, core, 0, level);
360
ARMCPU *cpu = ARM_CPU(obj);
23
+ bcm2836_control_set_local_irq(opaque, core, IRQ_CNTPSIRQ, level);
361
@@ -XXX,XX +XXX,XX @@ static void cortex_a15_initfn(Object *obj)
362
define_arm_cp_regs(cpu, cortexa15_cp_reginfo);
24
}
363
}
25
364
26
static void bcm2836_control_set_local_irq1(void *opaque, int core, int level)
365
-static void cortex_m0_initfn(Object *obj)
27
{
366
-{
28
- bcm2836_control_set_local_irq(opaque, core, 1, level);
367
- ARMCPU *cpu = ARM_CPU(obj);
29
+ bcm2836_control_set_local_irq(opaque, core, IRQ_CNTPNSIRQ, level);
368
- set_feature(&cpu->env, ARM_FEATURE_V6);
369
- set_feature(&cpu->env, ARM_FEATURE_M);
370
-
371
- cpu->midr = 0x410cc200;
372
-
373
- /*
374
- * These ID register values are not guest visible, because
375
- * we do not implement the Main Extension. They must be set
376
- * to values corresponding to the Cortex-M0's implemented
377
- * features, because QEMU generally controls its emulation
378
- * by looking at ID register fields. We use the same values as
379
- * for the M3.
380
- */
381
- cpu->isar.id_pfr0 = 0x00000030;
382
- cpu->isar.id_pfr1 = 0x00000200;
383
- cpu->isar.id_dfr0 = 0x00100000;
384
- cpu->id_afr0 = 0x00000000;
385
- cpu->isar.id_mmfr0 = 0x00000030;
386
- cpu->isar.id_mmfr1 = 0x00000000;
387
- cpu->isar.id_mmfr2 = 0x00000000;
388
- cpu->isar.id_mmfr3 = 0x00000000;
389
- cpu->isar.id_isar0 = 0x01141110;
390
- cpu->isar.id_isar1 = 0x02111000;
391
- cpu->isar.id_isar2 = 0x21112231;
392
- cpu->isar.id_isar3 = 0x01111110;
393
- cpu->isar.id_isar4 = 0x01310102;
394
- cpu->isar.id_isar5 = 0x00000000;
395
- cpu->isar.id_isar6 = 0x00000000;
396
-}
397
-
398
-static void cortex_m3_initfn(Object *obj)
399
-{
400
- ARMCPU *cpu = ARM_CPU(obj);
401
- set_feature(&cpu->env, ARM_FEATURE_V7);
402
- set_feature(&cpu->env, ARM_FEATURE_M);
403
- set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
404
- cpu->midr = 0x410fc231;
405
- cpu->pmsav7_dregion = 8;
406
- cpu->isar.id_pfr0 = 0x00000030;
407
- cpu->isar.id_pfr1 = 0x00000200;
408
- cpu->isar.id_dfr0 = 0x00100000;
409
- cpu->id_afr0 = 0x00000000;
410
- cpu->isar.id_mmfr0 = 0x00000030;
411
- cpu->isar.id_mmfr1 = 0x00000000;
412
- cpu->isar.id_mmfr2 = 0x00000000;
413
- cpu->isar.id_mmfr3 = 0x00000000;
414
- cpu->isar.id_isar0 = 0x01141110;
415
- cpu->isar.id_isar1 = 0x02111000;
416
- cpu->isar.id_isar2 = 0x21112231;
417
- cpu->isar.id_isar3 = 0x01111110;
418
- cpu->isar.id_isar4 = 0x01310102;
419
- cpu->isar.id_isar5 = 0x00000000;
420
- cpu->isar.id_isar6 = 0x00000000;
421
-}
422
-
423
-static void cortex_m4_initfn(Object *obj)
424
-{
425
- ARMCPU *cpu = ARM_CPU(obj);
426
-
427
- set_feature(&cpu->env, ARM_FEATURE_V7);
428
- set_feature(&cpu->env, ARM_FEATURE_M);
429
- set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
430
- set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP);
431
- cpu->midr = 0x410fc240; /* r0p0 */
432
- cpu->pmsav7_dregion = 8;
433
- cpu->isar.mvfr0 = 0x10110021;
434
- cpu->isar.mvfr1 = 0x11000011;
435
- cpu->isar.mvfr2 = 0x00000000;
436
- cpu->isar.id_pfr0 = 0x00000030;
437
- cpu->isar.id_pfr1 = 0x00000200;
438
- cpu->isar.id_dfr0 = 0x00100000;
439
- cpu->id_afr0 = 0x00000000;
440
- cpu->isar.id_mmfr0 = 0x00000030;
441
- cpu->isar.id_mmfr1 = 0x00000000;
442
- cpu->isar.id_mmfr2 = 0x00000000;
443
- cpu->isar.id_mmfr3 = 0x00000000;
444
- cpu->isar.id_isar0 = 0x01141110;
445
- cpu->isar.id_isar1 = 0x02111000;
446
- cpu->isar.id_isar2 = 0x21112231;
447
- cpu->isar.id_isar3 = 0x01111110;
448
- cpu->isar.id_isar4 = 0x01310102;
449
- cpu->isar.id_isar5 = 0x00000000;
450
- cpu->isar.id_isar6 = 0x00000000;
451
-}
452
-
453
-static void cortex_m7_initfn(Object *obj)
454
-{
455
- ARMCPU *cpu = ARM_CPU(obj);
456
-
457
- set_feature(&cpu->env, ARM_FEATURE_V7);
458
- set_feature(&cpu->env, ARM_FEATURE_M);
459
- set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
460
- set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP);
461
- cpu->midr = 0x411fc272; /* r1p2 */
462
- cpu->pmsav7_dregion = 8;
463
- cpu->isar.mvfr0 = 0x10110221;
464
- cpu->isar.mvfr1 = 0x12000011;
465
- cpu->isar.mvfr2 = 0x00000040;
466
- cpu->isar.id_pfr0 = 0x00000030;
467
- cpu->isar.id_pfr1 = 0x00000200;
468
- cpu->isar.id_dfr0 = 0x00100000;
469
- cpu->id_afr0 = 0x00000000;
470
- cpu->isar.id_mmfr0 = 0x00100030;
471
- cpu->isar.id_mmfr1 = 0x00000000;
472
- cpu->isar.id_mmfr2 = 0x01000000;
473
- cpu->isar.id_mmfr3 = 0x00000000;
474
- cpu->isar.id_isar0 = 0x01101110;
475
- cpu->isar.id_isar1 = 0x02112000;
476
- cpu->isar.id_isar2 = 0x20232231;
477
- cpu->isar.id_isar3 = 0x01111131;
478
- cpu->isar.id_isar4 = 0x01310132;
479
- cpu->isar.id_isar5 = 0x00000000;
480
- cpu->isar.id_isar6 = 0x00000000;
481
-}
482
-
483
-static void cortex_m33_initfn(Object *obj)
484
-{
485
- ARMCPU *cpu = ARM_CPU(obj);
486
-
487
- set_feature(&cpu->env, ARM_FEATURE_V8);
488
- set_feature(&cpu->env, ARM_FEATURE_M);
489
- set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
490
- set_feature(&cpu->env, ARM_FEATURE_M_SECURITY);
491
- set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP);
492
- cpu->midr = 0x410fd213; /* r0p3 */
493
- cpu->pmsav7_dregion = 16;
494
- cpu->sau_sregion = 8;
495
- cpu->isar.mvfr0 = 0x10110021;
496
- cpu->isar.mvfr1 = 0x11000011;
497
- cpu->isar.mvfr2 = 0x00000040;
498
- cpu->isar.id_pfr0 = 0x00000030;
499
- cpu->isar.id_pfr1 = 0x00000210;
500
- cpu->isar.id_dfr0 = 0x00200000;
501
- cpu->id_afr0 = 0x00000000;
502
- cpu->isar.id_mmfr0 = 0x00101F40;
503
- cpu->isar.id_mmfr1 = 0x00000000;
504
- cpu->isar.id_mmfr2 = 0x01000000;
505
- cpu->isar.id_mmfr3 = 0x00000000;
506
- cpu->isar.id_isar0 = 0x01101110;
507
- cpu->isar.id_isar1 = 0x02212000;
508
- cpu->isar.id_isar2 = 0x20232232;
509
- cpu->isar.id_isar3 = 0x01111131;
510
- cpu->isar.id_isar4 = 0x01310132;
511
- cpu->isar.id_isar5 = 0x00000000;
512
- cpu->isar.id_isar6 = 0x00000000;
513
- cpu->clidr = 0x00000000;
514
- cpu->ctr = 0x8000c000;
515
-}
516
-
517
-static void cortex_m55_initfn(Object *obj)
518
-{
519
- ARMCPU *cpu = ARM_CPU(obj);
520
-
521
- set_feature(&cpu->env, ARM_FEATURE_V8);
522
- set_feature(&cpu->env, ARM_FEATURE_V8_1M);
523
- set_feature(&cpu->env, ARM_FEATURE_M);
524
- set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
525
- set_feature(&cpu->env, ARM_FEATURE_M_SECURITY);
526
- set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP);
527
- cpu->midr = 0x410fd221; /* r0p1 */
528
- cpu->revidr = 0;
529
- cpu->pmsav7_dregion = 16;
530
- cpu->sau_sregion = 8;
531
- /* These are the MVFR* values for the FPU + full MVE configuration */
532
- cpu->isar.mvfr0 = 0x10110221;
533
- cpu->isar.mvfr1 = 0x12100211;
534
- cpu->isar.mvfr2 = 0x00000040;
535
- cpu->isar.id_pfr0 = 0x20000030;
536
- cpu->isar.id_pfr1 = 0x00000230;
537
- cpu->isar.id_dfr0 = 0x10200000;
538
- cpu->id_afr0 = 0x00000000;
539
- cpu->isar.id_mmfr0 = 0x00111040;
540
- cpu->isar.id_mmfr1 = 0x00000000;
541
- cpu->isar.id_mmfr2 = 0x01000000;
542
- cpu->isar.id_mmfr3 = 0x00000011;
543
- cpu->isar.id_isar0 = 0x01103110;
544
- cpu->isar.id_isar1 = 0x02212000;
545
- cpu->isar.id_isar2 = 0x20232232;
546
- cpu->isar.id_isar3 = 0x01111131;
547
- cpu->isar.id_isar4 = 0x01310132;
548
- cpu->isar.id_isar5 = 0x00000000;
549
- cpu->isar.id_isar6 = 0x00000000;
550
- cpu->clidr = 0x00000000; /* caches not implemented */
551
- cpu->ctr = 0x8303c003;
552
-}
553
-
554
static const ARMCPRegInfo cortexr5_cp_reginfo[] = {
555
/* Dummy the TCM region regs for the moment */
556
{ .name = "ATCM", .cp = 15, .opc1 = 0, .crn = 9, .crm = 1, .opc2 = 0,
557
@@ -XXX,XX +XXX,XX @@ static void pxa270c5_initfn(Object *obj)
558
cpu->reset_sctlr = 0x00000078;
30
}
559
}
31
560
32
static void bcm2836_control_set_local_irq2(void *opaque, int core, int level)
561
-static const TCGCPUOps arm_v7m_tcg_ops = {
33
{
562
- .initialize = arm_translate_init,
34
- bcm2836_control_set_local_irq(opaque, core, 2, level);
563
- .synchronize_from_tb = arm_cpu_synchronize_from_tb,
35
+ bcm2836_control_set_local_irq(opaque, core, IRQ_CNTHPIRQ, level);
564
- .debug_excp_handler = arm_debug_excp_handler,
36
}
565
- .restore_state_to_opc = arm_restore_state_to_opc,
37
566
-
38
static void bcm2836_control_set_local_irq3(void *opaque, int core, int level)
567
-#ifdef CONFIG_USER_ONLY
39
{
568
- .record_sigsegv = arm_cpu_record_sigsegv,
40
- bcm2836_control_set_local_irq(opaque, core, 3, level);
569
- .record_sigbus = arm_cpu_record_sigbus,
41
+ bcm2836_control_set_local_irq(opaque, core, IRQ_CNTVIRQ, level);
570
-#else
42
}
571
- .tlb_fill = arm_cpu_tlb_fill,
43
572
- .cpu_exec_interrupt = arm_v7m_cpu_exec_interrupt,
44
static void bcm2836_control_set_gpu_irq(void *opaque, int irq, int level)
573
- .do_interrupt = arm_v7m_cpu_do_interrupt,
574
- .do_transaction_failed = arm_cpu_do_transaction_failed,
575
- .do_unaligned_access = arm_cpu_do_unaligned_access,
576
- .adjust_watchpoint_address = arm_adjust_watchpoint_address,
577
- .debug_check_watchpoint = arm_debug_check_watchpoint,
578
- .debug_check_breakpoint = arm_debug_check_breakpoint,
579
-#endif /* !CONFIG_USER_ONLY */
580
-};
581
-
582
-static void arm_v7m_class_init(ObjectClass *oc, void *data)
583
-{
584
- ARMCPUClass *acc = ARM_CPU_CLASS(oc);
585
- CPUClass *cc = CPU_CLASS(oc);
586
-
587
- acc->info = data;
588
- cc->tcg_ops = &arm_v7m_tcg_ops;
589
- cc->gdb_core_xml_file = "arm-m-profile.xml";
590
-}
591
-
592
#ifndef TARGET_AARCH64
593
/*
594
* -cpu max: a CPU with as many features enabled as our emulation supports.
595
@@ -XXX,XX +XXX,XX @@ static const ARMCPUInfo arm_tcg_cpus[] = {
596
{ .name = "cortex-a8", .initfn = cortex_a8_initfn },
597
{ .name = "cortex-a9", .initfn = cortex_a9_initfn },
598
{ .name = "cortex-a15", .initfn = cortex_a15_initfn },
599
- { .name = "cortex-m0", .initfn = cortex_m0_initfn,
600
- .class_init = arm_v7m_class_init },
601
- { .name = "cortex-m3", .initfn = cortex_m3_initfn,
602
- .class_init = arm_v7m_class_init },
603
- { .name = "cortex-m4", .initfn = cortex_m4_initfn,
604
- .class_init = arm_v7m_class_init },
605
- { .name = "cortex-m7", .initfn = cortex_m7_initfn,
606
- .class_init = arm_v7m_class_init },
607
- { .name = "cortex-m33", .initfn = cortex_m33_initfn,
608
- .class_init = arm_v7m_class_init },
609
- { .name = "cortex-m55", .initfn = cortex_m55_initfn,
610
- .class_init = arm_v7m_class_init },
611
{ .name = "cortex-r5", .initfn = cortex_r5_initfn },
612
{ .name = "cortex-r5f", .initfn = cortex_r5f_initfn },
613
{ .name = "cortex-r52", .initfn = cortex_r52_initfn },
614
diff --git a/target/arm/meson.build b/target/arm/meson.build
615
index XXXXXXX..XXXXXXX 100644
616
--- a/target/arm/meson.build
617
+++ b/target/arm/meson.build
618
@@ -XXX,XX +XXX,XX @@ arm_system_ss.add(files(
619
'ptw.c',
620
))
621
622
+arm_user_ss = ss.source_set()
623
+
624
subdir('hvf')
625
626
if 'CONFIG_TCG' in config_all_accel
627
@@ -XXX,XX +XXX,XX @@ endif
628
629
target_arch += {'arm': arm_ss}
630
target_system_arch += {'arm': arm_system_ss}
631
+target_user_arch += {'arm': arm_user_ss}
632
diff --git a/target/arm/tcg/meson.build b/target/arm/tcg/meson.build
633
index XXXXXXX..XXXXXXX 100644
634
--- a/target/arm/tcg/meson.build
635
+++ b/target/arm/tcg/meson.build
636
@@ -XXX,XX +XXX,XX @@ arm_ss.add(when: 'TARGET_AARCH64', if_true: files(
637
arm_system_ss.add(files(
638
'psci.c',
639
))
640
+
641
+arm_system_ss.add(when: 'CONFIG_ARM_V7M', if_true: files('cpu-v7m.c'))
642
+arm_user_ss.add(when: 'TARGET_AARCH64', if_false: files('cpu-v7m.c'))
45
--
643
--
46
2.20.1
644
2.34.1
47
48
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
We already have the full ARMMMUIdx as computed from the
4
function parameter.
5
6
For the purpose of regime_has_2_ranges, we can ignore any
7
difference between AccType_Normal and AccType_Unpriv, which
8
would be the only difference between the passed mmu_idx
9
and arm_mmu_idx_el.
10
11
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
12
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
13
Reviewed-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
14
Tested-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
15
Message-id: 20201008162155.161886-2-richard.henderson@linaro.org
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
---
18
target/arm/mte_helper.c | 3 +--
19
1 file changed, 1 insertion(+), 2 deletions(-)
20
21
diff --git a/target/arm/mte_helper.c b/target/arm/mte_helper.c
22
index XXXXXXX..XXXXXXX 100644
23
--- a/target/arm/mte_helper.c
24
+++ b/target/arm/mte_helper.c
25
@@ -XXX,XX +XXX,XX @@ static void mte_check_fail(CPUARMState *env, uint32_t desc,
26
27
case 2:
28
/* Tag check fail causes asynchronous flag set. */
29
- mmu_idx = arm_mmu_idx_el(env, el);
30
- if (regime_has_2_ranges(mmu_idx)) {
31
+ if (regime_has_2_ranges(arm_mmu_idx)) {
32
select = extract64(dirty_ptr, 55, 1);
33
} else {
34
select = 0;
35
--
36
2.20.1
37
38
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
The reporting in AArch64.TagCheckFail only depends on PSTATE.EL,
4
and not the AccType of the operation. There are two guest
5
visible problems that affect LDTR and STTR because of this:
6
7
(1) Selecting TCF0 vs TCF1 to decide on reporting,
8
(2) Report "data abort same el" not "data abort lower el".
9
10
Reported-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
11
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
12
Reviewed-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
13
Tested-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
14
Message-id: 20201008162155.161886-3-richard.henderson@linaro.org
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
---
17
target/arm/mte_helper.c | 10 +++-------
18
1 file changed, 3 insertions(+), 7 deletions(-)
19
20
diff --git a/target/arm/mte_helper.c b/target/arm/mte_helper.c
21
index XXXXXXX..XXXXXXX 100644
22
--- a/target/arm/mte_helper.c
23
+++ b/target/arm/mte_helper.c
24
@@ -XXX,XX +XXX,XX @@ static void mte_check_fail(CPUARMState *env, uint32_t desc,
25
reg_el = regime_el(env, arm_mmu_idx);
26
sctlr = env->cp15.sctlr_el[reg_el];
27
28
- switch (arm_mmu_idx) {
29
- case ARMMMUIdx_E10_0:
30
- case ARMMMUIdx_E20_0:
31
- el = 0;
32
+ el = arm_current_el(env);
33
+ if (el == 0) {
34
tcf = extract64(sctlr, 38, 2);
35
- break;
36
- default:
37
- el = reg_el;
38
+ } else {
39
tcf = extract64(sctlr, 40, 2);
40
}
41
42
--
43
2.20.1
44
45
diff view generated by jsdifflib
Deleted patch
1
From: Peng Liang <liangpeng10@huawei.com>
2
1
3
VMStateDescription.fields should be end with VMSTATE_END_OF_LIST().
4
However, microbit_i2c_vmstate doesn't follow it. Let's change it.
5
6
Fixes: 9d68bf564e ("arm: Stub out NRF51 TWI magnetometer/accelerometer detection")
7
Reported-by: Euler Robot <euler.robot@huawei.com>
8
Signed-off-by: Peng Liang <liangpeng10@huawei.com>
9
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
10
Message-id: 20201019093401.2993833-1-liangpeng10@huawei.com
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
13
hw/i2c/microbit_i2c.c | 1 +
14
1 file changed, 1 insertion(+)
15
16
diff --git a/hw/i2c/microbit_i2c.c b/hw/i2c/microbit_i2c.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/i2c/microbit_i2c.c
19
+++ b/hw/i2c/microbit_i2c.c
20
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription microbit_i2c_vmstate = {
21
.fields = (VMStateField[]) {
22
VMSTATE_UINT32_ARRAY(regs, MicrobitI2CState, MICROBIT_I2C_NREGS),
23
VMSTATE_UINT32(read_idx, MicrobitI2CState),
24
+ VMSTATE_END_OF_LIST()
25
},
26
};
27
28
--
29
2.20.1
30
31
diff view generated by jsdifflib
Deleted patch
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
1
3
Commit 7998beb9c2e removed the ram_size initialization in the
4
arm_boot_info structure, however it is used by arm_load_kernel().
5
6
Initialize the field to fix:
7
8
$ qemu-system-arm -M n800 -append 'console=ttyS1' \
9
-kernel meego-arm-n8x0-1.0.80.20100712.1431-vmlinuz-2.6.35~rc4-129.1-n8x0
10
qemu-system-arm: kernel 'meego-arm-n8x0-1.0.80.20100712.1431-vmlinuz-2.6.35~rc4-129.1-n8x0' is too large to fit in RAM (kernel size 1964608, RAM size 0)
11
12
Noticed while running the test introduced in commit 050a82f0c5b
13
("tests/acceptance: Add a test for the N800 and N810 arm machines").
14
15
Fixes: 7998beb9c2e ("arm/nseries: use memdev for RAM")
16
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
17
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
18
Tested-by: Thomas Huth <thuth@redhat.com>
19
Message-id: 20201019095148.1602119-1-f4bug@amsat.org
20
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
---
22
hw/arm/nseries.c | 1 +
23
1 file changed, 1 insertion(+)
24
25
diff --git a/hw/arm/nseries.c b/hw/arm/nseries.c
26
index XXXXXXX..XXXXXXX 100644
27
--- a/hw/arm/nseries.c
28
+++ b/hw/arm/nseries.c
29
@@ -XXX,XX +XXX,XX @@ static void n8x0_init(MachineState *machine,
30
g_free(sz);
31
exit(EXIT_FAILURE);
32
}
33
+ binfo->ram_size = machine->ram_size;
34
35
memory_region_add_subregion(get_system_memory(), OMAP2_Q2_BASE,
36
machine->ram);
37
--
38
2.20.1
39
40
diff view generated by jsdifflib
Deleted patch
1
For nested groups like:
2
1
3
{
4
[
5
pattern 1
6
pattern 2
7
]
8
pattern 3
9
}
10
11
the intended behaviour is that patterns 1 and 2 must not
12
overlap with each other; if the insn matches neither then
13
we fall through to pattern 3 as the next thing in the
14
outer overlapping group.
15
16
Currently we generate incorrect code for this situation,
17
because in the code path for a failed match inside the
18
inner non-overlapping group we generate a "return" statement,
19
which causes decode to stop entirely rather than continuing
20
to the next thing in the outer group.
21
22
Generate a "break" instead, so that decode flow behaves
23
as required for this nested group case.
24
25
Suggested-by: Richard Henderson <richard.henderson@linaro.org>
26
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
27
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
28
Message-id: 20201019151301.2046-2-peter.maydell@linaro.org
29
---
30
scripts/decodetree.py | 2 +-
31
1 file changed, 1 insertion(+), 1 deletion(-)
32
33
diff --git a/scripts/decodetree.py b/scripts/decodetree.py
34
index XXXXXXX..XXXXXXX 100644
35
--- a/scripts/decodetree.py
36
+++ b/scripts/decodetree.py
37
@@ -XXX,XX +XXX,XX @@ class Tree:
38
output(ind, ' /* ',
39
str_match_bits(innerbits, innermask), ' */\n')
40
s.output_code(i + 4, extracted, innerbits, innermask)
41
- output(ind, ' return false;\n')
42
+ output(ind, ' break;\n')
43
output(ind, '}\n')
44
# end Tree
45
46
--
47
2.20.1
48
49
diff view generated by jsdifflib
Deleted patch
1
v8.1M brings four new insns to M-profile:
2
* CSEL : Rd = cond ? Rn : Rm
3
* CSINC : Rd = cond ? Rn : Rm+1
4
* CSINV : Rd = cond ? Rn : ~Rm
5
* CSNEG : Rd = cond ? Rn : -Rm
6
1
7
Implement these.
8
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Message-id: 20201019151301.2046-4-peter.maydell@linaro.org
12
---
13
target/arm/t32.decode | 3 +++
14
target/arm/translate.c | 60 ++++++++++++++++++++++++++++++++++++++++++
15
2 files changed, 63 insertions(+)
16
17
diff --git a/target/arm/t32.decode b/target/arm/t32.decode
18
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/t32.decode
20
+++ b/target/arm/t32.decode
21
@@ -XXX,XX +XXX,XX @@ SBC_rrri 1110101 1011 . .... 0 ... .... .... .... @s_rrr_shi
22
}
23
RSB_rrri 1110101 1110 . .... 0 ... .... .... .... @s_rrr_shi
24
25
+# v8.1M CSEL and friends
26
+CSEL 1110101 0010 1 rn:4 10 op:2 rd:4 fcond:4 rm:4
27
+
28
# Data-processing (register-shifted register)
29
30
MOV_rxrr 1111 1010 0 shty:2 s:1 rm:4 1111 rd:4 0000 rs:4 \
31
diff --git a/target/arm/translate.c b/target/arm/translate.c
32
index XXXXXXX..XXXXXXX 100644
33
--- a/target/arm/translate.c
34
+++ b/target/arm/translate.c
35
@@ -XXX,XX +XXX,XX @@ static bool trans_IT(DisasContext *s, arg_IT *a)
36
return true;
37
}
38
39
+/* v8.1M CSEL/CSINC/CSNEG/CSINV */
40
+static bool trans_CSEL(DisasContext *s, arg_CSEL *a)
41
+{
42
+ TCGv_i32 rn, rm, zero;
43
+ DisasCompare c;
44
+
45
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
46
+ return false;
47
+ }
48
+
49
+ if (a->rm == 13) {
50
+ /* SEE "Related encodings" (MVE shifts) */
51
+ return false;
52
+ }
53
+
54
+ if (a->rd == 13 || a->rd == 15 || a->rn == 13 || a->fcond >= 14) {
55
+ /* CONSTRAINED UNPREDICTABLE: we choose to UNDEF */
56
+ return false;
57
+ }
58
+
59
+ /* In this insn input reg fields of 0b1111 mean "zero", not "PC" */
60
+ if (a->rn == 15) {
61
+ rn = tcg_const_i32(0);
62
+ } else {
63
+ rn = load_reg(s, a->rn);
64
+ }
65
+ if (a->rm == 15) {
66
+ rm = tcg_const_i32(0);
67
+ } else {
68
+ rm = load_reg(s, a->rm);
69
+ }
70
+
71
+ switch (a->op) {
72
+ case 0: /* CSEL */
73
+ break;
74
+ case 1: /* CSINC */
75
+ tcg_gen_addi_i32(rm, rm, 1);
76
+ break;
77
+ case 2: /* CSINV */
78
+ tcg_gen_not_i32(rm, rm);
79
+ break;
80
+ case 3: /* CSNEG */
81
+ tcg_gen_neg_i32(rm, rm);
82
+ break;
83
+ default:
84
+ g_assert_not_reached();
85
+ }
86
+
87
+ arm_test_cc(&c, a->fcond);
88
+ zero = tcg_const_i32(0);
89
+ tcg_gen_movcond_i32(c.cond, rn, c.value, zero, rn, rm);
90
+ arm_free_cc(&c);
91
+ tcg_temp_free_i32(zero);
92
+
93
+ store_reg(s, a->rd, rn);
94
+ tcg_temp_free_i32(rm);
95
+
96
+ return true;
97
+}
98
+
99
/*
100
* Legacy decoder.
101
*/
102
--
103
2.20.1
104
105
diff view generated by jsdifflib
Deleted patch
1
The t32 decode has a group which represents a set of insns
2
which overlap with B_cond_thumb because they have [25:23]=111
3
(which is an invalid condition code field for the branch insn).
4
This group is currently defined using the {} overlap-OK syntax,
5
but it is almost entirely non-overlapping patterns. Switch
6
it over to use a non-overlapping group.
7
1
8
For this to be valid syntactically, CPS must move into the same
9
overlapping-group as the hint insns (CPS vs hints was the
10
only actual use of the overlap facility for the group).
11
12
The non-overlapping subgroup for CLREX/DSB/DMB/ISB/SB is no longer
13
necessary and so we can remove it (promoting those insns to
14
be members of the parent group).
15
16
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
Message-id: 20201019151301.2046-5-peter.maydell@linaro.org
19
---
20
target/arm/t32.decode | 26 ++++++++++++--------------
21
1 file changed, 12 insertions(+), 14 deletions(-)
22
23
diff --git a/target/arm/t32.decode b/target/arm/t32.decode
24
index XXXXXXX..XXXXXXX 100644
25
--- a/target/arm/t32.decode
26
+++ b/target/arm/t32.decode
27
@@ -XXX,XX +XXX,XX @@ CLZ 1111 1010 1011 ---- 1111 .... 1000 .... @rdm
28
{
29
# Group insn[25:23] = 111, which is cond=111x for the branch below,
30
# or unconditional, which would be illegal for the branch.
31
- {
32
- # Hints
33
+ [
34
+ # Hints, and CPS
35
{
36
YIELD 1111 0011 1010 1111 1000 0000 0000 0001
37
WFE 1111 0011 1010 1111 1000 0000 0000 0010
38
@@ -XXX,XX +XXX,XX @@ CLZ 1111 1010 1011 ---- 1111 .... 1000 .... @rdm
39
# The canonical nop ends in 0000 0000, but the whole rest
40
# of the space is "reserved hint, behaves as nop".
41
NOP 1111 0011 1010 1111 1000 0000 ---- ----
42
+
43
+ # If imod == '00' && M == '0' then SEE "Hint instructions", above.
44
+ CPS 1111 0011 1010 1111 1000 0 imod:2 M:1 A:1 I:1 F:1 mode:5 \
45
+ &cps
46
}
47
48
- # If imod == '00' && M == '0' then SEE "Hint instructions", above.
49
- CPS 1111 0011 1010 1111 1000 0 imod:2 M:1 A:1 I:1 F:1 mode:5 \
50
- &cps
51
-
52
# Miscellaneous control
53
- [
54
- CLREX 1111 0011 1011 1111 1000 1111 0010 1111
55
- DSB 1111 0011 1011 1111 1000 1111 0100 ----
56
- DMB 1111 0011 1011 1111 1000 1111 0101 ----
57
- ISB 1111 0011 1011 1111 1000 1111 0110 ----
58
- SB 1111 0011 1011 1111 1000 1111 0111 0000
59
- ]
60
+ CLREX 1111 0011 1011 1111 1000 1111 0010 1111
61
+ DSB 1111 0011 1011 1111 1000 1111 0100 ----
62
+ DMB 1111 0011 1011 1111 1000 1111 0101 ----
63
+ ISB 1111 0011 1011 1111 1000 1111 0110 ----
64
+ SB 1111 0011 1011 1111 1000 1111 0111 0000
65
66
# Note that the v7m insn overlaps both the normal and banked insn.
67
{
68
@@ -XXX,XX +XXX,XX @@ CLZ 1111 1010 1011 ---- 1111 .... 1000 .... @rdm
69
HVC 1111 0111 1110 .... 1000 .... .... .... \
70
&i imm=%imm16_16_0
71
UDF 1111 0111 1111 ---- 1010 ---- ---- ----
72
- }
73
+ ]
74
B_cond_thumb 1111 0. cond:4 ...... 10.0 ............ &ci imm=%imm21
75
}
76
77
--
78
2.20.1
79
80
diff view generated by jsdifflib
Deleted patch
1
The BLX immediate insn in the Thumb encoding always performs
2
a switch from Thumb to Arm state. This would be totally useless
3
in M-profile which has no Arm decoder, and so the instruction
4
does not exist at all there. Make the encoding UNDEF for M-profile.
5
1
6
(This part of the encoding space is used for the branch-future
7
and low-overhead-loop insns in v8.1M.)
8
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Message-id: 20201019151301.2046-6-peter.maydell@linaro.org
12
---
13
target/arm/translate.c | 8 ++++++++
14
1 file changed, 8 insertions(+)
15
16
diff --git a/target/arm/translate.c b/target/arm/translate.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/translate.c
19
+++ b/target/arm/translate.c
20
@@ -XXX,XX +XXX,XX @@ static bool trans_BLX_i(DisasContext *s, arg_BLX_i *a)
21
{
22
TCGv_i32 tmp;
23
24
+ /*
25
+ * BLX <imm> would be useless on M-profile; the encoding space
26
+ * is used for other insns from v8.1M onward, and UNDEFs before that.
27
+ */
28
+ if (arm_dc_feature(s, ARM_FEATURE_M)) {
29
+ return false;
30
+ }
31
+
32
/* For A32, ARM_FEATURE_V5 is checked near the start of the uncond block. */
33
if (s->thumb && (a->imm & 2)) {
34
return false;
35
--
36
2.20.1
37
38
diff view generated by jsdifflib
Deleted patch
1
In arm_cpu_realizefn(), if the CPU has VFP or Neon disabled then we
2
squash the ID register fields so that we don't advertise it to the
3
guest. This code was written for A-profile and needs some tweaks to
4
work correctly on M-profile:
5
1
6
* A-profile only fields should not be zeroed on M-profile:
7
- MVFR0.FPSHVEC,FPTRAP
8
- MVFR1.SIMDLS,SIMDINT,SIMDSP,SIMDHP
9
- MVFR2.SIMDMISC
10
* M-profile only fields should be zeroed on M-profile:
11
- MVFR1.FP16
12
13
In particular, because MVFR1.SIMDHP on A-profile is the same field as
14
MVFR1.FP16 on M-profile this code was incorrectly disabling FP16
15
support on an M-profile CPU (where has_neon is always false). This
16
isn't a visible bug yet because we don't have any M-profile CPUs with
17
FP16 support, but the change is necessary before we introduce any.
18
19
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
20
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
Message-id: 20201019151301.2046-9-peter.maydell@linaro.org
22
---
23
target/arm/cpu.c | 29 ++++++++++++++++++-----------
24
1 file changed, 18 insertions(+), 11 deletions(-)
25
26
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
27
index XXXXXXX..XXXXXXX 100644
28
--- a/target/arm/cpu.c
29
+++ b/target/arm/cpu.c
30
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
31
u = cpu->isar.mvfr0;
32
u = FIELD_DP32(u, MVFR0, FPSP, 0);
33
u = FIELD_DP32(u, MVFR0, FPDP, 0);
34
- u = FIELD_DP32(u, MVFR0, FPTRAP, 0);
35
u = FIELD_DP32(u, MVFR0, FPDIVIDE, 0);
36
u = FIELD_DP32(u, MVFR0, FPSQRT, 0);
37
- u = FIELD_DP32(u, MVFR0, FPSHVEC, 0);
38
u = FIELD_DP32(u, MVFR0, FPROUND, 0);
39
+ if (!arm_feature(env, ARM_FEATURE_M)) {
40
+ u = FIELD_DP32(u, MVFR0, FPTRAP, 0);
41
+ u = FIELD_DP32(u, MVFR0, FPSHVEC, 0);
42
+ }
43
cpu->isar.mvfr0 = u;
44
45
u = cpu->isar.mvfr1;
46
u = FIELD_DP32(u, MVFR1, FPFTZ, 0);
47
u = FIELD_DP32(u, MVFR1, FPDNAN, 0);
48
u = FIELD_DP32(u, MVFR1, FPHP, 0);
49
+ if (arm_feature(env, ARM_FEATURE_M)) {
50
+ u = FIELD_DP32(u, MVFR1, FP16, 0);
51
+ }
52
cpu->isar.mvfr1 = u;
53
54
u = cpu->isar.mvfr2;
55
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
56
u = FIELD_DP32(u, ID_ISAR6, FHM, 0);
57
cpu->isar.id_isar6 = u;
58
59
- u = cpu->isar.mvfr1;
60
- u = FIELD_DP32(u, MVFR1, SIMDLS, 0);
61
- u = FIELD_DP32(u, MVFR1, SIMDINT, 0);
62
- u = FIELD_DP32(u, MVFR1, SIMDSP, 0);
63
- u = FIELD_DP32(u, MVFR1, SIMDHP, 0);
64
- cpu->isar.mvfr1 = u;
65
+ if (!arm_feature(env, ARM_FEATURE_M)) {
66
+ u = cpu->isar.mvfr1;
67
+ u = FIELD_DP32(u, MVFR1, SIMDLS, 0);
68
+ u = FIELD_DP32(u, MVFR1, SIMDINT, 0);
69
+ u = FIELD_DP32(u, MVFR1, SIMDSP, 0);
70
+ u = FIELD_DP32(u, MVFR1, SIMDHP, 0);
71
+ cpu->isar.mvfr1 = u;
72
73
- u = cpu->isar.mvfr2;
74
- u = FIELD_DP32(u, MVFR2, SIMDMISC, 0);
75
- cpu->isar.mvfr2 = u;
76
+ u = cpu->isar.mvfr2;
77
+ u = FIELD_DP32(u, MVFR2, SIMDMISC, 0);
78
+ cpu->isar.mvfr2 = u;
79
+ }
80
}
81
82
if (!cpu->has_neon && !cpu->has_vfp) {
83
--
84
2.20.1
85
86
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
The kernel sets btype for the signal handler as if for a call.
4
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20201016184207.786698-2-richard.henderson@linaro.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
linux-user/aarch64/signal.c | 10 ++++++++--
11
1 file changed, 8 insertions(+), 2 deletions(-)
12
13
diff --git a/linux-user/aarch64/signal.c b/linux-user/aarch64/signal.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/linux-user/aarch64/signal.c
16
+++ b/linux-user/aarch64/signal.c
17
@@ -XXX,XX +XXX,XX @@ static void target_setup_frame(int usig, struct target_sigaction *ka,
18
+ offsetof(struct target_rt_frame_record, tramp);
19
}
20
env->xregs[0] = usig;
21
- env->xregs[31] = frame_addr;
22
env->xregs[29] = frame_addr + fr_ofs;
23
- env->pc = ka->_sa_handler;
24
env->xregs[30] = return_addr;
25
+ env->xregs[31] = frame_addr;
26
+ env->pc = ka->_sa_handler;
27
+
28
+ /* Invoke the signal handler as if by indirect call. */
29
+ if (cpu_isar_feature(aa64_bti, env_archcpu(env))) {
30
+ env->btype = 2;
31
+ }
32
+
33
if (info) {
34
tswap_siginfo(&frame->info, info);
35
env->xregs[1] = frame_addr + offsetof(struct target_rt_sigframe, info);
36
--
37
2.20.1
38
39
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
Transform the prot bit to a qemu internal page bit, and save
4
it in the page tables.
5
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20201016184207.786698-3-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
include/exec/cpu-all.h | 2 ++
12
linux-user/syscall_defs.h | 4 ++++
13
target/arm/cpu.h | 5 +++++
14
linux-user/mmap.c | 16 ++++++++++++++++
15
target/arm/translate-a64.c | 6 +++---
16
5 files changed, 30 insertions(+), 3 deletions(-)
17
18
diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h
19
index XXXXXXX..XXXXXXX 100644
20
--- a/include/exec/cpu-all.h
21
+++ b/include/exec/cpu-all.h
22
@@ -XXX,XX +XXX,XX @@ extern intptr_t qemu_host_page_mask;
23
/* FIXME: Code that sets/uses this is broken and needs to go away. */
24
#define PAGE_RESERVED 0x0020
25
#endif
26
+/* Target-specific bits that will be used via page_get_flags(). */
27
+#define PAGE_TARGET_1 0x0080
28
29
#if defined(CONFIG_USER_ONLY)
30
void page_dump(FILE *f);
31
diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
32
index XXXXXXX..XXXXXXX 100644
33
--- a/linux-user/syscall_defs.h
34
+++ b/linux-user/syscall_defs.h
35
@@ -XXX,XX +XXX,XX @@ struct target_winsize {
36
#define TARGET_PROT_SEM 0x08
37
#endif
38
39
+#ifdef TARGET_AARCH64
40
+#define TARGET_PROT_BTI 0x10
41
+#endif
42
+
43
/* Common */
44
#define TARGET_MAP_SHARED    0x01        /* Share changes */
45
#define TARGET_MAP_PRIVATE    0x02        /* Changes are private */
46
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
47
index XXXXXXX..XXXXXXX 100644
48
--- a/target/arm/cpu.h
49
+++ b/target/arm/cpu.h
50
@@ -XXX,XX +XXX,XX @@ static inline MemTxAttrs *typecheck_memtxattrs(MemTxAttrs *x)
51
#define arm_tlb_bti_gp(x) (typecheck_memtxattrs(x)->target_tlb_bit0)
52
#define arm_tlb_mte_tagged(x) (typecheck_memtxattrs(x)->target_tlb_bit1)
53
54
+/*
55
+ * AArch64 usage of the PAGE_TARGET_* bits for linux-user.
56
+ */
57
+#define PAGE_BTI PAGE_TARGET_1
58
+
59
/*
60
* Naming convention for isar_feature functions:
61
* Functions which test 32-bit ID registers should have _aa32_ in
62
diff --git a/linux-user/mmap.c b/linux-user/mmap.c
63
index XXXXXXX..XXXXXXX 100644
64
--- a/linux-user/mmap.c
65
+++ b/linux-user/mmap.c
66
@@ -XXX,XX +XXX,XX @@ static int validate_prot_to_pageflags(int *host_prot, int prot)
67
*host_prot = (prot & (PROT_READ | PROT_WRITE))
68
| (prot & PROT_EXEC ? PROT_READ : 0);
69
70
+#ifdef TARGET_AARCH64
71
+ /*
72
+ * The PROT_BTI bit is only accepted if the cpu supports the feature.
73
+ * Since this is the unusual case, don't bother checking unless
74
+ * the bit has been requested. If set and valid, record the bit
75
+ * within QEMU's page_flags.
76
+ */
77
+ if (prot & TARGET_PROT_BTI) {
78
+ ARMCPU *cpu = ARM_CPU(thread_cpu);
79
+ if (cpu_isar_feature(aa64_bti, cpu)) {
80
+ valid |= TARGET_PROT_BTI;
81
+ page_flags |= PAGE_BTI;
82
+ }
83
+ }
84
+#endif
85
+
86
return prot & ~valid ? 0 : page_flags;
87
}
88
89
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
90
index XXXXXXX..XXXXXXX 100644
91
--- a/target/arm/translate-a64.c
92
+++ b/target/arm/translate-a64.c
93
@@ -XXX,XX +XXX,XX @@ static void disas_data_proc_simd_fp(DisasContext *s, uint32_t insn)
94
*/
95
static bool is_guarded_page(CPUARMState *env, DisasContext *s)
96
{
97
-#ifdef CONFIG_USER_ONLY
98
- return false; /* FIXME */
99
-#else
100
uint64_t addr = s->base.pc_first;
101
+#ifdef CONFIG_USER_ONLY
102
+ return page_get_flags(addr) & PAGE_BTI;
103
+#else
104
int mmu_idx = arm_to_core_mmu_idx(s->mmu_idx);
105
unsigned int index = tlb_index(env, mmu_idx, addr);
106
CPUTLBEntry *entry = tlb_entry(env, mmu_idx, addr);
107
--
108
2.20.1
109
110
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
These are all of the defines required to parse
4
GNU_PROPERTY_AARCH64_FEATURE_1_AND, copied from binutils.
5
Other missing defines related to other GNU program headers
6
and notes are elided for now.
7
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20201016184207.786698-4-richard.henderson@linaro.org
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
13
include/elf.h | 22 ++++++++++++++++++++++
14
1 file changed, 22 insertions(+)
15
16
diff --git a/include/elf.h b/include/elf.h
17
index XXXXXXX..XXXXXXX 100644
18
--- a/include/elf.h
19
+++ b/include/elf.h
20
@@ -XXX,XX +XXX,XX @@ typedef int64_t Elf64_Sxword;
21
#define PT_NOTE 4
22
#define PT_SHLIB 5
23
#define PT_PHDR 6
24
+#define PT_LOOS 0x60000000
25
+#define PT_HIOS 0x6fffffff
26
#define PT_LOPROC 0x70000000
27
#define PT_HIPROC 0x7fffffff
28
29
+#define PT_GNU_PROPERTY (PT_LOOS + 0x474e553)
30
+
31
#define PT_MIPS_REGINFO 0x70000000
32
#define PT_MIPS_RTPROC 0x70000001
33
#define PT_MIPS_OPTIONS 0x70000002
34
@@ -XXX,XX +XXX,XX @@ typedef struct elf64_shdr {
35
#define NT_ARM_SYSTEM_CALL 0x404 /* ARM system call number */
36
#define NT_ARM_SVE 0x405 /* ARM Scalable Vector Extension regs */
37
38
+/* Defined note types for GNU systems. */
39
+
40
+#define NT_GNU_PROPERTY_TYPE_0 5 /* Program property */
41
+
42
+/* Values used in GNU .note.gnu.property notes (NT_GNU_PROPERTY_TYPE_0). */
43
+
44
+#define GNU_PROPERTY_STACK_SIZE 1
45
+#define GNU_PROPERTY_NO_COPY_ON_PROTECTED 2
46
+
47
+#define GNU_PROPERTY_LOPROC 0xc0000000
48
+#define GNU_PROPERTY_HIPROC 0xdfffffff
49
+#define GNU_PROPERTY_LOUSER 0xe0000000
50
+#define GNU_PROPERTY_HIUSER 0xffffffff
51
+
52
+#define GNU_PROPERTY_AARCH64_FEATURE_1_AND 0xc0000000
53
+#define GNU_PROPERTY_AARCH64_FEATURE_1_BTI (1u << 0)
54
+#define GNU_PROPERTY_AARCH64_FEATURE_1_PAC (1u << 1)
55
+
56
/*
57
* Physical entry point into the kernel.
58
*
59
--
60
2.20.1
61
62
diff view generated by jsdifflib
Deleted patch
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
1
3
Fix an unlikely memory leak in load_elf_image().
4
5
Fixes: bf858897b7 ("linux-user: Re-use load_elf_image for the main binary.")
6
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20201016184207.786698-5-richard.henderson@linaro.org
9
Message-Id: <20201003174944.1972444-1-f4bug@amsat.org>
10
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
14
linux-user/elfload.c | 8 ++++----
15
1 file changed, 4 insertions(+), 4 deletions(-)
16
17
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/linux-user/elfload.c
20
+++ b/linux-user/elfload.c
21
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
22
info->brk = vaddr_em;
23
}
24
} else if (eppnt->p_type == PT_INTERP && pinterp_name) {
25
- char *interp_name;
26
+ g_autofree char *interp_name = NULL;
27
28
if (*pinterp_name) {
29
errmsg = "Multiple PT_INTERP entries";
30
goto exit_errmsg;
31
}
32
- interp_name = malloc(eppnt->p_filesz);
33
+ interp_name = g_malloc(eppnt->p_filesz);
34
if (!interp_name) {
35
goto exit_perror;
36
}
37
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
38
errmsg = "Invalid PT_INTERP entry";
39
goto exit_errmsg;
40
}
41
- *pinterp_name = interp_name;
42
+ *pinterp_name = g_steal_pointer(&interp_name);
43
#ifdef TARGET_MIPS
44
} else if (eppnt->p_type == PT_MIPS_ABIFLAGS) {
45
Mips_elf_abiflags_v0 abiflags;
46
@@ -XXX,XX +XXX,XX @@ int load_elf_binary(struct linux_binprm *bprm, struct image_info *info)
47
if (elf_interpreter) {
48
info->load_bias = interp_info.load_bias;
49
info->entry = interp_info.entry;
50
- free(elf_interpreter);
51
+ g_free(elf_interpreter);
52
}
53
54
#ifdef USE_ELF_CORE_DUMP
55
--
56
2.20.1
57
58
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
Fixing this now will clarify following patches.
4
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Message-id: 20201016184207.786698-6-richard.henderson@linaro.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
linux-user/elfload.c | 12 +++++++++---
11
1 file changed, 9 insertions(+), 3 deletions(-)
12
13
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/linux-user/elfload.c
16
+++ b/linux-user/elfload.c
17
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
18
abi_ulong vaddr, vaddr_po, vaddr_ps, vaddr_ef, vaddr_em, vaddr_len;
19
int elf_prot = 0;
20
21
- if (eppnt->p_flags & PF_R) elf_prot = PROT_READ;
22
- if (eppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;
23
- if (eppnt->p_flags & PF_X) elf_prot |= PROT_EXEC;
24
+ if (eppnt->p_flags & PF_R) {
25
+ elf_prot |= PROT_READ;
26
+ }
27
+ if (eppnt->p_flags & PF_W) {
28
+ elf_prot |= PROT_WRITE;
29
+ }
30
+ if (eppnt->p_flags & PF_X) {
31
+ elf_prot |= PROT_EXEC;
32
+ }
33
34
vaddr = load_bias + eppnt->p_vaddr;
35
vaddr_po = TARGET_ELF_PAGEOFFSET(vaddr);
36
--
37
2.20.1
38
39
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
The second loop uses a loop induction variable, and the first
4
does not. Transform the first to match the second, to simplify
5
a following patch moving code between them.
6
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Message-id: 20201016184207.786698-7-richard.henderson@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
linux-user/elfload.c | 9 +++++----
13
1 file changed, 5 insertions(+), 4 deletions(-)
14
15
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/linux-user/elfload.c
18
+++ b/linux-user/elfload.c
19
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
20
loaddr = -1, hiaddr = 0;
21
info->alignment = 0;
22
for (i = 0; i < ehdr->e_phnum; ++i) {
23
- if (phdr[i].p_type == PT_LOAD) {
24
- abi_ulong a = phdr[i].p_vaddr - phdr[i].p_offset;
25
+ struct elf_phdr *eppnt = phdr + i;
26
+ if (eppnt->p_type == PT_LOAD) {
27
+ abi_ulong a = eppnt->p_vaddr - eppnt->p_offset;
28
if (a < loaddr) {
29
loaddr = a;
30
}
31
- a = phdr[i].p_vaddr + phdr[i].p_memsz;
32
+ a = eppnt->p_vaddr + eppnt->p_memsz;
33
if (a > hiaddr) {
34
hiaddr = a;
35
}
36
++info->nsegs;
37
- info->alignment |= phdr[i].p_align;
38
+ info->alignment |= eppnt->p_align;
39
}
40
}
41
42
--
43
2.20.1
44
45
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
For BTI, we need to know if the executable is static or dynamic,
4
which means looking for PT_INTERP earlier.
5
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20201016184207.786698-8-richard.henderson@linaro.org
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
linux-user/elfload.c | 60 +++++++++++++++++++++++---------------------
12
1 file changed, 31 insertions(+), 29 deletions(-)
13
14
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/linux-user/elfload.c
17
+++ b/linux-user/elfload.c
18
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
19
20
mmap_lock();
21
22
- /* Find the maximum size of the image and allocate an appropriate
23
- amount of memory to handle that. */
24
+ /*
25
+ * Find the maximum size of the image and allocate an appropriate
26
+ * amount of memory to handle that. Locate the interpreter, if any.
27
+ */
28
loaddr = -1, hiaddr = 0;
29
info->alignment = 0;
30
for (i = 0; i < ehdr->e_phnum; ++i) {
31
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
32
}
33
++info->nsegs;
34
info->alignment |= eppnt->p_align;
35
+ } else if (eppnt->p_type == PT_INTERP && pinterp_name) {
36
+ g_autofree char *interp_name = NULL;
37
+
38
+ if (*pinterp_name) {
39
+ errmsg = "Multiple PT_INTERP entries";
40
+ goto exit_errmsg;
41
+ }
42
+ interp_name = g_malloc(eppnt->p_filesz);
43
+ if (!interp_name) {
44
+ goto exit_perror;
45
+ }
46
+
47
+ if (eppnt->p_offset + eppnt->p_filesz <= BPRM_BUF_SIZE) {
48
+ memcpy(interp_name, bprm_buf + eppnt->p_offset,
49
+ eppnt->p_filesz);
50
+ } else {
51
+ retval = pread(image_fd, interp_name, eppnt->p_filesz,
52
+ eppnt->p_offset);
53
+ if (retval != eppnt->p_filesz) {
54
+ goto exit_perror;
55
+ }
56
+ }
57
+ if (interp_name[eppnt->p_filesz - 1] != 0) {
58
+ errmsg = "Invalid PT_INTERP entry";
59
+ goto exit_errmsg;
60
+ }
61
+ *pinterp_name = g_steal_pointer(&interp_name);
62
}
63
}
64
65
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
66
if (vaddr_em > info->brk) {
67
info->brk = vaddr_em;
68
}
69
- } else if (eppnt->p_type == PT_INTERP && pinterp_name) {
70
- g_autofree char *interp_name = NULL;
71
-
72
- if (*pinterp_name) {
73
- errmsg = "Multiple PT_INTERP entries";
74
- goto exit_errmsg;
75
- }
76
- interp_name = g_malloc(eppnt->p_filesz);
77
- if (!interp_name) {
78
- goto exit_perror;
79
- }
80
-
81
- if (eppnt->p_offset + eppnt->p_filesz <= BPRM_BUF_SIZE) {
82
- memcpy(interp_name, bprm_buf + eppnt->p_offset,
83
- eppnt->p_filesz);
84
- } else {
85
- retval = pread(image_fd, interp_name, eppnt->p_filesz,
86
- eppnt->p_offset);
87
- if (retval != eppnt->p_filesz) {
88
- goto exit_perror;
89
- }
90
- }
91
- if (interp_name[eppnt->p_filesz - 1] != 0) {
92
- errmsg = "Invalid PT_INTERP entry";
93
- goto exit_errmsg;
94
- }
95
- *pinterp_name = g_steal_pointer(&interp_name);
96
#ifdef TARGET_MIPS
97
} else if (eppnt->p_type == PT_MIPS_ABIFLAGS) {
98
Mips_elf_abiflags_v0 abiflags;
99
--
100
2.20.1
101
102
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
This is slightly clearer than just using strerror, though
4
the different forms produced by error_setg_file_open and
5
error_setg_errno isn't entirely convenient.
6
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Message-id: 20201016184207.786698-10-richard.henderson@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
linux-user/elfload.c | 15 ++++++++-------
13
1 file changed, 8 insertions(+), 7 deletions(-)
14
15
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/linux-user/elfload.c
18
+++ b/linux-user/elfload.c
19
@@ -XXX,XX +XXX,XX @@ static void load_elf_interp(const char *filename, struct image_info *info,
20
char bprm_buf[BPRM_BUF_SIZE])
21
{
22
int fd, retval;
23
+ Error *err = NULL;
24
25
fd = open(path(filename), O_RDONLY);
26
if (fd < 0) {
27
- goto exit_perror;
28
+ error_setg_file_open(&err, errno, filename);
29
+ error_report_err(err);
30
+ exit(-1);
31
}
32
33
retval = read(fd, bprm_buf, BPRM_BUF_SIZE);
34
if (retval < 0) {
35
- goto exit_perror;
36
+ error_setg_errno(&err, errno, "Error reading file header");
37
+ error_reportf_err(err, "%s: ", filename);
38
+ exit(-1);
39
}
40
+
41
if (retval < BPRM_BUF_SIZE) {
42
memset(bprm_buf + retval, 0, BPRM_BUF_SIZE - retval);
43
}
44
45
load_elf_image(filename, fd, info, NULL, bprm_buf);
46
- return;
47
-
48
- exit_perror:
49
- fprintf(stderr, "%s: %s\n", filename, strerror(errno));
50
- exit(-1);
51
}
52
53
static int symfind(const void *s0, const void *s1)
54
--
55
2.20.1
56
57
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
Use the new generic support for NT_GNU_PROPERTY_TYPE_0.
4
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20201016184207.786698-12-richard.henderson@linaro.org
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
linux-user/elfload.c | 48 ++++++++++++++++++++++++++++++++++++++++++--
11
1 file changed, 46 insertions(+), 2 deletions(-)
12
13
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/linux-user/elfload.c
16
+++ b/linux-user/elfload.c
17
@@ -XXX,XX +XXX,XX @@ static void elf_core_copy_regs(target_elf_gregset_t *regs,
18
19
#include "elf.h"
20
21
+/* We must delay the following stanzas until after "elf.h". */
22
+#if defined(TARGET_AARCH64)
23
+
24
+static bool arch_parse_elf_property(uint32_t pr_type, uint32_t pr_datasz,
25
+ const uint32_t *data,
26
+ struct image_info *info,
27
+ Error **errp)
28
+{
29
+ if (pr_type == GNU_PROPERTY_AARCH64_FEATURE_1_AND) {
30
+ if (pr_datasz != sizeof(uint32_t)) {
31
+ error_setg(errp, "Ill-formed GNU_PROPERTY_AARCH64_FEATURE_1_AND");
32
+ return false;
33
+ }
34
+ /* We will extract GNU_PROPERTY_AARCH64_FEATURE_1_BTI later. */
35
+ info->note_flags = *data;
36
+ }
37
+ return true;
38
+}
39
+#define ARCH_USE_GNU_PROPERTY 1
40
+
41
+#else
42
+
43
static bool arch_parse_elf_property(uint32_t pr_type, uint32_t pr_datasz,
44
const uint32_t *data,
45
struct image_info *info,
46
@@ -XXX,XX +XXX,XX @@ static bool arch_parse_elf_property(uint32_t pr_type, uint32_t pr_datasz,
47
}
48
#define ARCH_USE_GNU_PROPERTY 0
49
50
+#endif
51
+
52
struct exec
53
{
54
unsigned int a_info; /* Use macros N_MAGIC, etc for access */
55
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
56
struct elfhdr *ehdr = (struct elfhdr *)bprm_buf;
57
struct elf_phdr *phdr;
58
abi_ulong load_addr, load_bias, loaddr, hiaddr, error;
59
- int i, retval;
60
+ int i, retval, prot_exec;
61
Error *err = NULL;
62
63
/* First of all, some simple consistency checks */
64
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
65
info->brk = 0;
66
info->elf_flags = ehdr->e_flags;
67
68
+ prot_exec = PROT_EXEC;
69
+#ifdef TARGET_AARCH64
70
+ /*
71
+ * If the BTI feature is present, this indicates that the executable
72
+ * pages of the startup binary should be mapped with PROT_BTI, so that
73
+ * branch targets are enforced.
74
+ *
75
+ * The startup binary is either the interpreter or the static executable.
76
+ * The interpreter is responsible for all pages of a dynamic executable.
77
+ *
78
+ * Elf notes are backward compatible to older cpus.
79
+ * Do not enable BTI unless it is supported.
80
+ */
81
+ if ((info->note_flags & GNU_PROPERTY_AARCH64_FEATURE_1_BTI)
82
+ && (pinterp_name == NULL || *pinterp_name == 0)
83
+ && cpu_isar_feature(aa64_bti, ARM_CPU(thread_cpu))) {
84
+ prot_exec |= TARGET_PROT_BTI;
85
+ }
86
+#endif
87
+
88
for (i = 0; i < ehdr->e_phnum; i++) {
89
struct elf_phdr *eppnt = phdr + i;
90
if (eppnt->p_type == PT_LOAD) {
91
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
92
elf_prot |= PROT_WRITE;
93
}
94
if (eppnt->p_flags & PF_X) {
95
- elf_prot |= PROT_EXEC;
96
+ elf_prot |= prot_exec;
97
}
98
99
vaddr = load_bias + eppnt->p_vaddr;
100
--
101
2.20.1
102
103
diff view generated by jsdifflib