1
target-arm queue. The big thing here is the landing of the 3-phase
1
The following changes since commit 8f6330a807f2642dc2a3cdf33347aa28a4c00a87:
2
reset patches...
3
2
4
-- PMM
3
Merge tag 'pull-maintainer-updates-060324-1' of https://gitlab.com/stsquad/qemu into staging (2024-03-06 16:56:20 +0000)
5
6
The following changes since commit 204aa60b37c23a89e690d418f49787d274303ca7:
7
8
Merge remote-tracking branch 'remotes/amarkovic/tags/mips-queue-jan-29-2020' into staging (2020-01-30 14:18:45 +0000)
9
4
10
are available in the Git repository at:
5
are available in the Git repository at:
11
6
12
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20200130
7
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20240308
13
8
14
for you to fetch changes up to dea101a1ae9968c9fec6ab0291489dad7c49f36f:
9
for you to fetch changes up to bbf6c6dbead82292a20951eb1204442a6b838de9:
15
10
16
target/arm/cpu: Add the kvm-no-adjvtime CPU property (2020-01-30 16:02:06 +0000)
11
target/arm: Move v7m-related code from cpu32.c into a separate file (2024-03-08 14:45:03 +0000)
17
12
18
----------------------------------------------------------------
13
----------------------------------------------------------------
19
target-arm queue:
14
target-arm queue:
20
* hw/core/or-irq: Fix incorrect assert forbidding num-lines == MAX_OR_LINES
15
* Implement FEAT_ECV
21
* target/arm/arm-semi: Don't let the guest close stdin/stdout/stderr
16
* STM32L4x5: Implement GPIO device
22
* aspeed: some minor bugfixes
17
* Fix 32-bit SMOPA
23
* aspeed: add eMMC controller model for AST2600 SoC
18
* Refactor v7m related code from cpu32.c into its own file
24
* hw/arm/raspi: Remove obsolete use of -smp to set the soc 'enabled-cpus'
19
* hw/rtc/sun4v-rtc: Relicense to GPLv2-or-later
25
* New 3-phase reset API for device models
26
* hw/intc/arm_gicv3_kvm: Stop wrongly programming GICR_PENDBASER.PTZ bit
27
* Arm KVM: stop/restart the guest counter when the VM is stopped and started
28
20
29
----------------------------------------------------------------
21
----------------------------------------------------------------
30
Andrew Jeffery (2):
22
Inès Varhol (3):
31
hw/sd: Configure number of slots exposed by the ASPEED SDHCI model
23
hw/gpio: Implement STM32L4x5 GPIO
32
hw/arm: ast2600: Wire up the eMMC controller
24
hw/arm: Connect STM32L4x5 GPIO to STM32L4x5 SoC
25
tests/qtest: Add STM32L4x5 GPIO QTest testcase
33
26
34
Andrew Jones (6):
27
Peter Maydell (9):
35
target/arm/kvm: trivial: Clean up header documentation
28
target/arm: Move some register related defines to internals.h
36
hw/arm/virt: Add missing 5.0 options call to 4.2 options
29
target/arm: Timer _EL02 registers UNDEF for E2H == 0
37
target/arm/kvm64: kvm64 cpus have timer registers
30
target/arm: use FIELD macro for CNTHCTL bit definitions
38
tests/arm-cpu-features: Check feature default values
31
target/arm: Don't allow RES0 CNTHCTL_EL2 bits to be written
39
target/arm/kvm: Implement virtual time adjustment
32
target/arm: Implement new FEAT_ECV trap bits
40
target/arm/cpu: Add the kvm-no-adjvtime CPU property
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
41
37
42
Cédric Le Goater (2):
38
Richard Henderson (1):
43
ftgmac100: check RX and TX buffer alignment
39
target/arm: Fix 32-bit SMOPA
44
hw/arm/aspeed: add a 'execute-in-place' property to boot directly from CE0
45
40
46
Damien Hedde (11):
41
Thomas Huth (1):
47
add device_legacy_reset function to prepare for reset api change
42
target/arm: Move v7m-related code from cpu32.c into a separate file
48
hw/core/qdev: add trace events to help with resettable transition
49
hw/core: create Resettable QOM interface
50
hw/core: add Resettable support to BusClass and DeviceClass
51
hw/core/resettable: add support for changing parent
52
hw/core/qdev: handle parent bus change regarding resettable
53
hw/core/qdev: update hotplug reset regarding resettable
54
hw/core: deprecate old reset functions and introduce new ones
55
docs/devel/reset.rst: add doc about Resettable interface
56
vl: replace deprecated qbus_reset_all registration
57
hw/s390x/ipl: replace deprecated qdev_reset_all registration
58
43
59
Joel Stanley (1):
44
MAINTAINERS | 1 +
60
misc/pca9552: Add qom set and get
45
docs/system/arm/b-l475e-iot01a.rst | 2 +-
46
docs/system/arm/emulation.rst | 1 +
47
include/hw/arm/stm32l4x5_soc.h | 2 +
48
include/hw/gpio/stm32l4x5_gpio.h | 71 +++++
49
include/hw/misc/stm32l4x5_syscfg.h | 3 +-
50
include/hw/rtc/sun4v-rtc.h | 2 +-
51
target/arm/cpu-features.h | 10 +
52
target/arm/cpu.h | 129 +--------
53
target/arm/internals.h | 151 ++++++++++
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
61
82
62
Peter Maydell (2):
63
hw/core/or-irq: Fix incorrect assert forbidding num-lines == MAX_OR_LINES
64
target/arm/arm-semi: Don't let the guest close stdin/stdout/stderr
65
66
Philippe Mathieu-Daudé (1):
67
hw/arm/raspi: Remove obsolete use of -smp to set the soc 'enabled-cpus'
68
69
Zenghui Yu (1):
70
hw/intc/arm_gicv3_kvm: Stop wrongly programming GICR_PENDBASER.PTZ bit
71
72
hw/core/Makefile.objs | 1 +
73
tests/Makefile.include | 1 +
74
include/hw/arm/aspeed.h | 2 +
75
include/hw/arm/aspeed_soc.h | 2 +
76
include/hw/arm/virt.h | 1 +
77
include/hw/qdev-core.h | 58 +++++++-
78
include/hw/resettable.h | 247 +++++++++++++++++++++++++++++++++
79
include/hw/sd/aspeed_sdhci.h | 1 +
80
target/arm/cpu.h | 7 +
81
target/arm/kvm_arm.h | 95 ++++++++++---
82
hw/arm/aspeed.c | 72 ++++++++--
83
hw/arm/aspeed_ast2600.c | 31 ++++-
84
hw/arm/aspeed_soc.c | 2 +
85
hw/arm/raspi.c | 2 -
86
hw/arm/virt.c | 9 ++
87
hw/audio/intel-hda.c | 2 +-
88
hw/core/bus.c | 102 ++++++++++++++
89
hw/core/or-irq.c | 2 +-
90
hw/core/qdev.c | 160 ++++++++++++++++++++--
91
hw/core/resettable.c | 301 +++++++++++++++++++++++++++++++++++++++++
92
hw/hyperv/hyperv.c | 2 +-
93
hw/i386/microvm.c | 2 +-
94
hw/i386/pc.c | 2 +-
95
hw/ide/microdrive.c | 8 +-
96
hw/intc/arm_gicv3_kvm.c | 11 +-
97
hw/intc/spapr_xive.c | 2 +-
98
hw/misc/pca9552.c | 90 ++++++++++++
99
hw/net/ftgmac100.c | 13 ++
100
hw/ppc/pnv_psi.c | 4 +-
101
hw/ppc/spapr_pci.c | 2 +-
102
hw/ppc/spapr_vio.c | 2 +-
103
hw/s390x/ipl.c | 10 +-
104
hw/s390x/s390-pci-inst.c | 2 +-
105
hw/scsi/vmw_pvscsi.c | 2 +-
106
hw/sd/aspeed_sdhci.c | 11 +-
107
hw/sd/omap_mmc.c | 2 +-
108
hw/sd/pl181.c | 2 +-
109
target/arm/arm-semi.c | 9 ++
110
target/arm/cpu.c | 2 +
111
target/arm/cpu64.c | 1 +
112
target/arm/kvm.c | 120 ++++++++++++++++
113
target/arm/kvm32.c | 3 +
114
target/arm/kvm64.c | 4 +
115
target/arm/machine.c | 7 +
116
target/arm/monitor.c | 1 +
117
tests/qtest/arm-cpu-features.c | 41 ++++--
118
vl.c | 10 +-
119
docs/arm-cpu-features.rst | 37 ++++-
120
docs/devel/index.rst | 1 +
121
docs/devel/reset.rst | 289 +++++++++++++++++++++++++++++++++++++++
122
hw/core/trace-events | 27 ++++
123
51 files changed, 1727 insertions(+), 90 deletions(-)
124
create mode 100644 include/hw/resettable.h
125
create mode 100644 hw/core/resettable.c
126
create mode 100644 docs/devel/reset.rst
127
diff view generated by jsdifflib
1
From: Andrew Jones <drjones@redhat.com>
1
cpu.h has a lot of #defines relating to CPU register fields.
2
Most of these aren't actually used outside target/arm code,
3
so there's no point in cluttering up the cpu.h file with them.
4
Move some easy ones to internals.h.
2
5
3
When a VM is stopped (such as when it's paused) guest virtual time
4
should stop counting. Otherwise, when the VM is resumed it will
5
experience time jumps and its kernel may report soft lockups. Not
6
counting virtual time while the VM is stopped has the side effect
7
of making the guest's time appear to lag when compared with real
8
time, and even with time derived from the physical counter. For
9
this reason, this change, which is enabled by default, comes with
10
a KVM CPU feature allowing it to be disabled, restoring legacy
11
behavior.
12
13
This patch only provides the implementation of the virtual time
14
adjustment. A subsequent patch will provide the CPU property
15
allowing the change to be enabled and disabled.
16
17
Reported-by: Bijan Mottahedeh <bijan.mottahedeh@oracle.com>
18
Signed-off-by: Andrew Jones <drjones@redhat.com>
19
Message-id: 20200120101023.16030-6-drjones@redhat.com
20
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
21
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>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20240301183219.2424889-2-peter.maydell@linaro.org
22
---
10
---
23
target/arm/cpu.h | 7 ++++
11
target/arm/cpu.h | 128 -----------------------------------------
24
target/arm/kvm_arm.h | 38 ++++++++++++++++++
12
target/arm/internals.h | 128 +++++++++++++++++++++++++++++++++++++++++
25
target/arm/kvm.c | 92 ++++++++++++++++++++++++++++++++++++++++++++
13
2 files changed, 128 insertions(+), 128 deletions(-)
26
target/arm/kvm32.c | 3 ++
27
target/arm/kvm64.c | 3 ++
28
target/arm/machine.c | 7 ++++
29
6 files changed, 150 insertions(+)
30
14
31
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
32
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
33
--- a/target/arm/cpu.h
17
--- a/target/arm/cpu.h
34
+++ b/target/arm/cpu.h
18
+++ b/target/arm/cpu.h
35
@@ -XXX,XX +XXX,XX @@ struct ARMCPU {
19
@@ -XXX,XX +XXX,XX @@ typedef struct ARMGenericTimer {
36
/* KVM init features for this CPU */
20
uint64_t ctl; /* Timer Control register */
37
uint32_t kvm_init_features[7];
21
} ARMGenericTimer;
38
22
39
+ /* KVM CPU state */
23
-#define VTCR_NSW (1u << 29)
40
+
24
-#define VTCR_NSA (1u << 30)
41
+ /* KVM virtual time adjustment */
25
-#define VSTCR_SW VTCR_NSW
42
+ bool kvm_adjvtime;
26
-#define VSTCR_SA VTCR_NSA
43
+ bool kvm_vtime_dirty;
27
-
44
+ uint64_t kvm_vtime;
28
/* Define a maximum sized vector register.
45
+
29
* For 32-bit, this is a 128-bit NEON/AdvSIMD register.
46
/* Uniprocessor system with MP extensions */
30
* For 64-bit, this is a 2048-bit SVE register.
47
bool mp_is_up;
31
@@ -XXX,XX +XXX,XX @@ void pmu_init(ARMCPU *cpu);
48
32
#define SCTLR_SPINTMASK (1ULL << 62) /* FEAT_NMI */
49
diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h
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
50
index XXXXXXX..XXXXXXX 100644
183
index XXXXXXX..XXXXXXX 100644
51
--- a/target/arm/kvm_arm.h
184
--- a/target/arm/internals.h
52
+++ b/target/arm/kvm_arm.h
185
+++ b/target/arm/internals.h
53
@@ -XXX,XX +XXX,XX @@ bool write_list_to_kvmstate(ARMCPU *cpu, int level);
186
@@ -XXX,XX +XXX,XX @@ FIELD(DBGWCR, WT, 20, 1)
54
*/
187
FIELD(DBGWCR, MASK, 24, 5)
55
bool write_kvmstate_to_list(ARMCPU *cpu);
188
FIELD(DBGWCR, SSCE, 29, 1)
56
189
57
+/**
190
+#define VTCR_NSW (1u << 29)
58
+ * kvm_arm_cpu_pre_save:
191
+#define VTCR_NSA (1u << 30)
59
+ * @cpu: ARMCPU
192
+#define VSTCR_SW VTCR_NSW
60
+ *
193
+#define VSTCR_SA VTCR_NSA
61
+ * Called after write_kvmstate_to_list() from cpu_pre_save() to update
194
+
62
+ * the cpreg list with KVM CPU state.
195
+/* Bit definitions for CPACR (AArch32 only) */
63
+ */
196
+FIELD(CPACR, CP10, 20, 2)
64
+void kvm_arm_cpu_pre_save(ARMCPU *cpu);
197
+FIELD(CPACR, CP11, 22, 2)
65
+
198
+FIELD(CPACR, TRCDIS, 28, 1) /* matches CPACR_EL1.TTA */
66
+/**
199
+FIELD(CPACR, D32DIS, 30, 1) /* up to v7; RAZ in v8 */
67
+ * kvm_arm_cpu_post_load:
200
+FIELD(CPACR, ASEDIS, 31, 1)
68
+ * @cpu: ARMCPU
201
+
69
+ *
202
+/* Bit definitions for CPACR_EL1 (AArch64 only) */
70
+ * Called from cpu_post_load() to update KVM CPU state from the cpreg list.
203
+FIELD(CPACR_EL1, ZEN, 16, 2)
71
+ */
204
+FIELD(CPACR_EL1, FPEN, 20, 2)
72
+void kvm_arm_cpu_post_load(ARMCPU *cpu);
205
+FIELD(CPACR_EL1, SMEN, 24, 2)
73
+
206
+FIELD(CPACR_EL1, TTA, 28, 1) /* matches CPACR.TRCDIS */
74
/**
207
+
75
* kvm_arm_reset_vcpu:
208
+/* Bit definitions for HCPTR (AArch32 only) */
76
* @cpu: ARMCPU
209
+FIELD(HCPTR, TCP10, 10, 1)
77
@@ -XXX,XX +XXX,XX @@ int kvm_arm_sync_mpstate_to_kvm(ARMCPU *cpu);
210
+FIELD(HCPTR, TCP11, 11, 1)
78
*/
211
+FIELD(HCPTR, TASE, 15, 1)
79
int kvm_arm_sync_mpstate_to_qemu(ARMCPU *cpu);
212
+FIELD(HCPTR, TTA, 20, 1)
80
213
+FIELD(HCPTR, TAM, 30, 1) /* matches CPTR_EL2.TAM */
81
+/**
214
+FIELD(HCPTR, TCPAC, 31, 1) /* matches CPTR_EL2.TCPAC */
82
+ * kvm_arm_get_virtual_time:
215
+
83
+ * @cs: CPUState
216
+/* Bit definitions for CPTR_EL2 (AArch64 only) */
84
+ *
217
+FIELD(CPTR_EL2, TZ, 8, 1) /* !E2H */
85
+ * Gets the VCPU's virtual counter and stores it in the KVM CPU state.
218
+FIELD(CPTR_EL2, TFP, 10, 1) /* !E2H, matches HCPTR.TCP10 */
86
+ */
219
+FIELD(CPTR_EL2, TSM, 12, 1) /* !E2H */
87
+void kvm_arm_get_virtual_time(CPUState *cs);
220
+FIELD(CPTR_EL2, ZEN, 16, 2) /* E2H */
88
+
221
+FIELD(CPTR_EL2, FPEN, 20, 2) /* E2H */
89
+/**
222
+FIELD(CPTR_EL2, SMEN, 24, 2) /* E2H */
90
+ * kvm_arm_put_virtual_time:
223
+FIELD(CPTR_EL2, TTA, 28, 1)
91
+ * @cs: CPUState
224
+FIELD(CPTR_EL2, TAM, 30, 1) /* matches HCPTR.TAM */
92
+ *
225
+FIELD(CPTR_EL2, TCPAC, 31, 1) /* matches HCPTR.TCPAC */
93
+ * Sets the VCPU's virtual counter to the value stored in the KVM CPU state.
226
+
94
+ */
227
+/* Bit definitions for CPTR_EL3 (AArch64 only) */
95
+void kvm_arm_put_virtual_time(CPUState *cs);
228
+FIELD(CPTR_EL3, EZ, 8, 1)
96
+
229
+FIELD(CPTR_EL3, TFP, 10, 1)
97
+void kvm_arm_vm_state_change(void *opaque, int running, RunState state);
230
+FIELD(CPTR_EL3, ESM, 12, 1)
98
+
231
+FIELD(CPTR_EL3, TTA, 20, 1)
99
int kvm_arm_vgic_probe(void);
232
+FIELD(CPTR_EL3, TAM, 30, 1)
100
233
+FIELD(CPTR_EL3, TCPAC, 31, 1)
101
void kvm_arm_pmu_set_irq(CPUState *cs, int irq);
234
+
102
@@ -XXX,XX +XXX,XX @@ static inline void kvm_arm_pmu_set_irq(CPUState *cs, int irq) {}
235
+#define MDCR_MTPME (1U << 28)
103
static inline void kvm_arm_pmu_init(CPUState *cs) {}
236
+#define MDCR_TDCC (1U << 27)
104
237
+#define MDCR_HLP (1U << 26) /* MDCR_EL2 */
105
static inline void kvm_arm_sve_get_vls(CPUState *cs, unsigned long *map) {}
238
+#define MDCR_SCCD (1U << 23) /* MDCR_EL3 */
106
+
239
+#define MDCR_HCCD (1U << 23) /* MDCR_EL2 */
107
+static inline void kvm_arm_get_virtual_time(CPUState *cs) {}
240
+#define MDCR_EPMAD (1U << 21)
108
+static inline void kvm_arm_put_virtual_time(CPUState *cs) {}
241
+#define MDCR_EDAD (1U << 20)
109
#endif
242
+#define MDCR_TTRF (1U << 19)
110
243
+#define MDCR_STE (1U << 18) /* MDCR_EL3 */
111
static inline const char *gic_class_name(void)
244
+#define MDCR_SPME (1U << 17) /* MDCR_EL3 */
112
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
245
+#define MDCR_HPMD (1U << 17) /* MDCR_EL2 */
113
index XXXXXXX..XXXXXXX 100644
246
+#define MDCR_SDD (1U << 16)
114
--- a/target/arm/kvm.c
247
+#define MDCR_SPD (3U << 14)
115
+++ b/target/arm/kvm.c
248
+#define MDCR_TDRA (1U << 11)
116
@@ -XXX,XX +XXX,XX @@ static int compare_u64(const void *a, const void *b)
249
+#define MDCR_TDOSA (1U << 10)
117
return 0;
250
+#define MDCR_TDA (1U << 9)
118
}
251
+#define MDCR_TDE (1U << 8)
119
252
+#define MDCR_HPME (1U << 7)
120
+/*
253
+#define MDCR_TPM (1U << 6)
121
+ * cpreg_values are sorted in ascending order by KVM register ID
254
+#define MDCR_TPMCR (1U << 5)
122
+ * (see kvm_arm_init_cpreg_list). This allows us to cheaply find
255
+#define MDCR_HPMN (0x1fU)
123
+ * the storage for a KVM register by ID with a binary search.
256
+
124
+ */
257
+/* Not all of the MDCR_EL3 bits are present in the 32-bit SDCR */
125
+static uint64_t *kvm_arm_get_cpreg_ptr(ARMCPU *cpu, uint64_t regidx)
258
+#define SDCR_VALID_MASK (MDCR_MTPME | MDCR_TDCC | MDCR_SCCD | \
126
+{
259
+ MDCR_EPMAD | MDCR_EDAD | MDCR_TTRF | \
127
+ uint64_t *res;
260
+ MDCR_STE | MDCR_SPME | MDCR_SPD)
128
+
261
+
129
+ res = bsearch(&regidx, cpu->cpreg_indexes, cpu->cpreg_array_len,
262
+#define TTBCR_N (7U << 0) /* TTBCR.EAE==0 */
130
+ sizeof(uint64_t), compare_u64);
263
+#define TTBCR_T0SZ (7U << 0) /* TTBCR.EAE==1 */
131
+ assert(res);
264
+#define TTBCR_PD0 (1U << 4)
132
+
265
+#define TTBCR_PD1 (1U << 5)
133
+ return &cpu->cpreg_values[res - cpu->cpreg_indexes];
266
+#define TTBCR_EPD0 (1U << 7)
134
+}
267
+#define TTBCR_IRGN0 (3U << 8)
135
+
268
+#define TTBCR_ORGN0 (3U << 10)
136
/* Initialize the ARMCPU cpreg list according to the kernel's
269
+#define TTBCR_SH0 (3U << 12)
137
* definition of what CPU registers it knows about (and throw away
270
+#define TTBCR_T1SZ (3U << 16)
138
* the previous TCG-created cpreg list).
271
+#define TTBCR_A1 (1U << 22)
139
@@ -XXX,XX +XXX,XX @@ bool write_list_to_kvmstate(ARMCPU *cpu, int level)
272
+#define TTBCR_EPD1 (1U << 23)
140
return ok;
273
+#define TTBCR_IRGN1 (3U << 24)
141
}
274
+#define TTBCR_ORGN1 (3U << 26)
142
275
+#define TTBCR_SH1 (1U << 28)
143
+void kvm_arm_cpu_pre_save(ARMCPU *cpu)
276
+#define TTBCR_EAE (1U << 31)
144
+{
277
+
145
+ /* KVM virtual time adjustment */
278
+FIELD(VTCR, T0SZ, 0, 6)
146
+ if (cpu->kvm_vtime_dirty) {
279
+FIELD(VTCR, SL0, 6, 2)
147
+ *kvm_arm_get_cpreg_ptr(cpu, KVM_REG_ARM_TIMER_CNT) = cpu->kvm_vtime;
280
+FIELD(VTCR, IRGN0, 8, 2)
148
+ }
281
+FIELD(VTCR, ORGN0, 10, 2)
149
+}
282
+FIELD(VTCR, SH0, 12, 2)
150
+
283
+FIELD(VTCR, TG0, 14, 2)
151
+void kvm_arm_cpu_post_load(ARMCPU *cpu)
284
+FIELD(VTCR, PS, 16, 3)
152
+{
285
+FIELD(VTCR, VS, 19, 1)
153
+ /* KVM virtual time adjustment */
286
+FIELD(VTCR, HA, 21, 1)
154
+ if (cpu->kvm_adjvtime) {
287
+FIELD(VTCR, HD, 22, 1)
155
+ cpu->kvm_vtime = *kvm_arm_get_cpreg_ptr(cpu, KVM_REG_ARM_TIMER_CNT);
288
+FIELD(VTCR, HWU59, 25, 1)
156
+ cpu->kvm_vtime_dirty = true;
289
+FIELD(VTCR, HWU60, 26, 1)
157
+ }
290
+FIELD(VTCR, HWU61, 27, 1)
158
+}
291
+FIELD(VTCR, HWU62, 28, 1)
159
+
292
+FIELD(VTCR, NSW, 29, 1)
160
void kvm_arm_reset_vcpu(ARMCPU *cpu)
293
+FIELD(VTCR, NSA, 30, 1)
161
{
294
+FIELD(VTCR, DS, 32, 1)
162
int ret;
295
+FIELD(VTCR, SL2, 33, 1)
163
@@ -XXX,XX +XXX,XX @@ int kvm_arm_sync_mpstate_to_qemu(ARMCPU *cpu)
296
+
164
return 0;
297
+#define HCRX_ENAS0 (1ULL << 0)
165
}
298
+#define HCRX_ENALS (1ULL << 1)
166
299
+#define HCRX_ENASR (1ULL << 2)
167
+void kvm_arm_get_virtual_time(CPUState *cs)
300
+#define HCRX_FNXS (1ULL << 3)
168
+{
301
+#define HCRX_FGTNXS (1ULL << 4)
169
+ ARMCPU *cpu = ARM_CPU(cs);
302
+#define HCRX_SMPME (1ULL << 5)
170
+ struct kvm_one_reg reg = {
303
+#define HCRX_TALLINT (1ULL << 6)
171
+ .id = KVM_REG_ARM_TIMER_CNT,
304
+#define HCRX_VINMI (1ULL << 7)
172
+ .addr = (uintptr_t)&cpu->kvm_vtime,
305
+#define HCRX_VFNMI (1ULL << 8)
173
+ };
306
+#define HCRX_CMOW (1ULL << 9)
174
+ int ret;
307
+#define HCRX_MCE2 (1ULL << 10)
175
+
308
+#define HCRX_MSCEN (1ULL << 11)
176
+ if (cpu->kvm_vtime_dirty) {
309
+
177
+ return;
310
+#define HPFAR_NS (1ULL << 63)
178
+ }
311
+
179
+
312
+#define HSTR_TTEE (1 << 16)
180
+ ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &reg);
313
+#define HSTR_TJDBX (1 << 17)
181
+ if (ret) {
314
+
182
+ error_report("Failed to get KVM_REG_ARM_TIMER_CNT");
315
+#define CNTHCTL_CNTVMASK (1 << 18)
183
+ abort();
316
+#define CNTHCTL_CNTPMASK (1 << 19)
184
+ }
317
+
185
+
318
/* We use a few fake FSR values for internal purposes in M profile.
186
+ cpu->kvm_vtime_dirty = true;
319
* M profile cores don't have A/R format FSRs, but currently our
187
+}
320
* get_phys_addr() code assumes A/R profile and reports failures via
188
+
189
+void kvm_arm_put_virtual_time(CPUState *cs)
190
+{
191
+ ARMCPU *cpu = ARM_CPU(cs);
192
+ struct kvm_one_reg reg = {
193
+ .id = KVM_REG_ARM_TIMER_CNT,
194
+ .addr = (uintptr_t)&cpu->kvm_vtime,
195
+ };
196
+ int ret;
197
+
198
+ if (!cpu->kvm_vtime_dirty) {
199
+ return;
200
+ }
201
+
202
+ ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &reg);
203
+ if (ret) {
204
+ error_report("Failed to set KVM_REG_ARM_TIMER_CNT");
205
+ abort();
206
+ }
207
+
208
+ cpu->kvm_vtime_dirty = false;
209
+}
210
+
211
int kvm_put_vcpu_events(ARMCPU *cpu)
212
{
213
CPUARMState *env = &cpu->env;
214
@@ -XXX,XX +XXX,XX @@ MemTxAttrs kvm_arch_post_run(CPUState *cs, struct kvm_run *run)
215
return MEMTXATTRS_UNSPECIFIED;
216
}
217
218
+void kvm_arm_vm_state_change(void *opaque, int running, RunState state)
219
+{
220
+ CPUState *cs = opaque;
221
+ ARMCPU *cpu = ARM_CPU(cs);
222
+
223
+ if (running) {
224
+ if (cpu->kvm_adjvtime) {
225
+ kvm_arm_put_virtual_time(cs);
226
+ }
227
+ } else {
228
+ if (cpu->kvm_adjvtime) {
229
+ kvm_arm_get_virtual_time(cs);
230
+ }
231
+ }
232
+}
233
234
int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run)
235
{
236
diff --git a/target/arm/kvm32.c b/target/arm/kvm32.c
237
index XXXXXXX..XXXXXXX 100644
238
--- a/target/arm/kvm32.c
239
+++ b/target/arm/kvm32.c
240
@@ -XXX,XX +XXX,XX @@
241
#include "qemu-common.h"
242
#include "cpu.h"
243
#include "qemu/timer.h"
244
+#include "sysemu/runstate.h"
245
#include "sysemu/kvm.h"
246
#include "kvm_arm.h"
247
#include "internals.h"
248
@@ -XXX,XX +XXX,XX @@ int kvm_arch_init_vcpu(CPUState *cs)
249
return -EINVAL;
250
}
251
252
+ qemu_add_vm_change_state_handler(kvm_arm_vm_state_change, cs);
253
+
254
/* Determine init features for this CPU */
255
memset(cpu->kvm_init_features, 0, sizeof(cpu->kvm_init_features));
256
if (cpu->start_powered_off) {
257
diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
258
index XXXXXXX..XXXXXXX 100644
259
--- a/target/arm/kvm64.c
260
+++ b/target/arm/kvm64.c
261
@@ -XXX,XX +XXX,XX @@
262
#include "qemu/host-utils.h"
263
#include "qemu/main-loop.h"
264
#include "exec/gdbstub.h"
265
+#include "sysemu/runstate.h"
266
#include "sysemu/kvm.h"
267
#include "sysemu/kvm_int.h"
268
#include "kvm_arm.h"
269
@@ -XXX,XX +XXX,XX @@ int kvm_arch_init_vcpu(CPUState *cs)
270
return -EINVAL;
271
}
272
273
+ qemu_add_vm_change_state_handler(kvm_arm_vm_state_change, cs);
274
+
275
/* Determine init features for this CPU */
276
memset(cpu->kvm_init_features, 0, sizeof(cpu->kvm_init_features));
277
if (cpu->start_powered_off) {
278
diff --git a/target/arm/machine.c b/target/arm/machine.c
279
index XXXXXXX..XXXXXXX 100644
280
--- a/target/arm/machine.c
281
+++ b/target/arm/machine.c
282
@@ -XXX,XX +XXX,XX @@ static int cpu_pre_save(void *opaque)
283
/* This should never fail */
284
abort();
285
}
286
+
287
+ /*
288
+ * kvm_arm_cpu_pre_save() must be called after
289
+ * write_kvmstate_to_list()
290
+ */
291
+ kvm_arm_cpu_pre_save(cpu);
292
} else {
293
if (!write_cpustate_to_list(cpu, false)) {
294
/* This should never fail. */
295
@@ -XXX,XX +XXX,XX @@ static int cpu_post_load(void *opaque, int version_id)
296
* we're using it.
297
*/
298
write_list_to_cpustate(cpu);
299
+ kvm_arm_cpu_post_load(cpu);
300
} else {
301
if (!write_list_to_cpustate(cpu)) {
302
return -1;
303
--
321
--
304
2.20.1
322
2.34.1
305
323
306
324
diff view generated by jsdifflib
1
The num-lines property of the TYPE_OR_GATE device sets the number
1
The timer _EL02 registers should UNDEF for invalid accesses from EL2
2
of input lines it has. An assert() in or_irq_realize() restricts
2
or EL3 when HCR_EL2.E2H == 0, not take a cp access trap. We were
3
this to the maximum supported by the implementation. However we
3
delivering the exception to EL2 with the wrong syndrome.
4
got the condition in the assert wrong: it should be using <=,
5
because num-lines == MAX_OR_LINES is permitted, and means that
6
all entries from 0 to MAX_OR_LINES-1 in the s->levels[] array
7
are used.
8
4
9
We didn't notice this previously because no user has so far
10
needed that many input lines.
11
12
Reported-by: Guenter Roeck <linux@roeck-us.net>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
Reviewed-by: Guenter Roeck <linux@roeck-us.net>
7
Message-id: 20240301183219.2424889-3-peter.maydell@linaro.org
16
Message-id: 20200120142235.10432-1-peter.maydell@linaro.org
17
---
8
---
18
hw/core/or-irq.c | 2 +-
9
target/arm/helper.c | 2 +-
19
1 file changed, 1 insertion(+), 1 deletion(-)
10
1 file changed, 1 insertion(+), 1 deletion(-)
20
11
21
diff --git a/hw/core/or-irq.c b/hw/core/or-irq.c
12
diff --git a/target/arm/helper.c b/target/arm/helper.c
22
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
23
--- a/hw/core/or-irq.c
14
--- a/target/arm/helper.c
24
+++ b/hw/core/or-irq.c
15
+++ b/target/arm/helper.c
25
@@ -XXX,XX +XXX,XX @@ static void or_irq_realize(DeviceState *dev, Error **errp)
16
@@ -XXX,XX +XXX,XX @@ static CPAccessResult e2h_access(CPUARMState *env, const ARMCPRegInfo *ri,
26
{
17
return CP_ACCESS_OK;
27
qemu_or_irq *s = OR_IRQ(dev);
18
}
28
19
if (!(arm_hcr_el2_eff(env) & HCR_E2H)) {
29
- assert(s->num_lines < MAX_OR_LINES);
20
- return CP_ACCESS_TRAP;
30
+ assert(s->num_lines <= MAX_OR_LINES);
21
+ return CP_ACCESS_TRAP_UNCATEGORIZED;
31
22
}
32
qdev_init_gpio_in(dev, or_irq_handler, s->num_lines);
23
return CP_ACCESS_OK;
33
}
24
}
34
--
25
--
35
2.20.1
26
2.34.1
36
37
diff view generated by jsdifflib
1
From: Damien Hedde <damien.hedde@greensocs.com>
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
In qdev_set_parent_bus(), when changing the parent bus of a
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
realized device, if the source and destination buses are not in the
5
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
5
same reset state, some adaptations are required. This patch adds
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
needed call to resettable_change_parent() to make sure a device reset
7
Message-id: 20240301183219.2424889-4-peter.maydell@linaro.org
7
state stays coherent with its parent bus.
8
---
9
target/arm/internals.h | 27 +++++++++++++++++++++++++--
10
target/arm/helper.c | 9 ++++-----
11
2 files changed, 29 insertions(+), 7 deletions(-)
8
12
9
The addition is a no-op if:
13
diff --git a/target/arm/internals.h b/target/arm/internals.h
10
1. the device being parented is not realized.
11
2. the device is realized, but both buses are not under reset.
12
13
Case 2 means that as long as qdev_set_parent_bus() is called
14
during the machine realization procedure (which is before the
15
machine reset so nothing is in reset), it is a no op.
16
17
There are 52 call sites of qdev_set_parent_bus(). All but one fall
18
into the no-op case:
19
+ 29 trivial calls related to virtio (in hw/{s390x,display,virtio}/
20
{vhost,virtio}-xxx.c) to set a vdev(or vgpu) composing device
21
parent bus just before realizing the same vdev(vgpu).
22
+ hw/core/qdev.c: when creating a device in qdev_try_create()
23
+ hw/core/sysbus.c: when initializing a device in the sysbus
24
+ hw/i386/amd_iommu.c: before realizing AMDVIState/pci
25
+ hw/isa/piix4.c: before realizing PIIX4State/rtc
26
+ hw/misc/auxbus.c: when creating an AUXBus
27
+ hw/misc/auxbus.c: when creating an AUXBus child
28
+ hw/misc/macio/macio.c: when initializing a MACIOState child
29
+ hw/misc/macio/macio.c: before realizing NewWorldMacIOState/pmu
30
+ hw/misc/macio/macio.c: before realizing NewWorldMacIOState/cuda
31
+ hw/net/virtio-net.c: Used for migration when using the failover
32
mechanism to migration a vfio-pci/net. It is
33
a no-op because at this point the device is
34
already on the bus.
35
+ hw/pci-host/designware.c: before realizing DesignwarePCIEHost/root
36
+ hw/pci-host/gpex.c: before realizing GPEXHost/root
37
+ hw/pci-host/prep.c: when initialiazing PREPPCIState/pci_dev
38
+ hw/pci-host/q35.c: before realizing Q35PCIHost/mch
39
+ hw/pci-host/versatile.c: when initializing PCIVPBState/pci_dev
40
+ hw/pci-host/xilinx-pcie.c: before realizing XilinxPCIEHost/root
41
+ hw/s390x/event-facility.c: when creating SCLPEventFacility/
42
TYPE_SCLP_QUIESCE
43
+ hw/s390x/event-facility.c: ditto with SCLPEventFacility/
44
TYPE_SCLP_CPU_HOTPLUG
45
+ hw/s390x/sclp.c: Not trivial because it is called on a SLCPDevice
46
just after realizing it. Ok because at this point the destination
47
bus (sysbus) is not in reset; the realize step is before the
48
machine reset.
49
+ hw/sd/core.c: Not OK. Used in sdbus_reparent_card(). See below.
50
+ hw/ssi/ssi.c: Used to put spi slave on spi bus and connect the cs
51
line in ssi_auto_connect_slave(). Ok because this function is only
52
used in realize step in hw/ssi/aspeed_smc.ci, hw/ssi/imx_spi.c,
53
hw/ssi/mss-spi.c, hw/ssi/xilinx_spi.c and hw/ssi/xilinx_spips.c.
54
+ hw/xen/xen-legacy-backend.c: when creating a XenLegacyDevice device
55
+ qdev-monitor.c: in device hotplug creation procedure before realize
56
57
Note that this commit alone will have no effect, right now there is no
58
use of resettable API to reset anything. So a bus will never be tagged
59
as in-reset by this same API.
60
61
The one place where side-effect will occurs is in hw/sd/core.c in
62
sdbus_reparent_card(). This function is only used in the raspi machines,
63
including during the sysbus reset procedure. This case will be
64
carrefully handled when doing the multiple phase reset transition.
65
66
Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
67
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
68
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
69
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
70
Message-id: 20200123132823.1117486-7-damien.hedde@greensocs.com
71
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
72
---
73
hw/core/qdev.c | 16 +++++++++++-----
74
1 file changed, 11 insertions(+), 5 deletions(-)
75
76
diff --git a/hw/core/qdev.c b/hw/core/qdev.c
77
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
78
--- a/hw/core/qdev.c
15
--- a/target/arm/internals.h
79
+++ b/hw/core/qdev.c
16
+++ b/target/arm/internals.h
80
@@ -XXX,XX +XXX,XX @@ static void bus_add_child(BusState *bus, DeviceState *child)
17
@@ -XXX,XX +XXX,XX @@ FIELD(VTCR, SL2, 33, 1)
81
18
#define HSTR_TTEE (1 << 16)
82
void qdev_set_parent_bus(DeviceState *dev, BusState *bus)
19
#define HSTR_TJDBX (1 << 17)
20
21
-#define CNTHCTL_CNTVMASK (1 << 18)
22
-#define CNTHCTL_CNTPMASK (1 << 19)
23
+/*
24
+ * Depending on the value of HCR_EL2.E2H, bits 0 and 1
25
+ * have different bit definitions, and EL1PCTEN might be
26
+ * bit 0 or bit 10. We use _E2H1 and _E2H0 suffixes to
27
+ * disambiguate if necessary.
28
+ */
29
+FIELD(CNTHCTL, EL0PCTEN_E2H1, 0, 1)
30
+FIELD(CNTHCTL, EL0VCTEN_E2H1, 1, 1)
31
+FIELD(CNTHCTL, EL1PCTEN_E2H0, 0, 1)
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
51
diff --git a/target/arm/helper.c b/target/arm/helper.c
52
index XXXXXXX..XXXXXXX 100644
53
--- a/target/arm/helper.c
54
+++ b/target/arm/helper.c
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,
83
{
67
{
84
- bool replugging = dev->parent_bus != NULL;
68
ARMCPU *cpu = env_archcpu(env);
85
+ BusState *old_parent_bus = dev->parent_bus;
69
uint32_t oldval = env->cp15.cnthctl_el2;
86
70
-
87
- if (replugging) {
71
raw_write(env, ri, value);
88
+ if (old_parent_bus) {
72
89
trace_qdev_update_parent_bus(dev, object_get_typename(OBJECT(dev)),
73
- if ((oldval ^ value) & CNTHCTL_CNTVMASK) {
90
- dev->parent_bus, object_get_typename(OBJECT(dev->parent_bus)),
74
+ if ((oldval ^ value) & R_CNTHCTL_CNTVMASK_MASK) {
91
+ old_parent_bus, object_get_typename(OBJECT(old_parent_bus)),
75
gt_update_irq(cpu, GTIMER_VIRT);
92
OBJECT(bus), object_get_typename(OBJECT(bus)));
76
- } else if ((oldval ^ value) & CNTHCTL_CNTPMASK) {
93
/*
77
+ } else if ((oldval ^ value) & R_CNTHCTL_CNTPMASK_MASK) {
94
* Keep a reference to the device while it's not plugged into
78
gt_update_irq(cpu, GTIMER_PHYS);
95
* any bus, to avoid it potentially evaporating when it is
96
* dereffed in bus_remove_child().
97
+ * Also keep the ref of the parent bus until the end, so that
98
+ * we can safely call resettable_change_parent() below.
99
*/
100
object_ref(OBJECT(dev));
101
bus_remove_child(dev->parent_bus, dev);
102
- object_unref(OBJECT(dev->parent_bus));
103
}
104
dev->parent_bus = bus;
105
object_ref(OBJECT(bus));
106
bus_add_child(bus, dev);
107
- if (replugging) {
108
+ if (dev->realized) {
109
+ resettable_change_parent(OBJECT(dev), OBJECT(bus),
110
+ OBJECT(old_parent_bus));
111
+ }
112
+ if (old_parent_bus) {
113
+ object_unref(OBJECT(old_parent_bus));
114
object_unref(OBJECT(dev));
115
}
79
}
116
}
80
}
117
--
81
--
118
2.20.1
82
2.34.1
119
83
120
84
diff view generated by jsdifflib
1
From: Andrew Jones <drjones@redhat.com>
1
Don't allow the guest to write CNTHCTL_EL2 bits which don't exist.
2
This is not strictly architecturally required, but it is how we've
3
tended to implement registers more recently.
2
4
3
kvm-no-adjvtime is a KVM specific CPU property and a first of its
5
In particular, bits [19:18] are only present with FEAT_RME,
4
kind. To accommodate it we also add kvm_arm_add_vcpu_properties()
6
and bits [17:12] will only be present with FEAT_ECV.
5
and a KVM specific CPU properties description to the CPU features
6
document.
7
7
8
Signed-off-by: Andrew Jones <drjones@redhat.com>
9
Message-id: 20200120101023.16030-7-drjones@redhat.com
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20240301183219.2424889-5-peter.maydell@linaro.org
12
---
11
---
13
include/hw/arm/virt.h | 1 +
12
target/arm/helper.c | 18 ++++++++++++++++++
14
target/arm/kvm_arm.h | 11 ++++++++++
13
1 file changed, 18 insertions(+)
15
hw/arm/virt.c | 8 ++++++++
16
target/arm/cpu.c | 2 ++
17
target/arm/cpu64.c | 1 +
18
target/arm/kvm.c | 28 +++++++++++++++++++++++++
19
target/arm/monitor.c | 1 +
20
tests/qtest/arm-cpu-features.c | 4 ++++
21
docs/arm-cpu-features.rst | 37 +++++++++++++++++++++++++++++++++-
22
9 files changed, 92 insertions(+), 1 deletion(-)
23
14
24
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.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/include/hw/arm/virt.h
17
--- a/target/arm/helper.c
27
+++ b/include/hw/arm/virt.h
18
+++ b/target/arm/helper.c
28
@@ -XXX,XX +XXX,XX @@ typedef struct {
19
@@ -XXX,XX +XXX,XX @@ static void gt_cnthctl_write(CPUARMState *env, const ARMCPRegInfo *ri,
29
bool smbios_old_sys_ver;
20
{
30
bool no_highmem_ecam;
21
ARMCPU *cpu = env_archcpu(env);
31
bool no_ged; /* Machines < 4.2 has no support for ACPI GED device */
22
uint32_t oldval = env->cp15.cnthctl_el2;
32
+ bool kvm_no_adjvtime;
23
+ uint32_t valid_mask =
33
} VirtMachineClass;
24
+ R_CNTHCTL_EL0PCTEN_E2H1_MASK |
34
25
+ R_CNTHCTL_EL0VCTEN_E2H1_MASK |
35
typedef struct {
26
+ R_CNTHCTL_EVNTEN_MASK |
36
diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h
27
+ R_CNTHCTL_EVNTDIR_MASK |
37
index XXXXXXX..XXXXXXX 100644
28
+ R_CNTHCTL_EVNTI_MASK |
38
--- a/target/arm/kvm_arm.h
29
+ R_CNTHCTL_EL0VTEN_MASK |
39
+++ b/target/arm/kvm_arm.h
30
+ R_CNTHCTL_EL0PTEN_MASK |
40
@@ -XXX,XX +XXX,XX @@ void kvm_arm_sve_get_vls(CPUState *cs, unsigned long *map);
31
+ R_CNTHCTL_EL1PCTEN_E2H1_MASK |
41
*/
32
+ R_CNTHCTL_EL1PTEN_MASK;
42
void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu);
43
44
+/**
45
+ * kvm_arm_add_vcpu_properties:
46
+ * @obj: The CPU object to add the properties to
47
+ *
48
+ * Add all KVM specific CPU properties to the CPU object. These
49
+ * are the CPU properties with "kvm-" prefixed names.
50
+ */
51
+void kvm_arm_add_vcpu_properties(Object *obj);
52
+
33
+
53
/**
34
+ if (cpu_isar_feature(aa64_rme, cpu)) {
54
* kvm_arm_aarch32_supported:
35
+ valid_mask |= R_CNTHCTL_CNTVMASK_MASK | R_CNTHCTL_CNTPMASK_MASK;
55
* @cs: CPUState
56
@@ -XXX,XX +XXX,XX @@ static inline void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu)
57
cpu->host_cpu_probe_failed = true;
58
}
59
60
+static inline void kvm_arm_add_vcpu_properties(Object *obj) {}
61
+
62
static inline bool kvm_arm_aarch32_supported(CPUState *cs)
63
{
64
return false;
65
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
66
index XXXXXXX..XXXXXXX 100644
67
--- a/hw/arm/virt.c
68
+++ b/hw/arm/virt.c
69
@@ -XXX,XX +XXX,XX @@ static void machvirt_init(MachineState *machine)
70
}
71
}
72
73
+ if (vmc->kvm_no_adjvtime &&
74
+ object_property_find(cpuobj, "kvm-no-adjvtime", NULL)) {
75
+ object_property_set_bool(cpuobj, true, "kvm-no-adjvtime", NULL);
76
+ }
77
+
78
if (vmc->no_pmu && object_property_find(cpuobj, "pmu", NULL)) {
79
object_property_set_bool(cpuobj, false, "pmu", NULL);
80
}
81
@@ -XXX,XX +XXX,XX @@ DEFINE_VIRT_MACHINE_AS_LATEST(5, 0)
82
83
static void virt_machine_4_2_options(MachineClass *mc)
84
{
85
+ VirtMachineClass *vmc = VIRT_MACHINE_CLASS(OBJECT_CLASS(mc));
86
+
87
virt_machine_5_0_options(mc);
88
compat_props_add(mc->compat_props, hw_compat_4_2, hw_compat_4_2_len);
89
+ vmc->kvm_no_adjvtime = true;
90
}
91
DEFINE_VIRT_MACHINE(4, 2)
92
93
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
94
index XXXXXXX..XXXXXXX 100644
95
--- a/target/arm/cpu.c
96
+++ b/target/arm/cpu.c
97
@@ -XXX,XX +XXX,XX @@ static void arm_max_initfn(Object *obj)
98
99
if (kvm_enabled()) {
100
kvm_arm_set_cpu_features_from_host(cpu);
101
+ kvm_arm_add_vcpu_properties(obj);
102
} else {
103
cortex_a15_initfn(obj);
104
105
@@ -XXX,XX +XXX,XX @@ static void arm_host_initfn(Object *obj)
106
if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) {
107
aarch64_add_sve_properties(obj);
108
}
109
+ kvm_arm_add_vcpu_properties(obj);
110
arm_cpu_post_init(obj);
111
}
112
113
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
114
index XXXXXXX..XXXXXXX 100644
115
--- a/target/arm/cpu64.c
116
+++ b/target/arm/cpu64.c
117
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
118
119
if (kvm_enabled()) {
120
kvm_arm_set_cpu_features_from_host(cpu);
121
+ kvm_arm_add_vcpu_properties(obj);
122
} else {
123
uint64_t t;
124
uint32_t u;
125
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
126
index XXXXXXX..XXXXXXX 100644
127
--- a/target/arm/kvm.c
128
+++ b/target/arm/kvm.c
129
@@ -XXX,XX +XXX,XX @@
130
#include "qemu/timer.h"
131
#include "qemu/error-report.h"
132
#include "qemu/main-loop.h"
133
+#include "qom/object.h"
134
+#include "qapi/error.h"
135
#include "sysemu/sysemu.h"
136
#include "sysemu/kvm.h"
137
#include "sysemu/kvm_int.h"
138
@@ -XXX,XX +XXX,XX @@ void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu)
139
env->features = arm_host_cpu_features.features;
140
}
141
142
+static bool kvm_no_adjvtime_get(Object *obj, Error **errp)
143
+{
144
+ return !ARM_CPU(obj)->kvm_adjvtime;
145
+}
146
+
147
+static void kvm_no_adjvtime_set(Object *obj, bool value, Error **errp)
148
+{
149
+ ARM_CPU(obj)->kvm_adjvtime = !value;
150
+}
151
+
152
+/* KVM VCPU properties should be prefixed with "kvm-". */
153
+void kvm_arm_add_vcpu_properties(Object *obj)
154
+{
155
+ if (!kvm_enabled()) {
156
+ return;
157
+ }
36
+ }
158
+
37
+
159
+ ARM_CPU(obj)->kvm_adjvtime = true;
38
+ /* Clear RES0 bits */
160
+ object_property_add_bool(obj, "kvm-no-adjvtime", kvm_no_adjvtime_get,
39
+ value &= valid_mask;
161
+ kvm_no_adjvtime_set, &error_abort);
162
+ object_property_set_description(obj, "kvm-no-adjvtime",
163
+ "Set on to disable the adjustment of "
164
+ "the virtual counter. VM stopped time "
165
+ "will be counted.", &error_abort);
166
+}
167
+
40
+
168
bool kvm_arm_pmu_supported(CPUState *cpu)
41
raw_write(env, ri, value);
169
{
42
170
return kvm_check_extension(cpu->kvm_state, KVM_CAP_ARM_PMU_V3);
43
if ((oldval ^ value) & R_CNTHCTL_CNTVMASK_MASK) {
171
diff --git a/target/arm/monitor.c b/target/arm/monitor.c
172
index XXXXXXX..XXXXXXX 100644
173
--- a/target/arm/monitor.c
174
+++ b/target/arm/monitor.c
175
@@ -XXX,XX +XXX,XX @@ static const char *cpu_model_advertised_features[] = {
176
"sve128", "sve256", "sve384", "sve512",
177
"sve640", "sve768", "sve896", "sve1024", "sve1152", "sve1280",
178
"sve1408", "sve1536", "sve1664", "sve1792", "sve1920", "sve2048",
179
+ "kvm-no-adjvtime",
180
NULL
181
};
182
183
diff --git a/tests/qtest/arm-cpu-features.c b/tests/qtest/arm-cpu-features.c
184
index XXXXXXX..XXXXXXX 100644
185
--- a/tests/qtest/arm-cpu-features.c
186
+++ b/tests/qtest/arm-cpu-features.c
187
@@ -XXX,XX +XXX,XX @@ static void test_query_cpu_model_expansion(const void *data)
188
assert_has_feature_enabled(qts, "cortex-a15", "pmu");
189
assert_has_not_feature(qts, "cortex-a15", "aarch64");
190
191
+ assert_has_not_feature(qts, "max", "kvm-no-adjvtime");
192
+
193
if (g_str_equal(qtest_get_arch(), "aarch64")) {
194
assert_has_feature_enabled(qts, "max", "aarch64");
195
assert_has_feature_enabled(qts, "max", "sve");
196
@@ -XXX,XX +XXX,XX @@ static void test_query_cpu_model_expansion_kvm(const void *data)
197
return;
198
}
199
200
+ assert_has_feature_disabled(qts, "host", "kvm-no-adjvtime");
201
+
202
if (g_str_equal(qtest_get_arch(), "aarch64")) {
203
bool kvm_supports_sve;
204
char max_name[8], name[8];
205
diff --git a/docs/arm-cpu-features.rst b/docs/arm-cpu-features.rst
206
index XXXXXXX..XXXXXXX 100644
207
--- a/docs/arm-cpu-features.rst
208
+++ b/docs/arm-cpu-features.rst
209
@@ -XXX,XX +XXX,XX @@ supporting the feature or only supporting the feature under certain
210
configurations. For example, the `aarch64` CPU feature, which, when
211
disabled, enables the optional AArch32 CPU feature, is only supported
212
when using the KVM accelerator and when running on a host CPU type that
213
-supports the feature.
214
+supports the feature. While `aarch64` currently only works with KVM,
215
+it could work with TCG. CPU features that are specific to KVM are
216
+prefixed with "kvm-" and are described in "KVM VCPU Features".
217
218
CPU Feature Probing
219
===================
220
@@ -XXX,XX +XXX,XX @@ disabling many SVE vector lengths would be quite verbose, the `sve<N>` CPU
221
properties have special semantics (see "SVE CPU Property Parsing
222
Semantics").
223
224
+KVM VCPU Features
225
+=================
226
+
227
+KVM VCPU features are CPU features that are specific to KVM, such as
228
+paravirt features or features that enable CPU virtualization extensions.
229
+The features' CPU properties are only available when KVM is enabled and
230
+are named with the prefix "kvm-". KVM VCPU features may be probed,
231
+enabled, and disabled in the same way as other CPU features. Below is
232
+the list of KVM VCPU features and their descriptions.
233
+
234
+ kvm-no-adjvtime By default kvm-no-adjvtime is disabled. This
235
+ means that by default the virtual time
236
+ adjustment is enabled (vtime is *not not*
237
+ adjusted).
238
+
239
+ When virtual time adjustment is enabled each
240
+ time the VM transitions back to running state
241
+ the VCPU's virtual counter is updated to ensure
242
+ stopped time is not counted. This avoids time
243
+ jumps surprising guest OSes and applications,
244
+ as long as they use the virtual counter for
245
+ timekeeping. However it has the side effect of
246
+ the virtual and physical counters diverging.
247
+ All timekeeping based on the virtual counter
248
+ will appear to lag behind any timekeeping that
249
+ does not subtract VM stopped time. The guest
250
+ may resynchronize its virtual counter with
251
+ other time sources as needed.
252
+
253
+ Enable kvm-no-adjvtime to disable virtual time
254
+ adjustment, also restoring the legacy (pre-5.0)
255
+ behavior.
256
+
257
SVE CPU Properties
258
==================
259
260
--
44
--
261
2.20.1
45
2.34.1
262
263
diff view generated by jsdifflib
1
From: Damien Hedde <damien.hedde@greensocs.com>
1
The functionality defined by ID_AA64MMFR0_EL1.ECV == 1 is:
2
* four new trap bits for various counter and timer registers
3
* the CNTHCTL_EL2.EVNTIS and CNTKCTL_EL1.EVNTIS bits which control
4
scaling of the event stream. This is a no-op for us, because we don't
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.
2
15
3
Deprecate device_legacy_reset(), qdev_reset_all() and
16
In this commit we implement the trap handling and permit the new
4
qbus_reset_all() to be replaced by new functions
17
CNTHCTL_EL2 bits to be written.
5
device_cold_reset() and bus_cold_reset() which uses resettable API.
6
18
7
Also introduce resettable_cold_reset_fn() which may be used as a
19
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
replacement for qdev_reset_all_fn and qbus_reset_all_fn().
20
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
21
Message-id: 20240301183219.2424889-6-peter.maydell@linaro.org
22
---
23
target/arm/cpu-features.h | 5 ++++
24
target/arm/helper.c | 51 +++++++++++++++++++++++++++++++++++----
25
2 files changed, 51 insertions(+), 5 deletions(-)
9
26
10
Following patches will be needed to look at legacy reset call sites
27
diff --git a/target/arm/cpu-features.h b/target/arm/cpu-features.h
11
and switch to resettable api. The legacy functions will be removed
12
when unused.
13
14
Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
15
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
16
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
17
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
18
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
19
Message-id: 20200123132823.1117486-9-damien.hedde@greensocs.com
20
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
---
22
include/hw/qdev-core.h | 27 +++++++++++++++++++++++++++
23
include/hw/resettable.h | 9 +++++++++
24
hw/core/bus.c | 5 +++++
25
hw/core/qdev.c | 5 +++++
26
hw/core/resettable.c | 5 +++++
27
5 files changed, 51 insertions(+)
28
29
diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
30
index XXXXXXX..XXXXXXX 100644
28
index XXXXXXX..XXXXXXX 100644
31
--- a/include/hw/qdev-core.h
29
--- a/target/arm/cpu-features.h
32
+++ b/include/hw/qdev-core.h
30
+++ b/target/arm/cpu-features.h
33
@@ -XXX,XX +XXX,XX @@ int qdev_walk_children(DeviceState *dev,
31
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa64_fgt(const ARMISARegisters *id)
34
qdev_walkerfn *post_devfn, qbus_walkerfn *post_busfn,
32
return FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, FGT) != 0;
35
void *opaque);
36
37
+/**
38
+ * @qdev_reset_all:
39
+ * Reset @dev. See @qbus_reset_all() for more details.
40
+ *
41
+ * Note: This function is deprecated and will be removed when it becomes unused.
42
+ * Please use device_cold_reset() now.
43
+ */
44
void qdev_reset_all(DeviceState *dev);
45
void qdev_reset_all_fn(void *opaque);
46
47
@@ -XXX,XX +XXX,XX @@ void qdev_reset_all_fn(void *opaque);
48
* hard reset means that qbus_reset_all will reset all state of the device.
49
* For PCI devices, for example, this will include the base address registers
50
* or configuration space.
51
+ *
52
+ * Note: This function is deprecated and will be removed when it becomes unused.
53
+ * Please use bus_cold_reset() now.
54
*/
55
void qbus_reset_all(BusState *bus);
56
void qbus_reset_all_fn(void *opaque);
57
58
+/**
59
+ * device_cold_reset:
60
+ * Reset device @dev and perform a recursive processing using the resettable
61
+ * interface. It triggers a RESET_TYPE_COLD.
62
+ */
63
+void device_cold_reset(DeviceState *dev);
64
+
65
+/**
66
+ * bus_cold_reset:
67
+ *
68
+ * Reset bus @bus and perform a recursive processing using the resettable
69
+ * interface. It triggers a RESET_TYPE_COLD.
70
+ */
71
+void bus_cold_reset(BusState *bus);
72
+
73
/**
74
* device_is_in_reset:
75
* Return true if the device @dev is currently being reset.
76
@@ -XXX,XX +XXX,XX @@ void qdev_machine_init(void);
77
* device_legacy_reset:
78
*
79
* Reset a single device (by calling the reset method).
80
+ * Note: This function is deprecated and will be removed when it becomes unused.
81
+ * Please use device_cold_reset() now.
82
*/
83
void device_legacy_reset(DeviceState *dev);
84
85
diff --git a/include/hw/resettable.h b/include/hw/resettable.h
86
index XXXXXXX..XXXXXXX 100644
87
--- a/include/hw/resettable.h
88
+++ b/include/hw/resettable.h
89
@@ -XXX,XX +XXX,XX @@ bool resettable_is_in_reset(Object *obj);
90
*/
91
void resettable_change_parent(Object *obj, Object *newp, Object *oldp);
92
93
+/**
94
+ * resettable_cold_reset_fn:
95
+ * Helper to call resettable_reset((Object *) opaque, RESET_TYPE_COLD).
96
+ *
97
+ * This function is typically useful to register a reset handler with
98
+ * qemu_register_reset.
99
+ */
100
+void resettable_cold_reset_fn(void *opaque);
101
+
102
/**
103
* resettable_class_set_parent_phases:
104
*
105
diff --git a/hw/core/bus.c b/hw/core/bus.c
106
index XXXXXXX..XXXXXXX 100644
107
--- a/hw/core/bus.c
108
+++ b/hw/core/bus.c
109
@@ -XXX,XX +XXX,XX @@ int qbus_walk_children(BusState *bus,
110
return 0;
111
}
33
}
112
34
113
+void bus_cold_reset(BusState *bus)
35
+static inline bool isar_feature_aa64_ecv_traps(const ARMISARegisters *id)
114
+{
36
+{
115
+ resettable_reset(OBJECT(bus), RESET_TYPE_COLD);
37
+ return FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, ECV) > 0;
116
+}
38
+}
117
+
39
+
118
bool bus_is_in_reset(BusState *bus)
40
static inline bool isar_feature_aa64_vh(const ARMISARegisters *id)
119
{
41
{
120
return resettable_is_in_reset(OBJECT(bus));
42
return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, VH) != 0;
121
diff --git a/hw/core/qdev.c b/hw/core/qdev.c
43
diff --git a/target/arm/helper.c b/target/arm/helper.c
122
index XXXXXXX..XXXXXXX 100644
44
index XXXXXXX..XXXXXXX 100644
123
--- a/hw/core/qdev.c
45
--- a/target/arm/helper.c
124
+++ b/hw/core/qdev.c
46
+++ b/target/arm/helper.c
125
@@ -XXX,XX +XXX,XX @@ void qbus_reset_all_fn(void *opaque)
47
@@ -XXX,XX +XXX,XX @@ static CPAccessResult gt_counter_access(CPUARMState *env, int timeridx,
126
qbus_reset_all(bus);
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;
127
}
96
}
128
97
129
+void device_cold_reset(DeviceState *dev)
98
+static CPAccessResult access_el1nvpct(CPUARMState *env, const ARMCPRegInfo *ri,
99
+ bool isread)
130
+{
100
+{
131
+ resettable_reset(OBJECT(dev), RESET_TYPE_COLD);
101
+ if (arm_current_el(env) == 1) {
102
+ /* This must be a FEAT_NV access with NVx == 101 */
103
+ if (FIELD_EX64(env->cp15.cnthctl_el2, CNTHCTL, EL1NVPCT)) {
104
+ return CP_ACCESS_TRAP_EL2;
105
+ }
106
+ }
107
+ return e2h_access(env, ri, isread);
132
+}
108
+}
133
+
109
+
134
bool device_is_in_reset(DeviceState *dev)
110
+static CPAccessResult access_el1nvvct(CPUARMState *env, const ARMCPRegInfo *ri,
135
{
111
+ bool isread)
136
return resettable_is_in_reset(OBJECT(dev));
137
diff --git a/hw/core/resettable.c b/hw/core/resettable.c
138
index XXXXXXX..XXXXXXX 100644
139
--- a/hw/core/resettable.c
140
+++ b/hw/core/resettable.c
141
@@ -XXX,XX +XXX,XX @@ void resettable_change_parent(Object *obj, Object *newp, Object *oldp)
142
}
143
}
144
145
+void resettable_cold_reset_fn(void *opaque)
146
+{
112
+{
147
+ resettable_reset((Object *) opaque, RESET_TYPE_COLD);
113
+ if (arm_current_el(env) == 1) {
114
+ /* This must be a FEAT_NV access with NVx == 101 */
115
+ if (FIELD_EX64(env->cp15.cnthctl_el2, CNTHCTL, EL1NVVCT)) {
116
+ return CP_ACCESS_TRAP_EL2;
117
+ }
118
+ }
119
+ return e2h_access(env, ri, isread);
148
+}
120
+}
149
+
121
+
150
void resettable_class_set_parent_phases(ResettableClass *rc,
122
/* Test if system register redirection is to occur in the current state. */
151
ResettableEnterPhase enter,
123
static bool redirect_for_e2h(CPUARMState *env)
152
ResettableHoldPhase hold,
124
{
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
};
153
--
159
--
154
2.20.1
160
2.34.1
155
156
diff view generated by jsdifflib
1
From: Andrew Jeffery <andrew@aj.id.au>
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
The AST2600 includes a second cut-down version of the SD/MMC controller
8
For QEMU, all our system registers are self-synchronized, so we can
4
found in the AST2500, named the eMMC controller. It's cut down in the
9
simply copy the existing implementation of CNTPCT_EL0 and CNTVCT_EL0
5
sense that it only supports one slot rather than two, but it brings the
10
to the new register encodings.
6
total number of slots supported by the AST2600 to three.
7
11
8
The existing code assumed that the SD controller always provided two
12
This means we now implement all the functionality required for
9
slots. Rework the SDHCI object to expose the number of slots as a
13
ID_AA64MMFR0_EL1.ECV == 0b0001.
10
property to be set by the SoC configuration.
11
14
12
Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
13
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
14
Reviewed-by: Cédric Le Goater <clg@kaod.org>
15
Signed-off-by: Cédric Le Goater <clg@kaod.org>
16
Message-id: 20200114103433.30534-2-clg@kaod.org
17
[PMM: fixed up to use device_class_set_props()]
18
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
19
---
18
---
20
include/hw/sd/aspeed_sdhci.h | 1 +
19
target/arm/helper.c | 43 +++++++++++++++++++++++++++++++++++++++++++
21
hw/arm/aspeed.c | 2 +-
20
1 file changed, 43 insertions(+)
22
hw/arm/aspeed_ast2600.c | 2 ++
23
hw/arm/aspeed_soc.c | 2 ++
24
hw/sd/aspeed_sdhci.c | 11 +++++++++--
25
5 files changed, 15 insertions(+), 3 deletions(-)
26
21
27
diff --git a/include/hw/sd/aspeed_sdhci.h b/include/hw/sd/aspeed_sdhci.h
22
diff --git a/target/arm/helper.c b/target/arm/helper.c
28
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
29
--- a/include/hw/sd/aspeed_sdhci.h
24
--- a/target/arm/helper.c
30
+++ b/include/hw/sd/aspeed_sdhci.h
25
+++ b/target/arm/helper.c
31
@@ -XXX,XX +XXX,XX @@ typedef struct AspeedSDHCIState {
26
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo generic_timer_cp_reginfo[] = {
32
SysBusDevice parent;
33
34
SDHCIState slots[ASPEED_SDHCI_NUM_SLOTS];
35
+ uint8_t num_slots;
36
37
MemoryRegion iomem;
38
qemu_irq irq;
39
diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
40
index XXXXXXX..XXXXXXX 100644
41
--- a/hw/arm/aspeed.c
42
+++ b/hw/arm/aspeed.c
43
@@ -XXX,XX +XXX,XX @@ static void aspeed_machine_init(MachineState *machine)
44
amc->i2c_init(bmc);
45
}
46
47
- for (i = 0; i < ARRAY_SIZE(bmc->soc.sdhci.slots); i++) {
48
+ for (i = 0; i < bmc->soc.sdhci.num_slots; i++) {
49
SDHCIState *sdhci = &bmc->soc.sdhci.slots[i];
50
DriveInfo *dinfo = drive_get_next(IF_SD);
51
BlockBackend *blk;
52
diff --git a/hw/arm/aspeed_ast2600.c b/hw/arm/aspeed_ast2600.c
53
index XXXXXXX..XXXXXXX 100644
54
--- a/hw/arm/aspeed_ast2600.c
55
+++ b/hw/arm/aspeed_ast2600.c
56
@@ -XXX,XX +XXX,XX @@ static void aspeed_soc_ast2600_init(Object *obj)
57
sysbus_init_child_obj(obj, "sdc", OBJECT(&s->sdhci), sizeof(s->sdhci),
58
TYPE_ASPEED_SDHCI);
59
60
+ object_property_set_int(OBJECT(&s->sdhci), 2, "num-slots", &error_abort);
61
+
62
/* Init sd card slot class here so that they're under the correct parent */
63
for (i = 0; i < ASPEED_SDHCI_NUM_SLOTS; ++i) {
64
sysbus_init_child_obj(obj, "sdhci[*]", OBJECT(&s->sdhci.slots[i]),
65
diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c
66
index XXXXXXX..XXXXXXX 100644
67
--- a/hw/arm/aspeed_soc.c
68
+++ b/hw/arm/aspeed_soc.c
69
@@ -XXX,XX +XXX,XX @@ static void aspeed_soc_init(Object *obj)
70
sysbus_init_child_obj(obj, "sdc", OBJECT(&s->sdhci), sizeof(s->sdhci),
71
TYPE_ASPEED_SDHCI);
72
73
+ object_property_set_int(OBJECT(&s->sdhci), 2, "num-slots", &error_abort);
74
+
75
/* Init sd card slot class here so that they're under the correct parent */
76
for (i = 0; i < ASPEED_SDHCI_NUM_SLOTS; ++i) {
77
sysbus_init_child_obj(obj, "sdhci[*]", OBJECT(&s->sdhci.slots[i]),
78
diff --git a/hw/sd/aspeed_sdhci.c b/hw/sd/aspeed_sdhci.c
79
index XXXXXXX..XXXXXXX 100644
80
--- a/hw/sd/aspeed_sdhci.c
81
+++ b/hw/sd/aspeed_sdhci.c
82
@@ -XXX,XX +XXX,XX @@
83
#include "qapi/error.h"
84
#include "hw/irq.h"
85
#include "migration/vmstate.h"
86
+#include "hw/qdev-properties.h"
87
88
#define ASPEED_SDHCI_INFO 0x00
89
#define ASPEED_SDHCI_INFO_RESET 0x00030000
90
@@ -XXX,XX +XXX,XX @@ static void aspeed_sdhci_realize(DeviceState *dev, Error **errp)
91
92
/* Create input irqs for the slots */
93
qdev_init_gpio_in_named_with_opaque(DEVICE(sbd), aspeed_sdhci_set_irq,
94
- sdhci, NULL, ASPEED_SDHCI_NUM_SLOTS);
95
+ sdhci, NULL, sdhci->num_slots);
96
97
sysbus_init_irq(sbd, &sdhci->irq);
98
memory_region_init_io(&sdhci->iomem, OBJECT(sdhci), &aspeed_sdhci_ops,
99
sdhci, TYPE_ASPEED_SDHCI, 0x1000);
100
sysbus_init_mmio(sbd, &sdhci->iomem);
101
102
- for (int i = 0; i < ASPEED_SDHCI_NUM_SLOTS; ++i) {
103
+ for (int i = 0; i < sdhci->num_slots; ++i) {
104
Object *sdhci_slot = OBJECT(&sdhci->slots[i]);
105
SysBusDevice *sbd_slot = SYS_BUS_DEVICE(&sdhci->slots[i]);
106
107
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_aspeed_sdhci = {
108
},
27
},
109
};
28
};
110
29
111
+static Property aspeed_sdhci_properties[] = {
30
+/*
112
+ DEFINE_PROP_UINT8("num-slots", AspeedSDHCIState, num_slots, 0),
31
+ * FEAT_ECV adds extra views of CNTVCT_EL0 and CNTPCT_EL0 which
113
+ DEFINE_PROP_END_OF_LIST(),
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
+ },
114
+};
56
+};
115
+
57
+
116
static void aspeed_sdhci_class_init(ObjectClass *classp, void *data)
58
#else
117
{
59
118
DeviceClass *dc = DEVICE_CLASS(classp);
60
/*
119
@@ -XXX,XX +XXX,XX @@ static void aspeed_sdhci_class_init(ObjectClass *classp, void *data)
61
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo generic_timer_cp_reginfo[] = {
120
dc->realize = aspeed_sdhci_realize;
62
},
121
dc->reset = aspeed_sdhci_reset;
63
};
122
dc->vmsd = &vmstate_aspeed_sdhci;
64
123
+ device_class_set_props(dc, aspeed_sdhci_properties);
65
+/*
124
}
66
+ * CNTVCTSS_EL0 has the same trap conditions as CNTVCT_EL0, so it also
125
67
+ * is exposed to userspace by Linux.
126
static TypeInfo aspeed_sdhci_info = {
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
+
77
#endif
78
79
static void par_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
80
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
81
if (arm_feature(env, ARM_FEATURE_GENERIC_TIMER)) {
82
define_arm_cp_regs(cpu, generic_timer_cp_reginfo);
83
}
84
+ if (cpu_isar_feature(aa64_ecv_traps, cpu)) {
85
+ define_arm_cp_regs(cpu, gen_timer_ecv_cp_reginfo);
86
+ }
87
if (arm_feature(env, ARM_FEATURE_VAPA)) {
88
ARMCPRegInfo vapa_cp_reginfo[] = {
89
{ .name = "PAR", .cp = 15, .crn = 7, .crm = 4, .opc1 = 0, .opc2 = 0,
127
--
90
--
128
2.20.1
91
2.34.1
129
130
diff view generated by jsdifflib
1
From: Damien Hedde <damien.hedde@greensocs.com>
1
When ID_AA64MMFR0_EL1.ECV is 0b0010, a new register CNTPOFF_EL2 is
2
implemented. This is similar to the existing CNTVOFF_EL2, except
3
that it controls a hypervisor-adjustable offset made to the physical
4
counter and timer.
2
5
3
This commit adds support of Resettable interface to buses and devices:
6
Implement the handling for this register, which includes control/trap
4
+ ResettableState structure is added in the Bus/Device state
7
bits in SCR_EL3 and CNTHCTL_EL2.
5
+ Resettable methods are implemented.
6
+ device/bus_is_in_reset function defined
7
8
8
This commit allows to transition the objects to the new
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
multi-phase interface without changing the reset behavior at all.
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Object single reset method can be split into the 3 different phases
11
Message-id: 20240301183219.2424889-8-peter.maydell@linaro.org
11
but the 3 phases are still executed in a row for a given object.
12
---
12
From the qdev/qbus reset api point of view, nothing is changed.
13
target/arm/cpu-features.h | 5 +++
13
qdev_reset_all() and qbus_reset_all() are not modified as well as
14
target/arm/cpu.h | 1 +
14
device_legacy_reset().
15
target/arm/helper.c | 68 +++++++++++++++++++++++++++++++++++++--
16
target/arm/trace-events | 1 +
17
4 files changed, 73 insertions(+), 2 deletions(-)
15
18
16
Transition of an object must be done from parent class to child class.
19
diff --git a/target/arm/cpu-features.h b/target/arm/cpu-features.h
17
Care has been taken to allow the transition of a parent class
18
without requiring the child classes to be transitioned at the same
19
time. Note that SysBus and SysBusDevice class do not need any transition
20
because they do not override the legacy reset method.
21
22
Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
23
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
24
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
25
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
26
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
27
Message-id: 20200123132823.1117486-5-damien.hedde@greensocs.com
28
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
29
---
30
tests/Makefile.include | 1 +
31
include/hw/qdev-core.h | 27 ++++++++++++
32
hw/core/bus.c | 97 ++++++++++++++++++++++++++++++++++++++++++
33
hw/core/qdev.c | 93 ++++++++++++++++++++++++++++++++++++++++
34
4 files changed, 218 insertions(+)
35
36
diff --git a/tests/Makefile.include b/tests/Makefile.include
37
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
38
--- a/tests/Makefile.include
21
--- a/target/arm/cpu-features.h
39
+++ b/tests/Makefile.include
22
+++ b/target/arm/cpu-features.h
40
@@ -XXX,XX +XXX,XX @@ tests/fp/%:
23
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa64_ecv_traps(const ARMISARegisters *id)
41
tests/test-qdev-global-props$(EXESUF): tests/test-qdev-global-props.o \
24
return FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, ECV) > 0;
42
    hw/core/qdev.o hw/core/qdev-properties.o hw/core/hotplug.o\
43
    hw/core/bus.o \
44
+    hw/core/resettable.o \
45
    hw/core/irq.o \
46
    hw/core/fw-path-provider.o \
47
    hw/core/reset.o \
48
diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
49
index XXXXXXX..XXXXXXX 100644
50
--- a/include/hw/qdev-core.h
51
+++ b/include/hw/qdev-core.h
52
@@ -XXX,XX +XXX,XX @@
53
#include "qemu/bitmap.h"
54
#include "qom/object.h"
55
#include "hw/hotplug.h"
56
+#include "hw/resettable.h"
57
58
enum {
59
DEV_NVECTORS_UNSPECIFIED = -1,
60
@@ -XXX,XX +XXX,XX @@ typedef struct DeviceClass {
61
bool hotpluggable;
62
63
/* callbacks */
64
+ /*
65
+ * Reset method here is deprecated and replaced by methods in the
66
+ * resettable class interface to implement a multi-phase reset.
67
+ * TODO: remove once every reset callback is unused
68
+ */
69
DeviceReset reset;
70
DeviceRealize realize;
71
DeviceUnrealize unrealize;
72
@@ -XXX,XX +XXX,XX @@ struct NamedGPIOList {
73
/**
74
* DeviceState:
75
* @realized: Indicates whether the device has been fully constructed.
76
+ * @reset: ResettableState for the device; handled by Resettable interface.
77
*
78
* This structure should not be accessed directly. We declare it here
79
* so that it can be embedded in individual device state structures.
80
@@ -XXX,XX +XXX,XX @@ struct DeviceState {
81
int num_child_bus;
82
int instance_id_alias;
83
int alias_required_for_version;
84
+ ResettableState reset;
85
};
86
87
struct DeviceListener {
88
@@ -XXX,XX +XXX,XX @@ typedef struct BusChild {
89
/**
90
* BusState:
91
* @hotplug_handler: link to a hotplug handler associated with bus.
92
+ * @reset: ResettableState for the bus; handled by Resettable interface.
93
*/
94
struct BusState {
95
Object obj;
96
@@ -XXX,XX +XXX,XX @@ struct BusState {
97
int num_children;
98
QTAILQ_HEAD(, BusChild) children;
99
QLIST_ENTRY(BusState) sibling;
100
+ ResettableState reset;
101
};
102
103
/**
104
@@ -XXX,XX +XXX,XX @@ void qdev_reset_all_fn(void *opaque);
105
void qbus_reset_all(BusState *bus);
106
void qbus_reset_all_fn(void *opaque);
107
108
+/**
109
+ * device_is_in_reset:
110
+ * Return true if the device @dev is currently being reset.
111
+ */
112
+bool device_is_in_reset(DeviceState *dev);
113
+
114
+/**
115
+ * bus_is_in_reset:
116
+ * Return true if the bus @bus is currently being reset.
117
+ */
118
+bool bus_is_in_reset(BusState *bus);
119
+
120
/* This should go away once we get rid of the NULL bus hack */
121
BusState *sysbus_get_default(void);
122
123
@@ -XXX,XX +XXX,XX @@ void device_legacy_reset(DeviceState *dev);
124
125
void device_class_set_props(DeviceClass *dc, Property *props);
126
127
+/**
128
+ * device_class_set_parent_reset:
129
+ * TODO: remove the function when DeviceClass's reset method
130
+ * is not used anymore.
131
+ */
132
void device_class_set_parent_reset(DeviceClass *dc,
133
DeviceReset dev_reset,
134
DeviceReset *parent_reset);
135
diff --git a/hw/core/bus.c b/hw/core/bus.c
136
index XXXXXXX..XXXXXXX 100644
137
--- a/hw/core/bus.c
138
+++ b/hw/core/bus.c
139
@@ -XXX,XX +XXX,XX @@ int qbus_walk_children(BusState *bus,
140
return 0;
141
}
25
}
142
26
143
+bool bus_is_in_reset(BusState *bus)
27
+static inline bool isar_feature_aa64_ecv(const ARMISARegisters *id)
144
+{
28
+{
145
+ return resettable_is_in_reset(OBJECT(bus));
29
+ return FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, ECV) > 1;
146
+}
30
+}
147
+
31
+
148
+static ResettableState *bus_get_reset_state(Object *obj)
32
static inline bool isar_feature_aa64_vh(const ARMISARegisters *id)
33
{
34
return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, VH) != 0;
35
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
36
index XXXXXXX..XXXXXXX 100644
37
--- a/target/arm/cpu.h
38
+++ b/target/arm/cpu.h
39
@@ -XXX,XX +XXX,XX @@ typedef struct CPUArchState {
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);
63
}
64
65
+static uint64_t gt_phys_raw_cnt_offset(CPUARMState *env)
149
+{
66
+{
150
+ BusState *bus = BUS(obj);
67
+ if ((env->cp15.scr_el3 & SCR_ECVEN) &&
151
+ return &bus->reset;
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;
152
+}
74
+}
153
+
75
+
154
+static void bus_reset_child_foreach(Object *obj, ResettableChildCallback cb,
76
+static uint64_t gt_phys_cnt_offset(CPUARMState *env)
155
+ void *opaque, ResetType type)
156
+{
77
+{
157
+ BusState *bus = BUS(obj);
78
+ if (arm_current_el(env) >= 2) {
158
+ BusChild *kid;
79
+ return 0;
159
+
160
+ QTAILQ_FOREACH(kid, &bus->children, sibling) {
161
+ cb(OBJECT(kid->child), opaque, type);
162
+ }
80
+ }
81
+ return gt_phys_raw_cnt_offset(env);
163
+}
82
+}
164
+
83
+
165
static void qbus_realize(BusState *bus, DeviceState *parent, const char *name)
84
static void gt_recalc_timer(ARMCPU *cpu, int timeridx)
166
{
85
{
167
const char *typename = object_get_typename(OBJECT(bus));
86
ARMGenericTimer *gt = &cpu->env.cp15.c14_timer[timeridx];
168
@@ -XXX,XX +XXX,XX @@ static char *default_bus_get_fw_dev_path(DeviceState *dev)
87
@@ -XXX,XX +XXX,XX @@ static void gt_recalc_timer(ARMCPU *cpu, int timeridx)
169
return g_strdup(object_get_typename(OBJECT(dev)));
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);
170
}
102
}
171
103
172
+/**
104
static uint64_t gt_virt_cnt_offset(CPUARMState *env)
173
+ * bus_phases_reset:
105
@@ -XXX,XX +XXX,XX @@ static uint64_t gt_tval_read(CPUARMState *env, const ARMCPRegInfo *ri,
174
+ * Transition reset method for buses to allow moving
106
case GTIMER_HYPVIRT:
175
+ * smoothly from legacy reset method to multi-phases
107
offset = gt_virt_cnt_offset(env);
176
+ */
108
break;
177
+static void bus_phases_reset(BusState *bus)
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)
178
+{
142
+{
179
+ ResettableClass *rc = RESETTABLE_GET_CLASS(bus);
143
+ if (arm_current_el(env) == 2 && !(env->cp15.scr_el3 & SCR_ECVEN)) {
180
+
144
+ return CP_ACCESS_TRAP_EL3;
181
+ if (rc->phases.enter) {
182
+ rc->phases.enter(OBJECT(bus), RESET_TYPE_COLD);
183
+ }
145
+ }
184
+ if (rc->phases.hold) {
146
+ return CP_ACCESS_OK;
185
+ rc->phases.hold(OBJECT(bus));
186
+ }
187
+ if (rc->phases.exit) {
188
+ rc->phases.exit(OBJECT(bus));
189
+ }
190
+}
147
+}
191
+
148
+
192
+static void bus_transitional_reset(Object *obj)
149
+static void gt_cntpoff_write(CPUARMState *env, const ARMCPRegInfo *ri,
150
+ uint64_t value)
193
+{
151
+{
194
+ BusClass *bc = BUS_GET_CLASS(obj);
152
+ ARMCPU *cpu = env_archcpu(env);
195
+
153
+
196
+ /*
154
+ trace_arm_gt_cntpoff_write(value);
197
+ * This will call either @bus_phases_reset (for multi-phases transitioned
155
+ raw_write(env, ri, value);
198
+ * buses) or a bus's specific method for not-yet transitioned buses.
156
+ gt_recalc_timer(cpu, GTIMER_PHYS);
199
+ * In both case, it does not reset children.
200
+ */
201
+ if (bc->reset) {
202
+ bc->reset(BUS(obj));
203
+ }
204
+}
157
+}
205
+
158
+
206
+/**
159
+static const ARMCPRegInfo gen_timer_cntpoff_reginfo = {
207
+ * bus_get_transitional_reset:
160
+ .name = "CNTPOFF_EL2", .state = ARM_CP_STATE_AA64,
208
+ * check if the bus's class is ready for multi-phase
161
+ .opc0 = 3, .opc1 = 4, .crn = 14, .crm = 0, .opc2 = 6,
209
+ */
162
+ .access = PL2_RW, .type = ARM_CP_IO, .resetvalue = 0,
210
+static ResettableTrFunction bus_get_transitional_reset(Object *obj)
163
+ .accessfn = gt_cntpoff_access, .writefn = gt_cntpoff_write,
211
+{
164
+ .nv2_redirect_offset = 0x1a8,
212
+ BusClass *dc = BUS_GET_CLASS(obj);
165
+ .fieldoffset = offsetof(CPUARMState, cp15.cntpoff_el2),
213
+ if (dc->reset != bus_phases_reset) {
166
+};
214
+ /*
167
#else
215
+ * dc->reset has been overridden by a subclass,
168
216
+ * the bus is not ready for multi phase yet.
169
/*
217
+ */
170
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
218
+ return bus_transitional_reset;
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);
219
+ }
177
+ }
220
+ return NULL;
178
+#endif
221
+}
179
if (arm_feature(env, ARM_FEATURE_VAPA)) {
222
+
180
ARMCPRegInfo vapa_cp_reginfo[] = {
223
static void bus_class_init(ObjectClass *class, void *data)
181
{ .name = "PAR", .cp = 15, .crn = 7, .crm = 4, .opc1 = 0, .opc2 = 0,
224
{
182
diff --git a/target/arm/trace-events b/target/arm/trace-events
225
BusClass *bc = BUS_CLASS(class);
226
+ ResettableClass *rc = RESETTABLE_CLASS(class);
227
228
class->unparent = bus_unparent;
229
bc->get_fw_dev_path = default_bus_get_fw_dev_path;
230
+
231
+ rc->get_state = bus_get_reset_state;
232
+ rc->child_foreach = bus_reset_child_foreach;
233
+
234
+ /*
235
+ * @bus_phases_reset is put as the default reset method below, allowing
236
+ * to do the multi-phase transition from base classes to leaf classes. It
237
+ * allows a legacy-reset Bus class to extend a multi-phases-reset
238
+ * Bus class for the following reason:
239
+ * + If a base class B has been moved to multi-phase, then it does not
240
+ * override this default reset method and may have defined phase methods.
241
+ * + A child class C (extending class B) which uses
242
+ * bus_class_set_parent_reset() (or similar means) to override the
243
+ * reset method will still work as expected. @bus_phases_reset function
244
+ * will be registered as the parent reset method and effectively call
245
+ * parent reset phases.
246
+ */
247
+ bc->reset = bus_phases_reset;
248
+ rc->get_transitional_function = bus_get_transitional_reset;
249
}
250
251
static void qbus_finalize(Object *obj)
252
@@ -XXX,XX +XXX,XX @@ static const TypeInfo bus_info = {
253
.instance_init = qbus_initfn,
254
.instance_finalize = qbus_finalize,
255
.class_init = bus_class_init,
256
+ .interfaces = (InterfaceInfo[]) {
257
+ { TYPE_RESETTABLE_INTERFACE },
258
+ { }
259
+ },
260
};
261
262
static void bus_register_types(void)
263
diff --git a/hw/core/qdev.c b/hw/core/qdev.c
264
index XXXXXXX..XXXXXXX 100644
183
index XXXXXXX..XXXXXXX 100644
265
--- a/hw/core/qdev.c
184
--- a/target/arm/trace-events
266
+++ b/hw/core/qdev.c
185
+++ b/target/arm/trace-events
267
@@ -XXX,XX +XXX,XX @@ void qbus_reset_all_fn(void *opaque)
186
@@ -XXX,XX +XXX,XX @@ arm_gt_tval_write(int timer, uint64_t value) "gt_tval_write: timer %d value 0x%"
268
qbus_reset_all(bus);
187
arm_gt_ctl_write(int timer, uint64_t value) "gt_ctl_write: timer %d value 0x%" PRIx64
269
}
188
arm_gt_imask_toggle(int timer) "gt_ctl_write: timer %d IMASK toggle"
270
189
arm_gt_cntvoff_write(uint64_t value) "gt_cntvoff_write: value 0x%" PRIx64
271
+bool device_is_in_reset(DeviceState *dev)
190
+arm_gt_cntpoff_write(uint64_t value) "gt_cntpoff_write: value 0x%" PRIx64
272
+{
191
arm_gt_update_irq(int timer, int irqstate) "gt_update_irq: timer %d irqstate %d"
273
+ return resettable_is_in_reset(OBJECT(dev));
192
274
+}
193
# kvm.c
275
+
276
+static ResettableState *device_get_reset_state(Object *obj)
277
+{
278
+ DeviceState *dev = DEVICE(obj);
279
+ return &dev->reset;
280
+}
281
+
282
+static void device_reset_child_foreach(Object *obj, ResettableChildCallback cb,
283
+ void *opaque, ResetType type)
284
+{
285
+ DeviceState *dev = DEVICE(obj);
286
+ BusState *bus;
287
+
288
+ QLIST_FOREACH(bus, &dev->child_bus, sibling) {
289
+ cb(OBJECT(bus), opaque, type);
290
+ }
291
+}
292
+
293
/* can be used as ->unplug() callback for the simple cases */
294
void qdev_simple_device_unplug_cb(HotplugHandler *hotplug_dev,
295
DeviceState *dev, Error **errp)
296
@@ -XXX,XX +XXX,XX @@ device_vmstate_if_get_id(VMStateIf *obj)
297
return qdev_get_dev_path(dev);
298
}
299
300
+/**
301
+ * device_phases_reset:
302
+ * Transition reset method for devices to allow moving
303
+ * smoothly from legacy reset method to multi-phases
304
+ */
305
+static void device_phases_reset(DeviceState *dev)
306
+{
307
+ ResettableClass *rc = RESETTABLE_GET_CLASS(dev);
308
+
309
+ if (rc->phases.enter) {
310
+ rc->phases.enter(OBJECT(dev), RESET_TYPE_COLD);
311
+ }
312
+ if (rc->phases.hold) {
313
+ rc->phases.hold(OBJECT(dev));
314
+ }
315
+ if (rc->phases.exit) {
316
+ rc->phases.exit(OBJECT(dev));
317
+ }
318
+}
319
+
320
+static void device_transitional_reset(Object *obj)
321
+{
322
+ DeviceClass *dc = DEVICE_GET_CLASS(obj);
323
+
324
+ /*
325
+ * This will call either @device_phases_reset (for multi-phases transitioned
326
+ * devices) or a device's specific method for not-yet transitioned devices.
327
+ * In both case, it does not reset children.
328
+ */
329
+ if (dc->reset) {
330
+ dc->reset(DEVICE(obj));
331
+ }
332
+}
333
+
334
+/**
335
+ * device_get_transitional_reset:
336
+ * check if the device's class is ready for multi-phase
337
+ */
338
+static ResettableTrFunction device_get_transitional_reset(Object *obj)
339
+{
340
+ DeviceClass *dc = DEVICE_GET_CLASS(obj);
341
+ if (dc->reset != device_phases_reset) {
342
+ /*
343
+ * dc->reset has been overridden by a subclass,
344
+ * the device is not ready for multi phase yet.
345
+ */
346
+ return device_transitional_reset;
347
+ }
348
+ return NULL;
349
+}
350
+
351
static void device_class_init(ObjectClass *class, void *data)
352
{
353
DeviceClass *dc = DEVICE_CLASS(class);
354
VMStateIfClass *vc = VMSTATE_IF_CLASS(class);
355
+ ResettableClass *rc = RESETTABLE_CLASS(class);
356
357
class->unparent = device_unparent;
358
359
@@ -XXX,XX +XXX,XX @@ static void device_class_init(ObjectClass *class, void *data)
360
dc->hotpluggable = true;
361
dc->user_creatable = true;
362
vc->get_id = device_vmstate_if_get_id;
363
+ rc->get_state = device_get_reset_state;
364
+ rc->child_foreach = device_reset_child_foreach;
365
+
366
+ /*
367
+ * @device_phases_reset is put as the default reset method below, allowing
368
+ * to do the multi-phase transition from base classes to leaf classes. It
369
+ * allows a legacy-reset Device class to extend a multi-phases-reset
370
+ * Device class for the following reason:
371
+ * + If a base class B has been moved to multi-phase, then it does not
372
+ * override this default reset method and may have defined phase methods.
373
+ * + A child class C (extending class B) which uses
374
+ * device_class_set_parent_reset() (or similar means) to override the
375
+ * reset method will still work as expected. @device_phases_reset function
376
+ * will be registered as the parent reset method and effectively call
377
+ * parent reset phases.
378
+ */
379
+ dc->reset = device_phases_reset;
380
+ rc->get_transitional_function = device_get_transitional_reset;
381
382
object_class_property_add_bool(class, "realized",
383
device_get_realized, device_set_realized,
384
@@ -XXX,XX +XXX,XX @@ static const TypeInfo device_type_info = {
385
.class_size = sizeof(DeviceClass),
386
.interfaces = (InterfaceInfo[]) {
387
{ TYPE_VMSTATE_IF },
388
+ { TYPE_RESETTABLE_INTERFACE },
389
{ }
390
}
391
};
392
--
194
--
393
2.20.1
195
2.34.1
394
395
diff view generated by jsdifflib
1
The guest can use the semihosting API to open a handle
1
Enable all FEAT_ECV features on the 'max' CPU.
2
corresponding to QEMU's own stdin, stdout, or stderr.
3
When the guest closes this handle, we should not
4
close the underlying host stdin/stdout/stderr
5
the way we would do if the handle corresponded to
6
a host fd we'd opened on behalf of the guest in SYS_OPEN.
7
2
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
4
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
10
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20200124172954.28481-1-peter.maydell@linaro.org
6
Message-id: 20240301183219.2424889-9-peter.maydell@linaro.org
12
---
7
---
13
target/arm/arm-semi.c | 9 +++++++++
8
docs/system/arm/emulation.rst | 1 +
14
1 file changed, 9 insertions(+)
9
target/arm/tcg/cpu64.c | 1 +
10
2 files changed, 2 insertions(+)
15
11
16
diff --git a/target/arm/arm-semi.c b/target/arm/arm-semi.c
12
diff --git a/docs/system/arm/emulation.rst b/docs/system/arm/emulation.rst
17
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/arm-semi.c
14
--- a/docs/system/arm/emulation.rst
19
+++ b/target/arm/arm-semi.c
15
+++ b/docs/system/arm/emulation.rst
20
@@ -XXX,XX +XXX,XX @@ static uint32_t host_closefn(ARMCPU *cpu, GuestFD *gf)
16
@@ -XXX,XX +XXX,XX @@ the following architecture extensions:
21
{
17
- FEAT_DotProd (Advanced SIMD dot product instructions)
22
CPUARMState *env = &cpu->env;
18
- FEAT_DoubleFault (Double Fault Extension)
23
19
- FEAT_E0PD (Preventing EL0 access to halves of address maps)
24
+ /*
20
+- FEAT_ECV (Enhanced Counter Virtualization)
25
+ * Only close the underlying host fd if it's one we opened on behalf
21
- FEAT_EPAC (Enhanced pointer authentication)
26
+ * of the guest in SYS_OPEN.
22
- FEAT_ETS (Enhanced Translation Synchronization)
27
+ */
23
- FEAT_EVT (Enhanced Virtualization Traps)
28
+ if (gf->hostfd == STDIN_FILENO ||
24
diff --git a/target/arm/tcg/cpu64.c b/target/arm/tcg/cpu64.c
29
+ gf->hostfd == STDOUT_FILENO ||
25
index XXXXXXX..XXXXXXX 100644
30
+ gf->hostfd == STDERR_FILENO) {
26
--- a/target/arm/tcg/cpu64.c
31
+ return 0;
27
+++ b/target/arm/tcg/cpu64.c
32
+ }
28
@@ -XXX,XX +XXX,XX @@ void aarch64_max_tcg_initfn(Object *obj)
33
return set_swi_errno(env, close(gf->hostfd));
29
t = FIELD_DP64(t, ID_AA64MMFR0, TGRAN64_2, 2); /* 64k stage2 supported */
34
}
30
t = FIELD_DP64(t, ID_AA64MMFR0, TGRAN4_2, 2); /* 4k stage2 supported */
35
31
t = FIELD_DP64(t, ID_AA64MMFR0, FGT, 1); /* FEAT_FGT */
32
+ t = FIELD_DP64(t, ID_AA64MMFR0, ECV, 2); /* FEAT_ECV */
33
cpu->isar.id_aa64mmfr0 = t;
34
35
t = cpu->isar.id_aa64mmfr1;
36
--
36
--
37
2.20.1
37
2.34.1
38
38
39
39
diff view generated by jsdifflib
1
From: Damien Hedde <damien.hedde@greensocs.com>
1
From: Inès Varhol <ines.varhol@telecom-paris.fr>
2
2
3
This commit defines an interface allowing multi-phase reset. This aims
3
Features supported :
4
to solve a problem of the actual single-phase reset (built in
4
- the 8 STM32L4x5 GPIOs are initialized with their reset values
5
DeviceClass and BusClass): reset behavior is dependent on the order
5
(except IDR, see below)
6
in which reset handlers are called. In particular doing external
6
- input mode : setting a pin in input mode "externally" (using input
7
side-effect (like setting an qemu_irq) is problematic because receiving
7
irqs) results in an out irq (transmitted to SYSCFG)
8
object may not be reset yet.
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
9
12
10
The Resettable interface divides the reset in 3 well defined phases.
13
Difference with the real GPIOs :
11
To reset an object tree, all 1st phases are executed then all 2nd then
14
- Alternate Function and Analog mode aren't implemented :
12
all 3rd. See the comments in include/hw/resettable.h for a more complete
15
pins in AF/Analog behave like pins in input mode
13
description. The interface defines 3 phases to let the future
16
- floating pins stay at their last value
14
possibility of holding an object into reset for some time.
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
15
25
16
The qdev/qbus reset in DeviceClass and BusClass will be modified in
26
Signed-off-by: Arnaud Minier <arnaud.minier@telecom-paris.fr>
17
following commits to use this interface. A mechanism is provided
27
Signed-off-by: Inès Varhol <ines.varhol@telecom-paris.fr>
18
to allow executing a transitional reset handler in place of the 2nd
28
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
19
phase which is executed in children-then-parent order inside a tree.
29
Acked-by: Alistair Francis <alistair.francis@wdc.com>
20
This will allow to transition devices and buses smoothly while
30
Message-id: 20240305210444.310665-2-ines.varhol@telecom-paris.fr
21
keeping the exact current qdev/qbus reset behavior for now.
22
23
Documentation will be added in a following commit.
24
25
Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
26
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
27
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
28
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
29
Message-id: 20200123132823.1117486-4-damien.hedde@greensocs.com
30
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
31
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
31
---
32
---
32
hw/core/Makefile.objs | 1 +
33
MAINTAINERS | 1 +
33
include/hw/resettable.h | 211 +++++++++++++++++++++++++++++++++++
34
docs/system/arm/b-l475e-iot01a.rst | 2 +-
34
hw/core/resettable.c | 238 ++++++++++++++++++++++++++++++++++++++++
35
include/hw/gpio/stm32l4x5_gpio.h | 70 +++++
35
hw/core/trace-events | 17 +++
36
hw/gpio/stm32l4x5_gpio.c | 477 +++++++++++++++++++++++++++++
36
4 files changed, 467 insertions(+)
37
hw/gpio/Kconfig | 3 +
37
create mode 100644 include/hw/resettable.h
38
hw/gpio/meson.build | 1 +
38
create mode 100644 hw/core/resettable.c
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
39
43
40
diff --git a/hw/core/Makefile.objs b/hw/core/Makefile.objs
44
diff --git a/MAINTAINERS b/MAINTAINERS
41
index XXXXXXX..XXXXXXX 100644
45
index XXXXXXX..XXXXXXX 100644
42
--- a/hw/core/Makefile.objs
46
--- a/MAINTAINERS
43
+++ b/hw/core/Makefile.objs
47
+++ b/MAINTAINERS
44
@@ -XXX,XX +XXX,XX @@
48
@@ -XXX,XX +XXX,XX @@ F: hw/arm/stm32l4x5_soc.c
45
common-obj-y += qdev.o qdev-properties.o
49
F: hw/misc/stm32l4x5_exti.c
46
common-obj-y += bus.o
50
F: hw/misc/stm32l4x5_syscfg.c
47
common-obj-y += cpu.o
51
F: hw/misc/stm32l4x5_rcc.c
48
+common-obj-y += resettable.o
52
+F: hw/gpio/stm32l4x5_gpio.c
49
common-obj-y += hotplug.o
53
F: include/hw/*/stm32l4x5_*.h
50
common-obj-y += vmstate-if.o
54
51
# irq.o needed for qdev GPIO handling:
55
B-L475E-IOT01A IoT Node
52
diff --git a/include/hw/resettable.h b/include/hw/resettable.h
56
diff --git a/docs/system/arm/b-l475e-iot01a.rst b/docs/system/arm/b-l475e-iot01a.rst
57
index XXXXXXX..XXXXXXX 100644
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
53
new file mode 100644
77
new file mode 100644
54
index XXXXXXX..XXXXXXX
78
index XXXXXXX..XXXXXXX
55
--- /dev/null
79
--- /dev/null
56
+++ b/include/hw/resettable.h
80
+++ b/include/hw/gpio/stm32l4x5_gpio.h
57
@@ -XXX,XX +XXX,XX @@
81
@@ -XXX,XX +XXX,XX @@
58
+/*
82
+/*
59
+ * Resettable interface header.
83
+ * STM32L4x5 GPIO (General Purpose Input/Ouput)
60
+ *
84
+ *
61
+ * Copyright (c) 2019 GreenSocs SAS
85
+ * Copyright (c) 2024 Arnaud Minier <arnaud.minier@telecom-paris.fr>
86
+ * Copyright (c) 2024 Inès Varhol <ines.varhol@telecom-paris.fr>
62
+ *
87
+ *
63
+ * Authors:
88
+ * SPDX-License-Identifier: GPL-2.0-or-later
64
+ * Damien Hedde
65
+ *
89
+ *
66
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
90
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
67
+ * See the COPYING file in the top-level directory.
91
+ * See the COPYING file in the top-level directory.
68
+ */
92
+ */
69
+
93
+
70
+#ifndef HW_RESETTABLE_H
94
+/*
71
+#define HW_RESETTABLE_H
95
+ * The reference used is the STMicroElectronics RM0351 Reference manual
72
+
96
+ * for STM32L4x5 and STM32L4x6 advanced Arm ® -based 32-bit MCUs.
97
+ * https://www.st.com/en/microcontrollers-microprocessors/stm32l4x5/documentation.html
98
+ */
99
+
100
+#ifndef HW_STM32L4X5_GPIO_H
101
+#define HW_STM32L4X5_GPIO_H
102
+
103
+#include "hw/sysbus.h"
73
+#include "qom/object.h"
104
+#include "qom/object.h"
74
+
105
+
75
+#define TYPE_RESETTABLE_INTERFACE "resettable"
106
+#define TYPE_STM32L4X5_GPIO "stm32l4x5-gpio"
76
+
107
+OBJECT_DECLARE_SIMPLE_TYPE(Stm32l4x5GpioState, STM32L4X5_GPIO)
77
+#define RESETTABLE_CLASS(class) \
108
+
78
+ OBJECT_CLASS_CHECK(ResettableClass, (class), TYPE_RESETTABLE_INTERFACE)
109
+#define GPIO_NUM_PINS 16
79
+
110
+
80
+#define RESETTABLE_GET_CLASS(obj) \
111
+struct Stm32l4x5GpioState {
81
+ OBJECT_GET_CLASS(ResettableClass, (obj), TYPE_RESETTABLE_INTERFACE)
112
+ SysBusDevice parent_obj;
82
+
113
+
83
+typedef struct ResettableState ResettableState;
114
+ MemoryRegion mmio;
84
+
115
+
85
+/**
116
+ /* GPIO registers */
86
+ * ResetType:
117
+ uint32_t moder;
87
+ * Types of reset.
118
+ uint32_t otyper;
88
+ *
119
+ uint32_t ospeedr;
89
+ * + Cold: reset resulting from a power cycle of the object.
120
+ uint32_t pupdr;
90
+ *
121
+ uint32_t idr;
91
+ * TODO: Support has to be added to handle more types. In particular,
122
+ uint32_t odr;
92
+ * ResettableState structure needs to be expanded.
123
+ uint32_t lckr;
93
+ */
124
+ uint32_t afrl;
94
+typedef enum ResetType {
125
+ uint32_t afrh;
95
+ RESET_TYPE_COLD,
126
+ uint32_t ascr;
96
+} ResetType;
127
+
97
+
128
+ /* GPIO registers reset values */
98
+/*
129
+ uint32_t moder_reset;
99
+ * ResettableClass:
130
+ uint32_t ospeedr_reset;
100
+ * Interface for resettable objects.
131
+ uint32_t pupdr_reset;
101
+ *
132
+
102
+ * See docs/devel/reset.rst for more detailed information about how QEMU models
133
+ /*
103
+ * reset. This whole API must only be used when holding the iothread mutex.
134
+ * External driving of pins.
104
+ *
135
+ * The pins can be set externally through the device
105
+ * All objects which can be reset must implement this interface;
136
+ * anonymous input GPIOs lines under certain conditions.
106
+ * it is usually provided by a base class such as DeviceClass or BusClass.
137
+ * The pin must not be in push-pull output mode,
107
+ * Every Resettable object must maintain some state tracking the
138
+ * and can't be set high in open-drain mode.
108
+ * progress of a reset operation by providing a ResettableState structure.
139
+ * Pins driven externally and configured to
109
+ * The functions defined in this module take care of updating the
140
+ * output mode will in general be "disconnected"
110
+ * state of the reset.
141
+ * (see `get_gpio_pinmask_to_disconnect()`)
111
+ * The base class implementation of the interface provides this
142
+ */
112
+ * state and implements the associated method: get_state.
143
+ uint16_t disconnected_pins;
113
+ *
144
+ uint16_t pins_connected_high;
114
+ * Concrete object implementations (typically specific devices
145
+
115
+ * such as a UART model) should provide the functions
146
+ char *name;
116
+ * for the phases.enter, phases.hold and phases.exit methods, which
147
+ Clock *clk;
117
+ * they can set in their class init function, either directly or
148
+ qemu_irq pin[GPIO_NUM_PINS];
118
+ * by calling resettable_class_set_parent_phases().
119
+ * The phase methods are guaranteed to only only ever be called once
120
+ * for any reset event, in the order 'enter', 'hold', 'exit'.
121
+ * An object will always move quickly from 'enter' to 'hold'
122
+ * but might remain in 'hold' for an arbitrary period of time
123
+ * before eventually reset is deasserted and the 'exit' phase is called.
124
+ * Object implementations should be prepared for functions handling
125
+ * inbound connections from other devices (such as qemu_irq handler
126
+ * functions) to be called at any point during reset after their
127
+ * 'enter' method has been called.
128
+ *
129
+ * Users of a resettable object should not call these methods
130
+ * directly, but instead use the function resettable_reset().
131
+ *
132
+ * @phases.enter: This phase is called when the object enters reset. It
133
+ * should reset local state of the object, but it must not do anything that
134
+ * has a side-effect on other objects, such as raising or lowering a qemu_irq
135
+ * line or reading or writing guest memory. It takes the reset's type as
136
+ * argument.
137
+ *
138
+ * @phases.hold: This phase is called for entry into reset, once every object
139
+ * in the system which is being reset has had its @phases.enter method called.
140
+ * At this point devices can do actions that affect other objects.
141
+ *
142
+ * @phases.exit: This phase is called when the object leaves the reset state.
143
+ * Actions affecting other objects are permitted.
144
+ *
145
+ * @get_state: Mandatory method which must return a pointer to a
146
+ * ResettableState.
147
+ *
148
+ * @get_transitional_function: transitional method to handle Resettable objects
149
+ * not yet fully moved to this interface. It will be removed as soon as it is
150
+ * not needed anymore. This method is optional and may return a pointer to a
151
+ * function to be used instead of the phases. If the method exists and returns
152
+ * a non-NULL function pointer then that function is executed as a replacement
153
+ * of the 'hold' phase method taking the object as argument. The two other phase
154
+ * methods are not executed.
155
+ *
156
+ * @child_foreach: Executes a given callback on every Resettable child. Child
157
+ * in this context means a child in the qbus tree, so the children of a qbus
158
+ * are the devices on it, and the children of a device are all the buses it
159
+ * owns. This is not the same as the QOM object hierarchy. The function takes
160
+ * additional opaque and ResetType arguments which must be passed unmodified to
161
+ * the callback.
162
+ */
163
+typedef void (*ResettableEnterPhase)(Object *obj, ResetType type);
164
+typedef void (*ResettableHoldPhase)(Object *obj);
165
+typedef void (*ResettableExitPhase)(Object *obj);
166
+typedef ResettableState * (*ResettableGetState)(Object *obj);
167
+typedef void (*ResettableTrFunction)(Object *obj);
168
+typedef ResettableTrFunction (*ResettableGetTrFunction)(Object *obj);
169
+typedef void (*ResettableChildCallback)(Object *, void *opaque,
170
+ ResetType type);
171
+typedef void (*ResettableChildForeach)(Object *obj,
172
+ ResettableChildCallback cb,
173
+ void *opaque, ResetType type);
174
+typedef struct ResettablePhases {
175
+ ResettableEnterPhase enter;
176
+ ResettableHoldPhase hold;
177
+ ResettableExitPhase exit;
178
+} ResettablePhases;
179
+typedef struct ResettableClass {
180
+ InterfaceClass parent_class;
181
+
182
+ /* Phase methods */
183
+ ResettablePhases phases;
184
+
185
+ /* State access method */
186
+ ResettableGetState get_state;
187
+
188
+ /* Transitional method for legacy reset compatibility */
189
+ ResettableGetTrFunction get_transitional_function;
190
+
191
+ /* Hierarchy handling method */
192
+ ResettableChildForeach child_foreach;
193
+} ResettableClass;
194
+
195
+/**
196
+ * ResettableState:
197
+ * Structure holding reset related state. The fields should not be accessed
198
+ * directly; the definition is here to allow further inclusion into other
199
+ * objects.
200
+ *
201
+ * @count: Number of reset level the object is into. It is incremented when
202
+ * the reset operation starts and decremented when it finishes.
203
+ * @hold_phase_pending: flag which indicates that we need to invoke the 'hold'
204
+ * phase handler for this object.
205
+ * @exit_phase_in_progress: true if we are currently in the exit phase
206
+ */
207
+struct ResettableState {
208
+ unsigned count;
209
+ bool hold_phase_pending;
210
+ bool exit_phase_in_progress;
211
+};
149
+};
212
+
150
+
213
+/**
214
+ * resettable_reset:
215
+ * Trigger a reset on an object @obj of type @type. @obj must implement
216
+ * Resettable interface.
217
+ *
218
+ * Calling this function is equivalent to calling @resettable_assert_reset()
219
+ * then @resettable_release_reset().
220
+ */
221
+void resettable_reset(Object *obj, ResetType type);
222
+
223
+/**
224
+ * resettable_assert_reset:
225
+ * Put an object @obj into reset. @obj must implement Resettable interface.
226
+ *
227
+ * @resettable_release_reset() must eventually be called after this call.
228
+ * There must be one call to @resettable_release_reset() per call of
229
+ * @resettable_assert_reset(), with the same type argument.
230
+ *
231
+ * NOTE: Until support for migration is added, the @resettable_release_reset()
232
+ * must not be delayed. It must occur just after @resettable_assert_reset() so
233
+ * that migration cannot be triggered in between. Prefer using
234
+ * @resettable_reset() for now.
235
+ */
236
+void resettable_assert_reset(Object *obj, ResetType type);
237
+
238
+/**
239
+ * resettable_release_reset:
240
+ * Release the object @obj from reset. @obj must implement Resettable interface.
241
+ *
242
+ * See @resettable_assert_reset() description for details.
243
+ */
244
+void resettable_release_reset(Object *obj, ResetType type);
245
+
246
+/**
247
+ * resettable_is_in_reset:
248
+ * Return true if @obj is under reset.
249
+ *
250
+ * @obj must implement Resettable interface.
251
+ */
252
+bool resettable_is_in_reset(Object *obj);
253
+
254
+/**
255
+ * resettable_class_set_parent_phases:
256
+ *
257
+ * Save @rc current reset phases into @parent_phases and override @rc phases
258
+ * by the given new methods (@enter, @hold and @exit).
259
+ * Each phase is overridden only if the new one is not NULL allowing to
260
+ * override a subset of phases.
261
+ */
262
+void resettable_class_set_parent_phases(ResettableClass *rc,
263
+ ResettableEnterPhase enter,
264
+ ResettableHoldPhase hold,
265
+ ResettableExitPhase exit,
266
+ ResettablePhases *parent_phases);
267
+
268
+#endif
151
+#endif
269
diff --git a/hw/core/resettable.c b/hw/core/resettable.c
152
diff --git a/hw/gpio/stm32l4x5_gpio.c b/hw/gpio/stm32l4x5_gpio.c
270
new file mode 100644
153
new file mode 100644
271
index XXXXXXX..XXXXXXX
154
index XXXXXXX..XXXXXXX
272
--- /dev/null
155
--- /dev/null
273
+++ b/hw/core/resettable.c
156
+++ b/hw/gpio/stm32l4x5_gpio.c
274
@@ -XXX,XX +XXX,XX @@
157
@@ -XXX,XX +XXX,XX @@
275
+/*
158
+/*
276
+ * Resettable interface.
159
+ * STM32L4x5 GPIO (General Purpose Input/Ouput)
277
+ *
160
+ *
278
+ * Copyright (c) 2019 GreenSocs SAS
161
+ * Copyright (c) 2024 Arnaud Minier <arnaud.minier@telecom-paris.fr>
162
+ * Copyright (c) 2024 Inès Varhol <ines.varhol@telecom-paris.fr>
279
+ *
163
+ *
280
+ * Authors:
164
+ * SPDX-License-Identifier: GPL-2.0-or-later
281
+ * Damien Hedde
282
+ *
165
+ *
283
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
166
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
284
+ * See the COPYING file in the top-level directory.
167
+ * See the COPYING file in the top-level directory.
285
+ */
168
+ */
286
+
169
+
170
+/*
171
+ * The reference used is the STMicroElectronics RM0351 Reference manual
172
+ * for STM32L4x5 and STM32L4x6 advanced Arm ® -based 32-bit MCUs.
173
+ * https://www.st.com/en/microcontrollers-microprocessors/stm32l4x5/documentation.html
174
+ */
175
+
287
+#include "qemu/osdep.h"
176
+#include "qemu/osdep.h"
288
+#include "qemu/module.h"
177
+#include "qemu/log.h"
289
+#include "hw/resettable.h"
178
+#include "hw/gpio/stm32l4x5_gpio.h"
179
+#include "hw/irq.h"
180
+#include "hw/qdev-clock.h"
181
+#include "hw/qdev-properties.h"
182
+#include "qapi/visitor.h"
183
+#include "qapi/error.h"
184
+#include "migration/vmstate.h"
290
+#include "trace.h"
185
+#include "trace.h"
291
+
186
+
292
+/**
187
+#define GPIO_MODER 0x00
293
+ * resettable_phase_enter/hold/exit:
188
+#define GPIO_OTYPER 0x04
294
+ * Function executing a phase recursively in a resettable object and its
189
+#define GPIO_OSPEEDR 0x08
295
+ * children.
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
+ */
335
+ }
336
+ }
337
+
338
+ s->idr = (old_idr & ~new_idr_mask) | (new_idr & new_idr_mask);
339
+ trace_stm32l4x5_gpio_update_idr(s->name, old_idr, s->idr);
340
+
341
+ for (int i = 0; i < GPIO_NUM_PINS; i++) {
342
+ if (new_idr_mask & (1 << i)) {
343
+ new_pin_state = (new_idr & (1 << i)) > 0;
344
+ old_pin_state = (old_idr & (1 << i)) > 0;
345
+ if (new_pin_state > old_pin_state) {
346
+ qemu_irq_raise(s->pin[i]);
347
+ } else if (new_pin_state < old_pin_state) {
348
+ qemu_irq_lower(s->pin[i]);
349
+ }
350
+ }
351
+ }
352
+}
353
+
354
+/*
355
+ * Return mask of pins that are both configured in output
356
+ * mode and externally driven (except pins in open-drain
357
+ * mode externally set to 0).
296
+ */
358
+ */
297
+static void resettable_phase_enter(Object *obj, void *opaque, ResetType type);
359
+static uint32_t get_gpio_pinmask_to_disconnect(Stm32l4x5GpioState *s)
298
+static void resettable_phase_hold(Object *obj, void *opaque, ResetType type);
360
+{
299
+static void resettable_phase_exit(Object *obj, void *opaque, ResetType type);
361
+ uint32_t pins_to_disconnect = 0;
300
+
362
+ for (int i = 0; i < GPIO_NUM_PINS; i++) {
301
+/**
363
+ /* for each connected pin in output mode */
302
+ * enter_phase_in_progress:
364
+ if (!(s->disconnected_pins & (1 << i)) && is_output(s, i)) {
303
+ * True if we are currently in reset enter phase.
365
+ /* if either push-pull or high level */
304
+ *
366
+ if (is_push_pull(s, i) || s->pins_connected_high & (1 << i)) {
305
+ * Note: This flag is only used to guarantee (using asserts) that the reset
367
+ pins_to_disconnect |= (1 << i);
306
+ * API is used correctly. We can use a global variable because we rely on the
368
+ qemu_log_mask(LOG_GUEST_ERROR,
307
+ * iothread mutex to ensure only one reset operation is in a progress at a
369
+ "Line %d can't be driven externally\n",
308
+ * given time.
370
+ i);
371
+ }
372
+ }
373
+ }
374
+ return pins_to_disconnect;
375
+}
376
+
377
+/*
378
+ * Set field `disconnected_pins` and call `update_gpio_idr()`
309
+ */
379
+ */
310
+static bool enter_phase_in_progress;
380
+static void disconnect_gpio_pins(Stm32l4x5GpioState *s, uint16_t lines)
311
+
381
+{
312
+void resettable_reset(Object *obj, ResetType type)
382
+ s->disconnected_pins |= lines;
313
+{
383
+ trace_stm32l4x5_gpio_pins(s->name, s->disconnected_pins,
314
+ trace_resettable_reset(obj, type);
384
+ s->pins_connected_high);
315
+ resettable_assert_reset(obj, type);
385
+ update_gpio_idr(s);
316
+ resettable_release_reset(obj, type);
386
+}
317
+}
387
+
318
+
388
+static void disconnected_pins_set(Object *obj, Visitor *v,
319
+void resettable_assert_reset(Object *obj, ResetType type)
389
+ const char *name, void *opaque, Error **errp)
320
+{
390
+{
321
+ /* TODO: change this assert when adding support for other reset types */
391
+ Stm32l4x5GpioState *s = STM32L4X5_GPIO(obj);
322
+ assert(type == RESET_TYPE_COLD);
392
+ uint16_t value;
323
+ trace_resettable_reset_assert_begin(obj, type);
393
+ if (!visit_type_uint16(v, name, &value, errp)) {
324
+ assert(!enter_phase_in_progress);
394
+ return;
325
+
395
+ }
326
+ enter_phase_in_progress = true;
396
+ disconnect_gpio_pins(s, value);
327
+ resettable_phase_enter(obj, NULL, type);
397
+}
328
+ enter_phase_in_progress = false;
398
+
329
+
399
+static void disconnected_pins_get(Object *obj, Visitor *v,
330
+ resettable_phase_hold(obj, NULL, type);
400
+ const char *name, void *opaque, Error **errp)
331
+
401
+{
332
+ trace_resettable_reset_assert_end(obj);
402
+ visit_type_uint16(v, name, (uint16_t *)opaque, errp);
333
+}
403
+}
334
+
404
+
335
+void resettable_release_reset(Object *obj, ResetType type)
405
+static void clock_freq_get(Object *obj, Visitor *v,
336
+{
406
+ const char *name, void *opaque, Error **errp)
337
+ /* TODO: change this assert when adding support for other reset types */
407
+{
338
+ assert(type == RESET_TYPE_COLD);
408
+ Stm32l4x5GpioState *s = STM32L4X5_GPIO(obj);
339
+ trace_resettable_reset_release_begin(obj, type);
409
+ uint32_t clock_freq_hz = clock_get_hz(s->clk);
340
+ assert(!enter_phase_in_progress);
410
+ visit_type_uint32(v, name, &clock_freq_hz, errp);
341
+
411
+}
342
+ resettable_phase_exit(obj, NULL, type);
412
+
343
+
413
+static void stm32l4x5_gpio_write(void *opaque, hwaddr addr,
344
+ trace_resettable_reset_release_end(obj);
414
+ uint64_t val64, unsigned int size)
345
+}
415
+{
346
+
416
+ Stm32l4x5GpioState *s = opaque;
347
+bool resettable_is_in_reset(Object *obj)
417
+
348
+{
418
+ uint32_t value = val64;
349
+ ResettableClass *rc = RESETTABLE_GET_CLASS(obj);
419
+ trace_stm32l4x5_gpio_write(s->name, addr, val64);
350
+ ResettableState *s = rc->get_state(obj);
420
+
351
+
421
+ switch (addr) {
352
+ return s->count > 0;
422
+ case GPIO_MODER:
353
+}
423
+ s->moder = value;
354
+
424
+ disconnect_gpio_pins(s, get_gpio_pinmask_to_disconnect(s));
355
+/**
425
+ qemu_log_mask(LOG_UNIMP,
356
+ * resettable_child_foreach:
426
+ "%s: Analog and AF modes aren't supported\n\
357
+ * helper to avoid checking the existence of the method.
427
+ Analog and AF mode behave like input mode\n",
358
+ */
428
+ __func__);
359
+static void resettable_child_foreach(ResettableClass *rc, Object *obj,
429
+ return;
360
+ ResettableChildCallback cb,
430
+ case GPIO_OTYPER:
361
+ void *opaque, ResetType type)
431
+ s->otyper = value & ~RESERVED_BITS_MASK;
362
+{
432
+ disconnect_gpio_pins(s, get_gpio_pinmask_to_disconnect(s));
363
+ if (rc->child_foreach) {
433
+ return;
364
+ rc->child_foreach(obj, cb, opaque, type);
434
+ case GPIO_OSPEEDR:
365
+ }
435
+ qemu_log_mask(LOG_UNIMP,
366
+}
436
+ "%s: Changing I/O output speed isn't supported\n\
367
+
437
+ I/O speed is already maximal\n",
368
+/**
438
+ __func__);
369
+ * resettable_get_tr_func:
439
+ s->ospeedr = value;
370
+ * helper to fetch transitional reset callback if any.
440
+ return;
371
+ */
441
+ case GPIO_PUPDR:
372
+static ResettableTrFunction resettable_get_tr_func(ResettableClass *rc,
442
+ s->pupdr = value;
373
+ Object *obj)
443
+ update_gpio_idr(s);
374
+{
444
+ return;
375
+ ResettableTrFunction tr_func = NULL;
445
+ case GPIO_IDR:
376
+ if (rc->get_transitional_function) {
446
+ qemu_log_mask(LOG_UNIMP,
377
+ tr_func = rc->get_transitional_function(obj);
447
+ "%s: GPIO->IDR is read-only\n",
378
+ }
448
+ __func__);
379
+ return tr_func;
449
+ return;
380
+}
450
+ case GPIO_ODR:
381
+
451
+ s->odr = value & ~RESERVED_BITS_MASK;
382
+static void resettable_phase_enter(Object *obj, void *opaque, ResetType type)
452
+ update_gpio_idr(s);
383
+{
453
+ return;
384
+ ResettableClass *rc = RESETTABLE_GET_CLASS(obj);
454
+ case GPIO_BSRR: {
385
+ ResettableState *s = rc->get_state(obj);
455
+ uint32_t bits_to_reset = (value & RESERVED_BITS_MASK) >> GPIO_NUM_PINS;
386
+ const char *obj_typename = object_get_typename(obj);
456
+ uint32_t bits_to_set = value & ~RESERVED_BITS_MASK;
387
+ bool action_needed = false;
457
+ /* If both BSx and BRx are set, BSx has priority.*/
388
+
458
+ s->odr &= ~bits_to_reset;
389
+ /* exit phase has to finish properly before entering back in reset */
459
+ s->odr |= bits_to_set;
390
+ assert(!s->exit_phase_in_progress);
460
+ update_gpio_idr(s);
391
+
461
+ return;
392
+ trace_resettable_phase_enter_begin(obj, obj_typename, s->count, type);
462
+ }
393
+
463
+ case GPIO_LCKR:
394
+ /* Only take action if we really enter reset for the 1st time. */
464
+ qemu_log_mask(LOG_UNIMP,
395
+ /*
465
+ "%s: Locking port bits configuration isn't supported\n",
396
+ * TODO: if adding more ResetType support, some additional checks
466
+ __func__);
397
+ * are probably needed here.
467
+ s->lckr = value & ~RESERVED_BITS_MASK;
398
+ */
468
+ return;
399
+ if (s->count++ == 0) {
469
+ case GPIO_AFRL:
400
+ action_needed = true;
470
+ qemu_log_mask(LOG_UNIMP,
401
+ }
471
+ "%s: Alternate functions aren't supported\n",
402
+ /*
472
+ __func__);
403
+ * We limit the count to an arbitrary "big" value. The value is big
473
+ s->afrl = value;
404
+ * enough not to be triggered normally.
474
+ return;
405
+ * The assert will stop an infinite loop if there is a cycle in the
475
+ case GPIO_AFRH:
406
+ * reset tree. The loop goes through resettable_foreach_child below
476
+ qemu_log_mask(LOG_UNIMP,
407
+ * which at some point will call us again.
477
+ "%s: Alternate functions aren't supported\n",
408
+ */
478
+ __func__);
409
+ assert(s->count <= 50);
479
+ s->afrh = value;
410
+
480
+ return;
411
+ /*
481
+ case GPIO_BRR: {
412
+ * handle the children even if action_needed is at false so that
482
+ uint32_t bits_to_reset = value & ~RESERVED_BITS_MASK;
413
+ * child counts are incremented too
483
+ s->odr &= ~bits_to_reset;
414
+ */
484
+ update_gpio_idr(s);
415
+ resettable_child_foreach(rc, obj, resettable_phase_enter, NULL, type);
485
+ return;
416
+
486
+ }
417
+ /* execute enter phase for the object if needed */
487
+ case GPIO_ASCR:
418
+ if (action_needed) {
488
+ qemu_log_mask(LOG_UNIMP,
419
+ trace_resettable_phase_enter_exec(obj, obj_typename, type,
489
+ "%s: ADC function isn't supported\n",
420
+ !!rc->phases.enter);
490
+ __func__);
421
+ if (rc->phases.enter && !resettable_get_tr_func(rc, obj)) {
491
+ s->ascr = value & ~RESERVED_BITS_MASK;
422
+ rc->phases.enter(obj, type);
492
+ return;
423
+ }
493
+ default:
424
+ s->hold_phase_pending = true;
494
+ qemu_log_mask(LOG_GUEST_ERROR,
425
+ }
495
+ "%s: Bad offset 0x%" HWADDR_PRIx "\n", __func__, addr);
426
+ trace_resettable_phase_enter_end(obj, obj_typename, s->count);
496
+ }
427
+}
497
+}
428
+
498
+
429
+static void resettable_phase_hold(Object *obj, void *opaque, ResetType type)
499
+static uint64_t stm32l4x5_gpio_read(void *opaque, hwaddr addr,
430
+{
500
+ unsigned int size)
431
+ ResettableClass *rc = RESETTABLE_GET_CLASS(obj);
501
+{
432
+ ResettableState *s = rc->get_state(obj);
502
+ Stm32l4x5GpioState *s = opaque;
433
+ const char *obj_typename = object_get_typename(obj);
503
+
434
+
504
+ trace_stm32l4x5_gpio_read(s->name, addr);
435
+ /* exit phase has to finish properly before entering back in reset */
505
+
436
+ assert(!s->exit_phase_in_progress);
506
+ switch (addr) {
437
+
507
+ case GPIO_MODER:
438
+ trace_resettable_phase_hold_begin(obj, obj_typename, s->count, type);
508
+ return s->moder;
439
+
509
+ case GPIO_OTYPER:
440
+ /* handle children first */
510
+ return s->otyper;
441
+ resettable_child_foreach(rc, obj, resettable_phase_hold, NULL, type);
511
+ case GPIO_OSPEEDR:
442
+
512
+ return s->ospeedr;
443
+ /* exec hold phase */
513
+ case GPIO_PUPDR:
444
+ if (s->hold_phase_pending) {
514
+ return s->pupdr;
445
+ s->hold_phase_pending = false;
515
+ case GPIO_IDR:
446
+ ResettableTrFunction tr_func = resettable_get_tr_func(rc, obj);
516
+ return s->idr;
447
+ trace_resettable_phase_hold_exec(obj, obj_typename, !!rc->phases.hold);
517
+ case GPIO_ODR:
448
+ if (tr_func) {
518
+ return s->odr;
449
+ trace_resettable_transitional_function(obj, obj_typename);
519
+ case GPIO_BSRR:
450
+ tr_func(obj);
520
+ return 0;
451
+ } else if (rc->phases.hold) {
521
+ case GPIO_LCKR:
452
+ rc->phases.hold(obj);
522
+ return s->lckr;
453
+ }
523
+ case GPIO_AFRL:
454
+ }
524
+ return s->afrl;
455
+ trace_resettable_phase_hold_end(obj, obj_typename, s->count);
525
+ case GPIO_AFRH:
456
+}
526
+ return s->afrh;
457
+
527
+ case GPIO_BRR:
458
+static void resettable_phase_exit(Object *obj, void *opaque, ResetType type)
528
+ return 0;
459
+{
529
+ case GPIO_ASCR:
460
+ ResettableClass *rc = RESETTABLE_GET_CLASS(obj);
530
+ return s->ascr;
461
+ ResettableState *s = rc->get_state(obj);
531
+ default:
462
+ const char *obj_typename = object_get_typename(obj);
532
+ qemu_log_mask(LOG_GUEST_ERROR,
463
+
533
+ "%s: Bad offset 0x%" HWADDR_PRIx "\n", __func__, addr);
464
+ assert(!s->exit_phase_in_progress);
534
+ return 0;
465
+ trace_resettable_phase_exit_begin(obj, obj_typename, s->count, type);
535
+ }
466
+
536
+}
467
+ /* exit_phase_in_progress ensures this phase is 'atomic' */
537
+
468
+ s->exit_phase_in_progress = true;
538
+static const MemoryRegionOps stm32l4x5_gpio_ops = {
469
+ resettable_child_foreach(rc, obj, resettable_phase_exit, NULL, type);
539
+ .read = stm32l4x5_gpio_read,
470
+
540
+ .write = stm32l4x5_gpio_write,
471
+ assert(s->count > 0);
541
+ .endianness = DEVICE_NATIVE_ENDIAN,
472
+ if (s->count == 1) {
542
+ .impl = {
473
+ trace_resettable_phase_exit_exec(obj, obj_typename, !!rc->phases.exit);
543
+ .min_access_size = 4,
474
+ if (rc->phases.exit && !resettable_get_tr_func(rc, obj)) {
544
+ .max_access_size = 4,
475
+ rc->phases.exit(obj);
545
+ .unaligned = false,
476
+ }
546
+ },
477
+ s->count = 0;
547
+ .valid = {
478
+ }
548
+ .min_access_size = 4,
479
+ s->exit_phase_in_progress = false;
549
+ .max_access_size = 4,
480
+ trace_resettable_phase_exit_end(obj, obj_typename, s->count);
550
+ .unaligned = false,
481
+}
551
+ },
482
+
483
+void resettable_class_set_parent_phases(ResettableClass *rc,
484
+ ResettableEnterPhase enter,
485
+ ResettableHoldPhase hold,
486
+ ResettableExitPhase exit,
487
+ ResettablePhases *parent_phases)
488
+{
489
+ *parent_phases = rc->phases;
490
+ if (enter) {
491
+ rc->phases.enter = enter;
492
+ }
493
+ if (hold) {
494
+ rc->phases.hold = hold;
495
+ }
496
+ if (exit) {
497
+ rc->phases.exit = exit;
498
+ }
499
+}
500
+
501
+static const TypeInfo resettable_interface_info = {
502
+ .name = TYPE_RESETTABLE_INTERFACE,
503
+ .parent = TYPE_INTERFACE,
504
+ .class_size = sizeof(ResettableClass),
505
+};
552
+};
506
+
553
+
507
+static void reset_register_types(void)
554
+static void stm32l4x5_gpio_init(Object *obj)
508
+{
555
+{
509
+ type_register_static(&resettable_interface_info);
556
+ Stm32l4x5GpioState *s = STM32L4X5_GPIO(obj);
510
+}
557
+
511
+
558
+ memory_region_init_io(&s->mmio, obj, &stm32l4x5_gpio_ops, s,
512
+type_init(reset_register_types)
559
+ TYPE_STM32L4X5_GPIO, 0x400);
513
diff --git a/hw/core/trace-events b/hw/core/trace-events
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
514
index XXXXXXX..XXXXXXX 100644
636
index XXXXXXX..XXXXXXX 100644
515
--- a/hw/core/trace-events
637
--- a/hw/gpio/Kconfig
516
+++ b/hw/core/trace-events
638
+++ b/hw/gpio/Kconfig
517
@@ -XXX,XX +XXX,XX @@ qbus_reset(void *obj, const char *objtype) "obj=%p(%s)"
639
@@ -XXX,XX +XXX,XX @@ config GPIO_PWR
518
qbus_reset_all(void *obj, const char *objtype) "obj=%p(%s)"
640
519
qbus_reset_tree(void *obj, const char *objtype) "obj=%p(%s)"
641
config SIFIVE_GPIO
520
qdev_update_parent_bus(void *obj, const char *objtype, void *oldp, const char *oldptype, void *newp, const char *newptype) "obj=%p(%s) old_parent=%p(%s) new_parent=%p(%s)"
642
bool
521
+
643
+
522
+# resettable.c
644
+config STM32L4X5_GPIO
523
+resettable_reset(void *obj, int cold) "obj=%p cold=%d"
645
+ bool
524
+resettable_reset_assert_begin(void *obj, int cold) "obj=%p cold=%d"
646
diff --git a/hw/gpio/meson.build b/hw/gpio/meson.build
525
+resettable_reset_assert_end(void *obj) "obj=%p"
647
index XXXXXXX..XXXXXXX 100644
526
+resettable_reset_release_begin(void *obj, int cold) "obj=%p cold=%d"
648
--- a/hw/gpio/meson.build
527
+resettable_reset_release_end(void *obj) "obj=%p"
649
+++ b/hw/gpio/meson.build
528
+resettable_phase_enter_begin(void *obj, const char *objtype, unsigned count, int type) "obj=%p(%s) count=%d type=%d"
650
@@ -XXX,XX +XXX,XX @@ system_ss.add(when: 'CONFIG_RASPI', if_true: files(
529
+resettable_phase_enter_exec(void *obj, const char *objtype, int type, int has_method) "obj=%p(%s) type=%d method=%d"
651
'bcm2835_gpio.c',
530
+resettable_phase_enter_end(void *obj, const char *objtype, unsigned count) "obj=%p(%s) count=%d"
652
'bcm2838_gpio.c'
531
+resettable_phase_hold_begin(void *obj, const char *objtype, unsigned count, int type) "obj=%p(%s) count=%d type=%d"
653
))
532
+resettable_phase_hold_exec(void *obj, const char *objtype, int has_method) "obj=%p(%s) method=%d"
654
+system_ss.add(when: 'CONFIG_STM32L4X5_SOC', if_true: files('stm32l4x5_gpio.c'))
533
+resettable_phase_hold_end(void *obj, const char *objtype, unsigned count) "obj=%p(%s) count=%d"
655
system_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files('aspeed_gpio.c'))
534
+resettable_phase_exit_begin(void *obj, const char *objtype, unsigned count, int type) "obj=%p(%s) count=%d type=%d"
656
system_ss.add(when: 'CONFIG_SIFIVE_GPIO', if_true: files('sifive_gpio.c'))
535
+resettable_phase_exit_exec(void *obj, const char *objtype, int has_method) "obj=%p(%s) method=%d"
657
diff --git a/hw/gpio/trace-events b/hw/gpio/trace-events
536
+resettable_phase_exit_end(void *obj, const char *objtype, unsigned count) "obj=%p(%s) count=%d"
658
index XXXXXXX..XXXXXXX 100644
537
+resettable_transitional_function(void *obj, const char *objtype) "obj=%p(%s)"
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"
538
--
671
--
539
2.20.1
672
2.34.1
540
673
541
674
diff view generated by jsdifflib
1
From: Joel Stanley <joel@jms.id.au>
1
From: Inès Varhol <ines.varhol@telecom-paris.fr>
2
2
3
Following the pattern of the work recently done with the ASPEED GPIO
3
Signed-off-by: Arnaud Minier <arnaud.minier@telecom-paris.fr>
4
model, this adds support for inspecting and modifying the PCA9552 LEDs
4
Signed-off-by: Inès Varhol <ines.varhol@telecom-paris.fr>
5
from the monitor.
5
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
6
6
Acked-by: Alistair Francis <alistair.francis@wdc.com>
7
(qemu) qom-set /machine/unattached/device[17] led0 on
7
Message-id: 20240305210444.310665-3-ines.varhol@telecom-paris.fr
8
(qemu) qom-set /machine/unattached/device[17] led0 off
9
(qemu) qom-set /machine/unattached/device[17] led0 pwm0
10
(qemu) qom-set /machine/unattached/device[17] led0 pwm1
11
12
Signed-off-by: Joel Stanley <joel@jms.id.au>
13
Signed-off-by: Cédric Le Goater <clg@kaod.org>
14
Message-id: 20200114103433.30534-6-clg@kaod.org
15
[clg: - removed the "qom-get" examples from the commit log
16
- merged memory leak fixes from Joel ]
17
Signed-off-by: Cédric Le Goater <clg@kaod.org>
18
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
19
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
20
---
9
---
21
hw/misc/pca9552.c | 90 +++++++++++++++++++++++++++++++++++++++++++++++
10
include/hw/arm/stm32l4x5_soc.h | 2 +
22
1 file changed, 90 insertions(+)
11
include/hw/gpio/stm32l4x5_gpio.h | 1 +
23
12
include/hw/misc/stm32l4x5_syscfg.h | 3 +-
24
diff --git a/hw/misc/pca9552.c b/hw/misc/pca9552.c
13
hw/arm/stm32l4x5_soc.c | 71 +++++++++++++++++++++++-------
25
index XXXXXXX..XXXXXXX 100644
14
hw/misc/stm32l4x5_syscfg.c | 1 +
26
--- a/hw/misc/pca9552.c
15
hw/arm/Kconfig | 3 +-
27
+++ b/hw/misc/pca9552.c
16
6 files changed, 63 insertions(+), 18 deletions(-)
28
@@ -XXX,XX +XXX,XX @@
17
29
#include "hw/misc/pca9552.h"
18
diff --git a/include/hw/arm/stm32l4x5_soc.h b/include/hw/arm/stm32l4x5_soc.h
30
#include "hw/misc/pca9552_regs.h"
19
index XXXXXXX..XXXXXXX 100644
31
#include "migration/vmstate.h"
20
--- a/include/hw/arm/stm32l4x5_soc.h
32
+#include "qapi/error.h"
21
+++ b/include/hw/arm/stm32l4x5_soc.h
33
+#include "qapi/visitor.h"
22
@@ -XXX,XX +XXX,XX @@
34
23
#include "hw/misc/stm32l4x5_syscfg.h"
35
#define PCA9552_LED_ON 0x0
24
#include "hw/misc/stm32l4x5_exti.h"
36
#define PCA9552_LED_OFF 0x1
25
#include "hw/misc/stm32l4x5_rcc.h"
37
#define PCA9552_LED_PWM0 0x2
26
+#include "hw/gpio/stm32l4x5_gpio.h"
38
#define PCA9552_LED_PWM1 0x3
27
#include "qom/object.h"
39
28
40
+static const char *led_state[] = {"on", "off", "pwm0", "pwm1"};
29
#define TYPE_STM32L4X5_SOC "stm32l4x5-soc"
41
+
30
@@ -XXX,XX +XXX,XX @@ struct Stm32l4x5SocState {
42
static uint8_t pca9552_pin_get_config(PCA9552State *s, int pin)
31
OrIRQState exti_or_gates[NUM_EXTI_OR_GATES];
32
Stm32l4x5SyscfgState syscfg;
33
Stm32l4x5RccState rcc;
34
+ Stm32l4x5GpioState gpio[NUM_GPIOS];
35
36
MemoryRegion sram1;
37
MemoryRegion sram2;
38
diff --git a/include/hw/gpio/stm32l4x5_gpio.h b/include/hw/gpio/stm32l4x5_gpio.h
39
index XXXXXXX..XXXXXXX 100644
40
--- a/include/hw/gpio/stm32l4x5_gpio.h
41
+++ b/include/hw/gpio/stm32l4x5_gpio.h
42
@@ -XXX,XX +XXX,XX @@
43
#define TYPE_STM32L4X5_GPIO "stm32l4x5-gpio"
44
OBJECT_DECLARE_SIMPLE_TYPE(Stm32l4x5GpioState, STM32L4X5_GPIO)
45
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)
43
{
101
{
44
uint8_t reg = PCA9552_LS0 + (pin / 4);
102
Stm32l4x5SocState *s = STM32L4X5_SOC(obj);
45
@@ -XXX,XX +XXX,XX @@ static int pca9552_event(I2CSlave *i2c, enum i2c_event event)
103
@@ -XXX,XX +XXX,XX @@ static void stm32l4x5_soc_initfn(Object *obj)
46
return 0;
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
+ }
47
}
112
}
48
113
49
+static void pca9552_get_led(Object *obj, Visitor *v, const char *name,
114
static void stm32l4x5_soc_realize(DeviceState *dev_soc, Error **errp)
50
+ void *opaque, Error **errp)
115
@@ -XXX,XX +XXX,XX @@ static void stm32l4x5_soc_realize(DeviceState *dev_soc, Error **errp)
51
+{
116
Stm32l4x5SocState *s = STM32L4X5_SOC(dev_soc);
52
+ PCA9552State *s = PCA9552(obj);
117
const Stm32l4x5SocClass *sc = STM32L4X5_SOC_GET_CLASS(dev_soc);
53
+ int led, rc, reg;
118
MemoryRegion *system_memory = get_system_memory();
54
+ uint8_t state;
119
- DeviceState *armv7m;
55
+
120
+ DeviceState *armv7m, *dev;
56
+ rc = sscanf(name, "led%2d", &led);
121
SysBusDevice *busdev;
57
+ if (rc != 1) {
122
+ uint32_t pin_index;
58
+ error_setg(errp, "%s: error reading %s", __func__, name);
123
59
+ return;
124
if (!memory_region_init_rom(&s->flash, OBJECT(dev_soc), "flash",
125
sc->flash_size, errp)) {
126
@@ -XXX,XX +XXX,XX @@ static void stm32l4x5_soc_realize(DeviceState *dev_soc, Error **errp)
127
return;
128
}
129
130
+ /* GPIOs */
131
+ for (unsigned i = 0; i < NUM_GPIOS; i++) {
132
+ g_autofree char *name = g_strdup_printf("%c", 'A' + i);
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);
60
+ }
150
+ }
61
+ if (led < 0 || led > s->nr_leds) {
151
+
62
+ error_setg(errp, "%s invalid led %s", __func__, name);
152
/* System configuration controller */
63
+ return;
153
busdev = SYS_BUS_DEVICE(&s->syscfg);
64
+ }
154
if (!sysbus_realize(busdev, errp)) {
65
+ /*
155
return;
66
+ * Get the LSx register as the qom interface should expose the device
156
}
67
+ * state, not the modeled 'input line' behaviour which would come from
157
sysbus_mmio_map(busdev, 0, SYSCFG_ADDR);
68
+ * reading the INPUTx reg
158
- /*
69
+ */
159
- * TODO: when the GPIO device is implemented, connect it
70
+ reg = PCA9552_LS0 + led / 4;
160
- * to SYCFG using `qdev_connect_gpio_out`, NUM_GPIOS and
71
+ state = (pca9552_read(s, reg) >> (led % 8)) & 0x3;
161
- * GPIO_NUM_PINS.
72
+ visit_type_str(v, name, (char **)&led_state[state], errp);
162
- */
73
+}
163
+
74
+
164
+ for (unsigned i = 0; i < NUM_GPIOS; i++) {
75
+/*
165
+ for (unsigned j = 0; j < GPIO_NUM_PINS; j++) {
76
+ * Return an LED selector register value based on an existing one, with
166
+ pin_index = GPIO_NUM_PINS * i + j;
77
+ * the appropriate 2-bit state value set for the given LED number (0-3).
167
+ qdev_connect_gpio_out(DEVICE(&s->gpio[i]), j,
78
+ */
168
+ qdev_get_gpio_in(DEVICE(&s->syscfg),
79
+static inline uint8_t pca955x_ledsel(uint8_t oldval, int led_num, int state)
169
+ pin_index));
80
+{
81
+ return (oldval & (~(0x3 << (led_num << 1)))) |
82
+ ((state & 0x3) << (led_num << 1));
83
+}
84
+
85
+static void pca9552_set_led(Object *obj, Visitor *v, const char *name,
86
+ void *opaque, Error **errp)
87
+{
88
+ PCA9552State *s = PCA9552(obj);
89
+ Error *local_err = NULL;
90
+ int led, rc, reg, val;
91
+ uint8_t state;
92
+ char *state_str;
93
+
94
+ visit_type_str(v, name, &state_str, &local_err);
95
+ if (local_err) {
96
+ error_propagate(errp, local_err);
97
+ return;
98
+ }
99
+ rc = sscanf(name, "led%2d", &led);
100
+ if (rc != 1) {
101
+ error_setg(errp, "%s: error reading %s", __func__, name);
102
+ return;
103
+ }
104
+ if (led < 0 || led > s->nr_leds) {
105
+ error_setg(errp, "%s invalid led %s", __func__, name);
106
+ return;
107
+ }
108
+
109
+ for (state = 0; state < ARRAY_SIZE(led_state); state++) {
110
+ if (!strcmp(state_str, led_state[state])) {
111
+ break;
112
+ }
170
+ }
113
+ }
171
+ }
114
+ if (state >= ARRAY_SIZE(led_state)) {
172
115
+ error_setg(errp, "%s invalid led state %s", __func__, state_str);
173
/* EXTI device */
116
+ return;
174
busdev = SYS_BUS_DEVICE(&s->exti);
117
+ }
175
@@ -XXX,XX +XXX,XX @@ static void stm32l4x5_soc_realize(DeviceState *dev_soc, Error **errp)
118
+
176
}
119
+ reg = PCA9552_LS0 + led / 4;
177
}
120
+ val = pca9552_read(s, reg);
178
121
+ val = pca955x_ledsel(val, led % 4, state);
179
- for (unsigned i = 0; i < 16; i++) {
122
+ pca9552_write(s, reg, val);
180
+ for (unsigned i = 0; i < GPIO_NUM_PINS; i++) {
123
+}
181
qdev_connect_gpio_out(DEVICE(&s->syscfg), i,
124
+
182
qdev_get_gpio_in(DEVICE(&s->exti), i));
125
static const VMStateDescription pca9552_vmstate = {
183
}
126
.name = "PCA9552",
184
@@ -XXX,XX +XXX,XX @@ static void stm32l4x5_soc_realize(DeviceState *dev_soc, Error **errp)
127
.version_id = 0,
185
/* RESERVED: 0x40024400, 0x7FDBC00 */
128
@@ -XXX,XX +XXX,XX @@ static void pca9552_reset(DeviceState *dev)
186
129
static void pca9552_initfn(Object *obj)
187
/* AHB2 BUS */
130
{
188
- create_unimplemented_device("GPIOA", 0x48000000, 0x400);
131
PCA9552State *s = PCA9552(obj);
189
- create_unimplemented_device("GPIOB", 0x48000400, 0x400);
132
+ int led;
190
- create_unimplemented_device("GPIOC", 0x48000800, 0x400);
133
191
- create_unimplemented_device("GPIOD", 0x48000C00, 0x400);
134
/* If support for the other PCA955X devices are implemented, these
192
- create_unimplemented_device("GPIOE", 0x48001000, 0x400);
135
* constant values might be part of class structure describing the
193
- create_unimplemented_device("GPIOF", 0x48001400, 0x400);
136
@@ -XXX,XX +XXX,XX @@ static void pca9552_initfn(Object *obj)
194
- create_unimplemented_device("GPIOG", 0x48001800, 0x400);
137
*/
195
- create_unimplemented_device("GPIOH", 0x48001C00, 0x400);
138
s->max_reg = PCA9552_LS3;
196
/* RESERVED: 0x48002000, 0x7FDBC00 */
139
s->nr_leds = 16;
197
create_unimplemented_device("OTG_FS", 0x50000000, 0x40000);
140
+
198
create_unimplemented_device("ADC", 0x50040000, 0x400);
141
+ for (led = 0; led < s->nr_leds; led++) {
199
diff --git a/hw/misc/stm32l4x5_syscfg.c b/hw/misc/stm32l4x5_syscfg.c
142
+ char *name;
200
index XXXXXXX..XXXXXXX 100644
143
+
201
--- a/hw/misc/stm32l4x5_syscfg.c
144
+ name = g_strdup_printf("led%d", led);
202
+++ b/hw/misc/stm32l4x5_syscfg.c
145
+ object_property_add(obj, name, "bool", pca9552_get_led, pca9552_set_led,
203
@@ -XXX,XX +XXX,XX @@
146
+ NULL, NULL, NULL);
204
#include "hw/irq.h"
147
+ g_free(name);
205
#include "migration/vmstate.h"
148
+ }
206
#include "hw/misc/stm32l4x5_syscfg.h"
149
}
207
+#include "hw/gpio/stm32l4x5_gpio.h"
150
208
151
static void pca9552_class_init(ObjectClass *klass, void *data)
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
152
--
227
--
153
2.20.1
228
2.34.1
154
229
155
230
diff view generated by jsdifflib
1
From: Damien Hedde <damien.hedde@greensocs.com>
1
From: Inès Varhol <ines.varhol@telecom-paris.fr>
2
2
3
Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
3
The testcase contains :
4
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
- `test_idr_reset_value()` :
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Checks the reset values of MODER, OTYPER, PUPDR, ODR and IDR.
6
Message-id: 20200123132823.1117486-10-damien.hedde@greensocs.com
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.
24
25
Acked-by: Thomas Huth <thuth@redhat.com>
26
Signed-off-by: Arnaud Minier <arnaud.minier@telecom-paris.fr>
27
Signed-off-by: Inès Varhol <ines.varhol@telecom-paris.fr>
28
Message-id: 20240305210444.310665-4-ines.varhol@telecom-paris.fr
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
29
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
---
30
---
9
docs/devel/index.rst | 1 +
31
tests/qtest/stm32l4x5_gpio-test.c | 551 ++++++++++++++++++++++++++++++
10
docs/devel/reset.rst | 289 +++++++++++++++++++++++++++++++++++++++++++
32
tests/qtest/meson.build | 3 +-
11
2 files changed, 290 insertions(+)
33
2 files changed, 553 insertions(+), 1 deletion(-)
12
create mode 100644 docs/devel/reset.rst
34
create mode 100644 tests/qtest/stm32l4x5_gpio-test.c
13
35
14
diff --git a/docs/devel/index.rst b/docs/devel/index.rst
36
diff --git a/tests/qtest/stm32l4x5_gpio-test.c b/tests/qtest/stm32l4x5_gpio-test.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/docs/devel/index.rst
17
+++ b/docs/devel/index.rst
18
@@ -XXX,XX +XXX,XX @@ Contents:
19
tcg
20
tcg-plugins
21
bitops
22
+ reset
23
diff --git a/docs/devel/reset.rst b/docs/devel/reset.rst
24
new file mode 100644
37
new file mode 100644
25
index XXXXXXX..XXXXXXX
38
index XXXXXXX..XXXXXXX
26
--- /dev/null
39
--- /dev/null
27
+++ b/docs/devel/reset.rst
40
+++ b/tests/qtest/stm32l4x5_gpio-test.c
28
@@ -XXX,XX +XXX,XX @@
41
@@ -XXX,XX +XXX,XX @@
29
+
42
+/*
30
+=======================================
43
+ * QTest testcase for STM32L4x5_GPIO
31
+Reset in QEMU: the Resettable interface
44
+ *
32
+=======================================
45
+ * Copyright (c) 2024 Arnaud Minier <arnaud.minier@telecom-paris.fr>
33
+
46
+ * Copyright (c) 2024 Inès Varhol <ines.varhol@telecom-paris.fr>
34
+The reset of qemu objects is handled using the resettable interface declared
47
+ *
35
+in ``include/hw/resettable.h``.
48
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
36
+
49
+ * See the COPYING file in the top-level directory.
37
+This interface allows objects to be grouped (on a tree basis); so that the
50
+ */
38
+whole group can be reset consistently. Each individual member object does not
51
+
39
+have to care about others; in particular, problems of order (which object is
52
+#include "qemu/osdep.h"
40
+reset first) are addressed.
53
+#include "libqtest-single.h"
41
+
54
+
42
+As of now DeviceClass and BusClass implement this interface.
55
+#define GPIO_BASE_ADDR 0x48000000
43
+
56
+#define GPIO_SIZE 0x400
44
+
57
+#define NUM_GPIOS 8
45
+Triggering reset
58
+#define NUM_GPIO_PINS 16
46
+----------------
59
+
47
+
60
+#define GPIO_A 0x48000000
48
+This section documents the APIs which "users" of a resettable object should use
61
+#define GPIO_B 0x48000400
49
+to control it. All resettable control functions must be called while holding
62
+#define GPIO_C 0x48000800
50
+the iothread lock.
63
+#define GPIO_D 0x48000C00
51
+
64
+#define GPIO_E 0x48001000
52
+You can apply a reset to an object using ``resettable_assert_reset()``. You need
65
+#define GPIO_F 0x48001400
53
+to call ``resettable_release_reset()`` to release the object from reset. To
66
+#define GPIO_G 0x48001800
54
+instantly reset an object, without keeping it in reset state, just call
67
+#define GPIO_H 0x48001C00
55
+``resettable_reset()``. These functions take two parameters: a pointer to the
68
+
56
+object to reset and a reset type.
69
+#define MODER 0x00
57
+
70
+#define OTYPER 0x04
58
+Several types of reset will be supported. For now only cold reset is defined;
71
+#define PUPDR 0x0C
59
+others may be added later. The Resettable interface handles reset types with an
72
+#define IDR 0x10
60
+enum:
73
+#define ODR 0x14
61
+
74
+#define BSRR 0x18
62
+``RESET_TYPE_COLD``
75
+#define BRR 0x28
63
+ Cold reset is supported by every resettable object. In QEMU, it means we reset
76
+
64
+ to the initial state corresponding to the start of QEMU; this might differ
77
+#define MODER_INPUT 0
65
+ from what is a real hardware cold reset. It differs from other resets (like
78
+#define MODER_OUTPUT 1
66
+ warm or bus resets) which may keep certain parts untouched.
79
+
67
+
80
+#define PUPDR_NONE 0
68
+Calling ``resettable_reset()`` is equivalent to calling
81
+#define PUPDR_PULLUP 1
69
+``resettable_assert_reset()`` then ``resettable_release_reset()``. It is
82
+#define PUPDR_PULLDOWN 2
70
+possible to interleave multiple calls to these three functions. There may
83
+
71
+be several reset sources/controllers of a given object. The interface handles
84
+#define OTYPER_PUSH_PULL 0
72
+everything and the different reset controllers do not need to know anything
85
+#define OTYPER_OPEN_DRAIN 1
73
+about each others. The object will leave reset state only when each other
86
+
74
+controllers end their reset operation. This point is handled internally by
87
+const uint32_t moder_reset[NUM_GPIOS] = {
75
+maintaining a count of in-progress resets; it is crucial to call
88
+ 0xABFFFFFF,
76
+``resettable_release_reset()`` one time and only one time per
89
+ 0xFFFFFEBF,
77
+``resettable_assert_reset()`` call.
90
+ 0xFFFFFFFF,
78
+
91
+ 0xFFFFFFFF,
79
+For now migration of a device or bus in reset is not supported. Care must be
92
+ 0xFFFFFFFF,
80
+taken not to delay ``resettable_release_reset()`` after its
93
+ 0xFFFFFFFF,
81
+``resettable_assert_reset()`` counterpart.
94
+ 0xFFFFFFFF,
82
+
95
+ 0x0000000F
83
+Note that, since resettable is an interface, the API takes a simple Object as
96
+};
84
+parameter. Still, it is a programming error to call a resettable function on a
97
+
85
+non-resettable object and it will trigger a run time assert error. Since most
98
+const uint32_t pupdr_reset[NUM_GPIOS] = {
86
+calls to resettable interface are done through base class functions, such an
99
+ 0x64000000,
87
+error is not likely to happen.
100
+ 0x00000100,
88
+
101
+ 0x00000000,
89
+For Devices and Buses, the following helper functions exist:
102
+ 0x00000000,
90
+
103
+ 0x00000000,
91
+- ``device_cold_reset()``
104
+ 0x00000000,
92
+- ``bus_cold_reset()``
105
+ 0x00000000,
93
+
106
+ 0x00000000
94
+These are simple wrappers around resettable_reset() function; they only cast the
107
+};
95
+Device or Bus into an Object and pass the cold reset type. When possible
108
+
96
+prefer to use these functions instead of ``resettable_reset()``.
109
+const uint32_t idr_reset[NUM_GPIOS] = {
97
+
110
+ 0x0000A000,
98
+Device and bus functions co-exist because there can be semantic differences
111
+ 0x00000010,
99
+between resetting a bus and resetting the controller bridge which owns it.
112
+ 0x00000000,
100
+For example, consider a SCSI controller. Resetting the controller puts all
113
+ 0x00000000,
101
+its registers back to what reset state was as well as reset everything on the
114
+ 0x00000000,
102
+SCSI bus, whereas resetting just the SCSI bus only resets everything that's on
115
+ 0x00000000,
103
+it but not the controller.
116
+ 0x00000000,
104
+
117
+ 0x00000000
105
+
118
+};
106
+Multi-phase mechanism
119
+
107
+---------------------
120
+static uint32_t gpio_readl(unsigned int gpio, unsigned int offset)
108
+
121
+{
109
+This section documents the internals of the resettable interface.
122
+ return readl(gpio + offset);
110
+
123
+}
111
+The resettable interface uses a multi-phase system to relieve objects and
124
+
112
+machines from reset ordering problems. To address this, the reset operation
125
+static void gpio_writel(unsigned int gpio, unsigned int offset, uint32_t value)
113
+of an object is split into three well defined phases.
126
+{
114
+
127
+ writel(gpio + offset, value);
115
+When resetting several objects (for example the whole machine at simulation
128
+}
116
+startup), all first phases of all objects are executed, then all second phases
129
+
117
+and then all third phases.
130
+static void gpio_set_bit(unsigned int gpio, unsigned int reg,
118
+
131
+ unsigned int pin, uint32_t value)
119
+The three phases are:
132
+{
120
+
133
+ uint32_t mask = 0xFFFFFFFF & ~(0x1 << pin);
121
+1. The **enter** phase is executed when the object enters reset. It resets only
134
+ gpio_writel(gpio, reg, (gpio_readl(gpio, reg) & mask) | value << pin);
122
+ local state of the object; it must not do anything that has a side-effect
135
+}
123
+ on other objects, such as raising or lowering a qemu_irq line or reading or
136
+
124
+ writing guest memory.
137
+static void gpio_set_2bits(unsigned int gpio, unsigned int reg,
125
+
138
+ unsigned int pin, uint32_t value)
126
+2. The **hold** phase is executed for entry into reset, once every object in the
139
+{
127
+ group which is being reset has had its *enter* phase executed. At this point
140
+ uint32_t offset = 2 * pin;
128
+ devices can do actions that affect other objects.
141
+ uint32_t mask = 0xFFFFFFFF & ~(0x3 << offset);
129
+
142
+ gpio_writel(gpio, reg, (gpio_readl(gpio, reg) & mask) | value << offset);
130
+3. The **exit** phase is executed when the object leaves the reset state.
143
+}
131
+ Actions affecting other objects are permitted.
144
+
132
+
145
+static unsigned int get_gpio_id(uint32_t gpio_addr)
133
+As said in previous section, the interface maintains a count of reset. This
146
+{
134
+count is used to ensure phases are executed only when required. *enter* and
147
+ return (gpio_addr - GPIO_BASE_ADDR) / GPIO_SIZE;
135
+*hold* phases are executed only when asserting reset for the first time
148
+}
136
+(if an object is already in reset state when calling
149
+
137
+``resettable_assert_reset()`` or ``resettable_reset()``, they are not
150
+static void gpio_set_irq(unsigned int gpio, int num, int level)
138
+executed).
151
+{
139
+The *exit* phase is executed only when the last reset operation ends. Therefore
152
+ g_autofree char *name = g_strdup_printf("/machine/soc/gpio%c",
140
+the object does not need to care how many of reset controllers it has and how
153
+ get_gpio_id(gpio) + 'a');
141
+many of them have started a reset.
154
+ qtest_set_irq_in(global_qtest, name, NULL, num, level);
142
+
155
+}
143
+
156
+
144
+Handling reset in a resettable object
157
+static void disconnect_all_pins(unsigned int gpio)
145
+-------------------------------------
158
+{
146
+
159
+ g_autofree char *path = g_strdup_printf("/machine/soc/gpio%c",
147
+This section documents the APIs that an implementation of a resettable object
160
+ get_gpio_id(gpio) + 'a');
148
+must provide and what functions it has access to. It is intended for people
161
+ QDict *r;
149
+who want to implement or convert a class which has the resettable interface;
162
+
150
+for example when specializing an existing device or bus.
163
+ r = qtest_qmp(global_qtest, "{ 'execute': 'qom-set', 'arguments': "
151
+
164
+ "{ 'path': %s, 'property': 'disconnected-pins', 'value': %d } }",
152
+Methods to implement
165
+ path, 0xFFFF);
153
+....................
166
+ g_assert_false(qdict_haskey(r, "error"));
154
+
167
+ qobject_unref(r);
155
+Three methods should be defined or left empty. Each method corresponds to a
168
+}
156
+phase of the reset; they are name ``phases.enter()``, ``phases.hold()`` and
169
+
157
+``phases.exit()``. They all take the object as parameter. The *enter* method
170
+static uint32_t get_disconnected_pins(unsigned int gpio)
158
+also take the reset type as second parameter.
171
+{
159
+
172
+ g_autofree char *path = g_strdup_printf("/machine/soc/gpio%c",
160
+When extending an existing class, these methods may need to be extended too.
173
+ get_gpio_id(gpio) + 'a');
161
+The ``resettable_class_set_parent_phases()`` class function may be used to
174
+ uint32_t disconnected_pins = 0;
162
+backup parent class methods.
175
+ QDict *r;
163
+
176
+
164
+Here follows an example to implement reset for a Device which sets an IO while
177
+ r = qtest_qmp(global_qtest, "{ 'execute': 'qom-get', 'arguments':"
165
+in reset.
178
+ " { 'path': %s, 'property': 'disconnected-pins'} }", path);
166
+
179
+ g_assert_false(qdict_haskey(r, "error"));
167
+::
180
+ disconnected_pins = qdict_get_int(r, "return");
168
+
181
+ qobject_unref(r);
169
+ static void mydev_reset_enter(Object *obj, ResetType type)
182
+ return disconnected_pins;
170
+ {
183
+}
171
+ MyDevClass *myclass = MYDEV_GET_CLASS(obj);
184
+
172
+ MyDevState *mydev = MYDEV(obj);
185
+static uint32_t reset(uint32_t gpio, unsigned int offset)
173
+ /* call parent class enter phase */
186
+{
174
+ if (myclass->parent_phases.enter) {
187
+ switch (offset) {
175
+ myclass->parent_phases.enter(obj, type);
188
+ case MODER:
176
+ }
189
+ return moder_reset[get_gpio_id(gpio)];
177
+ /* initialize local state only */
190
+ case PUPDR:
178
+ mydev->var = 0;
191
+ return pupdr_reset[get_gpio_id(gpio)];
192
+ case IDR:
193
+ return idr_reset[get_gpio_id(gpio)];
179
+ }
194
+ }
180
+
195
+ return 0x0;
181
+ static void mydev_reset_hold(Object *obj)
196
+}
182
+ {
197
+
183
+ MyDevClass *myclass = MYDEV_GET_CLASS(obj);
198
+static void system_reset(void)
184
+ MyDevState *mydev = MYDEV(obj);
199
+{
185
+ /* call parent class hold phase */
200
+ QDict *r;
186
+ if (myclass->parent_phases.hold) {
201
+ r = qtest_qmp(global_qtest, "{'execute': 'system_reset'}");
187
+ myclass->parent_phases.hold(obj);
202
+ g_assert_false(qdict_haskey(r, "error"));
188
+ }
203
+ qobject_unref(r);
189
+ /* set an IO */
204
+}
190
+ qemu_set_irq(mydev->irq, 1);
205
+
191
+ }
206
+static void test_idr_reset_value(void)
192
+
207
+{
193
+ static void mydev_reset_exit(Object *obj)
208
+ /*
194
+ {
209
+ * Checks that the values in MODER, OTYPER, PUPDR and ODR
195
+ MyDevClass *myclass = MYDEV_GET_CLASS(obj);
210
+ * after reset are correct, and that the value in IDR is
196
+ MyDevState *mydev = MYDEV(obj);
211
+ * coherent.
197
+ /* call parent class exit phase */
212
+ * Since AF and analog modes aren't implemented, IDR reset
198
+ if (myclass->parent_phases.exit) {
213
+ * values aren't the same as with a real board.
199
+ myclass->parent_phases.exit(obj);
214
+ *
200
+ }
215
+ * Register IDR contains the actual values of all GPIO pins.
201
+ /* clear an IO */
216
+ * Its value depends on the pins' configuration
202
+ qemu_set_irq(mydev->irq, 0);
217
+ * (intput/output/analog : register MODER, push-pull/open-drain :
203
+ }
218
+ * register OTYPER, pull-up/pull-down/none : register PUPDR)
204
+
219
+ * and on the values stored in register ODR
205
+ typedef struct MyDevClass {
220
+ * (in case the pin is in output mode).
206
+ MyParentClass parent_class;
221
+ */
207
+ /* to store eventual parent reset methods */
222
+
208
+ ResettablePhases parent_phases;
223
+ gpio_writel(GPIO_A, MODER, 0xDEADBEEF);
209
+ } MyDevClass;
224
+ gpio_writel(GPIO_A, ODR, 0xDEADBEEF);
210
+
225
+ gpio_writel(GPIO_A, OTYPER, 0xDEADBEEF);
211
+ static void mydev_class_init(ObjectClass *class, void *data)
226
+ gpio_writel(GPIO_A, PUPDR, 0xDEADBEEF);
212
+ {
227
+
213
+ MyDevClass *myclass = MYDEV_CLASS(class);
228
+ gpio_writel(GPIO_B, MODER, 0xDEADBEEF);
214
+ ResettableClass *rc = RESETTABLE_CLASS(class);
229
+ gpio_writel(GPIO_B, ODR, 0xDEADBEEF);
215
+ resettable_class_set_parent_reset_phases(rc,
230
+ gpio_writel(GPIO_B, OTYPER, 0xDEADBEEF);
216
+ mydev_reset_enter,
231
+ gpio_writel(GPIO_B, PUPDR, 0xDEADBEEF);
217
+ mydev_reset_hold,
232
+
218
+ mydev_reset_exit,
233
+ gpio_writel(GPIO_C, MODER, 0xDEADBEEF);
219
+ &myclass->parent_phases);
234
+ gpio_writel(GPIO_C, ODR, 0xDEADBEEF);
220
+ }
235
+ gpio_writel(GPIO_C, OTYPER, 0xDEADBEEF);
221
+
236
+ gpio_writel(GPIO_C, PUPDR, 0xDEADBEEF);
222
+In the above example, we override all three phases. It is possible to override
237
+
223
+only some of them by passing NULL instead of a function pointer to
238
+ gpio_writel(GPIO_H, MODER, 0xDEADBEEF);
224
+``resettable_class_set_parent_reset_phases()``. For example, the following will
239
+ gpio_writel(GPIO_H, ODR, 0xDEADBEEF);
225
+only override the *enter* phase and leave *hold* and *exit* untouched::
240
+ gpio_writel(GPIO_H, OTYPER, 0xDEADBEEF);
226
+
241
+ gpio_writel(GPIO_H, PUPDR, 0xDEADBEEF);
227
+ resettable_class_set_parent_reset_phases(rc, mydev_reset_enter,
242
+
228
+ NULL, NULL,
243
+ system_reset();
229
+ &myclass->parent_phases);
244
+
230
+
245
+ uint32_t moder = gpio_readl(GPIO_A, MODER);
231
+This is equivalent to providing a trivial implementation of the hold and exit
246
+ uint32_t odr = gpio_readl(GPIO_A, ODR);
232
+phases which does nothing but call the parent class's implementation of the
247
+ uint32_t otyper = gpio_readl(GPIO_A, OTYPER);
233
+phase.
248
+ uint32_t pupdr = gpio_readl(GPIO_A, PUPDR);
234
+
249
+ uint32_t idr = gpio_readl(GPIO_A, IDR);
235
+Polling the reset state
250
+ /* 15: AF, 14: AF, 13: AF, 12: Analog ... */
236
+.......................
251
+ /* here AF is the same as Analog and Input mode */
237
+
252
+ g_assert_cmphex(moder, ==, reset(GPIO_A, MODER));
238
+Resettable interface provides the ``resettable_is_in_reset()`` function.
253
+ g_assert_cmphex(odr, ==, reset(GPIO_A, ODR));
239
+This function returns true if the object parameter is currently under reset.
254
+ g_assert_cmphex(otyper, ==, reset(GPIO_A, OTYPER));
240
+
255
+ /* 15: pull-up, 14: pull-down, 13: pull-up, 12: neither ... */
241
+An object is under reset from the beginning of the *init* phase to the end of
256
+ g_assert_cmphex(pupdr, ==, reset(GPIO_A, PUPDR));
242
+the *exit* phase. During all three phases, the function will return that the
257
+ /* 15 : 1, 14: 0, 13: 1, 12 : reset value ... */
243
+object is in reset.
258
+ g_assert_cmphex(idr, ==, reset(GPIO_A, IDR));
244
+
259
+
245
+This function may be used if the object behavior has to be adapted
260
+ moder = gpio_readl(GPIO_B, MODER);
246
+while in reset state. For example if a device has an irq input,
261
+ odr = gpio_readl(GPIO_B, ODR);
247
+it will probably need to ignore it while in reset; then it can for
262
+ otyper = gpio_readl(GPIO_B, OTYPER);
248
+example check the reset state at the beginning of the irq callback.
263
+ pupdr = gpio_readl(GPIO_B, PUPDR);
249
+
264
+ idr = gpio_readl(GPIO_B, IDR);
250
+Note that until migration of the reset state is supported, an object
265
+ /* ... 5: Analog, 4: AF, 3: AF, 2: Analog ... */
251
+should not be left in reset. So apart from being currently executing
266
+ /* here AF is the same as Analog and Input mode */
252
+one of the reset phases, the only cases when this function will return
267
+ g_assert_cmphex(moder, ==, reset(GPIO_B, MODER));
253
+true is if an external interaction (like changing an io) is made during
268
+ g_assert_cmphex(odr, ==, reset(GPIO_B, ODR));
254
+*hold* or *exit* phase of another object in the same reset group.
269
+ g_assert_cmphex(otyper, ==, reset(GPIO_B, OTYPER));
255
+
270
+ /* ... 5: neither, 4: pull-up, 3: neither ... */
256
+Helpers ``device_is_in_reset()`` and ``bus_is_in_reset()`` are also provided
271
+ g_assert_cmphex(pupdr, ==, reset(GPIO_B, PUPDR));
257
+for devices and buses and should be preferred.
272
+ /* ... 5 : reset value, 4 : 1, 3 : reset value ... */
258
+
273
+ g_assert_cmphex(idr, ==, reset(GPIO_B, IDR));
259
+
274
+
260
+Base class handling of reset
275
+ moder = gpio_readl(GPIO_C, MODER);
261
+----------------------------
276
+ odr = gpio_readl(GPIO_C, ODR);
262
+
277
+ otyper = gpio_readl(GPIO_C, OTYPER);
263
+This section documents parts of the reset mechanism that you only need to know
278
+ pupdr = gpio_readl(GPIO_C, PUPDR);
264
+about if you are extending it to work with a new base class other than
279
+ idr = gpio_readl(GPIO_C, IDR);
265
+DeviceClass or BusClass, or maintaining the existing code in those classes. Most
280
+ /* Analog, same as Input mode*/
266
+people can ignore it.
281
+ g_assert_cmphex(moder, ==, reset(GPIO_C, MODER));
267
+
282
+ g_assert_cmphex(odr, ==, reset(GPIO_C, ODR));
268
+Methods to implement
283
+ g_assert_cmphex(otyper, ==, reset(GPIO_C, OTYPER));
269
+....................
284
+ /* no pull-up or pull-down */
270
+
285
+ g_assert_cmphex(pupdr, ==, reset(GPIO_C, PUPDR));
271
+There are two other methods that need to exist in a class implementing the
286
+ /* reset value */
272
+interface: ``get_state()`` and ``child_foreach()``.
287
+ g_assert_cmphex(idr, ==, reset(GPIO_C, IDR));
273
+
288
+
274
+``get_state()`` is simple. *resettable* is an interface and, as a consequence,
289
+ moder = gpio_readl(GPIO_H, MODER);
275
+does not have any class state structure. But in order to factorize the code, we
290
+ odr = gpio_readl(GPIO_H, ODR);
276
+need one. This method must return a pointer to ``ResettableState`` structure.
291
+ otyper = gpio_readl(GPIO_H, OTYPER);
277
+The structure must be allocated by the base class; preferably it should be
292
+ pupdr = gpio_readl(GPIO_H, PUPDR);
278
+located inside the object instance structure.
293
+ idr = gpio_readl(GPIO_H, IDR);
279
+
294
+ /* Analog, same as Input mode */
280
+``child_foreach()`` is more complex. It should execute the given callback on
295
+ g_assert_cmphex(moder, ==, reset(GPIO_H, MODER));
281
+every reset child of the given resettable object. All children must be
296
+ g_assert_cmphex(odr, ==, reset(GPIO_H, ODR));
282
+resettable too. Additional parameters (a reset type and an opaque pointer) must
297
+ g_assert_cmphex(otyper, ==, reset(GPIO_H, OTYPER));
283
+be passed to the callback too.
298
+ /* no pull-up or pull-down */
284
+
299
+ g_assert_cmphex(pupdr, ==, reset(GPIO_H, PUPDR));
285
+In ``DeviceClass`` and ``BusClass`` the ``ResettableState`` is located
300
+ /* reset value */
286
+``DeviceState`` and ``BusState`` structure. ``child_foreach()`` is implemented
301
+ g_assert_cmphex(idr, ==, reset(GPIO_H, IDR));
287
+to follow the bus hierarchy; for a bus, it calls the function on every child
302
+}
288
+device; for a device, it calls the function on every bus child. When we reset
303
+
289
+the main system bus, we reset the whole machine bus tree.
304
+static void test_gpio_output_mode(const void *data)
290
+
305
+{
291
+Changing a resettable parent
306
+ /*
292
+............................
307
+ * Checks that setting a bit in ODR sets the corresponding
293
+
308
+ * GPIO line high : it should set the right bit in IDR
294
+One thing which should be taken care of by the base class is handling reset
309
+ * and send an irq to syscfg.
295
+hierarchy changes.
310
+ * Additionally, it checks that values written to ODR
296
+
311
+ * when not in output mode are stored and not discarded.
297
+The reset hierarchy is supposed to be static and built during machine creation.
312
+ */
298
+But there are actually some exceptions. To cope with this, the resettable API
313
+ unsigned int pin = ((uint64_t)data) & 0xF;
299
+provides ``resettable_change_parent()``. This function allows to set, update or
314
+ uint32_t gpio = ((uint64_t)data) >> 32;
300
+remove the parent of a resettable object after machine creation is done. As
315
+ unsigned int gpio_id = get_gpio_id(gpio);
301
+parameters, it takes the object being moved, the old parent if any and the new
316
+
302
+parent if any.
317
+ qtest_irq_intercept_in(global_qtest, "/machine/soc/syscfg");
303
+
318
+
304
+This function can be used at any time when not in a reset operation. During
319
+ /* Set a bit in ODR and check nothing happens */
305
+a reset operation it must be used only in *hold* phase. Using it in *enter* or
320
+ gpio_set_bit(gpio, ODR, pin, 1);
306
+*exit* phase is an error.
321
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR));
307
+Also it should not be used during machine creation, although it is harmless to
322
+ g_assert_false(get_irq(gpio_id * NUM_GPIO_PINS + pin));
308
+do so: the function is a no-op as long as old and new parent are NULL or not
323
+
309
+in reset.
324
+ /* Configure the relevant line as output and check the pin is high */
310
+
325
+ gpio_set_2bits(gpio, MODER, pin, MODER_OUTPUT);
311
+There is currently 2 cases where this function is used:
326
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) | (1 << pin));
312
+
327
+ g_assert_true(get_irq(gpio_id * NUM_GPIO_PINS + pin));
313
+1. *device hotplug*; it means a new device is introduced on a live bus.
328
+
314
+
329
+ /* Reset the bit in ODR and check the pin is low */
315
+2. *hot bus change*; it means an existing live device is added, moved or
330
+ gpio_set_bit(gpio, ODR, pin, 0);
316
+ removed in the bus hierarchy. At the moment, it occurs only in the raspi
331
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) & ~(1 << pin));
317
+ machines for changing the sdbus used by sd card.
332
+ g_assert_false(get_irq(gpio_id * NUM_GPIO_PINS + pin));
333
+
334
+ /* Clean the test */
335
+ gpio_writel(gpio, ODR, reset(gpio, ODR));
336
+ gpio_writel(gpio, MODER, reset(gpio, MODER));
337
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR));
338
+ g_assert_false(get_irq(gpio_id * NUM_GPIO_PINS + pin));
339
+}
340
+
341
+static void test_gpio_input_mode(const void *data)
342
+{
343
+ /*
344
+ * Test that setting a line high/low externally sets the
345
+ * corresponding GPIO line high/low : it should set the
346
+ * right bit in IDR and send an irq to syscfg.
347
+ */
348
+ unsigned int pin = ((uint64_t)data) & 0xF;
349
+ uint32_t gpio = ((uint64_t)data) >> 32;
350
+ unsigned int gpio_id = get_gpio_id(gpio);
351
+
352
+ qtest_irq_intercept_in(global_qtest, "/machine/soc/syscfg");
353
+
354
+ /* Configure a line as input, raise it, and check that the pin is high */
355
+ gpio_set_2bits(gpio, MODER, pin, MODER_INPUT);
356
+ gpio_set_irq(gpio, pin, 1);
357
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) | (1 << pin));
358
+ g_assert_true(get_irq(gpio_id * NUM_GPIO_PINS + pin));
359
+
360
+ /* Lower the line and check that the pin is low */
361
+ gpio_set_irq(gpio, pin, 0);
362
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) & ~(1 << pin));
363
+ g_assert_false(get_irq(gpio_id * NUM_GPIO_PINS + pin));
364
+
365
+ /* Clean the test */
366
+ gpio_writel(gpio, MODER, reset(gpio, MODER));
367
+ disconnect_all_pins(gpio);
368
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR));
369
+}
370
+
371
+static void test_pull_up_pull_down(const void *data)
372
+{
373
+ /*
374
+ * Test that a floating pin with pull-up sets the pin
375
+ * high and vice-versa.
376
+ */
377
+ unsigned int pin = ((uint64_t)data) & 0xF;
378
+ uint32_t gpio = ((uint64_t)data) >> 32;
379
+ unsigned int gpio_id = get_gpio_id(gpio);
380
+
381
+ qtest_irq_intercept_in(global_qtest, "/machine/soc/syscfg");
382
+
383
+ /* Configure a line as input with pull-up, check the line is set high */
384
+ gpio_set_2bits(gpio, MODER, pin, MODER_INPUT);
385
+ gpio_set_2bits(gpio, PUPDR, pin, PUPDR_PULLUP);
386
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) | (1 << pin));
387
+ g_assert_true(get_irq(gpio_id * NUM_GPIO_PINS + pin));
388
+
389
+ /* Configure the line with pull-down, check the line is low */
390
+ gpio_set_2bits(gpio, PUPDR, pin, PUPDR_PULLDOWN);
391
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) & ~(1 << pin));
392
+ g_assert_false(get_irq(gpio_id * NUM_GPIO_PINS + pin));
393
+
394
+ /* Clean the test */
395
+ gpio_writel(gpio, MODER, reset(gpio, MODER));
396
+ gpio_writel(gpio, PUPDR, reset(gpio, PUPDR));
397
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR));
398
+}
399
+
400
+static void test_push_pull(const void *data)
401
+{
402
+ /*
403
+ * Test that configuring a line in push-pull output mode
404
+ * disconnects the pin, that the pin can't be set or reset
405
+ * externally afterwards.
406
+ */
407
+ unsigned int pin = ((uint64_t)data) & 0xF;
408
+ uint32_t gpio = ((uint64_t)data) >> 32;
409
+ uint32_t gpio2 = GPIO_BASE_ADDR + (GPIO_H - gpio);
410
+
411
+ qtest_irq_intercept_in(global_qtest, "/machine/soc/syscfg");
412
+
413
+ /* Setting a line high externally, configuring it in push-pull output */
414
+ /* And checking the pin was disconnected */
415
+ gpio_set_irq(gpio, pin, 1);
416
+ gpio_set_2bits(gpio, MODER, pin, MODER_OUTPUT);
417
+ g_assert_cmphex(get_disconnected_pins(gpio), ==, 0xFFFF);
418
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) & ~(1 << pin));
419
+
420
+ /* Setting a line low externally, configuring it in push-pull output */
421
+ /* And checking the pin was disconnected */
422
+ gpio_set_irq(gpio2, pin, 0);
423
+ gpio_set_bit(gpio2, ODR, pin, 1);
424
+ gpio_set_2bits(gpio2, MODER, pin, MODER_OUTPUT);
425
+ g_assert_cmphex(get_disconnected_pins(gpio2), ==, 0xFFFF);
426
+ g_assert_cmphex(gpio_readl(gpio2, IDR), ==, reset(gpio2, IDR) | (1 << pin));
427
+
428
+ /* Trying to set a push-pull output pin, checking it doesn't work */
429
+ gpio_set_irq(gpio, pin, 1);
430
+ g_assert_cmphex(get_disconnected_pins(gpio), ==, 0xFFFF);
431
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) & ~(1 << pin));
432
+
433
+ /* Trying to reset a push-pull output pin, checking it doesn't work */
434
+ gpio_set_irq(gpio2, pin, 0);
435
+ g_assert_cmphex(get_disconnected_pins(gpio2), ==, 0xFFFF);
436
+ g_assert_cmphex(gpio_readl(gpio2, IDR), ==, reset(gpio2, IDR) | (1 << pin));
437
+
438
+ /* Clean the test */
439
+ gpio_writel(gpio, MODER, reset(gpio, MODER));
440
+ gpio_writel(gpio2, ODR, reset(gpio2, ODR));
441
+ gpio_writel(gpio2, MODER, reset(gpio2, MODER));
442
+}
443
+
444
+static void test_open_drain(const void *data)
445
+{
446
+ /*
447
+ * Test that configuring a line in open-drain output mode
448
+ * disconnects a pin set high externally and that the pin
449
+ * can't be set high externally while configured in open-drain.
450
+ *
451
+ * However a pin set low externally shouldn't be disconnected,
452
+ * and it can be set low externally when in open-drain mode.
453
+ */
454
+ unsigned int pin = ((uint64_t)data) & 0xF;
455
+ uint32_t gpio = ((uint64_t)data) >> 32;
456
+ uint32_t gpio2 = GPIO_BASE_ADDR + (GPIO_H - gpio);
457
+
458
+ qtest_irq_intercept_in(global_qtest, "/machine/soc/syscfg");
459
+
460
+ /* Setting a line high externally, configuring it in open-drain output */
461
+ /* And checking the pin was disconnected */
462
+ gpio_set_irq(gpio, pin, 1);
463
+ gpio_set_bit(gpio, OTYPER, pin, OTYPER_OPEN_DRAIN);
464
+ gpio_set_2bits(gpio, MODER, pin, MODER_OUTPUT);
465
+ g_assert_cmphex(get_disconnected_pins(gpio), ==, 0xFFFF);
466
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) & ~(1 << pin));
467
+
468
+ /* Setting a line low externally, configuring it in open-drain output */
469
+ /* And checking the pin wasn't disconnected */
470
+ gpio_set_irq(gpio2, pin, 0);
471
+ gpio_set_bit(gpio2, ODR, pin, 1);
472
+ gpio_set_bit(gpio2, OTYPER, pin, OTYPER_OPEN_DRAIN);
473
+ gpio_set_2bits(gpio2, MODER, pin, MODER_OUTPUT);
474
+ g_assert_cmphex(get_disconnected_pins(gpio2), ==, 0xFFFF & ~(1 << pin));
475
+ g_assert_cmphex(gpio_readl(gpio2, IDR), ==,
476
+ reset(gpio2, IDR) & ~(1 << pin));
477
+
478
+ /* Trying to set a open-drain output pin, checking it doesn't work */
479
+ gpio_set_irq(gpio, pin, 1);
480
+ g_assert_cmphex(get_disconnected_pins(gpio), ==, 0xFFFF);
481
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) & ~(1 << pin));
482
+
483
+ /* Trying to reset a open-drain output pin, checking it works */
484
+ gpio_set_bit(gpio, ODR, pin, 1);
485
+ gpio_set_irq(gpio, pin, 0);
486
+ g_assert_cmphex(get_disconnected_pins(gpio2), ==, 0xFFFF & ~(1 << pin));
487
+ g_assert_cmphex(gpio_readl(gpio2, IDR), ==,
488
+ reset(gpio2, IDR) & ~(1 << pin));
489
+
490
+ /* Clean the test */
491
+ disconnect_all_pins(gpio2);
492
+ gpio_writel(gpio2, OTYPER, reset(gpio2, OTYPER));
493
+ gpio_writel(gpio2, ODR, reset(gpio2, ODR));
494
+ gpio_writel(gpio2, MODER, reset(gpio2, MODER));
495
+ g_assert_cmphex(gpio_readl(gpio2, IDR), ==, reset(gpio2, IDR));
496
+ disconnect_all_pins(gpio);
497
+ gpio_writel(gpio, OTYPER, reset(gpio, OTYPER));
498
+ gpio_writel(gpio, ODR, reset(gpio, ODR));
499
+ gpio_writel(gpio, MODER, reset(gpio, MODER));
500
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR));
501
+}
502
+
503
+static void test_bsrr_brr(const void *data)
504
+{
505
+ /*
506
+ * Test that writing a '1' in BSS and BSRR
507
+ * has the desired effect on ODR.
508
+ * In BSRR, BSx has priority over BRx.
509
+ */
510
+ unsigned int pin = ((uint64_t)data) & 0xF;
511
+ uint32_t gpio = ((uint64_t)data) >> 32;
512
+
513
+ gpio_writel(gpio, BSRR, (1 << pin));
514
+ g_assert_cmphex(gpio_readl(gpio, ODR), ==, reset(gpio, ODR) | (1 << pin));
515
+
516
+ gpio_writel(gpio, BSRR, (1 << (pin + NUM_GPIO_PINS)));
517
+ g_assert_cmphex(gpio_readl(gpio, ODR), ==, reset(gpio, ODR));
518
+
519
+ gpio_writel(gpio, BSRR, (1 << pin));
520
+ g_assert_cmphex(gpio_readl(gpio, ODR), ==, reset(gpio, ODR) | (1 << pin));
521
+
522
+ gpio_writel(gpio, BRR, (1 << pin));
523
+ g_assert_cmphex(gpio_readl(gpio, ODR), ==, reset(gpio, ODR));
524
+
525
+ /* BSx should have priority over BRx */
526
+ gpio_writel(gpio, BSRR, (1 << pin) | (1 << (pin + NUM_GPIO_PINS)));
527
+ g_assert_cmphex(gpio_readl(gpio, ODR), ==, reset(gpio, ODR) | (1 << pin));
528
+
529
+ gpio_writel(gpio, BRR, (1 << pin));
530
+ g_assert_cmphex(gpio_readl(gpio, ODR), ==, reset(gpio, ODR));
531
+
532
+ gpio_writel(gpio, ODR, reset(gpio, ODR));
533
+}
534
+
535
+int main(int argc, char **argv)
536
+{
537
+ int ret;
538
+
539
+ g_test_init(&argc, &argv, NULL);
540
+ g_test_set_nonfatal_assertions();
541
+ qtest_add_func("stm32l4x5/gpio/test_idr_reset_value",
542
+ test_idr_reset_value);
543
+ /*
544
+ * The inputs for the tests (gpio and pin) can be changed,
545
+ * but the tests don't work for pins that are high at reset
546
+ * (GPIOA15, GPIO13 and GPIOB5).
547
+ * Specifically, rising the pin then checking `get_irq()`
548
+ * is problematic since the pin was already high.
549
+ */
550
+ qtest_add_data_func("stm32l4x5/gpio/test_gpioc5_output_mode",
551
+ (void *)((uint64_t)GPIO_C << 32 | 5),
552
+ test_gpio_output_mode);
553
+ qtest_add_data_func("stm32l4x5/gpio/test_gpioh3_output_mode",
554
+ (void *)((uint64_t)GPIO_H << 32 | 3),
555
+ test_gpio_output_mode);
556
+ qtest_add_data_func("stm32l4x5/gpio/test_gpio_input_mode1",
557
+ (void *)((uint64_t)GPIO_D << 32 | 6),
558
+ test_gpio_input_mode);
559
+ qtest_add_data_func("stm32l4x5/gpio/test_gpio_input_mode2",
560
+ (void *)((uint64_t)GPIO_C << 32 | 10),
561
+ test_gpio_input_mode);
562
+ qtest_add_data_func("stm32l4x5/gpio/test_gpio_pull_up_pull_down1",
563
+ (void *)((uint64_t)GPIO_B << 32 | 5),
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");
588
+ ret = g_test_run();
589
+ qtest_end();
590
+
591
+ return ret;
592
+}
593
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
594
index XXXXXXX..XXXXXXX 100644
595
--- a/tests/qtest/meson.build
596
+++ b/tests/qtest/meson.build
597
@@ -XXX,XX +XXX,XX @@ qtests_aspeed = \
598
qtests_stm32l4x5 = \
599
['stm32l4x5_exti-test',
600
'stm32l4x5_syscfg-test',
601
- 'stm32l4x5_rcc-test']
602
+ 'stm32l4x5_rcc-test',
603
+ 'stm32l4x5_gpio-test']
604
605
qtests_arm = \
606
(config_all_devices.has_key('CONFIG_MPS2') ? ['sse-timer-test'] : []) + \
318
--
607
--
319
2.20.1
608
2.34.1
320
609
321
610
diff view generated by jsdifflib
1
From: Andrew Jeffery <andrew@aj.id.au>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Initialise another SDHCI model instance for the AST2600's eMMC
3
While the 8-bit input elements are sequential in the input vector,
4
controller and use the SDHCI's num_slots value introduced previously to
4
the 32-bit output elements are not sequential in the output matrix.
5
determine whether we should create an SD card instance for the new slot.
5
Do not attempt to compute 2 32-bit outputs at the same time.
6
6
7
Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
7
Cc: qemu-stable@nongnu.org
8
Reviewed-by: Cédric Le Goater <clg@kaod.org>
8
Fixes: 23a5e3859f5 ("target/arm: Implement SME integer outer product")
9
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
9
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2083
10
Signed-off-by: Cédric Le Goater <clg@kaod.org>
10
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20200114103433.30534-3-clg@kaod.org
11
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
12
[ clg : - removed ternary operator from sdhci_attach_drive()
12
Message-id: 20240305163931.242795-1-richard.henderson@linaro.org
13
- renamed SDHCI objects with a '-controller' prefix ]
14
Signed-off-by: Cédric Le Goater <clg@kaod.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
---
14
---
17
include/hw/arm/aspeed_soc.h | 2 ++
15
target/arm/tcg/sme_helper.c | 77 ++++++++++++++++++-------------
18
hw/arm/aspeed.c | 26 +++++++++++++++++---------
16
tests/tcg/aarch64/sme-smopa-1.c | 47 +++++++++++++++++++
19
hw/arm/aspeed_ast2600.c | 29 ++++++++++++++++++++++++++---
17
tests/tcg/aarch64/sme-smopa-2.c | 54 ++++++++++++++++++++++
20
3 files changed, 45 insertions(+), 12 deletions(-)
18
tests/tcg/aarch64/Makefile.target | 2 +-
21
19
4 files changed, 147 insertions(+), 33 deletions(-)
22
diff --git a/include/hw/arm/aspeed_soc.h b/include/hw/arm/aspeed_soc.h
20
create mode 100644 tests/tcg/aarch64/sme-smopa-1.c
21
create mode 100644 tests/tcg/aarch64/sme-smopa-2.c
22
23
diff --git a/target/arm/tcg/sme_helper.c b/target/arm/tcg/sme_helper.c
23
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
24
--- a/include/hw/arm/aspeed_soc.h
25
--- a/target/arm/tcg/sme_helper.c
25
+++ b/include/hw/arm/aspeed_soc.h
26
+++ b/target/arm/tcg/sme_helper.c
26
@@ -XXX,XX +XXX,XX @@ typedef struct AspeedSoCState {
27
@@ -XXX,XX +XXX,XX @@ void HELPER(sme_bfmopa)(void *vza, void *vzn, void *vzm, void *vpn,
27
AspeedGPIOState gpio;
28
AspeedGPIOState gpio_1_8v;
29
AspeedSDHCIState sdhci;
30
+ AspeedSDHCIState emmc;
31
} AspeedSoCState;
32
33
#define TYPE_ASPEED_SOC "aspeed-soc"
34
@@ -XXX,XX +XXX,XX @@ enum {
35
ASPEED_MII4,
36
ASPEED_SDRAM,
37
ASPEED_XDMA,
38
+ ASPEED_EMMC,
39
};
40
41
#endif /* ASPEED_SOC_H */
42
diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
43
index XXXXXXX..XXXXXXX 100644
44
--- a/hw/arm/aspeed.c
45
+++ b/hw/arm/aspeed.c
46
@@ -XXX,XX +XXX,XX @@ static void aspeed_board_init_flashes(AspeedSMCState *s, const char *flashtype,
47
}
28
}
48
}
29
}
49
30
50
+static void sdhci_attach_drive(SDHCIState *sdhci, DriveInfo *dinfo)
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)
51
+{
36
+{
52
+ DeviceState *card;
37
+ intptr_t row, col, oprsz = simd_oprsz(desc) / 4;
53
+
38
+ bool neg = simd_data(desc);
54
+ card = qdev_create(qdev_get_child_bus(DEVICE(sdhci), "sd-bus"),
39
55
+ TYPE_SD_CARD);
40
-static inline void do_imopa(uint64_t *za, uint64_t *zn, uint64_t *zm,
56
+ if (dinfo) {
41
- uint8_t *pn, uint8_t *pm,
57
+ qdev_prop_set_drive(card, "drive", blk_by_legacy_dinfo(dinfo),
42
- uint32_t desc, IMOPFn *fn)
58
+ &error_fatal);
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);
59
+ }
53
+ }
60
+ object_property_set_bool(OBJECT(card), true, "realized", &error_fatal);
54
+ }
61
+}
55
+}
62
+
56
+
63
static void aspeed_machine_init(MachineState *machine)
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)
64
{
61
{
65
AspeedBoardState *bmc;
62
intptr_t row, col, oprsz = simd_oprsz(desc) / 8;
66
@@ -XXX,XX +XXX,XX @@ static void aspeed_machine_init(MachineState *machine)
63
bool neg = simd_data(desc);
67
}
64
@@ -XXX,XX +XXX,XX @@ static inline void do_imopa(uint64_t *za, uint64_t *zn, uint64_t *zm,
68
65
}
69
for (i = 0; i < bmc->soc.sdhci.num_slots; i++) {
66
70
- SDHCIState *sdhci = &bmc->soc.sdhci.slots[i];
67
#define DEF_IMOP_32(NAME, NTYPE, MTYPE) \
71
- DriveInfo *dinfo = drive_get_next(IF_SD);
68
-static uint64_t NAME(uint64_t n, uint64_t m, uint64_t a, uint8_t p, bool neg) \
72
- BlockBackend *blk;
69
+static uint32_t NAME(uint32_t n, uint32_t m, uint32_t a, uint8_t p, bool neg) \
73
- DeviceState *card;
70
{ \
74
+ sdhci_attach_drive(&bmc->soc.sdhci.slots[i], drive_get_next(IF_SD));
71
- uint32_t sum0 = 0, sum1 = 0; \
75
+ }
72
+ uint32_t sum = 0; \
76
73
/* Apply P to N as a mask, making the inactive elements 0. */ \
77
- blk = dinfo ? blk_by_legacy_dinfo(dinfo) : NULL;
74
n &= expand_pred_b(p); \
78
- card = qdev_create(qdev_get_child_bus(DEVICE(sdhci), "sd-bus"),
75
- sum0 += (NTYPE)(n >> 0) * (MTYPE)(m >> 0); \
79
- TYPE_SD_CARD);
76
- sum0 += (NTYPE)(n >> 8) * (MTYPE)(m >> 8); \
80
- qdev_prop_set_drive(card, "drive", blk, &error_fatal);
77
- sum0 += (NTYPE)(n >> 16) * (MTYPE)(m >> 16); \
81
- object_property_set_bool(OBJECT(card), true, "realized", &error_fatal);
78
- sum0 += (NTYPE)(n >> 24) * (MTYPE)(m >> 24); \
82
+ if (bmc->soc.emmc.num_slots) {
79
- sum1 += (NTYPE)(n >> 32) * (MTYPE)(m >> 32); \
83
+ sdhci_attach_drive(&bmc->soc.emmc.slots[0], drive_get_next(IF_SD));
80
- sum1 += (NTYPE)(n >> 40) * (MTYPE)(m >> 40); \
84
}
81
- sum1 += (NTYPE)(n >> 48) * (MTYPE)(m >> 48); \
85
82
- sum1 += (NTYPE)(n >> 56) * (MTYPE)(m >> 56); \
86
arm_load_kernel(ARM_CPU(first_cpu), machine, &aspeed_board_binfo);
83
- if (neg) { \
87
diff --git a/hw/arm/aspeed_ast2600.c b/hw/arm/aspeed_ast2600.c
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
128
new file mode 100644
129
index XXXXXXX..XXXXXXX
130
--- /dev/null
131
+++ b/tests/tcg/aarch64/sme-smopa-1.c
132
@@ -XXX,XX +XXX,XX @@
133
+#include <stdio.h>
134
+#include <string.h>
135
+
136
+int main()
137
+{
138
+ static const int cmp[4][4] = {
139
+ { 110, 134, 158, 182 },
140
+ { 390, 478, 566, 654 },
141
+ { 670, 822, 974, 1126 },
142
+ { 950, 1166, 1382, 1598 }
143
+ };
144
+ int dst[4][4];
145
+ int *tmp = &dst[0][0];
146
+
147
+ asm volatile(
148
+ ".arch armv8-r+sme\n\t"
149
+ "smstart\n\t"
150
+ "index z0.b, #0, #1\n\t"
151
+ "movprfx z1, z0\n\t"
152
+ "add z1.b, z1.b, #16\n\t"
153
+ "ptrue p0.b\n\t"
154
+ "smopa za0.s, p0/m, p0/m, z0.b, z1.b\n\t"
155
+ "ptrue p0.s, vl4\n\t"
156
+ "mov w12, #0\n\t"
157
+ "st1w { za0h.s[w12, #0] }, p0, [%0]\n\t"
158
+ "add %0, %0, #16\n\t"
159
+ "st1w { za0h.s[w12, #1] }, p0, [%0]\n\t"
160
+ "add %0, %0, #16\n\t"
161
+ "st1w { za0h.s[w12, #2] }, p0, [%0]\n\t"
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;
179
+}
180
diff --git a/tests/tcg/aarch64/sme-smopa-2.c b/tests/tcg/aarch64/sme-smopa-2.c
181
new file mode 100644
182
index XXXXXXX..XXXXXXX
183
--- /dev/null
184
+++ b/tests/tcg/aarch64/sme-smopa-2.c
185
@@ -XXX,XX +XXX,XX @@
186
+#include <stdio.h>
187
+#include <string.h>
188
+
189
+int main()
190
+{
191
+ static const long cmp[4][4] = {
192
+ { 110, 134, 158, 182 },
193
+ { 390, 478, 566, 654 },
194
+ { 670, 822, 974, 1126 },
195
+ { 950, 1166, 1382, 1598 }
196
+ };
197
+ long dst[4][4];
198
+ long *tmp = &dst[0][0];
199
+ long svl;
200
+
201
+ /* Validate that we have a wide enough vector for 4 elements. */
202
+ asm(".arch armv8-r+sme-i64\n\trdsvl %0, #1" : "=r"(svl));
203
+ if (svl < 32) {
204
+ return 0;
205
+ }
206
+
207
+ asm volatile(
208
+ "smstart\n\t"
209
+ "index z0.h, #0, #1\n\t"
210
+ "movprfx z1, z0\n\t"
211
+ "add z1.h, z1.h, #16\n\t"
212
+ "ptrue p0.b\n\t"
213
+ "smopa za0.d, p0/m, p0/m, z0.h, z1.h\n\t"
214
+ "ptrue p0.d, vl4\n\t"
215
+ "mov w12, #0\n\t"
216
+ "st1d { za0h.d[w12, #0] }, p0, [%0]\n\t"
217
+ "add %0, %0, #32\n\t"
218
+ "st1d { za0h.d[w12, #1] }, p0, [%0]\n\t"
219
+ "mov w12, #2\n\t"
220
+ "add %0, %0, #32\n\t"
221
+ "st1d { za0h.d[w12, #0] }, p0, [%0]\n\t"
222
+ "add %0, %0, #32\n\t"
223
+ "st1d { za0h.d[w12, #1] }, p0, [%0]\n\t"
224
+ "smstop"
225
+ : "+r"(tmp) : : "memory");
226
+
227
+ if (memcmp(cmp, dst, sizeof(dst)) == 0) {
228
+ return 0;
229
+ }
230
+
231
+ /* See above for correct results. */
232
+ for (int i = 0; i < 4; ++i) {
233
+ for (int j = 0; j < 4; ++j) {
234
+ printf("%6ld", dst[i][j]);
235
+ }
236
+ printf("\n");
237
+ }
238
+ return 1;
239
+}
240
diff --git a/tests/tcg/aarch64/Makefile.target b/tests/tcg/aarch64/Makefile.target
88
index XXXXXXX..XXXXXXX 100644
241
index XXXXXXX..XXXXXXX 100644
89
--- a/hw/arm/aspeed_ast2600.c
242
--- a/tests/tcg/aarch64/Makefile.target
90
+++ b/hw/arm/aspeed_ast2600.c
243
+++ b/tests/tcg/aarch64/Makefile.target
91
@@ -XXX,XX +XXX,XX @@ static const hwaddr aspeed_soc_ast2600_memmap[] = {
244
@@ -XXX,XX +XXX,XX @@ endif
92
[ASPEED_ADC] = 0x1E6E9000,
245
93
[ASPEED_VIDEO] = 0x1E700000,
246
# SME Tests
94
[ASPEED_SDHCI] = 0x1E740000,
247
ifneq ($(CROSS_AS_HAS_ARMV9_SME),)
95
+ [ASPEED_EMMC] = 0x1E750000,
248
-AARCH64_TESTS += sme-outprod1
96
[ASPEED_GPIO] = 0x1E780000,
249
+AARCH64_TESTS += sme-outprod1 sme-smopa-1 sme-smopa-2
97
[ASPEED_GPIO_1_8V] = 0x1E780800,
250
endif
98
[ASPEED_RTC] = 0x1E781000,
251
99
@@ -XXX,XX +XXX,XX @@ static const hwaddr aspeed_soc_ast2600_memmap[] = {
252
# System Registers Tests
100
101
#define ASPEED_SOC_AST2600_MAX_IRQ 128
102
103
+/* Shared Peripheral Interrupt values below are offset by -32 from datasheet */
104
static const int aspeed_soc_ast2600_irqmap[] = {
105
[ASPEED_UART1] = 47,
106
[ASPEED_UART2] = 48,
107
@@ -XXX,XX +XXX,XX @@ static const int aspeed_soc_ast2600_irqmap[] = {
108
[ASPEED_ADC] = 78,
109
[ASPEED_XDMA] = 6,
110
[ASPEED_SDHCI] = 43,
111
+ [ASPEED_EMMC] = 15,
112
[ASPEED_GPIO] = 40,
113
[ASPEED_GPIO_1_8V] = 11,
114
[ASPEED_RTC] = 13,
115
@@ -XXX,XX +XXX,XX @@ static void aspeed_soc_ast2600_init(Object *obj)
116
sysbus_init_child_obj(obj, "gpio_1_8v", OBJECT(&s->gpio_1_8v),
117
sizeof(s->gpio_1_8v), typename);
118
119
- sysbus_init_child_obj(obj, "sdc", OBJECT(&s->sdhci), sizeof(s->sdhci),
120
- TYPE_ASPEED_SDHCI);
121
+ sysbus_init_child_obj(obj, "sd-controller", OBJECT(&s->sdhci),
122
+ sizeof(s->sdhci), TYPE_ASPEED_SDHCI);
123
124
object_property_set_int(OBJECT(&s->sdhci), 2, "num-slots", &error_abort);
125
126
/* Init sd card slot class here so that they're under the correct parent */
127
for (i = 0; i < ASPEED_SDHCI_NUM_SLOTS; ++i) {
128
- sysbus_init_child_obj(obj, "sdhci[*]", OBJECT(&s->sdhci.slots[i]),
129
+ sysbus_init_child_obj(obj, "sd-controller.sdhci[*]",
130
+ OBJECT(&s->sdhci.slots[i]),
131
sizeof(s->sdhci.slots[i]), TYPE_SYSBUS_SDHCI);
132
}
133
+
134
+ sysbus_init_child_obj(obj, "emmc-controller", OBJECT(&s->emmc),
135
+ sizeof(s->emmc), TYPE_ASPEED_SDHCI);
136
+
137
+ object_property_set_int(OBJECT(&s->emmc), 1, "num-slots", &error_abort);
138
+
139
+ sysbus_init_child_obj(obj, "emmc-controller.sdhci",
140
+ OBJECT(&s->emmc.slots[0]), sizeof(s->emmc.slots[0]),
141
+ TYPE_SYSBUS_SDHCI);
142
}
143
144
/*
145
@@ -XXX,XX +XXX,XX @@ static void aspeed_soc_ast2600_realize(DeviceState *dev, Error **errp)
146
sc->memmap[ASPEED_SDHCI]);
147
sysbus_connect_irq(SYS_BUS_DEVICE(&s->sdhci), 0,
148
aspeed_soc_get_irq(s, ASPEED_SDHCI));
149
+
150
+ /* eMMC */
151
+ object_property_set_bool(OBJECT(&s->emmc), true, "realized", &err);
152
+ if (err) {
153
+ error_propagate(errp, err);
154
+ return;
155
+ }
156
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->emmc), 0, sc->memmap[ASPEED_EMMC]);
157
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->emmc), 0,
158
+ aspeed_soc_get_irq(s, ASPEED_EMMC));
159
}
160
161
static void aspeed_soc_ast2600_class_init(ObjectClass *oc, void *data)
162
--
253
--
163
2.20.1
254
2.34.1
164
255
165
256
diff view generated by jsdifflib
Deleted patch
1
From: Cédric Le Goater <clg@kaod.org>
2
1
3
These buffers should be aligned on 16 bytes.
4
5
Ignore invalid RX and TX buffer addresses and log an error. All
6
incoming and outgoing traffic will be dropped because no valid RX or
7
TX descriptors will be available.
8
9
Signed-off-by: Cédric Le Goater <clg@kaod.org>
10
Message-id: 20200114103433.30534-4-clg@kaod.org
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
14
hw/net/ftgmac100.c | 13 +++++++++++++
15
1 file changed, 13 insertions(+)
16
17
diff --git a/hw/net/ftgmac100.c b/hw/net/ftgmac100.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/net/ftgmac100.c
20
+++ b/hw/net/ftgmac100.c
21
@@ -XXX,XX +XXX,XX @@ typedef struct {
22
uint32_t des3;
23
} FTGMAC100Desc;
24
25
+#define FTGMAC100_DESC_ALIGNMENT 16
26
+
27
/*
28
* Specific RTL8211E MII Registers
29
*/
30
@@ -XXX,XX +XXX,XX @@ static void ftgmac100_write(void *opaque, hwaddr addr,
31
s->itc = value;
32
break;
33
case FTGMAC100_RXR_BADR: /* Ring buffer address */
34
+ if (!QEMU_IS_ALIGNED(value, FTGMAC100_DESC_ALIGNMENT)) {
35
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad RX buffer alignment 0x%"
36
+ HWADDR_PRIx "\n", __func__, value);
37
+ return;
38
+ }
39
+
40
s->rx_ring = value;
41
s->rx_descriptor = s->rx_ring;
42
break;
43
@@ -XXX,XX +XXX,XX @@ static void ftgmac100_write(void *opaque, hwaddr addr,
44
break;
45
46
case FTGMAC100_NPTXR_BADR: /* Transmit buffer address */
47
+ if (!QEMU_IS_ALIGNED(value, FTGMAC100_DESC_ALIGNMENT)) {
48
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad TX buffer alignment 0x%"
49
+ HWADDR_PRIx "\n", __func__, value);
50
+ return;
51
+ }
52
s->tx_ring = value;
53
s->tx_descriptor = s->tx_ring;
54
break;
55
--
56
2.20.1
57
58
diff view generated by jsdifflib
Deleted patch
1
From: Cédric Le Goater <clg@kaod.org>
2
1
3
The overhead for the OpenBMC firmware images using the a custom U-Boot
4
is around 2 seconds, which is fine, but with a U-Boot from mainline,
5
it takes an extra 50 seconds or so to reach Linux. A quick survey on
6
the number of reads performed on the flash memory region gives the
7
following figures :
8
9
OpenBMC U-Boot 922478 (~ 3.5 MBytes)
10
Mainline U-Boot 20569977 (~ 80 MBytes)
11
12
QEMU must be trashing the TCG TBs and reloading text very often. Some
13
addresses are read more than 250.000 times. Until we find a solution
14
to improve boot time, execution from MMIO is not activated by default.
15
16
Setting this option also breaks migration compatibility.
17
18
Signed-off-by: Cédric Le Goater <clg@kaod.org>
19
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
20
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
21
Message-id: 20200114103433.30534-5-clg@kaod.org
22
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
23
---
24
include/hw/arm/aspeed.h | 2 ++
25
hw/arm/aspeed.c | 44 ++++++++++++++++++++++++++++++++++++-----
26
2 files changed, 41 insertions(+), 5 deletions(-)
27
28
diff --git a/include/hw/arm/aspeed.h b/include/hw/arm/aspeed.h
29
index XXXXXXX..XXXXXXX 100644
30
--- a/include/hw/arm/aspeed.h
31
+++ b/include/hw/arm/aspeed.h
32
@@ -XXX,XX +XXX,XX @@ typedef struct AspeedBoardState AspeedBoardState;
33
34
typedef struct AspeedMachine {
35
MachineState parent_obj;
36
+
37
+ bool mmio_exec;
38
} AspeedMachine;
39
40
#define ASPEED_MACHINE_CLASS(klass) \
41
diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
42
index XXXXXXX..XXXXXXX 100644
43
--- a/hw/arm/aspeed.c
44
+++ b/hw/arm/aspeed.c
45
@@ -XXX,XX +XXX,XX @@ static void aspeed_machine_init(MachineState *machine)
46
* SoC and 128MB for the AST2500 SoC, which is twice as big as
47
* needed by the flash modules of the Aspeed machines.
48
*/
49
- memory_region_init_rom(boot_rom, OBJECT(bmc), "aspeed.boot_rom",
50
- fl->size, &error_abort);
51
- memory_region_add_subregion(get_system_memory(), FIRMWARE_ADDR,
52
- boot_rom);
53
- write_boot_rom(drive0, FIRMWARE_ADDR, fl->size, &error_abort);
54
+ if (ASPEED_MACHINE(machine)->mmio_exec) {
55
+ memory_region_init_alias(boot_rom, OBJECT(bmc), "aspeed.boot_rom",
56
+ &fl->mmio, 0, fl->size);
57
+ memory_region_add_subregion(get_system_memory(), FIRMWARE_ADDR,
58
+ boot_rom);
59
+ } else {
60
+ memory_region_init_rom(boot_rom, OBJECT(bmc), "aspeed.boot_rom",
61
+ fl->size, &error_abort);
62
+ memory_region_add_subregion(get_system_memory(), FIRMWARE_ADDR,
63
+ boot_rom);
64
+ write_boot_rom(drive0, FIRMWARE_ADDR, fl->size, &error_abort);
65
+ }
66
}
67
68
aspeed_board_binfo.ram_size = ram_size;
69
@@ -XXX,XX +XXX,XX @@ static void witherspoon_bmc_i2c_init(AspeedBoardState *bmc)
70
/* Bus 11: TODO ucd90160@64 */
71
}
72
73
+static bool aspeed_get_mmio_exec(Object *obj, Error **errp)
74
+{
75
+ return ASPEED_MACHINE(obj)->mmio_exec;
76
+}
77
+
78
+static void aspeed_set_mmio_exec(Object *obj, bool value, Error **errp)
79
+{
80
+ ASPEED_MACHINE(obj)->mmio_exec = value;
81
+}
82
+
83
+static void aspeed_machine_instance_init(Object *obj)
84
+{
85
+ ASPEED_MACHINE(obj)->mmio_exec = false;
86
+}
87
+
88
+static void aspeed_machine_class_props_init(ObjectClass *oc)
89
+{
90
+ object_class_property_add_bool(oc, "execute-in-place",
91
+ aspeed_get_mmio_exec,
92
+ aspeed_set_mmio_exec, &error_abort);
93
+ object_class_property_set_description(oc, "execute-in-place",
94
+ "boot directly from CE0 flash device", &error_abort);
95
+}
96
+
97
static void aspeed_machine_class_init(ObjectClass *oc, void *data)
98
{
99
MachineClass *mc = MACHINE_CLASS(oc);
100
@@ -XXX,XX +XXX,XX @@ static void aspeed_machine_class_init(ObjectClass *oc, void *data)
101
mc->no_floppy = 1;
102
mc->no_cdrom = 1;
103
mc->no_parallel = 1;
104
+
105
+ aspeed_machine_class_props_init(oc);
106
}
107
108
static void aspeed_machine_palmetto_class_init(ObjectClass *oc, void *data)
109
@@ -XXX,XX +XXX,XX @@ static const TypeInfo aspeed_machine_types[] = {
110
.name = TYPE_ASPEED_MACHINE,
111
.parent = TYPE_MACHINE,
112
.instance_size = sizeof(AspeedMachine),
113
+ .instance_init = aspeed_machine_instance_init,
114
.class_size = sizeof(AspeedMachineClass),
115
.class_init = aspeed_machine_class_init,
116
.abstract = true,
117
--
118
2.20.1
119
120
diff view generated by jsdifflib
Deleted patch
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
1
3
Since we enabled parallel TCG code generation for softmmu (see
4
commit 3468b59 "tcg: enable multiple TCG contexts in softmmu")
5
and its subsequent fix (commit 72649619 "add .min_cpus and
6
.default_cpus fields to machine_class"), the raspi machines are
7
restricted to always use their 4 cores:
8
9
See in hw/arm/raspi2 (with BCM283X_NCPUS set to 4):
10
11
222 static void raspi2_machine_init(MachineClass *mc)
12
223 {
13
224 mc->desc = "Raspberry Pi 2";
14
230 mc->max_cpus = BCM283X_NCPUS;
15
231 mc->min_cpus = BCM283X_NCPUS;
16
232 mc->default_cpus = BCM283X_NCPUS;
17
235 };
18
236 DEFINE_MACHINE("raspi2", raspi2_machine_init)
19
20
We can no longer use the -smp option, as we get:
21
22
$ qemu-system-arm -M raspi2 -smp 1
23
qemu-system-arm: Invalid SMP CPUs 1. The min CPUs supported by machine 'raspi2' is 4
24
25
Since we can not set the TYPE_BCM283x SOC "enabled-cpus" with -smp,
26
remove the unuseful code.
27
28
We can achieve the same by using the '-global bcm2836.enabled-cpus=1'
29
option.
30
31
Reported-by: Laurent Bonnans <laurent.bonnans@here.com>
32
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
33
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
34
Message-id: 20200120235159.18510-2-f4bug@amsat.org
35
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
36
---
37
hw/arm/raspi.c | 2 --
38
1 file changed, 2 deletions(-)
39
40
diff --git a/hw/arm/raspi.c b/hw/arm/raspi.c
41
index XXXXXXX..XXXXXXX 100644
42
--- a/hw/arm/raspi.c
43
+++ b/hw/arm/raspi.c
44
@@ -XXX,XX +XXX,XX @@ static void raspi_init(MachineState *machine, int version)
45
/* Setup the SOC */
46
object_property_add_const_link(OBJECT(&s->soc), "ram", OBJECT(&s->ram),
47
&error_abort);
48
- object_property_set_int(OBJECT(&s->soc), machine->smp.cpus, "enabled-cpus",
49
- &error_abort);
50
int board_rev = version == 3 ? 0xa02082 : 0xa21041;
51
object_property_set_int(OBJECT(&s->soc), board_rev, "board-rev",
52
&error_abort);
53
--
54
2.20.1
55
56
diff view generated by jsdifflib
Deleted patch
1
From: Damien Hedde <damien.hedde@greensocs.com>
2
1
3
Provide a temporary device_legacy_reset function doing what
4
device_reset does to prepare for the transition with Resettable
5
API.
6
7
All occurrence of device_reset in the code tree are also replaced
8
by device_legacy_reset.
9
10
The new resettable API has different prototype and semantics
11
(resetting child buses as well as the specified device). Subsequent
12
commits will make the changeover for each call site individually; once
13
that is complete device_legacy_reset() will be removed.
14
15
Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
16
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
17
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
18
Acked-by: David Gibson <david@gibson.dropbear.id.au>
19
Acked-by: Cornelia Huck <cohuck@redhat.com>
20
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
21
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
22
Message-id: 20200123132823.1117486-2-damien.hedde@greensocs.com
23
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
24
---
25
include/hw/qdev-core.h | 4 ++--
26
hw/audio/intel-hda.c | 2 +-
27
hw/core/qdev.c | 6 +++---
28
hw/hyperv/hyperv.c | 2 +-
29
hw/i386/microvm.c | 2 +-
30
hw/i386/pc.c | 2 +-
31
hw/ide/microdrive.c | 8 ++++----
32
hw/intc/spapr_xive.c | 2 +-
33
hw/ppc/pnv_psi.c | 4 ++--
34
hw/ppc/spapr_pci.c | 2 +-
35
hw/ppc/spapr_vio.c | 2 +-
36
hw/s390x/s390-pci-inst.c | 2 +-
37
hw/scsi/vmw_pvscsi.c | 2 +-
38
hw/sd/omap_mmc.c | 2 +-
39
hw/sd/pl181.c | 2 +-
40
15 files changed, 22 insertions(+), 22 deletions(-)
41
42
diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
43
index XXXXXXX..XXXXXXX 100644
44
--- a/include/hw/qdev-core.h
45
+++ b/include/hw/qdev-core.h
46
@@ -XXX,XX +XXX,XX @@ char *qdev_get_own_fw_dev_path_from_handler(BusState *bus, DeviceState *dev);
47
void qdev_machine_init(void);
48
49
/**
50
- * @device_reset
51
+ * device_legacy_reset:
52
*
53
* Reset a single device (by calling the reset method).
54
*/
55
-void device_reset(DeviceState *dev);
56
+void device_legacy_reset(DeviceState *dev);
57
58
void device_class_set_props(DeviceClass *dc, Property *props);
59
60
diff --git a/hw/audio/intel-hda.c b/hw/audio/intel-hda.c
61
index XXXXXXX..XXXXXXX 100644
62
--- a/hw/audio/intel-hda.c
63
+++ b/hw/audio/intel-hda.c
64
@@ -XXX,XX +XXX,XX @@ static void intel_hda_reset(DeviceState *dev)
65
QTAILQ_FOREACH(kid, &d->codecs.qbus.children, sibling) {
66
DeviceState *qdev = kid->child;
67
cdev = HDA_CODEC_DEVICE(qdev);
68
- device_reset(DEVICE(cdev));
69
+ device_legacy_reset(DEVICE(cdev));
70
d->state_sts |= (1 << cdev->cad);
71
}
72
intel_hda_update_irq(d);
73
diff --git a/hw/core/qdev.c b/hw/core/qdev.c
74
index XXXXXXX..XXXXXXX 100644
75
--- a/hw/core/qdev.c
76
+++ b/hw/core/qdev.c
77
@@ -XXX,XX +XXX,XX @@ HotplugHandler *qdev_get_hotplug_handler(DeviceState *dev)
78
79
static int qdev_reset_one(DeviceState *dev, void *opaque)
80
{
81
- device_reset(dev);
82
+ device_legacy_reset(dev);
83
84
return 0;
85
}
86
@@ -XXX,XX +XXX,XX @@ static void device_set_realized(Object *obj, bool value, Error **errp)
87
}
88
}
89
if (dev->hotplugged) {
90
- device_reset(dev);
91
+ device_legacy_reset(dev);
92
}
93
dev->pending_deleted_event = false;
94
95
@@ -XXX,XX +XXX,XX @@ void device_class_set_parent_unrealize(DeviceClass *dc,
96
dc->unrealize = dev_unrealize;
97
}
98
99
-void device_reset(DeviceState *dev)
100
+void device_legacy_reset(DeviceState *dev)
101
{
102
DeviceClass *klass = DEVICE_GET_CLASS(dev);
103
104
diff --git a/hw/hyperv/hyperv.c b/hw/hyperv/hyperv.c
105
index XXXXXXX..XXXXXXX 100644
106
--- a/hw/hyperv/hyperv.c
107
+++ b/hw/hyperv/hyperv.c
108
@@ -XXX,XX +XXX,XX @@ void hyperv_synic_reset(CPUState *cs)
109
SynICState *synic = get_synic(cs);
110
111
if (synic) {
112
- device_reset(DEVICE(synic));
113
+ device_legacy_reset(DEVICE(synic));
114
}
115
}
116
117
diff --git a/hw/i386/microvm.c b/hw/i386/microvm.c
118
index XXXXXXX..XXXXXXX 100644
119
--- a/hw/i386/microvm.c
120
+++ b/hw/i386/microvm.c
121
@@ -XXX,XX +XXX,XX @@ static void microvm_machine_reset(MachineState *machine)
122
cpu = X86_CPU(cs);
123
124
if (cpu->apic_state) {
125
- device_reset(cpu->apic_state);
126
+ device_legacy_reset(cpu->apic_state);
127
}
128
}
129
}
130
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
131
index XXXXXXX..XXXXXXX 100644
132
--- a/hw/i386/pc.c
133
+++ b/hw/i386/pc.c
134
@@ -XXX,XX +XXX,XX @@ static void pc_machine_reset(MachineState *machine)
135
cpu = X86_CPU(cs);
136
137
if (cpu->apic_state) {
138
- device_reset(cpu->apic_state);
139
+ device_legacy_reset(cpu->apic_state);
140
}
141
}
142
}
143
diff --git a/hw/ide/microdrive.c b/hw/ide/microdrive.c
144
index XXXXXXX..XXXXXXX 100644
145
--- a/hw/ide/microdrive.c
146
+++ b/hw/ide/microdrive.c
147
@@ -XXX,XX +XXX,XX @@ static void md_attr_write(PCMCIACardState *card, uint32_t at, uint8_t value)
148
case 0x00:    /* Configuration Option Register */
149
s->opt = value & 0xcf;
150
if (value & OPT_SRESET) {
151
- device_reset(DEVICE(s));
152
+ device_legacy_reset(DEVICE(s));
153
}
154
md_interrupt_update(s);
155
break;
156
@@ -XXX,XX +XXX,XX @@ static void md_common_write(PCMCIACardState *card, uint32_t at, uint16_t value)
157
case 0xe:    /* Device Control */
158
s->ctrl = value;
159
if (value & CTRL_SRST) {
160
- device_reset(DEVICE(s));
161
+ device_legacy_reset(DEVICE(s));
162
}
163
md_interrupt_update(s);
164
break;
165
@@ -XXX,XX +XXX,XX @@ static int dscm1xxxx_attach(PCMCIACardState *card)
166
md->attr_base = pcc->cis[0x74] | (pcc->cis[0x76] << 8);
167
md->io_base = 0x0;
168
169
- device_reset(DEVICE(md));
170
+ device_legacy_reset(DEVICE(md));
171
md_interrupt_update(md);
172
173
return 0;
174
@@ -XXX,XX +XXX,XX @@ static int dscm1xxxx_detach(PCMCIACardState *card)
175
{
176
MicroDriveState *md = MICRODRIVE(card);
177
178
- device_reset(DEVICE(md));
179
+ device_legacy_reset(DEVICE(md));
180
return 0;
181
}
182
183
diff --git a/hw/intc/spapr_xive.c b/hw/intc/spapr_xive.c
184
index XXXXXXX..XXXXXXX 100644
185
--- a/hw/intc/spapr_xive.c
186
+++ b/hw/intc/spapr_xive.c
187
@@ -XXX,XX +XXX,XX @@ static target_ulong h_int_reset(PowerPCCPU *cpu,
188
return H_PARAMETER;
189
}
190
191
- device_reset(DEVICE(xive));
192
+ device_legacy_reset(DEVICE(xive));
193
194
if (kvm_irqchip_in_kernel()) {
195
Error *local_err = NULL;
196
diff --git a/hw/ppc/pnv_psi.c b/hw/ppc/pnv_psi.c
197
index XXXXXXX..XXXXXXX 100644
198
--- a/hw/ppc/pnv_psi.c
199
+++ b/hw/ppc/pnv_psi.c
200
@@ -XXX,XX +XXX,XX @@ static void pnv_psi_reset(DeviceState *dev)
201
202
static void pnv_psi_reset_handler(void *dev)
203
{
204
- device_reset(DEVICE(dev));
205
+ device_legacy_reset(DEVICE(dev));
206
}
207
208
static void pnv_psi_realize(DeviceState *dev, Error **errp)
209
@@ -XXX,XX +XXX,XX @@ static void pnv_psi_p9_mmio_write(void *opaque, hwaddr addr,
210
break;
211
case PSIHB9_INTERRUPT_CONTROL:
212
if (val & PSIHB9_IRQ_RESET) {
213
- device_reset(DEVICE(&psi9->source));
214
+ device_legacy_reset(DEVICE(&psi9->source));
215
}
216
psi->regs[reg] = val;
217
break;
218
diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c
219
index XXXXXXX..XXXXXXX 100644
220
--- a/hw/ppc/spapr_pci.c
221
+++ b/hw/ppc/spapr_pci.c
222
@@ -XXX,XX +XXX,XX @@ static int spapr_phb_children_reset(Object *child, void *opaque)
223
DeviceState *dev = (DeviceState *) object_dynamic_cast(child, TYPE_DEVICE);
224
225
if (dev) {
226
- device_reset(dev);
227
+ device_legacy_reset(dev);
228
}
229
230
return 0;
231
diff --git a/hw/ppc/spapr_vio.c b/hw/ppc/spapr_vio.c
232
index XXXXXXX..XXXXXXX 100644
233
--- a/hw/ppc/spapr_vio.c
234
+++ b/hw/ppc/spapr_vio.c
235
@@ -XXX,XX +XXX,XX @@ int spapr_vio_send_crq(SpaprVioDevice *dev, uint8_t *crq)
236
static void spapr_vio_quiesce_one(SpaprVioDevice *dev)
237
{
238
if (dev->tcet) {
239
- device_reset(DEVICE(dev->tcet));
240
+ device_legacy_reset(DEVICE(dev->tcet));
241
}
242
free_crq(dev);
243
}
244
diff --git a/hw/s390x/s390-pci-inst.c b/hw/s390x/s390-pci-inst.c
245
index XXXXXXX..XXXXXXX 100644
246
--- a/hw/s390x/s390-pci-inst.c
247
+++ b/hw/s390x/s390-pci-inst.c
248
@@ -XXX,XX +XXX,XX @@ int clp_service_call(S390CPU *cpu, uint8_t r2, uintptr_t ra)
249
stw_p(&ressetpci->hdr.rsp, CLP_RC_SETPCIFN_FHOP);
250
goto out;
251
}
252
- device_reset(DEVICE(pbdev));
253
+ device_legacy_reset(DEVICE(pbdev));
254
pbdev->fh &= ~FH_MASK_ENABLE;
255
pbdev->state = ZPCI_FS_DISABLED;
256
stl_p(&ressetpci->fh, pbdev->fh);
257
diff --git a/hw/scsi/vmw_pvscsi.c b/hw/scsi/vmw_pvscsi.c
258
index XXXXXXX..XXXXXXX 100644
259
--- a/hw/scsi/vmw_pvscsi.c
260
+++ b/hw/scsi/vmw_pvscsi.c
261
@@ -XXX,XX +XXX,XX @@ pvscsi_on_cmd_reset_device(PVSCSIState *s)
262
263
if (sdev != NULL) {
264
s->resetting++;
265
- device_reset(&sdev->qdev);
266
+ device_legacy_reset(&sdev->qdev);
267
s->resetting--;
268
return PVSCSI_COMMAND_PROCESSING_SUCCEEDED;
269
}
270
diff --git a/hw/sd/omap_mmc.c b/hw/sd/omap_mmc.c
271
index XXXXXXX..XXXXXXX 100644
272
--- a/hw/sd/omap_mmc.c
273
+++ b/hw/sd/omap_mmc.c
274
@@ -XXX,XX +XXX,XX @@ void omap_mmc_reset(struct omap_mmc_s *host)
275
* into any bus, and we must reset it manually. When omap_mmc is
276
* QOMified this must move into the QOM reset function.
277
*/
278
- device_reset(DEVICE(host->card));
279
+ device_legacy_reset(DEVICE(host->card));
280
}
281
282
static uint64_t omap_mmc_read(void *opaque, hwaddr offset,
283
diff --git a/hw/sd/pl181.c b/hw/sd/pl181.c
284
index XXXXXXX..XXXXXXX 100644
285
--- a/hw/sd/pl181.c
286
+++ b/hw/sd/pl181.c
287
@@ -XXX,XX +XXX,XX @@ static void pl181_reset(DeviceState *d)
288
/* Since we're still using the legacy SD API the card is not plugged
289
* into any bus, and we must reset it manually.
290
*/
291
- device_reset(DEVICE(s->card));
292
+ device_legacy_reset(DEVICE(s->card));
293
}
294
295
static void pl181_init(Object *obj)
296
--
297
2.20.1
298
299
diff view generated by jsdifflib
1
From: Andrew Jones <drjones@redhat.com>
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
Add the missing GENERIC_TIMER feature to kvm64 cpus.
5
Relicense the code in the .c and the .h file to GPL-v2-or-later,
6
to make it compatible with the rest of QEMU.
4
7
5
We don't currently use these registers when KVM is enabled, but it's
8
Cc: qemu-stable@nongnu.org
6
probably best we add the feature flag for consistency and potential
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
future use. There's also precedent, as we add the PMU feature flag to
10
Signed-off-by: Paolo Bonzini (for Red Hat) <pbonzini@redhat.com>
8
KVM enabled guests, even though we don't use those registers either.
11
Signed-off-by: Artyom Tarasenko <atar4qemu@gmail.com>
9
12
Signed-off-by: Markus Armbruster <armbru@redhat.com>
10
This change was originally posted as a hunk of a different, never
13
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
11
merged patch from Bijan Mottahedeh.
14
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
12
15
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
13
Signed-off-by: Andrew Jones <drjones@redhat.com>
16
Acked-by: Alex Bennée <alex.bennee@linaro.org>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
17
Message-id: 20240223161300.938542-1-peter.maydell@linaro.org
15
Message-id: 20200120101023.16030-4-drjones@redhat.com
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
---
19
---
18
target/arm/kvm64.c | 1 +
20
include/hw/rtc/sun4v-rtc.h | 2 +-
19
1 file changed, 1 insertion(+)
21
hw/rtc/sun4v-rtc.c | 2 +-
22
2 files changed, 2 insertions(+), 2 deletions(-)
20
23
21
diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
24
diff --git a/include/hw/rtc/sun4v-rtc.h b/include/hw/rtc/sun4v-rtc.h
22
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
23
--- a/target/arm/kvm64.c
26
--- a/include/hw/rtc/sun4v-rtc.h
24
+++ b/target/arm/kvm64.c
27
+++ b/include/hw/rtc/sun4v-rtc.h
25
@@ -XXX,XX +XXX,XX @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
28
@@ -XXX,XX +XXX,XX @@
26
set_feature(&features, ARM_FEATURE_NEON);
29
*
27
set_feature(&features, ARM_FEATURE_AARCH64);
30
* Copyright (c) 2016 Artyom Tarasenko
28
set_feature(&features, ARM_FEATURE_PMU);
31
*
29
+ set_feature(&features, ARM_FEATURE_GENERIC_TIMER);
32
- * This code is licensed under the GNU GPL v3 or (at your option) any later
30
33
+ * This code is licensed under the GNU GPL v2 or (at your option) any later
31
ahcf->features = features;
34
* version.
35
*/
36
37
diff --git a/hw/rtc/sun4v-rtc.c b/hw/rtc/sun4v-rtc.c
38
index XXXXXXX..XXXXXXX 100644
39
--- a/hw/rtc/sun4v-rtc.c
40
+++ b/hw/rtc/sun4v-rtc.c
41
@@ -XXX,XX +XXX,XX @@
42
*
43
* Copyright (c) 2016 Artyom Tarasenko
44
*
45
- * This code is licensed under the GNU GPL v3 or (at your option) any later
46
+ * This code is licensed under the GNU GPL v2 or (at your option) any later
47
* version.
48
*/
32
49
33
--
50
--
34
2.20.1
51
2.34.1
35
52
36
53
diff view generated by jsdifflib
1
From: Damien Hedde <damien.hedde@greensocs.com>
1
From: Thomas Huth <thuth@redhat.com>
2
2
3
Adds trace events to reset procedure and when updating the parent
3
Move the code to a separate file so that we do not have to compile
4
bus of a device.
4
it anymore if CONFIG_ARM_V7M is not set.
5
5
6
Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
6
Signed-off-by: Thomas Huth <thuth@redhat.com>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20240308141051.536599-2-thuth@redhat.com
8
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Cornelia Huck <cohuck@redhat.com>
10
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
11
Message-id: 20200123132823.1117486-3-damien.hedde@greensocs.com
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
10
---
14
hw/core/qdev.c | 29 ++++++++++++++++++++++++++---
11
target/arm/tcg/cpu-v7m.c | 290 +++++++++++++++++++++++++++++++++++++
15
hw/core/trace-events | 9 +++++++++
12
target/arm/tcg/cpu32.c | 261 ---------------------------------
16
2 files changed, 35 insertions(+), 3 deletions(-)
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
17
17
18
diff --git a/hw/core/qdev.c b/hw/core/qdev.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
19
index XXXXXXX..XXXXXXX 100644
315
index XXXXXXX..XXXXXXX 100644
20
--- a/hw/core/qdev.c
316
--- a/target/arm/tcg/cpu32.c
21
+++ b/hw/core/qdev.c
317
+++ b/target/arm/tcg/cpu32.c
22
@@ -XXX,XX +XXX,XX @@
318
@@ -XXX,XX +XXX,XX @@
23
#include "hw/boards.h"
319
#include "hw/boards.h"
24
#include "hw/sysbus.h"
320
#endif
25
#include "migration/vmstate.h"
321
#include "cpregs.h"
26
+#include "trace.h"
322
-#if !defined(CONFIG_USER_ONLY) && defined(CONFIG_TCG)
27
323
-#include "hw/intc/armv7m_nvic.h"
28
bool qdev_hotplug = false;
324
-#endif
29
static bool qdev_hot_added = false;
325
30
@@ -XXX,XX +XXX,XX @@ void qdev_set_parent_bus(DeviceState *dev, BusState *bus)
326
31
bool replugging = dev->parent_bus != NULL;
327
/* Share AArch32 -cpu max features with AArch64. */
32
328
@@ -XXX,XX +XXX,XX @@ void aa32_max_features(ARMCPU *cpu)
33
if (replugging) {
329
/* CPU models. These are not needed for the AArch64 linux-user build. */
34
- /* Keep a reference to the device while it's not plugged into
330
#if !defined(CONFIG_USER_ONLY) || !defined(TARGET_AARCH64)
35
+ trace_qdev_update_parent_bus(dev, object_get_typename(OBJECT(dev)),
331
36
+ dev->parent_bus, object_get_typename(OBJECT(dev->parent_bus)),
332
-#if !defined(CONFIG_USER_ONLY)
37
+ OBJECT(bus), object_get_typename(OBJECT(bus)));
333
-static bool arm_v7m_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
38
+ /*
334
-{
39
+ * Keep a reference to the device while it's not plugged into
335
- CPUClass *cc = CPU_GET_CLASS(cs);
40
* any bus, to avoid it potentially evaporating when it is
336
- ARMCPU *cpu = ARM_CPU(cs);
41
* dereffed in bus_remove_child().
337
- CPUARMState *env = &cpu->env;
42
*/
338
- bool ret = false;
43
@@ -XXX,XX +XXX,XX @@ HotplugHandler *qdev_get_hotplug_handler(DeviceState *dev)
339
-
44
return hotplug_ctrl;
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)
359
{
360
ARMCPU *cpu = ARM_CPU(obj);
361
@@ -XXX,XX +XXX,XX @@ static void cortex_a15_initfn(Object *obj)
362
define_arm_cp_regs(cpu, cortexa15_cp_reginfo);
45
}
363
}
46
364
47
+static int qdev_prereset(DeviceState *dev, void *opaque)
365
-static void cortex_m0_initfn(Object *obj)
48
+{
366
-{
49
+ trace_qdev_reset_tree(dev, object_get_typename(OBJECT(dev)));
367
- ARMCPU *cpu = ARM_CPU(obj);
50
+ return 0;
368
- set_feature(&cpu->env, ARM_FEATURE_V6);
51
+}
369
- set_feature(&cpu->env, ARM_FEATURE_M);
52
+
370
-
53
+static int qbus_prereset(BusState *bus, void *opaque)
371
- cpu->midr = 0x410cc200;
54
+{
372
-
55
+ trace_qbus_reset_tree(bus, object_get_typename(OBJECT(bus)));
373
- /*
56
+ return 0;
374
- * These ID register values are not guest visible, because
57
+}
375
- * we do not implement the Main Extension. They must be set
58
+
376
- * to values corresponding to the Cortex-M0's implemented
59
static int qdev_reset_one(DeviceState *dev, void *opaque)
377
- * features, because QEMU generally controls its emulation
60
{
378
- * by looking at ID register fields. We use the same values as
61
device_legacy_reset(dev);
379
- * for the M3.
62
@@ -XXX,XX +XXX,XX @@ static int qdev_reset_one(DeviceState *dev, void *opaque)
380
- */
63
static int qbus_reset_one(BusState *bus, void *opaque)
381
- cpu->isar.id_pfr0 = 0x00000030;
64
{
382
- cpu->isar.id_pfr1 = 0x00000200;
65
BusClass *bc = BUS_GET_CLASS(bus);
383
- cpu->isar.id_dfr0 = 0x00100000;
66
+ trace_qbus_reset(bus, object_get_typename(OBJECT(bus)));
384
- cpu->id_afr0 = 0x00000000;
67
if (bc->reset) {
385
- cpu->isar.id_mmfr0 = 0x00000030;
68
bc->reset(bus);
386
- cpu->isar.id_mmfr1 = 0x00000000;
69
}
387
- cpu->isar.id_mmfr2 = 0x00000000;
70
@@ -XXX,XX +XXX,XX @@ static int qbus_reset_one(BusState *bus, void *opaque)
388
- cpu->isar.id_mmfr3 = 0x00000000;
71
389
- cpu->isar.id_isar0 = 0x01141110;
72
void qdev_reset_all(DeviceState *dev)
390
- cpu->isar.id_isar1 = 0x02111000;
73
{
391
- cpu->isar.id_isar2 = 0x21112231;
74
- qdev_walk_children(dev, NULL, NULL, qdev_reset_one, qbus_reset_one, NULL);
392
- cpu->isar.id_isar3 = 0x01111110;
75
+ trace_qdev_reset_all(dev, object_get_typename(OBJECT(dev)));
393
- cpu->isar.id_isar4 = 0x01310102;
76
+ qdev_walk_children(dev, qdev_prereset, qbus_prereset,
394
- cpu->isar.id_isar5 = 0x00000000;
77
+ qdev_reset_one, qbus_reset_one, NULL);
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;
78
}
559
}
79
560
80
void qdev_reset_all_fn(void *opaque)
561
-static const TCGCPUOps arm_v7m_tcg_ops = {
81
@@ -XXX,XX +XXX,XX @@ void qdev_reset_all_fn(void *opaque)
562
- .initialize = arm_translate_init,
82
563
- .synchronize_from_tb = arm_cpu_synchronize_from_tb,
83
void qbus_reset_all(BusState *bus)
564
- .debug_excp_handler = arm_debug_excp_handler,
84
{
565
- .restore_state_to_opc = arm_restore_state_to_opc,
85
- qbus_walk_children(bus, NULL, NULL, qdev_reset_one, qbus_reset_one, NULL);
566
-
86
+ trace_qbus_reset_all(bus, object_get_typename(OBJECT(bus)));
567
-#ifdef CONFIG_USER_ONLY
87
+ qbus_walk_children(bus, qdev_prereset, qbus_prereset,
568
- .record_sigsegv = arm_cpu_record_sigsegv,
88
+ qdev_reset_one, qbus_reset_one, NULL);
569
- .record_sigbus = arm_cpu_record_sigbus,
89
}
570
-#else
90
571
- .tlb_fill = arm_cpu_tlb_fill,
91
void qbus_reset_all_fn(void *opaque)
572
- .cpu_exec_interrupt = arm_v7m_cpu_exec_interrupt,
92
@@ -XXX,XX +XXX,XX @@ void device_legacy_reset(DeviceState *dev)
573
- .do_interrupt = arm_v7m_cpu_do_interrupt,
93
{
574
- .do_transaction_failed = arm_cpu_do_transaction_failed,
94
DeviceClass *klass = DEVICE_GET_CLASS(dev);
575
- .do_unaligned_access = arm_cpu_do_unaligned_access,
95
576
- .adjust_watchpoint_address = arm_adjust_watchpoint_address,
96
+ trace_qdev_reset(dev, object_get_typename(OBJECT(dev)));
577
- .debug_check_watchpoint = arm_debug_check_watchpoint,
97
if (klass->reset) {
578
- .debug_check_breakpoint = arm_debug_check_breakpoint,
98
klass->reset(dev);
579
-#endif /* !CONFIG_USER_ONLY */
99
}
580
-};
100
diff --git a/hw/core/trace-events b/hw/core/trace-events
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
101
index XXXXXXX..XXXXXXX 100644
615
index XXXXXXX..XXXXXXX 100644
102
--- a/hw/core/trace-events
616
--- a/target/arm/meson.build
103
+++ b/hw/core/trace-events
617
+++ b/target/arm/meson.build
104
@@ -XXX,XX +XXX,XX @@
618
@@ -XXX,XX +XXX,XX @@ arm_system_ss.add(files(
105
# loader.c
619
'ptw.c',
106
loader_write_rom(const char *name, uint64_t gpa, uint64_t size, bool isrom) "%s: @0x%"PRIx64" size=0x%"PRIx64" ROM=%d"
620
))
107
+
621
108
+# qdev.c
622
+arm_user_ss = ss.source_set()
109
+qdev_reset(void *obj, const char *objtype) "obj=%p(%s)"
623
+
110
+qdev_reset_all(void *obj, const char *objtype) "obj=%p(%s)"
624
subdir('hvf')
111
+qdev_reset_tree(void *obj, const char *objtype) "obj=%p(%s)"
625
112
+qbus_reset(void *obj, const char *objtype) "obj=%p(%s)"
626
if 'CONFIG_TCG' in config_all_accel
113
+qbus_reset_all(void *obj, const char *objtype) "obj=%p(%s)"
627
@@ -XXX,XX +XXX,XX @@ endif
114
+qbus_reset_tree(void *obj, const char *objtype) "obj=%p(%s)"
628
115
+qdev_update_parent_bus(void *obj, const char *objtype, void *oldp, const char *oldptype, void *newp, const char *newptype) "obj=%p(%s) old_parent=%p(%s) new_parent=%p(%s)"
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'))
116
--
643
--
117
2.20.1
644
2.34.1
118
119
diff view generated by jsdifflib
Deleted patch
1
From: Damien Hedde <damien.hedde@greensocs.com>
2
1
3
Add a function resettable_change_parent() to do the required
4
plumbing when changing the parent a of Resettable object.
5
6
We need to make sure that the reset state of the object remains
7
coherent with the reset state of the new parent.
8
9
We make the 2 following hypothesis:
10
+ when an object is put in a parent under reset, the object goes in
11
reset.
12
+ when an object is removed from a parent under reset, the object
13
leaves reset.
14
15
The added function avoids any glitch if both old and new parent are
16
already in reset.
17
18
Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
19
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
20
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
21
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
22
Message-id: 20200123132823.1117486-6-damien.hedde@greensocs.com
23
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
24
---
25
include/hw/resettable.h | 16 +++++++++++
26
hw/core/resettable.c | 62 +++++++++++++++++++++++++++++++++++++++--
27
hw/core/trace-events | 1 +
28
3 files changed, 77 insertions(+), 2 deletions(-)
29
30
diff --git a/include/hw/resettable.h b/include/hw/resettable.h
31
index XXXXXXX..XXXXXXX 100644
32
--- a/include/hw/resettable.h
33
+++ b/include/hw/resettable.h
34
@@ -XXX,XX +XXX,XX @@ void resettable_release_reset(Object *obj, ResetType type);
35
*/
36
bool resettable_is_in_reset(Object *obj);
37
38
+/**
39
+ * resettable_change_parent:
40
+ * Indicate that the parent of Ressettable @obj is changing from @oldp to @newp.
41
+ * All 3 objects must implement resettable interface. @oldp or @newp may be
42
+ * NULL.
43
+ *
44
+ * This function will adapt the reset state of @obj so that it is coherent
45
+ * with the reset state of @newp. It may trigger @resettable_assert_reset()
46
+ * or @resettable_release_reset(). It will do such things only if the reset
47
+ * state of @newp and @oldp are different.
48
+ *
49
+ * When using this function during reset, it must only be called during
50
+ * a hold phase method. Calling this during enter or exit phase is an error.
51
+ */
52
+void resettable_change_parent(Object *obj, Object *newp, Object *oldp);
53
+
54
/**
55
* resettable_class_set_parent_phases:
56
*
57
diff --git a/hw/core/resettable.c b/hw/core/resettable.c
58
index XXXXXXX..XXXXXXX 100644
59
--- a/hw/core/resettable.c
60
+++ b/hw/core/resettable.c
61
@@ -XXX,XX +XXX,XX @@ static void resettable_phase_exit(Object *obj, void *opaque, ResetType type);
62
* enter_phase_in_progress:
63
* True if we are currently in reset enter phase.
64
*
65
- * Note: This flag is only used to guarantee (using asserts) that the reset
66
- * API is used correctly. We can use a global variable because we rely on the
67
+ * exit_phase_in_progress:
68
+ * count the number of exit phase we are in.
69
+ *
70
+ * Note: These flags are only used to guarantee (using asserts) that the reset
71
+ * API is used correctly. We can use global variables because we rely on the
72
* iothread mutex to ensure only one reset operation is in a progress at a
73
* given time.
74
*/
75
static bool enter_phase_in_progress;
76
+static unsigned exit_phase_in_progress;
77
78
void resettable_reset(Object *obj, ResetType type)
79
{
80
@@ -XXX,XX +XXX,XX @@ void resettable_release_reset(Object *obj, ResetType type)
81
trace_resettable_reset_release_begin(obj, type);
82
assert(!enter_phase_in_progress);
83
84
+ exit_phase_in_progress += 1;
85
resettable_phase_exit(obj, NULL, type);
86
+ exit_phase_in_progress -= 1;
87
88
trace_resettable_reset_release_end(obj);
89
}
90
@@ -XXX,XX +XXX,XX @@ static void resettable_phase_exit(Object *obj, void *opaque, ResetType type)
91
trace_resettable_phase_exit_end(obj, obj_typename, s->count);
92
}
93
94
+/*
95
+ * resettable_get_count:
96
+ * Get the count of the Resettable object @obj. Return 0 if @obj is NULL.
97
+ */
98
+static unsigned resettable_get_count(Object *obj)
99
+{
100
+ if (obj) {
101
+ ResettableClass *rc = RESETTABLE_GET_CLASS(obj);
102
+ return rc->get_state(obj)->count;
103
+ }
104
+ return 0;
105
+}
106
+
107
+void resettable_change_parent(Object *obj, Object *newp, Object *oldp)
108
+{
109
+ ResettableClass *rc = RESETTABLE_GET_CLASS(obj);
110
+ ResettableState *s = rc->get_state(obj);
111
+ unsigned newp_count = resettable_get_count(newp);
112
+ unsigned oldp_count = resettable_get_count(oldp);
113
+
114
+ /*
115
+ * Ensure we do not change parent when in enter or exit phase.
116
+ * During these phases, the reset subtree being updated is partly in reset
117
+ * and partly not in reset (it depends on the actual position in
118
+ * resettable_child_foreach()s). We are not able to tell in which part is a
119
+ * leaving or arriving device. Thus we cannot set the reset count of the
120
+ * moving device to the proper value.
121
+ */
122
+ assert(!enter_phase_in_progress && !exit_phase_in_progress);
123
+ trace_resettable_change_parent(obj, oldp, oldp_count, newp, newp_count);
124
+
125
+ /*
126
+ * At most one of the two 'for' loops will be executed below
127
+ * in order to cope with the difference between the two counts.
128
+ */
129
+ /* if newp is more reset than oldp */
130
+ for (unsigned i = oldp_count; i < newp_count; i++) {
131
+ resettable_assert_reset(obj, RESET_TYPE_COLD);
132
+ }
133
+ /*
134
+ * if obj is leaving a bus under reset, we need to ensure
135
+ * hold phase is not pending.
136
+ */
137
+ if (oldp_count && s->hold_phase_pending) {
138
+ resettable_phase_hold(obj, NULL, RESET_TYPE_COLD);
139
+ }
140
+ /* if oldp is more reset than newp */
141
+ for (unsigned i = newp_count; i < oldp_count; i++) {
142
+ resettable_release_reset(obj, RESET_TYPE_COLD);
143
+ }
144
+}
145
+
146
void resettable_class_set_parent_phases(ResettableClass *rc,
147
ResettableEnterPhase enter,
148
ResettableHoldPhase hold,
149
diff --git a/hw/core/trace-events b/hw/core/trace-events
150
index XXXXXXX..XXXXXXX 100644
151
--- a/hw/core/trace-events
152
+++ b/hw/core/trace-events
153
@@ -XXX,XX +XXX,XX @@ resettable_reset_assert_begin(void *obj, int cold) "obj=%p cold=%d"
154
resettable_reset_assert_end(void *obj) "obj=%p"
155
resettable_reset_release_begin(void *obj, int cold) "obj=%p cold=%d"
156
resettable_reset_release_end(void *obj) "obj=%p"
157
+resettable_change_parent(void *obj, void *o, unsigned oc, void *n, unsigned nc) "obj=%p from=%p(%d) to=%p(%d)"
158
resettable_phase_enter_begin(void *obj, const char *objtype, unsigned count, int type) "obj=%p(%s) count=%d type=%d"
159
resettable_phase_enter_exec(void *obj, const char *objtype, int type, int has_method) "obj=%p(%s) type=%d method=%d"
160
resettable_phase_enter_end(void *obj, const char *objtype, unsigned count) "obj=%p(%s) count=%d"
161
--
162
2.20.1
163
164
diff view generated by jsdifflib
Deleted patch
1
From: Damien Hedde <damien.hedde@greensocs.com>
2
1
3
This commit make use of the resettable API to reset the device being
4
hotplugged when it is realized. Also it ensures it is put in a reset
5
state coherent with the parent it is plugged into.
6
7
Note that there is a difference in the reset. Instead of resetting
8
only the hotplugged device, we reset also its subtree (switch to
9
resettable API). This is not expected to be a problem because
10
sub-buses are just realized too. If a hotplugged device has any
11
sub-buses it is logical to reset them too at this point.
12
13
The recently added should_be_hidden and PCI's partially_hotplugged
14
mechanisms do not interfere with realize operation:
15
+ In the should_be_hidden use case, device creation is
16
delayed.
17
+ The partially_hotplugged mechanism prevents a device to be
18
unplugged and unrealized from qdev POV and unrealized.
19
20
Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
21
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
22
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
23
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
24
Message-id: 20200123132823.1117486-8-damien.hedde@greensocs.com
25
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
26
---
27
include/hw/resettable.h | 11 +++++++++++
28
hw/core/qdev.c | 15 ++++++++++++++-
29
2 files changed, 25 insertions(+), 1 deletion(-)
30
31
diff --git a/include/hw/resettable.h b/include/hw/resettable.h
32
index XXXXXXX..XXXXXXX 100644
33
--- a/include/hw/resettable.h
34
+++ b/include/hw/resettable.h
35
@@ -XXX,XX +XXX,XX @@ struct ResettableState {
36
bool exit_phase_in_progress;
37
};
38
39
+/**
40
+ * resettable_state_clear:
41
+ * Clear the state. It puts the state to the initial (zeroed) state required
42
+ * to reuse an object. Typically used in realize step of base classes
43
+ * implementing the interface.
44
+ */
45
+static inline void resettable_state_clear(ResettableState *state)
46
+{
47
+ memset(state, 0, sizeof(ResettableState));
48
+}
49
+
50
/**
51
* resettable_reset:
52
* Trigger a reset on an object @obj of type @type. @obj must implement
53
diff --git a/hw/core/qdev.c b/hw/core/qdev.c
54
index XXXXXXX..XXXXXXX 100644
55
--- a/hw/core/qdev.c
56
+++ b/hw/core/qdev.c
57
@@ -XXX,XX +XXX,XX @@ static void device_set_realized(Object *obj, bool value, Error **errp)
58
}
59
}
60
61
+ /*
62
+ * Clear the reset state, in case the object was previously unrealized
63
+ * with a dirty state.
64
+ */
65
+ resettable_state_clear(&dev->reset);
66
+
67
QLIST_FOREACH(bus, &dev->child_bus, sibling) {
68
object_property_set_bool(OBJECT(bus), true, "realized",
69
&local_err);
70
@@ -XXX,XX +XXX,XX @@ static void device_set_realized(Object *obj, bool value, Error **errp)
71
}
72
}
73
if (dev->hotplugged) {
74
- device_legacy_reset(dev);
75
+ /*
76
+ * Reset the device, as well as its subtree which, at this point,
77
+ * should be realized too.
78
+ */
79
+ resettable_assert_reset(OBJECT(dev), RESET_TYPE_COLD);
80
+ resettable_change_parent(OBJECT(dev), OBJECT(dev->parent_bus),
81
+ NULL);
82
+ resettable_release_reset(OBJECT(dev), RESET_TYPE_COLD);
83
}
84
dev->pending_deleted_event = false;
85
86
--
87
2.20.1
88
89
diff view generated by jsdifflib
Deleted patch
1
From: Damien Hedde <damien.hedde@greensocs.com>
2
1
3
Replace deprecated qbus_reset_all by resettable_cold_reset_fn for
4
the sysbus reset registration.
5
6
Apart for the raspi machines, this does not impact the behavior
7
because:
8
+ at this point resettable just calls the old reset methods of devices
9
and buses in the same order as qdev/qbus.
10
+ resettable handlers registered with qemu_register_reset are
11
serialized; there is no interleaving.
12
+ eventual explicit calls to legacy reset API (device_reset or
13
qdev/qbus_reset) inside this reset handler will not be masked out
14
by resettable mechanism; they do not go through resettable api.
15
16
For the raspi machines, during the sysbus reset the sd-card is not
17
reset twice anymore but only once. This is a consequence of switching
18
both sysbus reset and changing parent to resettable; it detects the
19
second reset is not needed. This has no impact on the state after
20
reset; the sd-card reset method only reset local state and query
21
information from the block backend.
22
23
The raspi reset change can be observed by using the following command
24
(reset will occurs, then do Ctrl-C to end qemu; no firmware is
25
given here).
26
qemu-system-aarch64 -M raspi3 \
27
-trace resettable_phase_hold_exec \
28
-trace qdev_update_parent_bus \
29
-trace resettable_change_parent \
30
-trace qdev_reset -trace qbus_reset
31
32
Before the patch, the qdev/qbus_reset traces show when reset method are
33
called. After the patch, the resettable_phase_hold_exec show when reset
34
method are called.
35
36
The traced reset order of the raspi3 is listed below. I've added empty
37
lines and the tree structure.
38
39
+->bcm2835-peripherals reset
40
|
41
| +->sd-card reset
42
| +->sd-bus reset
43
+->bcm2835_gpio reset
44
| -> dev_update_parent_bus (move the sd-card on the sdhci-bus)
45
| -> resettable_change_parent
46
|
47
+->bcm2835-dma reset
48
|
49
| +->bcm2835-sdhost-bus reset
50
+->bcm2835-sdhost reset
51
|
52
| +->sd-card (reset ONLY BEFORE BEFORE THE PATCH)
53
| +->sdhci-bus reset
54
+->generic-sdhci reset
55
|
56
+->bcm2835-rng reset
57
+->bcm2835-property reset
58
+->bcm2835-fb reset
59
+->bcm2835-mbox reset
60
+->bcm2835-aux reset
61
+->pl011 reset
62
+->bcm2835-ic reset
63
+->bcm2836-control reset
64
System reset
65
66
In both case, the sd-card is reset (being on bcm2835_gpio/sd-bus) then moved
67
to generic-sdhci/sdhci-bus by the bcm2835_gpio reset method.
68
69
Before the patch, it is then reset again being part of generic-sdhci/sdhci-bus.
70
After the patch, it considered again for reset but its reset method is not
71
called because it is already flagged as reset.
72
73
Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
74
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
75
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
76
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
77
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
78
Message-id: 20200123132823.1117486-11-damien.hedde@greensocs.com
79
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
80
---
81
vl.c | 10 +++++++++-
82
1 file changed, 9 insertions(+), 1 deletion(-)
83
84
diff --git a/vl.c b/vl.c
85
index XXXXXXX..XXXXXXX 100644
86
--- a/vl.c
87
+++ b/vl.c
88
@@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv, char **envp)
89
90
/* TODO: once all bus devices are qdevified, this should be done
91
* when bus is created by qdev.c */
92
- qemu_register_reset(qbus_reset_all_fn, sysbus_get_default());
93
+ /*
94
+ * TODO: If we had a main 'reset container' that the whole system
95
+ * lived in, we could reset that using the multi-phase reset
96
+ * APIs. For the moment, we just reset the sysbus, which will cause
97
+ * all devices hanging off it (and all their child buses, recursively)
98
+ * to be reset. Note that this will *not* reset any Device objects
99
+ * which are not attached to some part of the qbus tree!
100
+ */
101
+ qemu_register_reset(resettable_cold_reset_fn, sysbus_get_default());
102
qemu_run_machine_init_done_notifiers();
103
104
if (rom_check_and_register_reset() != 0) {
105
--
106
2.20.1
107
108
diff view generated by jsdifflib
Deleted patch
1
From: Damien Hedde <damien.hedde@greensocs.com>
2
1
3
Replace deprecated qdev_reset_all by resettable_cold_reset_fn for
4
the ipl registration in the main reset handlers.
5
6
This does not impact the behavior for the following reasons:
7
+ at this point resettable just call the old reset methods of devices
8
and buses in the same order than qdev/qbus.
9
+ resettable handlers registered with qemu_register_reset are
10
serialized; there is no interleaving.
11
+ eventual explicit calls to legacy reset API (device_reset or
12
qdev/qbus_reset) inside this reset handler will not be masked out
13
by resettable mechanism; they do not go through resettable api.
14
15
Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
16
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
17
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
18
Reviewed-by: Cornelia Huck <cohuck@redhat.com>
19
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
20
Message-id: 20200123132823.1117486-12-damien.hedde@greensocs.com
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
22
---
23
hw/s390x/ipl.c | 10 +++++++++-
24
1 file changed, 9 insertions(+), 1 deletion(-)
25
26
diff --git a/hw/s390x/ipl.c b/hw/s390x/ipl.c
27
index XXXXXXX..XXXXXXX 100644
28
--- a/hw/s390x/ipl.c
29
+++ b/hw/s390x/ipl.c
30
@@ -XXX,XX +XXX,XX @@ static void s390_ipl_realize(DeviceState *dev, Error **errp)
31
*/
32
ipl->compat_start_addr = ipl->start_addr;
33
ipl->compat_bios_start_addr = ipl->bios_start_addr;
34
- qemu_register_reset(qdev_reset_all_fn, dev);
35
+ /*
36
+ * Because this Device is not on any bus in the qbus tree (it is
37
+ * not a sysbus device and it's not on some other bus like a PCI
38
+ * bus) it will not be automatically reset by the 'reset the
39
+ * sysbus' hook registered by vl.c like most devices. So we must
40
+ * manually register a reset hook for it.
41
+ * TODO: there should be a better way to do this.
42
+ */
43
+ qemu_register_reset(resettable_cold_reset_fn, dev);
44
error:
45
error_propagate(errp, err);
46
}
47
--
48
2.20.1
49
50
diff view generated by jsdifflib
Deleted patch
1
From: Zenghui Yu <yuzenghui@huawei.com>
2
1
3
If LPIs are disabled, KVM will just ignore the GICR_PENDBASER.PTZ bit when
4
restoring GICR_CTLR. Setting PTZ here makes littlt sense in "reduce GIC
5
initialization time".
6
7
And what's worse, PTZ is generally programmed by guest to indicate to the
8
Redistributor whether the LPI Pending table is zero when enabling LPIs.
9
If migration is triggered when the PTZ has just been cleared by guest (and
10
before enabling LPIs), we will see PTZ==1 on the destination side, which
11
is not as expected. Let's just drop this hackish userspace behavior.
12
13
Also take this chance to refine the comment a bit.
14
15
Fixes: 367b9f527bec ("hw/intc/arm_gicv3_kvm: Implement get/put functions")
16
Signed-off-by: Zenghui Yu <yuzenghui@huawei.com>
17
Message-id: 20200119133051.642-1-yuzenghui@huawei.com
18
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
19
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
20
---
21
hw/intc/arm_gicv3_kvm.c | 11 ++++-------
22
1 file changed, 4 insertions(+), 7 deletions(-)
23
24
diff --git a/hw/intc/arm_gicv3_kvm.c b/hw/intc/arm_gicv3_kvm.c
25
index XXXXXXX..XXXXXXX 100644
26
--- a/hw/intc/arm_gicv3_kvm.c
27
+++ b/hw/intc/arm_gicv3_kvm.c
28
@@ -XXX,XX +XXX,XX @@ static void kvm_arm_gicv3_put(GICv3State *s)
29
kvm_gicd_access(s, GICD_CTLR, &reg, true);
30
31
if (redist_typer & GICR_TYPER_PLPIS) {
32
- /* Set base addresses before LPIs are enabled by GICR_CTLR write */
33
+ /*
34
+ * Restore base addresses before LPIs are potentially enabled by
35
+ * GICR_CTLR write
36
+ */
37
for (ncpu = 0; ncpu < s->num_cpu; ncpu++) {
38
GICv3CPUState *c = &s->cpu[ncpu];
39
40
@@ -XXX,XX +XXX,XX @@ static void kvm_arm_gicv3_put(GICv3State *s)
41
kvm_gicr_access(s, GICR_PROPBASER + 4, ncpu, &regh, true);
42
43
reg64 = c->gicr_pendbaser;
44
- if (!(c->gicr_ctlr & GICR_CTLR_ENABLE_LPIS)) {
45
- /* Setting PTZ is advised if LPIs are disabled, to reduce
46
- * GIC initialization time.
47
- */
48
- reg64 |= GICR_PENDBASER_PTZ;
49
- }
50
regl = (uint32_t)reg64;
51
kvm_gicr_access(s, GICR_PENDBASER, ncpu, &regl, true);
52
regh = (uint32_t)(reg64 >> 32);
53
--
54
2.20.1
55
56
diff view generated by jsdifflib
Deleted patch
1
From: Andrew Jones <drjones@redhat.com>
2
1
3
Signed-off-by: Andrew Jones <drjones@redhat.com>
4
Message-id: 20200120101023.16030-2-drjones@redhat.com
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
8
target/arm/kvm_arm.h | 46 ++++++++++++++++++++++++++------------------
9
1 file changed, 27 insertions(+), 19 deletions(-)
10
11
diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h
12
index XXXXXXX..XXXXXXX 100644
13
--- a/target/arm/kvm_arm.h
14
+++ b/target/arm/kvm_arm.h
15
@@ -XXX,XX +XXX,XX @@
16
int kvm_arm_vcpu_init(CPUState *cs);
17
18
/**
19
- * kvm_arm_vcpu_finalize
20
+ * kvm_arm_vcpu_finalize:
21
* @cs: CPUState
22
- * @feature: int
23
+ * @feature: feature to finalize
24
*
25
* Finalizes the configuration of the specified VCPU feature by
26
* invoking the KVM_ARM_VCPU_FINALIZE ioctl. Features requiring
27
@@ -XXX,XX +XXX,XX @@ void kvm_arm_register_device(MemoryRegion *mr, uint64_t devid, uint64_t group,
28
int kvm_arm_init_cpreg_list(ARMCPU *cpu);
29
30
/**
31
- * kvm_arm_reg_syncs_via_cpreg_list
32
- * regidx: KVM register index
33
+ * kvm_arm_reg_syncs_via_cpreg_list:
34
+ * @regidx: KVM register index
35
*
36
* Return true if this KVM register should be synchronized via the
37
* cpreg list of arbitrary system registers, false if it is synchronized
38
@@ -XXX,XX +XXX,XX @@ int kvm_arm_init_cpreg_list(ARMCPU *cpu);
39
bool kvm_arm_reg_syncs_via_cpreg_list(uint64_t regidx);
40
41
/**
42
- * kvm_arm_cpreg_level
43
- * regidx: KVM register index
44
+ * kvm_arm_cpreg_level:
45
+ * @regidx: KVM register index
46
*
47
* Return the level of this coprocessor/system register. Return value is
48
* either KVM_PUT_RUNTIME_STATE, KVM_PUT_RESET_STATE, or KVM_PUT_FULL_STATE.
49
@@ -XXX,XX +XXX,XX @@ void kvm_arm_init_serror_injection(CPUState *cs);
50
* @cpu: ARMCPU
51
*
52
* Get VCPU related state from kvm.
53
+ *
54
+ * Returns: 0 if success else < 0 error code
55
*/
56
int kvm_get_vcpu_events(ARMCPU *cpu);
57
58
@@ -XXX,XX +XXX,XX @@ int kvm_get_vcpu_events(ARMCPU *cpu);
59
* @cpu: ARMCPU
60
*
61
* Put VCPU related state to kvm.
62
+ *
63
+ * Returns: 0 if success else < 0 error code
64
*/
65
int kvm_put_vcpu_events(ARMCPU *cpu);
66
67
@@ -XXX,XX +XXX,XX @@ typedef struct ARMHostCPUFeatures {
68
69
/**
70
* kvm_arm_get_host_cpu_features:
71
- * @ahcc: ARMHostCPUClass to fill in
72
+ * @ahcf: ARMHostCPUClass to fill in
73
*
74
* Probe the capabilities of the host kernel's preferred CPU and fill
75
* in the ARMHostCPUClass struct accordingly.
76
+ *
77
+ * Returns true on success and false otherwise.
78
*/
79
bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf);
80
81
@@ -XXX,XX +XXX,XX @@ void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu);
82
bool kvm_arm_aarch32_supported(CPUState *cs);
83
84
/**
85
- * bool kvm_arm_pmu_supported:
86
+ * kvm_arm_pmu_supported:
87
* @cs: CPUState
88
*
89
* Returns: true if the KVM VCPU can enable its PMU
90
@@ -XXX,XX +XXX,XX @@ bool kvm_arm_aarch32_supported(CPUState *cs);
91
bool kvm_arm_pmu_supported(CPUState *cs);
92
93
/**
94
- * bool kvm_arm_sve_supported:
95
+ * kvm_arm_sve_supported:
96
* @cs: CPUState
97
*
98
* Returns true if the KVM VCPU can enable SVE and false otherwise.
99
@@ -XXX,XX +XXX,XX @@ bool kvm_arm_pmu_supported(CPUState *cs);
100
bool kvm_arm_sve_supported(CPUState *cs);
101
102
/**
103
- * kvm_arm_get_max_vm_ipa_size - Returns the number of bits in the
104
- * IPA address space supported by KVM
105
- *
106
+ * kvm_arm_get_max_vm_ipa_size:
107
* @ms: Machine state handle
108
+ *
109
+ * Returns the number of bits in the IPA address space supported by KVM
110
*/
111
int kvm_arm_get_max_vm_ipa_size(MachineState *ms);
112
113
/**
114
- * kvm_arm_sync_mpstate_to_kvm
115
+ * kvm_arm_sync_mpstate_to_kvm:
116
* @cpu: ARMCPU
117
*
118
* If supported set the KVM MP_STATE based on QEMU's model.
119
+ *
120
+ * Returns 0 on success and -1 on failure.
121
*/
122
int kvm_arm_sync_mpstate_to_kvm(ARMCPU *cpu);
123
124
/**
125
- * kvm_arm_sync_mpstate_to_qemu
126
+ * kvm_arm_sync_mpstate_to_qemu:
127
* @cpu: ARMCPU
128
*
129
* If supported get the MP_STATE from KVM and store in QEMU's model.
130
+ *
131
+ * Returns 0 on success and aborts on failure.
132
*/
133
int kvm_arm_sync_mpstate_to_qemu(ARMCPU *cpu);
134
135
@@ -XXX,XX +XXX,XX @@ int kvm_arm_set_irq(int cpu, int irqtype, int irq, int level);
136
137
static inline void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu)
138
{
139
- /* This should never actually be called in the "not KVM" case,
140
+ /*
141
+ * This should never actually be called in the "not KVM" case,
142
* but set up the fields to indicate an error anyway.
143
*/
144
cpu->kvm_target = QEMU_KVM_ARM_TARGET_NONE;
145
@@ -XXX,XX +XXX,XX @@ bool kvm_arm_handle_debug(CPUState *cs, struct kvm_debug_exit_arch *debug_exit);
146
*
147
* Return: TRUE if any hardware breakpoints in use.
148
*/
149
-
150
bool kvm_arm_hw_debug_active(CPUState *cs);
151
152
/**
153
* kvm_arm_copy_hw_debug_data:
154
- *
155
* @ptr: kvm_guest_debug_arch structure
156
*
157
* Copy the architecture specific debug registers into the
158
* kvm_guest_debug ioctl structure.
159
*/
160
struct kvm_guest_debug_arch;
161
-
162
void kvm_arm_copy_hw_debug_data(struct kvm_guest_debug_arch *ptr);
163
164
/**
165
- * its_class_name
166
+ * its_class_name:
167
*
168
* Return the ITS class name to use depending on whether KVM acceleration
169
* and KVM CAP_SIGNAL_MSI are supported
170
--
171
2.20.1
172
173
diff view generated by jsdifflib
Deleted patch
1
From: Andrew Jones <drjones@redhat.com>
2
1
3
Signed-off-by: Andrew Jones <drjones@redhat.com>
4
Message-id: 20200120101023.16030-3-drjones@redhat.com
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
8
hw/arm/virt.c | 1 +
9
1 file changed, 1 insertion(+)
10
11
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/hw/arm/virt.c
14
+++ b/hw/arm/virt.c
15
@@ -XXX,XX +XXX,XX @@ DEFINE_VIRT_MACHINE_AS_LATEST(5, 0)
16
17
static void virt_machine_4_2_options(MachineClass *mc)
18
{
19
+ virt_machine_5_0_options(mc);
20
compat_props_add(mc->compat_props, hw_compat_4_2, hw_compat_4_2_len);
21
}
22
DEFINE_VIRT_MACHINE(4, 2)
23
--
24
2.20.1
25
26
diff view generated by jsdifflib
Deleted patch
1
From: Andrew Jones <drjones@redhat.com>
2
1
3
If we know what the default value should be then we can test for
4
that as well as the feature existence.
5
6
Signed-off-by: Andrew Jones <drjones@redhat.com>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20200120101023.16030-5-drjones@redhat.com
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
tests/qtest/arm-cpu-features.c | 37 +++++++++++++++++++++++++---------
12
1 file changed, 28 insertions(+), 9 deletions(-)
13
14
diff --git a/tests/qtest/arm-cpu-features.c b/tests/qtest/arm-cpu-features.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/tests/qtest/arm-cpu-features.c
17
+++ b/tests/qtest/arm-cpu-features.c
18
@@ -XXX,XX +XXX,XX @@ static bool resp_get_feature(QDict *resp, const char *feature)
19
qobject_unref(_resp); \
20
})
21
22
+#define assert_feature(qts, cpu_type, feature, expected_value) \
23
+({ \
24
+ QDict *_resp, *_props; \
25
+ \
26
+ _resp = do_query_no_props(qts, cpu_type); \
27
+ g_assert(_resp); \
28
+ g_assert(resp_has_props(_resp)); \
29
+ _props = resp_get_props(_resp); \
30
+ g_assert(qdict_get(_props, feature)); \
31
+ g_assert(qdict_get_bool(_props, feature) == (expected_value)); \
32
+ qobject_unref(_resp); \
33
+})
34
+
35
+#define assert_has_feature_enabled(qts, cpu_type, feature) \
36
+ assert_feature(qts, cpu_type, feature, true)
37
+
38
+#define assert_has_feature_disabled(qts, cpu_type, feature) \
39
+ assert_feature(qts, cpu_type, feature, false)
40
+
41
static void assert_type_full(QTestState *qts)
42
{
43
const char *error;
44
@@ -XXX,XX +XXX,XX @@ static void test_query_cpu_model_expansion(const void *data)
45
assert_error(qts, "host", "The CPU type 'host' requires KVM", NULL);
46
47
/* Test expected feature presence/absence for some cpu types */
48
- assert_has_feature(qts, "max", "pmu");
49
- assert_has_feature(qts, "cortex-a15", "pmu");
50
+ assert_has_feature_enabled(qts, "max", "pmu");
51
+ assert_has_feature_enabled(qts, "cortex-a15", "pmu");
52
assert_has_not_feature(qts, "cortex-a15", "aarch64");
53
54
if (g_str_equal(qtest_get_arch(), "aarch64")) {
55
- assert_has_feature(qts, "max", "aarch64");
56
- assert_has_feature(qts, "max", "sve");
57
- assert_has_feature(qts, "max", "sve128");
58
- assert_has_feature(qts, "cortex-a57", "pmu");
59
- assert_has_feature(qts, "cortex-a57", "aarch64");
60
+ assert_has_feature_enabled(qts, "max", "aarch64");
61
+ assert_has_feature_enabled(qts, "max", "sve");
62
+ assert_has_feature_enabled(qts, "max", "sve128");
63
+ assert_has_feature_enabled(qts, "cortex-a57", "pmu");
64
+ assert_has_feature_enabled(qts, "cortex-a57", "aarch64");
65
66
sve_tests_default(qts, "max");
67
68
@@ -XXX,XX +XXX,XX @@ static void test_query_cpu_model_expansion_kvm(const void *data)
69
QDict *resp;
70
char *error;
71
72
- assert_has_feature(qts, "host", "aarch64");
73
- assert_has_feature(qts, "host", "pmu");
74
+ assert_has_feature_enabled(qts, "host", "aarch64");
75
+ assert_has_feature_enabled(qts, "host", "pmu");
76
77
assert_error(qts, "cortex-a15",
78
"We cannot guarantee the CPU type 'cortex-a15' works "
79
--
80
2.20.1
81
82
diff view generated by jsdifflib