1
Last minute pullreq for arm related patches; quite large because
1
Hi; here's the first arm pullreq for 9.1.
2
there were several series that only just made it through code review
2
3
in time.
3
This includes the reset method function signature change, so it has
4
some chance of compile failures due to merge conflicts if some other
5
pullreq added a device reset method and that pullreq got applied
6
before this one. If so, the changes needed to fix those up can be
7
created by running the spatch rune described in the commit message of
8
the "hw, target: Add ResetType argument to hold and exit phase
9
methods" commit.
4
10
5
thanks
11
thanks
6
-- PMM
12
-- PMM
7
13
8
The following changes since commit 091e3e3dbc499d84c004e1c50bc9870af37f6e99:
14
The following changes since commit 5da72194df36535d773c8bdc951529ecd5e31707:
9
15
10
Merge remote-tracking branch 'remotes/ericb/tags/pull-bitmaps-2020-10-26' into staging (2020-10-26 22:36:35 +0000)
16
Merge tag 'pull-tcg-20240424' of https://gitlab.com/rth7680/qemu into staging (2024-04-24 15:51:49 -0700)
11
17
12
are available in the Git repository at:
18
are available in the Git repository at:
13
19
14
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20201027-1
20
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20240425
15
21
16
for you to fetch changes up to 32bd322a0134ed89db00f2b9b3894982db3dedcb:
22
for you to fetch changes up to 214652da123e3821657a64691ee556281e9f6238:
17
23
18
hw/timer/armv7m_systick: Rewrite to use ptimers (2020-10-27 11:15:31 +0000)
24
tests/qtest: Add tests for the STM32L4x5 USART (2024-04-25 10:21:59 +0100)
19
25
20
----------------------------------------------------------------
26
----------------------------------------------------------------
21
target-arm queue:
27
target-arm queue:
22
* raspi: add model of cprman clock manager
28
* Implement FEAT_NMI and NMI support in the GICv3
23
* sbsa-ref: add an SBSA generic watchdog device
29
* hw/dma: avoid apparent overflow in soc_dma_set_request
24
* arm/trace: Fix hex printing
30
* linux-user/flatload.c: Remove unused bFLT shared-library and ZFLAT code
25
* raspi: Add models of Pi 3 model A+, Pi Zero and Pi A+
31
* Add ResetType argument to Resettable hold and exit phase methods
26
* hw/arm/smmuv3: Set the restoration priority of the vSMMUv3 explicitly
32
* Add RESET_TYPE_SNAPSHOT_LOAD ResetType
27
* Nuvoton NPCM7xx: Add USB, RNG, GPIO and watchdog support
33
* Implement STM32L4x5 USART
28
* hw/arm: fix min_cpus for xlnx-versal-virt platform
29
* hw/arm/highbank: Silence warnings about missing fallthrough statements
30
* linux-user: Support Aarch64 BTI
31
* Armv7M systick: fix corner case bugs by rewriting to use ptimer
32
34
33
----------------------------------------------------------------
35
----------------------------------------------------------------
34
Dr. David Alan Gilbert (1):
36
Anastasia Belova (1):
35
arm/trace: Fix hex printing
37
hw/dma: avoid apparent overflow in soc_dma_set_request
36
38
37
Hao Wu (1):
39
Arnaud Minier (5):
38
hw/timer: Adding watchdog for NPCM7XX Timer.
40
hw/char: Implement STM32L4x5 USART skeleton
39
41
hw/char/stm32l4x5_usart: Enable serial read and write
40
Havard Skinnemoen (4):
42
hw/char/stm32l4x5_usart: Add options for serial parameters setting
41
Move npcm7xx_timer_reached_zero call out of npcm7xx_timer_pause
43
hw/arm: Add the USART to the stm32l4x5 SoC
42
hw/misc: Add npcm7xx random number generator
44
tests/qtest: Add tests for the STM32L4x5 USART
43
hw/arm/npcm7xx: Add EHCI and OHCI controllers
45
44
hw/gpio: Add GPIO model for Nuvoton NPCM7xx
46
Jinjie Ruan (22):
45
47
target/arm: Handle HCR_EL2 accesses for bits introduced with FEAT_NMI
46
Luc Michel (14):
48
target/arm: Add PSTATE.ALLINT
47
hw/core/clock: provide the VMSTATE_ARRAY_CLOCK macro
49
target/arm: Add support for FEAT_NMI, Non-maskable Interrupt
48
hw/core/clock: trace clock values in Hz instead of ns
50
target/arm: Implement ALLINT MSR (immediate)
49
hw/arm/raspi: fix CPRMAN base address
51
target/arm: Support MSR access to ALLINT
50
hw/arm/raspi: add a skeleton implementation of the CPRMAN
52
target/arm: Add support for Non-maskable Interrupt
51
hw/misc/bcm2835_cprman: add a PLL skeleton implementation
53
target/arm: Add support for NMI in arm_phys_excp_target_el()
52
hw/misc/bcm2835_cprman: implement PLLs behaviour
54
target/arm: Handle IS/FS in ISR_EL1 for NMI, VINMI and VFNMI
53
hw/misc/bcm2835_cprman: add a PLL channel skeleton implementation
55
target/arm: Handle PSTATE.ALLINT on taking an exception
54
hw/misc/bcm2835_cprman: implement PLL channels behaviour
56
hw/intc/arm_gicv3: Add external IRQ lines for NMI
55
hw/misc/bcm2835_cprman: add a clock mux skeleton implementation
57
hw/arm/virt: Wire NMI and VINMI irq lines from GIC to CPU
56
hw/misc/bcm2835_cprman: implement clock mux behaviour
58
target/arm: Handle NMI in arm_cpu_do_interrupt_aarch64()
57
hw/misc/bcm2835_cprman: add the DSI0HSCK multiplexer
59
hw/intc/arm_gicv3: Add has-nmi property to GICv3 device
58
hw/misc/bcm2835_cprman: add sane reset values to the registers
60
hw/intc/arm_gicv3_kvm: Not set has-nmi=true for the KVM GICv3
59
hw/char/pl011: add a clock input
61
hw/intc/arm_gicv3: Add irq non-maskable property
60
hw/arm/bcm2835_peripherals: connect the UART clock
62
hw/intc/arm_gicv3_redist: Implement GICR_INMIR0
61
63
hw/intc/arm_gicv3: Implement GICD_INMIR
62
Pavel Dovgalyuk (1):
64
hw/intc/arm_gicv3: Implement NMI interrupt priority
63
hw/arm: fix min_cpus for xlnx-versal-virt platform
65
hw/intc/arm_gicv3: Report the NMI interrupt in gicv3_cpuif_update()
64
66
hw/intc/arm_gicv3: Report the VINMI interrupt
65
Peter Maydell (2):
67
target/arm: Add FEAT_NMI to max
66
hw/core/ptimer: Support ptimer being disabled by timer callback
68
hw/arm/virt: Enable NMI support in the GIC if the CPU has FEAT_NMI
67
hw/timer/armv7m_systick: Rewrite to use ptimers
69
68
70
Peter Maydell (9):
69
Philippe Mathieu-Daudé (10):
71
hw/intc/arm_gicv3: Add NMI handling CPU interface registers
70
linux-user/elfload: Avoid leaking interp_name using GLib memory API
72
hw/intc/arm_gicv3: Handle icv_nmiar1_read() for icc_nmiar1_read()
71
hw/arm/bcm2836: Restrict BCM283XInfo declaration to C source
73
linux-user/flatload.c: Remove unused bFLT shared-library and ZFLAT code
72
hw/arm/bcm2836: QOM'ify more by adding class_init() to each SoC type
74
hw/misc: Don't special case RESET_TYPE_COLD in npcm7xx_clk, gcr
73
hw/arm/bcm2836: Introduce BCM283XClass::core_count
75
allwinner-i2c, adm1272: Use device_cold_reset() for software-triggered reset
74
hw/arm/bcm2836: Only provide "enabled-cpus" property to multicore SoCs
76
scripts/coccinelle: New script to add ResetType to hold and exit phases
75
hw/arm/bcm2836: Split out common realize() code
77
hw, target: Add ResetType argument to hold and exit phase methods
76
hw/arm/bcm2836: Introduce the BCM2835 SoC
78
docs/devel/reset: Update to new API for hold and exit phase methods
77
hw/arm/raspi: Add the Raspberry Pi A+ machine
79
reset: Add RESET_TYPE_SNAPSHOT_LOAD
78
hw/arm/raspi: Add the Raspberry Pi Zero machine
80
79
hw/arm/raspi: Add the Raspberry Pi 3 model A+
81
MAINTAINERS | 1 +
80
82
docs/devel/reset.rst | 25 +-
81
Richard Henderson (11):
83
docs/system/arm/b-l475e-iot01a.rst | 2 +-
82
linux-user/aarch64: Reset btype for signals
84
docs/system/arm/emulation.rst | 1 +
83
linux-user: Set PAGE_TARGET_1 for TARGET_PROT_BTI
85
scripts/coccinelle/reset-type.cocci | 133 ++++++++
84
include/elf: Add defines related to GNU property notes for AArch64
86
hw/intc/gicv3_internal.h | 13 +
85
linux-user/elfload: Fix coding style in load_elf_image
87
include/hw/arm/stm32l4x5_soc.h | 7 +
86
linux-user/elfload: Adjust iteration over phdr
88
include/hw/char/stm32l4x5_usart.h | 67 ++++
87
linux-user/elfload: Move PT_INTERP detection to first loop
89
include/hw/intc/arm_gic_common.h | 2 +
88
linux-user/elfload: Use Error for load_elf_image
90
include/hw/intc/arm_gicv3_common.h | 14 +
89
linux-user/elfload: Use Error for load_elf_interp
91
include/hw/resettable.h | 5 +-
90
linux-user/elfload: Parse NT_GNU_PROPERTY_TYPE_0 notes
92
linux-user/flat.h | 5 +-
91
linux-user/elfload: Parse GNU_PROPERTY_AARCH64_FEATURE_1_AND
93
target/arm/cpu-features.h | 5 +
92
tests/tcg/aarch64: Add bti smoke tests
94
target/arm/cpu-qom.h | 5 +-
93
95
target/arm/cpu.h | 9 +
94
Shashi Mallela (2):
96
target/arm/internals.h | 21 ++
95
hw/watchdog: Implement SBSA watchdog device
97
target/arm/tcg/helper-a64.h | 1 +
96
hw/arm/sbsa-ref: add SBSA watchdog device
98
target/arm/tcg/a64.decode | 1 +
97
99
hw/adc/npcm7xx_adc.c | 2 +-
98
Thomas Huth (1):
100
hw/arm/pxa2xx_pic.c | 2 +-
99
hw/arm/highbank: Silence warnings about missing fallthrough statements
101
hw/arm/smmu-common.c | 2 +-
100
102
hw/arm/smmuv3.c | 4 +-
101
Zenghui Yu (1):
103
hw/arm/stellaris.c | 10 +-
102
hw/arm/smmuv3: Set the restoration priority of the vSMMUv3 explicitly
104
hw/arm/stm32l4x5_soc.c | 83 ++++-
103
105
hw/arm/virt.c | 29 +-
104
docs/system/arm/nuvoton.rst | 6 +-
106
hw/audio/asc.c | 2 +-
105
hw/usb/hcd-ehci.h | 1 +
107
hw/char/cadence_uart.c | 2 +-
106
include/elf.h | 22 +
108
hw/char/sifive_uart.c | 2 +-
107
include/exec/cpu-all.h | 2 +
109
hw/char/stm32l4x5_usart.c | 637 ++++++++++++++++++++++++++++++++++++
108
include/hw/arm/bcm2835_peripherals.h | 5 +-
110
hw/core/cpu-common.c | 2 +-
109
include/hw/arm/bcm2836.h | 9 +-
111
hw/core/qdev.c | 4 +-
110
include/hw/arm/npcm7xx.h | 8 +
112
hw/core/reset.c | 17 +-
111
include/hw/arm/raspi_platform.h | 5 +-
113
hw/core/resettable.c | 8 +-
112
include/hw/char/pl011.h | 1 +
114
hw/display/virtio-vga.c | 4 +-
113
include/hw/clock.h | 5 +
115
hw/dma/soc_dma.c | 4 +-
114
include/hw/gpio/npcm7xx_gpio.h | 55 ++
116
hw/gpio/npcm7xx_gpio.c | 2 +-
115
include/hw/misc/bcm2835_cprman.h | 210 ++++++
117
hw/gpio/pl061.c | 2 +-
116
include/hw/misc/bcm2835_cprman_internals.h | 1019 ++++++++++++++++++++++++++++
118
hw/gpio/stm32l4x5_gpio.c | 2 +-
117
include/hw/misc/npcm7xx_clk.h | 2 +
119
hw/hyperv/vmbus.c | 2 +-
118
include/hw/misc/npcm7xx_rng.h | 34 +
120
hw/i2c/allwinner-i2c.c | 5 +-
119
include/hw/timer/armv7m_systick.h | 3 +-
121
hw/i2c/npcm7xx_smbus.c | 2 +-
120
include/hw/timer/npcm7xx_timer.h | 48 +-
122
hw/input/adb.c | 2 +-
121
include/hw/watchdog/sbsa_gwdt.h | 79 +++
123
hw/input/ps2.c | 12 +-
122
linux-user/qemu.h | 4 +
124
hw/intc/arm_gic_common.c | 2 +-
123
linux-user/syscall_defs.h | 4 +
125
hw/intc/arm_gic_kvm.c | 4 +-
124
target/arm/cpu.h | 5 +
126
hw/intc/arm_gicv3.c | 67 +++-
125
hw/arm/bcm2835_peripherals.c | 15 +-
127
hw/intc/arm_gicv3_common.c | 50 ++-
126
hw/arm/bcm2836.c | 182 +++--
128
hw/intc/arm_gicv3_cpuif.c | 268 ++++++++++++++-
127
hw/arm/highbank.c | 2 +
129
hw/intc/arm_gicv3_dist.c | 36 ++
128
hw/arm/npcm7xx.c | 126 +++-
130
hw/intc/arm_gicv3_its.c | 4 +-
129
hw/arm/raspi.c | 41 ++
131
hw/intc/arm_gicv3_its_common.c | 2 +-
130
hw/arm/sbsa-ref.c | 23 +
132
hw/intc/arm_gicv3_its_kvm.c | 4 +-
131
hw/arm/smmuv3.c | 1 +
133
hw/intc/arm_gicv3_kvm.c | 9 +-
132
hw/arm/xlnx-versal-virt.c | 1 +
134
hw/intc/arm_gicv3_redist.c | 22 ++
133
hw/char/pl011.c | 45 ++
135
hw/intc/xics.c | 2 +-
134
hw/core/clock.c | 6 +-
136
hw/m68k/q800-glue.c | 2 +-
135
hw/core/ptimer.c | 4 +
137
hw/misc/djmemc.c | 2 +-
136
hw/gpio/npcm7xx_gpio.c | 424 ++++++++++++
138
hw/misc/iosb.c | 2 +-
137
hw/misc/bcm2835_cprman.c | 808 ++++++++++++++++++++++
139
hw/misc/mac_via.c | 8 +-
138
hw/misc/npcm7xx_clk.c | 28 +
140
hw/misc/macio/cuda.c | 4 +-
139
hw/misc/npcm7xx_rng.c | 180 +++++
141
hw/misc/macio/pmu.c | 4 +-
140
hw/timer/armv7m_systick.c | 124 ++--
142
hw/misc/mos6522.c | 2 +-
141
hw/timer/npcm7xx_timer.c | 270 ++++++--
143
hw/misc/npcm7xx_clk.c | 13 +-
142
hw/usb/hcd-ehci-sysbus.c | 19 +
144
hw/misc/npcm7xx_gcr.c | 12 +-
143
hw/watchdog/sbsa_gwdt.c | 293 ++++++++
145
hw/misc/npcm7xx_mft.c | 2 +-
144
linux-user/aarch64/signal.c | 10 +-
146
hw/misc/npcm7xx_pwm.c | 2 +-
145
linux-user/elfload.c | 326 +++++++--
147
hw/misc/stm32l4x5_exti.c | 2 +-
146
linux-user/mmap.c | 16 +
148
hw/misc/stm32l4x5_rcc.c | 10 +-
147
target/arm/translate-a64.c | 6 +-
149
hw/misc/stm32l4x5_syscfg.c | 2 +-
148
tests/qtest/npcm7xx_gpio-test.c | 385 +++++++++++
150
hw/misc/xlnx-versal-cframe-reg.c | 2 +-
149
tests/qtest/npcm7xx_rng-test.c | 278 ++++++++
151
hw/misc/xlnx-versal-crl.c | 2 +-
150
tests/qtest/npcm7xx_watchdog_timer-test.c | 319 +++++++++
152
hw/misc/xlnx-versal-pmc-iou-slcr.c | 2 +-
151
tests/tcg/aarch64/bti-1.c | 62 ++
153
hw/misc/xlnx-versal-trng.c | 2 +-
152
tests/tcg/aarch64/bti-2.c | 116 ++++
154
hw/misc/xlnx-versal-xramc.c | 2 +-
153
tests/tcg/aarch64/bti-crt.inc.c | 51 ++
155
hw/misc/xlnx-zynqmp-apu-ctrl.c | 2 +-
154
MAINTAINERS | 1 +
156
hw/misc/xlnx-zynqmp-crf.c | 2 +-
155
hw/arm/Kconfig | 1 +
157
hw/misc/zynq_slcr.c | 4 +-
156
hw/arm/trace-events | 2 +-
158
hw/net/can/xlnx-zynqmp-can.c | 2 +-
157
hw/char/trace-events | 1 +
159
hw/net/e1000.c | 2 +-
158
hw/core/trace-events | 4 +-
160
hw/net/e1000e.c | 2 +-
159
hw/gpio/meson.build | 1 +
161
hw/net/igb.c | 2 +-
160
hw/gpio/trace-events | 7 +
162
hw/net/igbvf.c | 2 +-
161
hw/misc/meson.build | 2 +
163
hw/nvram/xlnx-bbram.c | 2 +-
162
hw/misc/trace-events | 9 +
164
hw/nvram/xlnx-versal-efuse-ctrl.c | 2 +-
163
hw/watchdog/Kconfig | 3 +
165
hw/nvram/xlnx-zynqmp-efuse.c | 2 +-
164
hw/watchdog/meson.build | 1 +
166
hw/pci-bridge/cxl_root_port.c | 4 +-
165
tests/qtest/meson.build | 6 +-
167
hw/pci-bridge/pcie_root_port.c | 2 +-
166
tests/tcg/aarch64/Makefile.target | 10 +
168
hw/pci-host/bonito.c | 2 +-
167
tests/tcg/configure.sh | 4 +
169
hw/pci-host/pnv_phb.c | 4 +-
168
64 files changed, 5461 insertions(+), 279 deletions(-)
170
hw/pci-host/pnv_phb3_msi.c | 4 +-
169
create mode 100644 include/hw/gpio/npcm7xx_gpio.h
171
hw/pci/pci.c | 4 +-
170
create mode 100644 include/hw/misc/bcm2835_cprman.h
172
hw/rtc/mc146818rtc.c | 2 +-
171
create mode 100644 include/hw/misc/bcm2835_cprman_internals.h
173
hw/s390x/css-bridge.c | 2 +-
172
create mode 100644 include/hw/misc/npcm7xx_rng.h
174
hw/sensor/adm1266.c | 2 +-
173
create mode 100644 include/hw/watchdog/sbsa_gwdt.h
175
hw/sensor/adm1272.c | 4 +-
174
create mode 100644 hw/gpio/npcm7xx_gpio.c
176
hw/sensor/isl_pmbus_vr.c | 10 +-
175
create mode 100644 hw/misc/bcm2835_cprman.c
177
hw/sensor/max31785.c | 2 +-
176
create mode 100644 hw/misc/npcm7xx_rng.c
178
hw/sensor/max34451.c | 2 +-
177
create mode 100644 hw/watchdog/sbsa_gwdt.c
179
hw/ssi/npcm7xx_fiu.c | 2 +-
178
create mode 100644 tests/qtest/npcm7xx_gpio-test.c
180
hw/timer/etraxfs_timer.c | 2 +-
179
create mode 100644 tests/qtest/npcm7xx_rng-test.c
181
hw/timer/npcm7xx_timer.c | 2 +-
180
create mode 100644 tests/qtest/npcm7xx_watchdog_timer-test.c
182
hw/usb/hcd-dwc2.c | 8 +-
181
create mode 100644 tests/tcg/aarch64/bti-1.c
183
hw/usb/xlnx-versal-usb2-ctrl-regs.c | 2 +-
182
create mode 100644 tests/tcg/aarch64/bti-2.c
184
hw/virtio/virtio-pci.c | 2 +-
183
create mode 100644 tests/tcg/aarch64/bti-crt.inc.c
185
linux-user/flatload.c | 293 +----------------
184
186
target/arm/cpu.c | 151 ++++++++-
187
target/arm/helper.c | 101 +++++-
188
target/arm/tcg/cpu64.c | 1 +
189
target/arm/tcg/helper-a64.c | 16 +-
190
target/arm/tcg/translate-a64.c | 19 ++
191
target/avr/cpu.c | 4 +-
192
target/cris/cpu.c | 4 +-
193
target/hexagon/cpu.c | 4 +-
194
target/i386/cpu.c | 4 +-
195
target/loongarch/cpu.c | 4 +-
196
target/m68k/cpu.c | 4 +-
197
target/microblaze/cpu.c | 4 +-
198
target/mips/cpu.c | 4 +-
199
target/openrisc/cpu.c | 4 +-
200
target/ppc/cpu_init.c | 4 +-
201
target/riscv/cpu.c | 4 +-
202
target/rx/cpu.c | 4 +-
203
target/sh4/cpu.c | 4 +-
204
target/sparc/cpu.c | 4 +-
205
target/tricore/cpu.c | 4 +-
206
target/xtensa/cpu.c | 4 +-
207
tests/qtest/stm32l4x5_usart-test.c | 315 ++++++++++++++++++
208
hw/arm/Kconfig | 1 +
209
hw/char/Kconfig | 3 +
210
hw/char/meson.build | 1 +
211
hw/char/trace-events | 12 +
212
hw/intc/trace-events | 2 +
213
tests/qtest/meson.build | 4 +-
214
133 files changed, 2239 insertions(+), 537 deletions(-)
215
create mode 100644 scripts/coccinelle/reset-type.cocci
216
create mode 100644 include/hw/char/stm32l4x5_usart.h
217
create mode 100644 hw/char/stm32l4x5_usart.c
218
create mode 100644 tests/qtest/stm32l4x5_usart-test.c
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
The kernel sets btype for the signal handler as if for a call.
4
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20201021173749.111103-2-richard.henderson@linaro.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
linux-user/aarch64/signal.c | 10 ++++++++--
11
1 file changed, 8 insertions(+), 2 deletions(-)
12
13
diff --git a/linux-user/aarch64/signal.c b/linux-user/aarch64/signal.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/linux-user/aarch64/signal.c
16
+++ b/linux-user/aarch64/signal.c
17
@@ -XXX,XX +XXX,XX @@ static void target_setup_frame(int usig, struct target_sigaction *ka,
18
+ offsetof(struct target_rt_frame_record, tramp);
19
}
20
env->xregs[0] = usig;
21
- env->xregs[31] = frame_addr;
22
env->xregs[29] = frame_addr + fr_ofs;
23
- env->pc = ka->_sa_handler;
24
env->xregs[30] = return_addr;
25
+ env->xregs[31] = frame_addr;
26
+ env->pc = ka->_sa_handler;
27
+
28
+ /* Invoke the signal handler as if by indirect call. */
29
+ if (cpu_isar_feature(aa64_bti, env_archcpu(env))) {
30
+ env->btype = 2;
31
+ }
32
+
33
if (info) {
34
tswap_siginfo(&frame->info, info);
35
env->xregs[1] = frame_addr + offsetof(struct target_rt_sigframe, info);
36
--
37
2.20.1
38
39
diff view generated by jsdifflib
1
From: Luc Michel <luc@lmichel.fr>
1
From: Jinjie Ruan <ruanjinjie@huawei.com>
2
2
3
A clock mux can be configured to select one of its 10 sources through
3
FEAT_NMI defines another three new bits in HCRX_EL2: TALLINT, HCRX_VINMI and
4
the CM_CTL register. It also embeds yet another clock divider, composed
4
HCRX_VFNMI. When the feature is enabled, allow these bits to be written in
5
of an integer part and a fractional part. The number of bits of each
5
HCRX_EL2.
6
part is mux dependent.
7
6
8
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com>
9
Signed-off-by: Luc Michel <luc@lmichel.fr>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Tested-by: Guenter Roeck <linux@roeck-us.net>
10
Message-id: 20240407081733.3231820-2-ruanjinjie@huawei.com
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
12
---
14
hw/misc/bcm2835_cprman.c | 53 +++++++++++++++++++++++++++++++++++++++-
13
target/arm/cpu-features.h | 5 +++++
15
1 file changed, 52 insertions(+), 1 deletion(-)
14
target/arm/helper.c | 8 +++++++-
15
2 files changed, 12 insertions(+), 1 deletion(-)
16
16
17
diff --git a/hw/misc/bcm2835_cprman.c b/hw/misc/bcm2835_cprman.c
17
diff --git a/target/arm/cpu-features.h b/target/arm/cpu-features.h
18
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/misc/bcm2835_cprman.c
19
--- a/target/arm/cpu-features.h
20
+++ b/hw/misc/bcm2835_cprman.c
20
+++ b/target/arm/cpu-features.h
21
@@ -XXX,XX +XXX,XX @@ static const TypeInfo cprman_pll_channel_info = {
21
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa64_sme(const ARMISARegisters *id)
22
22
return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, SME) != 0;
23
/* clock mux */
23
}
24
24
25
+static bool clock_mux_is_enabled(CprmanClockMuxState *mux)
25
+static inline bool isar_feature_aa64_nmi(const ARMISARegisters *id)
26
+{
26
+{
27
+ return FIELD_EX32(*mux->reg_ctl, CM_CLOCKx_CTL, ENABLE);
27
+ return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, NMI) != 0;
28
+}
28
+}
29
+
29
+
30
static void clock_mux_update(CprmanClockMuxState *mux)
30
static inline bool isar_feature_aa64_tgran4_lpa2(const ARMISARegisters *id)
31
{
31
{
32
- clock_update(mux->out, 0);
32
return FIELD_SEX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN4) >= 1;
33
+ uint64_t freq;
33
diff --git a/target/arm/helper.c b/target/arm/helper.c
34
+ uint32_t div, src = FIELD_EX32(*mux->reg_ctl, CM_CLOCKx_CTL, SRC);
34
index XXXXXXX..XXXXXXX 100644
35
+ bool enabled = clock_mux_is_enabled(mux);
35
--- a/target/arm/helper.c
36
+
36
+++ b/target/arm/helper.c
37
+ *mux->reg_ctl = FIELD_DP32(*mux->reg_ctl, CM_CLOCKx_CTL, BUSY, enabled);
37
@@ -XXX,XX +XXX,XX @@ bool el_is_in_host(CPUARMState *env, int el)
38
+
38
static void hcrx_write(CPUARMState *env, const ARMCPRegInfo *ri,
39
+ if (!enabled) {
39
uint64_t value)
40
+ clock_update(mux->out, 0);
40
{
41
+ return;
41
+ ARMCPU *cpu = env_archcpu(env);
42
uint64_t valid_mask = 0;
43
44
/* FEAT_MOPS adds MSCEn and MCE2 */
45
- if (cpu_isar_feature(aa64_mops, env_archcpu(env))) {
46
+ if (cpu_isar_feature(aa64_mops, cpu)) {
47
valid_mask |= HCRX_MSCEN | HCRX_MCE2;
48
}
49
50
+ /* FEAT_NMI adds TALLINT, VINMI and VFNMI */
51
+ if (cpu_isar_feature(aa64_nmi, cpu)) {
52
+ valid_mask |= HCRX_TALLINT | HCRX_VINMI | HCRX_VFNMI;
42
+ }
53
+ }
43
+
54
+
44
+ freq = clock_get_hz(mux->srcs[src]);
55
/* Clear RES0 bits. */
45
+
56
env->cp15.hcrx_el2 = value & valid_mask;
46
+ if (mux->int_bits == 0 && mux->frac_bits == 0) {
47
+ clock_update_hz(mux->out, freq);
48
+ return;
49
+ }
50
+
51
+ /*
52
+ * The divider has an integer and a fractional part. The size of each part
53
+ * varies with the muxes (int_bits and frac_bits). Both parts are
54
+ * concatenated, with the integer part always starting at bit 12.
55
+ *
56
+ * 31 12 11 0
57
+ * ------------------------------
58
+ * CM_DIV | | int | frac | |
59
+ * ------------------------------
60
+ * <-----> <------>
61
+ * int_bits frac_bits
62
+ */
63
+ div = extract32(*mux->reg_div,
64
+ R_CM_CLOCKx_DIV_FRAC_LENGTH - mux->frac_bits,
65
+ mux->int_bits + mux->frac_bits);
66
+
67
+ if (!div) {
68
+ clock_update(mux->out, 0);
69
+ return;
70
+ }
71
+
72
+ freq = muldiv64(freq, 1 << mux->frac_bits, div);
73
+
74
+ clock_update_hz(mux->out, freq);
75
}
76
77
static void clock_mux_src_update(void *opaque)
78
{
79
CprmanClockMuxState **backref = opaque;
80
CprmanClockMuxState *s = *backref;
81
+ CprmanClockMuxSource src = backref - s->backref;
82
+
83
+ if (FIELD_EX32(*s->reg_ctl, CM_CLOCKx_CTL, SRC) != src) {
84
+ return;
85
+ }
86
87
clock_mux_update(s);
88
}
57
}
89
--
58
--
90
2.20.1
59
2.34.1
91
92
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Jinjie Ruan <ruanjinjie@huawei.com>
2
2
3
Transform the prot bit to a qemu internal page bit, and save
3
When PSTATE.ALLINT is set, an IRQ or FIQ interrupt that is targeted to
4
it in the page tables.
4
ELx, with or without superpriority is masked. As Richard suggested, place
5
ALLINT bit in PSTATE in env->pstate.
5
6
7
In the pseudocode, AArch64.ExceptionReturn() calls SetPSTATEFromPSR(), which
8
treats PSTATE.ALLINT as one of the bits which are reinstated from SPSR to
9
PSTATE regardless of whether this is an illegal exception return or not. So
10
handle PSTATE.ALLINT the same way as PSTATE.DAIF in the illegal_return exit
11
path of the exception_return helper. With the change, exception entry and
12
return are automatically handled.
13
14
Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com>
15
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
16
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
17
Message-id: 20240407081733.3231820-3-ruanjinjie@huawei.com
8
Message-id: 20201021173749.111103-3-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
19
---
11
include/exec/cpu-all.h | 2 ++
20
target/arm/cpu.h | 1 +
12
linux-user/syscall_defs.h | 4 ++++
21
target/arm/tcg/helper-a64.c | 4 ++--
13
target/arm/cpu.h | 5 +++++
22
2 files changed, 3 insertions(+), 2 deletions(-)
14
linux-user/mmap.c | 16 ++++++++++++++++
15
target/arm/translate-a64.c | 6 +++---
16
5 files changed, 30 insertions(+), 3 deletions(-)
17
23
18
diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h
19
index XXXXXXX..XXXXXXX 100644
20
--- a/include/exec/cpu-all.h
21
+++ b/include/exec/cpu-all.h
22
@@ -XXX,XX +XXX,XX @@ extern intptr_t qemu_host_page_mask;
23
/* FIXME: Code that sets/uses this is broken and needs to go away. */
24
#define PAGE_RESERVED 0x0020
25
#endif
26
+/* Target-specific bits that will be used via page_get_flags(). */
27
+#define PAGE_TARGET_1 0x0080
28
29
#if defined(CONFIG_USER_ONLY)
30
void page_dump(FILE *f);
31
diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
32
index XXXXXXX..XXXXXXX 100644
33
--- a/linux-user/syscall_defs.h
34
+++ b/linux-user/syscall_defs.h
35
@@ -XXX,XX +XXX,XX @@ struct target_winsize {
36
#define TARGET_PROT_SEM 0x08
37
#endif
38
39
+#ifdef TARGET_AARCH64
40
+#define TARGET_PROT_BTI 0x10
41
+#endif
42
+
43
/* Common */
44
#define TARGET_MAP_SHARED    0x01        /* Share changes */
45
#define TARGET_MAP_PRIVATE    0x02        /* Changes are private */
46
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
24
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
47
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
48
--- a/target/arm/cpu.h
26
--- a/target/arm/cpu.h
49
+++ b/target/arm/cpu.h
27
+++ b/target/arm/cpu.h
50
@@ -XXX,XX +XXX,XX @@ static inline MemTxAttrs *typecheck_memtxattrs(MemTxAttrs *x)
28
@@ -XXX,XX +XXX,XX @@ void pmu_init(ARMCPU *cpu);
51
#define arm_tlb_bti_gp(x) (typecheck_memtxattrs(x)->target_tlb_bit0)
29
#define PSTATE_D (1U << 9)
52
#define arm_tlb_mte_tagged(x) (typecheck_memtxattrs(x)->target_tlb_bit1)
30
#define PSTATE_BTYPE (3U << 10)
53
31
#define PSTATE_SSBS (1U << 12)
54
+/*
32
+#define PSTATE_ALLINT (1U << 13)
55
+ * AArch64 usage of the PAGE_TARGET_* bits for linux-user.
33
#define PSTATE_IL (1U << 20)
56
+ */
34
#define PSTATE_SS (1U << 21)
57
+#define PAGE_BTI PAGE_TARGET_1
35
#define PSTATE_PAN (1U << 22)
58
+
36
diff --git a/target/arm/tcg/helper-a64.c b/target/arm/tcg/helper-a64.c
59
/*
60
* Naming convention for isar_feature functions:
61
* Functions which test 32-bit ID registers should have _aa32_ in
62
diff --git a/linux-user/mmap.c b/linux-user/mmap.c
63
index XXXXXXX..XXXXXXX 100644
37
index XXXXXXX..XXXXXXX 100644
64
--- a/linux-user/mmap.c
38
--- a/target/arm/tcg/helper-a64.c
65
+++ b/linux-user/mmap.c
39
+++ b/target/arm/tcg/helper-a64.c
66
@@ -XXX,XX +XXX,XX @@ static int validate_prot_to_pageflags(int *host_prot, int prot)
40
@@ -XXX,XX +XXX,XX @@ illegal_return:
67
*host_prot = (prot & (PROT_READ | PROT_WRITE))
41
*/
68
| (prot & PROT_EXEC ? PROT_READ : 0);
42
env->pstate |= PSTATE_IL;
69
43
env->pc = new_pc;
70
+#ifdef TARGET_AARCH64
44
- spsr &= PSTATE_NZCV | PSTATE_DAIF;
71
+ /*
45
- spsr |= pstate_read(env) & ~(PSTATE_NZCV | PSTATE_DAIF);
72
+ * The PROT_BTI bit is only accepted if the cpu supports the feature.
46
+ spsr &= PSTATE_NZCV | PSTATE_DAIF | PSTATE_ALLINT;
73
+ * Since this is the unusual case, don't bother checking unless
47
+ spsr |= pstate_read(env) & ~(PSTATE_NZCV | PSTATE_DAIF | PSTATE_ALLINT);
74
+ * the bit has been requested. If set and valid, record the bit
48
pstate_write(env, spsr);
75
+ * within QEMU's page_flags.
49
if (!arm_singlestep_active(env)) {
76
+ */
50
env->pstate &= ~PSTATE_SS;
77
+ if (prot & TARGET_PROT_BTI) {
78
+ ARMCPU *cpu = ARM_CPU(thread_cpu);
79
+ if (cpu_isar_feature(aa64_bti, cpu)) {
80
+ valid |= TARGET_PROT_BTI;
81
+ page_flags |= PAGE_BTI;
82
+ }
83
+ }
84
+#endif
85
+
86
return prot & ~valid ? 0 : page_flags;
87
}
88
89
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
90
index XXXXXXX..XXXXXXX 100644
91
--- a/target/arm/translate-a64.c
92
+++ b/target/arm/translate-a64.c
93
@@ -XXX,XX +XXX,XX @@ static void disas_data_proc_simd_fp(DisasContext *s, uint32_t insn)
94
*/
95
static bool is_guarded_page(CPUARMState *env, DisasContext *s)
96
{
97
-#ifdef CONFIG_USER_ONLY
98
- return false; /* FIXME */
99
-#else
100
uint64_t addr = s->base.pc_first;
101
+#ifdef CONFIG_USER_ONLY
102
+ return page_get_flags(addr) & PAGE_BTI;
103
+#else
104
int mmu_idx = arm_to_core_mmu_idx(s->mmu_idx);
105
unsigned int index = tlb_index(env, mmu_idx, addr);
106
CPUTLBEntry *entry = tlb_entry(env, mmu_idx, addr);
107
--
51
--
108
2.20.1
52
2.34.1
109
110
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
These are all of the defines required to parse
4
GNU_PROPERTY_AARCH64_FEATURE_1_AND, copied from binutils.
5
Other missing defines related to other GNU program headers
6
and notes are elided for now.
7
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20201021173749.111103-4-richard.henderson@linaro.org
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
13
include/elf.h | 22 ++++++++++++++++++++++
14
1 file changed, 22 insertions(+)
15
16
diff --git a/include/elf.h b/include/elf.h
17
index XXXXXXX..XXXXXXX 100644
18
--- a/include/elf.h
19
+++ b/include/elf.h
20
@@ -XXX,XX +XXX,XX @@ typedef int64_t Elf64_Sxword;
21
#define PT_NOTE 4
22
#define PT_SHLIB 5
23
#define PT_PHDR 6
24
+#define PT_LOOS 0x60000000
25
+#define PT_HIOS 0x6fffffff
26
#define PT_LOPROC 0x70000000
27
#define PT_HIPROC 0x7fffffff
28
29
+#define PT_GNU_PROPERTY (PT_LOOS + 0x474e553)
30
+
31
#define PT_MIPS_REGINFO 0x70000000
32
#define PT_MIPS_RTPROC 0x70000001
33
#define PT_MIPS_OPTIONS 0x70000002
34
@@ -XXX,XX +XXX,XX @@ typedef struct elf64_shdr {
35
#define NT_ARM_SYSTEM_CALL 0x404 /* ARM system call number */
36
#define NT_ARM_SVE 0x405 /* ARM Scalable Vector Extension regs */
37
38
+/* Defined note types for GNU systems. */
39
+
40
+#define NT_GNU_PROPERTY_TYPE_0 5 /* Program property */
41
+
42
+/* Values used in GNU .note.gnu.property notes (NT_GNU_PROPERTY_TYPE_0). */
43
+
44
+#define GNU_PROPERTY_STACK_SIZE 1
45
+#define GNU_PROPERTY_NO_COPY_ON_PROTECTED 2
46
+
47
+#define GNU_PROPERTY_LOPROC 0xc0000000
48
+#define GNU_PROPERTY_HIPROC 0xdfffffff
49
+#define GNU_PROPERTY_LOUSER 0xe0000000
50
+#define GNU_PROPERTY_HIUSER 0xffffffff
51
+
52
+#define GNU_PROPERTY_AARCH64_FEATURE_1_AND 0xc0000000
53
+#define GNU_PROPERTY_AARCH64_FEATURE_1_BTI (1u << 0)
54
+#define GNU_PROPERTY_AARCH64_FEATURE_1_PAC (1u << 1)
55
+
56
/*
57
* Physical entry point into the kernel.
58
*
59
--
60
2.20.1
61
62
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
From: Jinjie Ruan <ruanjinjie@huawei.com>
2
2
3
It makes no sense to set enabled-cpus=0 on single core SoCs.
3
Add support for FEAT_NMI. NMI (FEAT_NMI) is an mandatory feature in
4
ARMv8.8-A and ARM v9.3-A.
4
5
5
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
6
Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com>
6
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20201024170127.3592182-5-f4bug@amsat.org
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Message-id: 20240407081733.3231820-4-ruanjinjie@huawei.com
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
11
---
10
hw/arm/bcm2836.c | 15 +++++++--------
12
target/arm/internals.h | 3 +++
11
1 file changed, 7 insertions(+), 8 deletions(-)
13
1 file changed, 3 insertions(+)
12
14
13
diff --git a/hw/arm/bcm2836.c b/hw/arm/bcm2836.c
15
diff --git a/target/arm/internals.h b/target/arm/internals.h
14
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/arm/bcm2836.c
17
--- a/target/arm/internals.h
16
+++ b/hw/arm/bcm2836.c
18
+++ b/target/arm/internals.h
17
@@ -XXX,XX +XXX,XX @@ typedef struct BCM283XClass {
19
@@ -XXX,XX +XXX,XX @@ static inline uint32_t aarch64_pstate_valid_mask(const ARMISARegisters *id)
18
#define BCM283X_GET_CLASS(obj) \
20
if (isar_feature_aa64_mte(id)) {
19
OBJECT_GET_CLASS(BCM283XClass, (obj), TYPE_BCM283X)
21
valid |= PSTATE_TCO;
20
21
+static Property bcm2836_enabled_cores_property =
22
+ DEFINE_PROP_UINT32("enabled-cpus", BCM283XState, enabled_cpus, 0);
23
+
24
static void bcm2836_init(Object *obj)
25
{
26
BCM283XState *s = BCM283X(obj);
27
@@ -XXX,XX +XXX,XX @@ static void bcm2836_init(Object *obj)
28
object_initialize_child(obj, "cpu[*]", &s->cpu[n].core,
29
bc->cpu_type);
30
}
22
}
31
+ if (bc->core_count > 1) {
23
+ if (isar_feature_aa64_nmi(id)) {
32
+ qdev_property_add_static(DEVICE(obj), &bcm2836_enabled_cores_property);
24
+ valid |= PSTATE_ALLINT;
33
+ qdev_prop_set_uint32(DEVICE(obj), "enabled-cpus", bc->core_count);
34
+ }
25
+ }
35
26
36
object_initialize_child(obj, "control", &s->control, TYPE_BCM2836_CONTROL);
27
return valid;
37
38
@@ -XXX,XX +XXX,XX @@ static void bcm2836_realize(DeviceState *dev, Error **errp)
39
}
40
}
28
}
41
42
-static Property bcm2836_props[] = {
43
- DEFINE_PROP_UINT32("enabled-cpus", BCM283XState, enabled_cpus,
44
- BCM283X_NCPUS),
45
- DEFINE_PROP_END_OF_LIST()
46
-};
47
-
48
static void bcm283x_class_init(ObjectClass *oc, void *data)
49
{
50
DeviceClass *dc = DEVICE_CLASS(oc);
51
@@ -XXX,XX +XXX,XX @@ static void bcm2836_class_init(ObjectClass *oc, void *data)
52
bc->ctrl_base = 0x40000000;
53
bc->clusterid = 0xf;
54
dc->realize = bcm2836_realize;
55
- device_class_set_props(dc, bcm2836_props);
56
};
57
58
#ifdef TARGET_AARCH64
59
@@ -XXX,XX +XXX,XX @@ static void bcm2837_class_init(ObjectClass *oc, void *data)
60
bc->ctrl_base = 0x40000000;
61
bc->clusterid = 0x0;
62
dc->realize = bcm2836_realize;
63
- device_class_set_props(dc, bcm2836_props);
64
};
65
#endif
66
67
--
29
--
68
2.20.1
30
2.34.1
69
70
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
From: Jinjie Ruan <ruanjinjie@huawei.com>
2
2
3
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
3
Add ALLINT MSR (immediate) to decodetree, in which the CRm is 0b000x. The
4
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
4
EL0 check is necessary to ALLINT, and the EL1 check is necessary when
5
Message-id: 20201024170127.3592182-7-f4bug@amsat.org
5
imm == 1. So implement it inline for EL2/3, or EL1 with imm==0. Avoid the
6
unconditional write to pc and use raise_exception_ra to unwind.
7
8
Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Message-id: 20240407081733.3231820-5-ruanjinjie@huawei.com
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
13
---
8
include/hw/arm/bcm2836.h | 1 +
14
target/arm/tcg/helper-a64.h | 1 +
9
hw/arm/bcm2836.c | 34 ++++++++++++++++++++++++++++++++++
15
target/arm/tcg/a64.decode | 1 +
10
hw/arm/raspi.c | 2 ++
16
target/arm/tcg/helper-a64.c | 12 ++++++++++++
11
3 files changed, 37 insertions(+)
17
target/arm/tcg/translate-a64.c | 19 +++++++++++++++++++
18
4 files changed, 33 insertions(+)
12
19
13
diff --git a/include/hw/arm/bcm2836.h b/include/hw/arm/bcm2836.h
20
diff --git a/target/arm/tcg/helper-a64.h b/target/arm/tcg/helper-a64.h
14
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
15
--- a/include/hw/arm/bcm2836.h
22
--- a/target/arm/tcg/helper-a64.h
16
+++ b/include/hw/arm/bcm2836.h
23
+++ b/target/arm/tcg/helper-a64.h
17
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_TYPE(BCM283XState, BCM283XClass, BCM283X)
24
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_1(rbit64, TCG_CALL_NO_RWG_SE, i64, i64)
18
* them, code using these devices should always handle them via the
25
DEF_HELPER_2(msr_i_spsel, void, env, i32)
19
* BCM283x base class, so they have no BCM2836(obj) etc macros.
26
DEF_HELPER_2(msr_i_daifset, void, env, i32)
20
*/
27
DEF_HELPER_2(msr_i_daifclear, void, env, i32)
21
+#define TYPE_BCM2835 "bcm2835"
28
+DEF_HELPER_1(msr_set_allint_el1, void, env)
22
#define TYPE_BCM2836 "bcm2836"
29
DEF_HELPER_3(vfp_cmph_a64, i64, f16, f16, ptr)
23
#define TYPE_BCM2837 "bcm2837"
30
DEF_HELPER_3(vfp_cmpeh_a64, i64, f16, f16, ptr)
24
31
DEF_HELPER_3(vfp_cmps_a64, i64, f32, f32, ptr)
25
diff --git a/hw/arm/bcm2836.c b/hw/arm/bcm2836.c
32
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
26
index XXXXXXX..XXXXXXX 100644
33
index XXXXXXX..XXXXXXX 100644
27
--- a/hw/arm/bcm2836.c
34
--- a/target/arm/tcg/a64.decode
28
+++ b/hw/arm/bcm2836.c
35
+++ b/target/arm/tcg/a64.decode
29
@@ -XXX,XX +XXX,XX @@ static bool bcm283x_common_realize(DeviceState *dev, Error **errp)
36
@@ -XXX,XX +XXX,XX @@ MSR_i_DIT 1101 0101 0000 0 011 0100 .... 010 11111 @msr_i
37
MSR_i_TCO 1101 0101 0000 0 011 0100 .... 100 11111 @msr_i
38
MSR_i_DAIFSET 1101 0101 0000 0 011 0100 .... 110 11111 @msr_i
39
MSR_i_DAIFCLEAR 1101 0101 0000 0 011 0100 .... 111 11111 @msr_i
40
+MSR_i_ALLINT 1101 0101 0000 0 001 0100 000 imm:1 000 11111
41
MSR_i_SVCR 1101 0101 0000 0 011 0100 0 mask:2 imm:1 011 11111
42
43
# MRS, MSR (register), SYS, SYSL. These are all essentially the
44
diff --git a/target/arm/tcg/helper-a64.c b/target/arm/tcg/helper-a64.c
45
index XXXXXXX..XXXXXXX 100644
46
--- a/target/arm/tcg/helper-a64.c
47
+++ b/target/arm/tcg/helper-a64.c
48
@@ -XXX,XX +XXX,XX @@ void HELPER(msr_i_spsel)(CPUARMState *env, uint32_t imm)
49
update_spsel(env, imm);
50
}
51
52
+void HELPER(msr_set_allint_el1)(CPUARMState *env)
53
+{
54
+ /* ALLINT update to PSTATE. */
55
+ if (arm_hcrx_el2_eff(env) & HCRX_TALLINT) {
56
+ raise_exception_ra(env, EXCP_UDEF,
57
+ syn_aa64_sysregtrap(0, 1, 0, 4, 1, 0x1f, 0), 2,
58
+ GETPC());
59
+ }
60
+
61
+ env->pstate |= PSTATE_ALLINT;
62
+}
63
+
64
static void daif_check(CPUARMState *env, uint32_t op,
65
uint32_t imm, uintptr_t ra)
66
{
67
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
68
index XXXXXXX..XXXXXXX 100644
69
--- a/target/arm/tcg/translate-a64.c
70
+++ b/target/arm/tcg/translate-a64.c
71
@@ -XXX,XX +XXX,XX @@ static bool trans_MSR_i_DAIFCLEAR(DisasContext *s, arg_i *a)
30
return true;
72
return true;
31
}
73
}
32
74
33
+static void bcm2835_realize(DeviceState *dev, Error **errp)
75
+static bool trans_MSR_i_ALLINT(DisasContext *s, arg_i *a)
34
+{
76
+{
35
+ BCM283XState *s = BCM283X(dev);
77
+ if (!dc_isar_feature(aa64_nmi, s) || s->current_el == 0) {
36
+
78
+ return false;
37
+ if (!bcm283x_common_realize(dev, errp)) {
38
+ return;
39
+ }
79
+ }
40
+
80
+
41
+ if (!qdev_realize(DEVICE(&s->cpu[0].core), NULL, errp)) {
81
+ if (a->imm == 0) {
42
+ return;
82
+ clear_pstate_bits(PSTATE_ALLINT);
83
+ } else if (s->current_el > 1) {
84
+ set_pstate_bits(PSTATE_ALLINT);
85
+ } else {
86
+ gen_helper_msr_set_allint_el1(tcg_env);
43
+ }
87
+ }
44
+
88
+
45
+ /* Connect irq/fiq outputs from the interrupt controller. */
89
+ /* Exit the cpu loop to re-evaluate pending IRQs. */
46
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->peripherals), 0,
90
+ s->base.is_jmp = DISAS_UPDATE_EXIT;
47
+ qdev_get_gpio_in(DEVICE(&s->cpu[0].core), ARM_CPU_IRQ));
91
+ return true;
48
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->peripherals), 1,
49
+ qdev_get_gpio_in(DEVICE(&s->cpu[0].core), ARM_CPU_FIQ));
50
+}
92
+}
51
+
93
+
52
static void bcm2836_realize(DeviceState *dev, Error **errp)
94
static bool trans_MSR_i_SVCR(DisasContext *s, arg_MSR_i_SVCR *a)
53
{
95
{
54
BCM283XState *s = BCM283X(dev);
96
if (!dc_isar_feature(aa64_sme, s) || a->mask == 0) {
55
@@ -XXX,XX +XXX,XX @@ static void bcm283x_class_init(ObjectClass *oc, void *data)
56
dc->user_creatable = false;
57
}
58
59
+static void bcm2835_class_init(ObjectClass *oc, void *data)
60
+{
61
+ DeviceClass *dc = DEVICE_CLASS(oc);
62
+ BCM283XClass *bc = BCM283X_CLASS(oc);
63
+
64
+ bc->cpu_type = ARM_CPU_TYPE_NAME("arm1176");
65
+ bc->core_count = 1;
66
+ bc->peri_base = 0x20000000;
67
+ dc->realize = bcm2835_realize;
68
+};
69
+
70
static void bcm2836_class_init(ObjectClass *oc, void *data)
71
{
72
DeviceClass *dc = DEVICE_CLASS(oc);
73
@@ -XXX,XX +XXX,XX @@ static void bcm2837_class_init(ObjectClass *oc, void *data)
74
75
static const TypeInfo bcm283x_types[] = {
76
{
77
+ .name = TYPE_BCM2835,
78
+ .parent = TYPE_BCM283X,
79
+ .class_init = bcm2835_class_init,
80
+ }, {
81
.name = TYPE_BCM2836,
82
.parent = TYPE_BCM283X,
83
.class_init = bcm2836_class_init,
84
diff --git a/hw/arm/raspi.c b/hw/arm/raspi.c
85
index XXXXXXX..XXXXXXX 100644
86
--- a/hw/arm/raspi.c
87
+++ b/hw/arm/raspi.c
88
@@ -XXX,XX +XXX,XX @@ FIELD(REV_CODE, MEMORY_SIZE, 20, 3);
89
FIELD(REV_CODE, STYLE, 23, 1);
90
91
typedef enum RaspiProcessorId {
92
+ PROCESSOR_ID_BCM2835 = 0,
93
PROCESSOR_ID_BCM2836 = 1,
94
PROCESSOR_ID_BCM2837 = 2,
95
} RaspiProcessorId;
96
@@ -XXX,XX +XXX,XX @@ static const struct {
97
const char *type;
98
int cores_count;
99
} soc_property[] = {
100
+ [PROCESSOR_ID_BCM2835] = {TYPE_BCM2835, 1},
101
[PROCESSOR_ID_BCM2836] = {TYPE_BCM2836, BCM283X_NCPUS},
102
[PROCESSOR_ID_BCM2837] = {TYPE_BCM2837, BCM283X_NCPUS},
103
};
104
--
97
--
105
2.20.1
98
2.34.1
106
107
diff view generated by jsdifflib
1
From: Luc Michel <luc@lmichel.fr>
1
From: Jinjie Ruan <ruanjinjie@huawei.com>
2
2
3
PLLs are composed of multiple channels. Each channel outputs one clock
3
Support ALLINT msr access as follow:
4
signal. They are modeled as one device taking the PLL generated clock as
4
    mrs <xt>, ALLINT    // read allint
5
input, and outputting a new clock.
5
    msr ALLINT, <xt>    // write allint with imm
6
6
7
A channel shares the CM register with its parent PLL, and has its own
7
Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com>
8
A2W_CTRL register. A write to the CM register will trigger an update of
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
the PLL and all its channels, while a write to an A2W_CTRL channel
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
register will update the required channel only.
10
Message-id: 20240407081733.3231820-6-ruanjinjie@huawei.com
11
12
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
13
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
14
Signed-off-by: Luc Michel <luc@lmichel.fr>
15
Tested-by: Guenter Roeck <linux@roeck-us.net>
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
---
12
---
18
include/hw/misc/bcm2835_cprman.h | 44 ++++++
13
target/arm/helper.c | 35 +++++++++++++++++++++++++++++++++++
19
include/hw/misc/bcm2835_cprman_internals.h | 146 +++++++++++++++++++
14
1 file changed, 35 insertions(+)
20
hw/misc/bcm2835_cprman.c | 155 +++++++++++++++++++--
21
3 files changed, 337 insertions(+), 8 deletions(-)
22
15
23
diff --git a/include/hw/misc/bcm2835_cprman.h b/include/hw/misc/bcm2835_cprman.h
16
diff --git a/target/arm/helper.c b/target/arm/helper.c
24
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
25
--- a/include/hw/misc/bcm2835_cprman.h
18
--- a/target/arm/helper.c
26
+++ b/include/hw/misc/bcm2835_cprman.h
19
+++ b/target/arm/helper.c
27
@@ -XXX,XX +XXX,XX @@ typedef enum CprmanPll {
20
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo rme_mte_reginfo[] = {
28
CPRMAN_NUM_PLL
21
.opc0 = 1, .opc1 = 6, .crn = 7, .crm = 14, .opc2 = 5,
29
} CprmanPll;
22
.access = PL3_W, .type = ARM_CP_NOP },
30
23
};
31
+typedef enum CprmanPllChannel {
32
+ CPRMAN_PLLA_CHANNEL_DSI0 = 0,
33
+ CPRMAN_PLLA_CHANNEL_CORE,
34
+ CPRMAN_PLLA_CHANNEL_PER,
35
+ CPRMAN_PLLA_CHANNEL_CCP2,
36
+
24
+
37
+ CPRMAN_PLLC_CHANNEL_CORE2,
25
+static void aa64_allint_write(CPUARMState *env, const ARMCPRegInfo *ri,
38
+ CPRMAN_PLLC_CHANNEL_CORE1,
26
+ uint64_t value)
39
+ CPRMAN_PLLC_CHANNEL_PER,
40
+ CPRMAN_PLLC_CHANNEL_CORE0,
41
+
42
+ CPRMAN_PLLD_CHANNEL_DSI0,
43
+ CPRMAN_PLLD_CHANNEL_CORE,
44
+ CPRMAN_PLLD_CHANNEL_PER,
45
+ CPRMAN_PLLD_CHANNEL_DSI1,
46
+
47
+ CPRMAN_PLLH_CHANNEL_AUX,
48
+ CPRMAN_PLLH_CHANNEL_RCAL,
49
+ CPRMAN_PLLH_CHANNEL_PIX,
50
+
51
+ CPRMAN_PLLB_CHANNEL_ARM,
52
+
53
+ CPRMAN_NUM_PLL_CHANNEL,
54
+} CprmanPllChannel;
55
+
56
typedef struct CprmanPllState {
57
/*< private >*/
58
DeviceState parent_obj;
59
@@ -XXX,XX +XXX,XX @@ typedef struct CprmanPllState {
60
Clock *out;
61
} CprmanPllState;
62
63
+typedef struct CprmanPllChannelState {
64
+ /*< private >*/
65
+ DeviceState parent_obj;
66
+
67
+ /*< public >*/
68
+ CprmanPllChannel id;
69
+ CprmanPll parent;
70
+
71
+ uint32_t *reg_cm;
72
+ uint32_t hold_mask;
73
+ uint32_t load_mask;
74
+ uint32_t *reg_a2w_ctrl;
75
+ int fixed_divider;
76
+
77
+ Clock *pll_in;
78
+ Clock *out;
79
+} CprmanPllChannelState;
80
+
81
struct BCM2835CprmanState {
82
/*< private >*/
83
SysBusDevice parent_obj;
84
@@ -XXX,XX +XXX,XX @@ struct BCM2835CprmanState {
85
MemoryRegion iomem;
86
87
CprmanPllState plls[CPRMAN_NUM_PLL];
88
+ CprmanPllChannelState channels[CPRMAN_NUM_PLL_CHANNEL];
89
90
uint32_t regs[CPRMAN_NUM_REGS];
91
uint32_t xosc_freq;
92
diff --git a/include/hw/misc/bcm2835_cprman_internals.h b/include/hw/misc/bcm2835_cprman_internals.h
93
index XXXXXXX..XXXXXXX 100644
94
--- a/include/hw/misc/bcm2835_cprman_internals.h
95
+++ b/include/hw/misc/bcm2835_cprman_internals.h
96
@@ -XXX,XX +XXX,XX @@
97
#include "hw/misc/bcm2835_cprman.h"
98
99
#define TYPE_CPRMAN_PLL "bcm2835-cprman-pll"
100
+#define TYPE_CPRMAN_PLL_CHANNEL "bcm2835-cprman-pll-channel"
101
102
DECLARE_INSTANCE_CHECKER(CprmanPllState, CPRMAN_PLL,
103
TYPE_CPRMAN_PLL)
104
+DECLARE_INSTANCE_CHECKER(CprmanPllChannelState, CPRMAN_PLL_CHANNEL,
105
+ TYPE_CPRMAN_PLL_CHANNEL)
106
107
/* Register map */
108
109
@@ -XXX,XX +XXX,XX @@ REG32(A2W_PLLD_FRAC, 0x1240)
110
REG32(A2W_PLLH_FRAC, 0x1260)
111
REG32(A2W_PLLB_FRAC, 0x12e0)
112
113
+/* PLL channels */
114
+REG32(A2W_PLLA_DSI0, 0x1300)
115
+ FIELD(A2W_PLLx_CHANNELy, DIV, 0, 8)
116
+ FIELD(A2W_PLLx_CHANNELy, DISABLE, 8, 1)
117
+REG32(A2W_PLLA_CORE, 0x1400)
118
+REG32(A2W_PLLA_PER, 0x1500)
119
+REG32(A2W_PLLA_CCP2, 0x1600)
120
+
121
+REG32(A2W_PLLC_CORE2, 0x1320)
122
+REG32(A2W_PLLC_CORE1, 0x1420)
123
+REG32(A2W_PLLC_PER, 0x1520)
124
+REG32(A2W_PLLC_CORE0, 0x1620)
125
+
126
+REG32(A2W_PLLD_DSI0, 0x1340)
127
+REG32(A2W_PLLD_CORE, 0x1440)
128
+REG32(A2W_PLLD_PER, 0x1540)
129
+REG32(A2W_PLLD_DSI1, 0x1640)
130
+
131
+REG32(A2W_PLLH_AUX, 0x1360)
132
+REG32(A2W_PLLH_RCAL, 0x1460)
133
+REG32(A2W_PLLH_PIX, 0x1560)
134
+REG32(A2W_PLLH_STS, 0x1660)
135
+
136
+REG32(A2W_PLLB_ARM, 0x13e0)
137
+
138
/* misc registers */
139
REG32(CM_LOCK, 0x114)
140
FIELD(CM_LOCK, FLOCKH, 12, 1)
141
@@ -XXX,XX +XXX,XX @@ static inline void set_pll_init_info(BCM2835CprmanState *s,
142
pll->reg_a2w_frac = &s->regs[PLL_INIT_INFO[id].a2w_frac_offset];
143
}
144
145
+
146
+/* PLL channel init info */
147
+typedef struct PLLChannelInitInfo {
148
+ const char *name;
149
+ CprmanPll parent;
150
+ size_t cm_offset;
151
+ uint32_t cm_hold_mask;
152
+ uint32_t cm_load_mask;
153
+ size_t a2w_ctrl_offset;
154
+ unsigned int fixed_divider;
155
+} PLLChannelInitInfo;
156
+
157
+#define FILL_PLL_CHANNEL_INIT_INFO_common(pll_, channel_) \
158
+ .parent = CPRMAN_ ## pll_, \
159
+ .cm_offset = R_CM_ ## pll_, \
160
+ .cm_load_mask = R_CM_ ## pll_ ## _ ## LOAD ## channel_ ## _MASK, \
161
+ .a2w_ctrl_offset = R_A2W_ ## pll_ ## _ ## channel_
162
+
163
+#define FILL_PLL_CHANNEL_INIT_INFO(pll_, channel_) \
164
+ FILL_PLL_CHANNEL_INIT_INFO_common(pll_, channel_), \
165
+ .cm_hold_mask = R_CM_ ## pll_ ## _ ## HOLD ## channel_ ## _MASK, \
166
+ .fixed_divider = 1
167
+
168
+#define FILL_PLL_CHANNEL_INIT_INFO_nohold(pll_, channel_) \
169
+ FILL_PLL_CHANNEL_INIT_INFO_common(pll_, channel_), \
170
+ .cm_hold_mask = 0
171
+
172
+static PLLChannelInitInfo PLL_CHANNEL_INIT_INFO[] = {
173
+ [CPRMAN_PLLA_CHANNEL_DSI0] = {
174
+ .name = "plla-dsi0",
175
+ FILL_PLL_CHANNEL_INIT_INFO(PLLA, DSI0),
176
+ },
177
+ [CPRMAN_PLLA_CHANNEL_CORE] = {
178
+ .name = "plla-core",
179
+ FILL_PLL_CHANNEL_INIT_INFO(PLLA, CORE),
180
+ },
181
+ [CPRMAN_PLLA_CHANNEL_PER] = {
182
+ .name = "plla-per",
183
+ FILL_PLL_CHANNEL_INIT_INFO(PLLA, PER),
184
+ },
185
+ [CPRMAN_PLLA_CHANNEL_CCP2] = {
186
+ .name = "plla-ccp2",
187
+ FILL_PLL_CHANNEL_INIT_INFO(PLLA, CCP2),
188
+ },
189
+
190
+ [CPRMAN_PLLC_CHANNEL_CORE2] = {
191
+ .name = "pllc-core2",
192
+ FILL_PLL_CHANNEL_INIT_INFO(PLLC, CORE2),
193
+ },
194
+ [CPRMAN_PLLC_CHANNEL_CORE1] = {
195
+ .name = "pllc-core1",
196
+ FILL_PLL_CHANNEL_INIT_INFO(PLLC, CORE1),
197
+ },
198
+ [CPRMAN_PLLC_CHANNEL_PER] = {
199
+ .name = "pllc-per",
200
+ FILL_PLL_CHANNEL_INIT_INFO(PLLC, PER),
201
+ },
202
+ [CPRMAN_PLLC_CHANNEL_CORE0] = {
203
+ .name = "pllc-core0",
204
+ FILL_PLL_CHANNEL_INIT_INFO(PLLC, CORE0),
205
+ },
206
+
207
+ [CPRMAN_PLLD_CHANNEL_DSI0] = {
208
+ .name = "plld-dsi0",
209
+ FILL_PLL_CHANNEL_INIT_INFO(PLLD, DSI0),
210
+ },
211
+ [CPRMAN_PLLD_CHANNEL_CORE] = {
212
+ .name = "plld-core",
213
+ FILL_PLL_CHANNEL_INIT_INFO(PLLD, CORE),
214
+ },
215
+ [CPRMAN_PLLD_CHANNEL_PER] = {
216
+ .name = "plld-per",
217
+ FILL_PLL_CHANNEL_INIT_INFO(PLLD, PER),
218
+ },
219
+ [CPRMAN_PLLD_CHANNEL_DSI1] = {
220
+ .name = "plld-dsi1",
221
+ FILL_PLL_CHANNEL_INIT_INFO(PLLD, DSI1),
222
+ },
223
+
224
+ [CPRMAN_PLLH_CHANNEL_AUX] = {
225
+ .name = "pllh-aux",
226
+ .fixed_divider = 1,
227
+ FILL_PLL_CHANNEL_INIT_INFO_nohold(PLLH, AUX),
228
+ },
229
+ [CPRMAN_PLLH_CHANNEL_RCAL] = {
230
+ .name = "pllh-rcal",
231
+ .fixed_divider = 10,
232
+ FILL_PLL_CHANNEL_INIT_INFO_nohold(PLLH, RCAL),
233
+ },
234
+ [CPRMAN_PLLH_CHANNEL_PIX] = {
235
+ .name = "pllh-pix",
236
+ .fixed_divider = 10,
237
+ FILL_PLL_CHANNEL_INIT_INFO_nohold(PLLH, PIX),
238
+ },
239
+
240
+ [CPRMAN_PLLB_CHANNEL_ARM] = {
241
+ .name = "pllb-arm",
242
+ FILL_PLL_CHANNEL_INIT_INFO(PLLB, ARM),
243
+ },
244
+};
245
+
246
+#undef FILL_PLL_CHANNEL_INIT_INFO_nohold
247
+#undef FILL_PLL_CHANNEL_INIT_INFO
248
+#undef FILL_PLL_CHANNEL_INIT_INFO_common
249
+
250
+static inline void set_pll_channel_init_info(BCM2835CprmanState *s,
251
+ CprmanPllChannelState *channel,
252
+ CprmanPllChannel id)
253
+{
27
+{
254
+ channel->id = id;
28
+ env->pstate = (env->pstate & ~PSTATE_ALLINT) | (value & PSTATE_ALLINT);
255
+ channel->parent = PLL_CHANNEL_INIT_INFO[id].parent;
256
+ channel->reg_cm = &s->regs[PLL_CHANNEL_INIT_INFO[id].cm_offset];
257
+ channel->hold_mask = PLL_CHANNEL_INIT_INFO[id].cm_hold_mask;
258
+ channel->load_mask = PLL_CHANNEL_INIT_INFO[id].cm_load_mask;
259
+ channel->reg_a2w_ctrl = &s->regs[PLL_CHANNEL_INIT_INFO[id].a2w_ctrl_offset];
260
+ channel->fixed_divider = PLL_CHANNEL_INIT_INFO[id].fixed_divider;
261
+}
29
+}
262
+
30
+
263
#endif
31
+static uint64_t aa64_allint_read(CPUARMState *env, const ARMCPRegInfo *ri)
264
diff --git a/hw/misc/bcm2835_cprman.c b/hw/misc/bcm2835_cprman.c
265
index XXXXXXX..XXXXXXX 100644
266
--- a/hw/misc/bcm2835_cprman.c
267
+++ b/hw/misc/bcm2835_cprman.c
268
@@ -XXX,XX +XXX,XX @@ static const TypeInfo cprman_pll_info = {
269
};
270
271
272
+/* PLL channel */
273
+
274
+static void pll_channel_update(CprmanPllChannelState *channel)
275
+{
32
+{
276
+ clock_update(channel->out, 0);
33
+ return env->pstate & PSTATE_ALLINT;
277
+}
34
+}
278
+
35
+
279
+/* Update a PLL and all its channels */
36
+static CPAccessResult aa64_allint_access(CPUARMState *env,
280
+static void pll_update_all_channels(BCM2835CprmanState *s,
37
+ const ARMCPRegInfo *ri, bool isread)
281
+ CprmanPllState *pll)
282
+{
38
+{
283
+ size_t i;
39
+ if (!isread && arm_current_el(env) == 1 &&
284
+
40
+ (arm_hcrx_el2_eff(env) & HCRX_TALLINT)) {
285
+ pll_update(pll);
41
+ return CP_ACCESS_TRAP_EL2;
286
+
287
+ for (i = 0; i < CPRMAN_NUM_PLL_CHANNEL; i++) {
288
+ CprmanPllChannelState *channel = &s->channels[i];
289
+ if (channel->parent == pll->id) {
290
+ pll_channel_update(channel);
291
+ }
292
+ }
42
+ }
43
+ return CP_ACCESS_OK;
293
+}
44
+}
294
+
45
+
295
+static void pll_channel_pll_in_update(void *opaque)
46
+static const ARMCPRegInfo nmi_reginfo[] = {
296
+{
47
+ { .name = "ALLINT", .state = ARM_CP_STATE_AA64,
297
+ pll_channel_update(CPRMAN_PLL_CHANNEL(opaque));
48
+ .opc0 = 3, .opc1 = 0, .opc2 = 0, .crn = 4, .crm = 3,
298
+}
49
+ .type = ARM_CP_NO_RAW,
299
+
50
+ .access = PL1_RW, .accessfn = aa64_allint_access,
300
+static void pll_channel_init(Object *obj)
51
+ .fieldoffset = offsetof(CPUARMState, pstate),
301
+{
52
+ .writefn = aa64_allint_write, .readfn = aa64_allint_read,
302
+ CprmanPllChannelState *s = CPRMAN_PLL_CHANNEL(obj);
53
+ .resetfn = arm_cp_reset_ignore },
303
+
304
+ s->pll_in = qdev_init_clock_in(DEVICE(s), "pll-in",
305
+ pll_channel_pll_in_update, s);
306
+ s->out = qdev_init_clock_out(DEVICE(s), "out");
307
+}
308
+
309
+static const VMStateDescription pll_channel_vmstate = {
310
+ .name = TYPE_CPRMAN_PLL_CHANNEL,
311
+ .version_id = 1,
312
+ .minimum_version_id = 1,
313
+ .fields = (VMStateField[]) {
314
+ VMSTATE_CLOCK(pll_in, CprmanPllChannelState),
315
+ VMSTATE_END_OF_LIST()
316
+ }
317
+};
54
+};
318
+
55
#endif /* TARGET_AARCH64 */
319
+static void pll_channel_class_init(ObjectClass *klass, void *data)
56
320
+{
57
static void define_pmu_regs(ARMCPU *cpu)
321
+ DeviceClass *dc = DEVICE_CLASS(klass);
58
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
322
+
59
if (cpu_isar_feature(aa64_nv2, cpu)) {
323
+ dc->vmsd = &pll_channel_vmstate;
60
define_arm_cp_regs(cpu, nv2_reginfo);
324
+}
325
+
326
+static const TypeInfo cprman_pll_channel_info = {
327
+ .name = TYPE_CPRMAN_PLL_CHANNEL,
328
+ .parent = TYPE_DEVICE,
329
+ .instance_size = sizeof(CprmanPllChannelState),
330
+ .class_init = pll_channel_class_init,
331
+ .instance_init = pll_channel_init,
332
+};
333
+
334
+
335
/* CPRMAN "top level" model */
336
337
static uint32_t get_cm_lock(const BCM2835CprmanState *s)
338
@@ -XXX,XX +XXX,XX @@ static uint64_t cprman_read(void *opaque, hwaddr offset,
339
return r;
340
}
341
342
-#define CASE_PLL_REGS(pll_) \
343
- case R_CM_ ## pll_: \
344
+static inline void update_pll_and_channels_from_cm(BCM2835CprmanState *s,
345
+ size_t idx)
346
+{
347
+ size_t i;
348
+
349
+ for (i = 0; i < CPRMAN_NUM_PLL; i++) {
350
+ if (PLL_INIT_INFO[i].cm_offset == idx) {
351
+ pll_update_all_channels(s, &s->plls[i]);
352
+ return;
353
+ }
354
+ }
355
+}
356
+
357
+static inline void update_channel_from_a2w(BCM2835CprmanState *s, size_t idx)
358
+{
359
+ size_t i;
360
+
361
+ for (i = 0; i < CPRMAN_NUM_PLL_CHANNEL; i++) {
362
+ if (PLL_CHANNEL_INIT_INFO[i].a2w_ctrl_offset == idx) {
363
+ pll_channel_update(&s->channels[i]);
364
+ return;
365
+ }
366
+ }
367
+}
368
+
369
+#define CASE_PLL_A2W_REGS(pll_) \
370
case R_A2W_ ## pll_ ## _CTRL: \
371
case R_A2W_ ## pll_ ## _ANA0: \
372
case R_A2W_ ## pll_ ## _ANA1: \
373
@@ -XXX,XX +XXX,XX @@ static void cprman_write(void *opaque, hwaddr offset,
374
s->regs[idx] = value;
375
376
switch (idx) {
377
- CASE_PLL_REGS(PLLA) :
378
+ case R_CM_PLLA ... R_CM_PLLH:
379
+ case R_CM_PLLB:
380
+ /*
381
+ * A given CM_PLLx register is shared by both the PLL and the channels
382
+ * of this PLL.
383
+ */
384
+ update_pll_and_channels_from_cm(s, idx);
385
+ break;
386
+
387
+ CASE_PLL_A2W_REGS(PLLA) :
388
pll_update(&s->plls[CPRMAN_PLLA]);
389
break;
390
391
- CASE_PLL_REGS(PLLC) :
392
+ CASE_PLL_A2W_REGS(PLLC) :
393
pll_update(&s->plls[CPRMAN_PLLC]);
394
break;
395
396
- CASE_PLL_REGS(PLLD) :
397
+ CASE_PLL_A2W_REGS(PLLD) :
398
pll_update(&s->plls[CPRMAN_PLLD]);
399
break;
400
401
- CASE_PLL_REGS(PLLH) :
402
+ CASE_PLL_A2W_REGS(PLLH) :
403
pll_update(&s->plls[CPRMAN_PLLH]);
404
break;
405
406
- CASE_PLL_REGS(PLLB) :
407
+ CASE_PLL_A2W_REGS(PLLB) :
408
pll_update(&s->plls[CPRMAN_PLLB]);
409
break;
410
+
411
+ case R_A2W_PLLA_DSI0:
412
+ case R_A2W_PLLA_CORE:
413
+ case R_A2W_PLLA_PER:
414
+ case R_A2W_PLLA_CCP2:
415
+ case R_A2W_PLLC_CORE2:
416
+ case R_A2W_PLLC_CORE1:
417
+ case R_A2W_PLLC_PER:
418
+ case R_A2W_PLLC_CORE0:
419
+ case R_A2W_PLLD_DSI0:
420
+ case R_A2W_PLLD_CORE:
421
+ case R_A2W_PLLD_PER:
422
+ case R_A2W_PLLD_DSI1:
423
+ case R_A2W_PLLH_AUX:
424
+ case R_A2W_PLLH_RCAL:
425
+ case R_A2W_PLLH_PIX:
426
+ case R_A2W_PLLB_ARM:
427
+ update_channel_from_a2w(s, idx);
428
+ break;
429
}
430
}
431
432
-#undef CASE_PLL_REGS
433
+#undef CASE_PLL_A2W_REGS
434
435
static const MemoryRegionOps cprman_ops = {
436
.read = cprman_read,
437
@@ -XXX,XX +XXX,XX @@ static void cprman_reset(DeviceState *dev)
438
device_cold_reset(DEVICE(&s->plls[i]));
439
}
440
441
+ for (i = 0; i < CPRMAN_NUM_PLL_CHANNEL; i++) {
442
+ device_cold_reset(DEVICE(&s->channels[i]));
443
+ }
444
+
445
clock_update_hz(s->xosc, s->xosc_freq);
446
}
447
448
@@ -XXX,XX +XXX,XX @@ static void cprman_init(Object *obj)
449
set_pll_init_info(s, &s->plls[i], i);
450
}
451
452
+ for (i = 0; i < CPRMAN_NUM_PLL_CHANNEL; i++) {
453
+ object_initialize_child(obj, PLL_CHANNEL_INIT_INFO[i].name,
454
+ &s->channels[i],
455
+ TYPE_CPRMAN_PLL_CHANNEL);
456
+ set_pll_channel_init_info(s, &s->channels[i], i);
457
+ }
458
+
459
s->xosc = clock_new(obj, "xosc");
460
461
memory_region_init_io(&s->iomem, obj, &cprman_ops,
462
@@ -XXX,XX +XXX,XX @@ static void cprman_realize(DeviceState *dev, Error **errp)
463
return;
464
}
465
}
61
}
466
+
62
+
467
+ for (i = 0; i < CPRMAN_NUM_PLL_CHANNEL; i++) {
63
+ if (cpu_isar_feature(aa64_nmi, cpu)) {
468
+ CprmanPllChannelState *channel = &s->channels[i];
64
+ define_arm_cp_regs(cpu, nmi_reginfo);
469
+ CprmanPll parent = PLL_CHANNEL_INIT_INFO[i].parent;
470
+ Clock *parent_clk = s->plls[parent].out;
471
+
472
+ clock_set_source(channel->pll_in, parent_clk);
473
+
474
+ if (!qdev_realize(DEVICE(channel), NULL, errp)) {
475
+ return;
476
+ }
477
+ }
65
+ }
478
}
66
#endif
479
67
480
static const VMStateDescription cprman_vmstate = {
68
if (cpu_isar_feature(any_predinv, cpu)) {
481
@@ -XXX,XX +XXX,XX @@ static void cprman_register_types(void)
482
{
483
type_register_static(&cprman_info);
484
type_register_static(&cprman_pll_info);
485
+ type_register_static(&cprman_pll_channel_info);
486
}
487
488
type_init(cprman_register_types);
489
--
69
--
490
2.20.1
70
2.34.1
491
492
diff view generated by jsdifflib
1
From: Luc Michel <luc@lmichel.fr>
1
From: Jinjie Ruan <ruanjinjie@huawei.com>
2
2
3
The clock multiplexers are the last clock stage in the CPRMAN. Each mux
3
This only implements the external delivery method via the GICv3.
4
outputs one clock signal that goes out of the CPRMAN to the SoC
5
peripherals.
6
4
7
Each mux has at most 10 sources. The sources 0 to 3 are common to all
5
Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com>
8
muxes. They are:
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
0. ground (no clock signal)
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
1. the main oscillator (xosc)
8
Message-id: 20240407081733.3231820-7-ruanjinjie@huawei.com
11
2. "test debug 0" clock
12
3. "test debug 1" clock
13
14
Test debug 0 and 1 are actual clock muxes that can be used as sources to
15
other muxes (for debug purpose).
16
17
Sources 4 to 9 are mux specific and can be unpopulated (grounded). Those
18
sources are fed by the PLL channels outputs.
19
20
One corner case exists for DSI0E and DSI0P muxes. They have their source
21
number 4 connected to an intermediate multiplexer that can select
22
between PLLA-DSI0 and PLLD-DSI0 channel. This multiplexer is called
23
DSI0HSCK and is not a clock mux as such. It is really a simple mux from
24
the hardware point of view (see https://elinux.org/The_Undocumented_Pi).
25
This mux is not implemented in this commit.
26
27
Note that there is some muxes for which sources are unknown (because of
28
a lack of documentation). For those cases all the sources are connected
29
to ground in this implementation.
30
31
Each clock mux output is exported by the CPRMAN at the qdev level,
32
adding the suffix '-out' to the mux name to form the output clock name.
33
(E.g. the 'uart' mux sees its output exported as 'uart-out' at the
34
CPRMAN level.)
35
36
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
37
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
38
Signed-off-by: Luc Michel <luc@lmichel.fr>
39
Tested-by: Guenter Roeck <linux@roeck-us.net>
40
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
41
---
10
---
42
include/hw/misc/bcm2835_cprman.h | 85 +++++
11
target/arm/cpu-qom.h | 5 +-
43
include/hw/misc/bcm2835_cprman_internals.h | 422 +++++++++++++++++++++
12
target/arm/cpu.h | 6 ++
44
hw/misc/bcm2835_cprman.c | 151 ++++++++
13
target/arm/internals.h | 18 +++++
45
3 files changed, 658 insertions(+)
14
target/arm/cpu.c | 147 ++++++++++++++++++++++++++++++++++++++---
15
target/arm/helper.c | 33 +++++++--
16
5 files changed, 193 insertions(+), 16 deletions(-)
46
17
47
diff --git a/include/hw/misc/bcm2835_cprman.h b/include/hw/misc/bcm2835_cprman.h
18
diff --git a/target/arm/cpu-qom.h b/target/arm/cpu-qom.h
48
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
49
--- a/include/hw/misc/bcm2835_cprman.h
20
--- a/target/arm/cpu-qom.h
50
+++ b/include/hw/misc/bcm2835_cprman.h
21
+++ b/target/arm/cpu-qom.h
51
@@ -XXX,XX +XXX,XX @@ typedef enum CprmanPllChannel {
22
@@ -XXX,XX +XXX,XX @@ DECLARE_CLASS_CHECKERS(AArch64CPUClass, AARCH64_CPU,
52
CPRMAN_PLLB_CHANNEL_ARM,
23
#define ARM_CPU_TYPE_SUFFIX "-" TYPE_ARM_CPU
53
24
#define ARM_CPU_TYPE_NAME(name) (name ARM_CPU_TYPE_SUFFIX)
54
CPRMAN_NUM_PLL_CHANNEL,
25
55
+
26
-/* Meanings of the ARMCPU object's four inbound GPIO lines */
56
+ /* Special values used when connecting clock sources to clocks */
27
+/* Meanings of the ARMCPU object's seven inbound GPIO lines */
57
+ CPRMAN_CLOCK_SRC_NORMAL = -1,
28
#define ARM_CPU_IRQ 0
58
+ CPRMAN_CLOCK_SRC_FORCE_GROUND = -2,
29
#define ARM_CPU_FIQ 1
59
+ CPRMAN_CLOCK_SRC_DSI0HSCK = -3,
30
#define ARM_CPU_VIRQ 2
60
} CprmanPllChannel;
31
#define ARM_CPU_VFIQ 3
61
32
+#define ARM_CPU_NMI 4
62
+typedef enum CprmanClockMux {
33
+#define ARM_CPU_VINMI 5
63
+ CPRMAN_CLOCK_GNRIC,
34
+#define ARM_CPU_VFNMI 6
64
+ CPRMAN_CLOCK_VPU,
35
65
+ CPRMAN_CLOCK_SYS,
36
/* For M profile, some registers are banked secure vs non-secure;
66
+ CPRMAN_CLOCK_PERIA,
37
* these are represented as a 2-element array where the first element
67
+ CPRMAN_CLOCK_PERII,
38
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
68
+ CPRMAN_CLOCK_H264,
69
+ CPRMAN_CLOCK_ISP,
70
+ CPRMAN_CLOCK_V3D,
71
+ CPRMAN_CLOCK_CAM0,
72
+ CPRMAN_CLOCK_CAM1,
73
+ CPRMAN_CLOCK_CCP2,
74
+ CPRMAN_CLOCK_DSI0E,
75
+ CPRMAN_CLOCK_DSI0P,
76
+ CPRMAN_CLOCK_DPI,
77
+ CPRMAN_CLOCK_GP0,
78
+ CPRMAN_CLOCK_GP1,
79
+ CPRMAN_CLOCK_GP2,
80
+ CPRMAN_CLOCK_HSM,
81
+ CPRMAN_CLOCK_OTP,
82
+ CPRMAN_CLOCK_PCM,
83
+ CPRMAN_CLOCK_PWM,
84
+ CPRMAN_CLOCK_SLIM,
85
+ CPRMAN_CLOCK_SMI,
86
+ CPRMAN_CLOCK_TEC,
87
+ CPRMAN_CLOCK_TD0,
88
+ CPRMAN_CLOCK_TD1,
89
+ CPRMAN_CLOCK_TSENS,
90
+ CPRMAN_CLOCK_TIMER,
91
+ CPRMAN_CLOCK_UART,
92
+ CPRMAN_CLOCK_VEC,
93
+ CPRMAN_CLOCK_PULSE,
94
+ CPRMAN_CLOCK_SDC,
95
+ CPRMAN_CLOCK_ARM,
96
+ CPRMAN_CLOCK_AVEO,
97
+ CPRMAN_CLOCK_EMMC,
98
+ CPRMAN_CLOCK_EMMC2,
99
+
100
+ CPRMAN_NUM_CLOCK_MUX
101
+} CprmanClockMux;
102
+
103
+typedef enum CprmanClockMuxSource {
104
+ CPRMAN_CLOCK_SRC_GND = 0,
105
+ CPRMAN_CLOCK_SRC_XOSC,
106
+ CPRMAN_CLOCK_SRC_TD0,
107
+ CPRMAN_CLOCK_SRC_TD1,
108
+ CPRMAN_CLOCK_SRC_PLLA,
109
+ CPRMAN_CLOCK_SRC_PLLC,
110
+ CPRMAN_CLOCK_SRC_PLLD,
111
+ CPRMAN_CLOCK_SRC_PLLH,
112
+ CPRMAN_CLOCK_SRC_PLLC_CORE1,
113
+ CPRMAN_CLOCK_SRC_PLLC_CORE2,
114
+
115
+ CPRMAN_NUM_CLOCK_MUX_SRC
116
+} CprmanClockMuxSource;
117
+
118
typedef struct CprmanPllState {
119
/*< private >*/
120
DeviceState parent_obj;
121
@@ -XXX,XX +XXX,XX @@ typedef struct CprmanPllChannelState {
122
Clock *out;
123
} CprmanPllChannelState;
124
125
+typedef struct CprmanClockMuxState {
126
+ /*< private >*/
127
+ DeviceState parent_obj;
128
+
129
+ /*< public >*/
130
+ CprmanClockMux id;
131
+
132
+ uint32_t *reg_ctl;
133
+ uint32_t *reg_div;
134
+ int int_bits;
135
+ int frac_bits;
136
+
137
+ Clock *srcs[CPRMAN_NUM_CLOCK_MUX_SRC];
138
+ Clock *out;
139
+
140
+ /*
141
+ * Used by clock srcs update callback to retrieve both the clock and the
142
+ * source number.
143
+ */
144
+ struct CprmanClockMuxState *backref[CPRMAN_NUM_CLOCK_MUX_SRC];
145
+} CprmanClockMuxState;
146
+
147
struct BCM2835CprmanState {
148
/*< private >*/
149
SysBusDevice parent_obj;
150
@@ -XXX,XX +XXX,XX @@ struct BCM2835CprmanState {
151
152
CprmanPllState plls[CPRMAN_NUM_PLL];
153
CprmanPllChannelState channels[CPRMAN_NUM_PLL_CHANNEL];
154
+ CprmanClockMuxState clock_muxes[CPRMAN_NUM_CLOCK_MUX];
155
156
uint32_t regs[CPRMAN_NUM_REGS];
157
uint32_t xosc_freq;
158
159
Clock *xosc;
160
+ Clock *gnd;
161
};
162
163
#endif
164
diff --git a/include/hw/misc/bcm2835_cprman_internals.h b/include/hw/misc/bcm2835_cprman_internals.h
165
index XXXXXXX..XXXXXXX 100644
39
index XXXXXXX..XXXXXXX 100644
166
--- a/include/hw/misc/bcm2835_cprman_internals.h
40
--- a/target/arm/cpu.h
167
+++ b/include/hw/misc/bcm2835_cprman_internals.h
41
+++ b/target/arm/cpu.h
168
@@ -XXX,XX +XXX,XX @@
42
@@ -XXX,XX +XXX,XX @@
169
43
#define EXCP_DIVBYZERO 23 /* v7M DIVBYZERO UsageFault */
170
#define TYPE_CPRMAN_PLL "bcm2835-cprman-pll"
44
#define EXCP_VSERR 24
171
#define TYPE_CPRMAN_PLL_CHANNEL "bcm2835-cprman-pll-channel"
45
#define EXCP_GPC 25 /* v9 Granule Protection Check Fault */
172
+#define TYPE_CPRMAN_CLOCK_MUX "bcm2835-cprman-clock-mux"
46
+#define EXCP_NMI 26
173
47
+#define EXCP_VINMI 27
174
DECLARE_INSTANCE_CHECKER(CprmanPllState, CPRMAN_PLL,
48
+#define EXCP_VFNMI 28
175
TYPE_CPRMAN_PLL)
49
/* NB: add new EXCP_ defines to the array in arm_log_exception() too */
176
DECLARE_INSTANCE_CHECKER(CprmanPllChannelState, CPRMAN_PLL_CHANNEL,
50
177
TYPE_CPRMAN_PLL_CHANNEL)
51
#define ARMV7M_EXCP_RESET 1
178
+DECLARE_INSTANCE_CHECKER(CprmanClockMuxState, CPRMAN_CLOCK_MUX,
52
@@ -XXX,XX +XXX,XX @@
179
+ TYPE_CPRMAN_CLOCK_MUX)
53
#define CPU_INTERRUPT_VIRQ CPU_INTERRUPT_TGT_EXT_2
180
54
#define CPU_INTERRUPT_VFIQ CPU_INTERRUPT_TGT_EXT_3
181
/* Register map */
55
#define CPU_INTERRUPT_VSERR CPU_INTERRUPT_TGT_INT_0
182
56
+#define CPU_INTERRUPT_NMI CPU_INTERRUPT_TGT_EXT_4
183
@@ -XXX,XX +XXX,XX @@ REG32(A2W_PLLH_STS, 0x1660)
57
+#define CPU_INTERRUPT_VINMI CPU_INTERRUPT_TGT_EXT_0
184
58
+#define CPU_INTERRUPT_VFNMI CPU_INTERRUPT_TGT_INT_1
185
REG32(A2W_PLLB_ARM, 0x13e0)
59
186
60
/* The usual mapping for an AArch64 system register to its AArch32
187
+/* Clock muxes */
61
* counterpart is for the 32 bit world to have access to the lower
188
+REG32(CM_GNRICCTL, 0x000)
62
diff --git a/target/arm/internals.h b/target/arm/internals.h
189
+ FIELD(CM_CLOCKx_CTL, SRC, 0, 4)
63
index XXXXXXX..XXXXXXX 100644
190
+ FIELD(CM_CLOCKx_CTL, ENABLE, 4, 1)
64
--- a/target/arm/internals.h
191
+ FIELD(CM_CLOCKx_CTL, KILL, 5, 1)
65
+++ b/target/arm/internals.h
192
+ FIELD(CM_CLOCKx_CTL, GATE, 6, 1)
66
@@ -XXX,XX +XXX,XX @@ void arm_cpu_update_virq(ARMCPU *cpu);
193
+ FIELD(CM_CLOCKx_CTL, BUSY, 7, 1)
67
*/
194
+ FIELD(CM_CLOCKx_CTL, BUSYD, 8, 1)
68
void arm_cpu_update_vfiq(ARMCPU *cpu);
195
+ FIELD(CM_CLOCKx_CTL, MASH, 9, 2)
69
196
+ FIELD(CM_CLOCKx_CTL, FLIP, 11, 1)
70
+/**
197
+REG32(CM_GNRICDIV, 0x004)
71
+ * arm_cpu_update_vinmi: Update CPU_INTERRUPT_VINMI bit in cs->interrupt_request
198
+ FIELD(CM_CLOCKx_DIV, FRAC, 0, 12)
72
+ *
199
+REG32(CM_VPUCTL, 0x008)
73
+ * Update the CPU_INTERRUPT_VINMI bit in cs->interrupt_request, following
200
+REG32(CM_VPUDIV, 0x00c)
74
+ * a change to either the input VNMI line from the GIC or the HCRX_EL2.VINMI.
201
+REG32(CM_SYSCTL, 0x010)
75
+ * Must be called with the BQL held.
202
+REG32(CM_SYSDIV, 0x014)
76
+ */
203
+REG32(CM_PERIACTL, 0x018)
77
+void arm_cpu_update_vinmi(ARMCPU *cpu);
204
+REG32(CM_PERIADIV, 0x01c)
78
+
205
+REG32(CM_PERIICTL, 0x020)
79
+/**
206
+REG32(CM_PERIIDIV, 0x024)
80
+ * arm_cpu_update_vfnmi: Update CPU_INTERRUPT_VFNMI bit in cs->interrupt_request
207
+REG32(CM_H264CTL, 0x028)
81
+ *
208
+REG32(CM_H264DIV, 0x02c)
82
+ * Update the CPU_INTERRUPT_VFNMI bit in cs->interrupt_request, following
209
+REG32(CM_ISPCTL, 0x030)
83
+ * a change to the HCRX_EL2.VFNMI.
210
+REG32(CM_ISPDIV, 0x034)
84
+ * Must be called with the BQL held.
211
+REG32(CM_V3DCTL, 0x038)
85
+ */
212
+REG32(CM_V3DDIV, 0x03c)
86
+void arm_cpu_update_vfnmi(ARMCPU *cpu);
213
+REG32(CM_CAM0CTL, 0x040)
87
+
214
+REG32(CM_CAM0DIV, 0x044)
88
/**
215
+REG32(CM_CAM1CTL, 0x048)
89
* arm_cpu_update_vserr: Update CPU_INTERRUPT_VSERR bit
216
+REG32(CM_CAM1DIV, 0x04c)
90
*
217
+REG32(CM_CCP2CTL, 0x050)
91
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
218
+REG32(CM_CCP2DIV, 0x054)
92
index XXXXXXX..XXXXXXX 100644
219
+REG32(CM_DSI0ECTL, 0x058)
93
--- a/target/arm/cpu.c
220
+REG32(CM_DSI0EDIV, 0x05c)
94
+++ b/target/arm/cpu.c
221
+REG32(CM_DSI0PCTL, 0x060)
95
@@ -XXX,XX +XXX,XX @@ void arm_restore_state_to_opc(CPUState *cs,
222
+REG32(CM_DSI0PDIV, 0x064)
223
+REG32(CM_DPICTL, 0x068)
224
+REG32(CM_DPIDIV, 0x06c)
225
+REG32(CM_GP0CTL, 0x070)
226
+REG32(CM_GP0DIV, 0x074)
227
+REG32(CM_GP1CTL, 0x078)
228
+REG32(CM_GP1DIV, 0x07c)
229
+REG32(CM_GP2CTL, 0x080)
230
+REG32(CM_GP2DIV, 0x084)
231
+REG32(CM_HSMCTL, 0x088)
232
+REG32(CM_HSMDIV, 0x08c)
233
+REG32(CM_OTPCTL, 0x090)
234
+REG32(CM_OTPDIV, 0x094)
235
+REG32(CM_PCMCTL, 0x098)
236
+REG32(CM_PCMDIV, 0x09c)
237
+REG32(CM_PWMCTL, 0x0a0)
238
+REG32(CM_PWMDIV, 0x0a4)
239
+REG32(CM_SLIMCTL, 0x0a8)
240
+REG32(CM_SLIMDIV, 0x0ac)
241
+REG32(CM_SMICTL, 0x0b0)
242
+REG32(CM_SMIDIV, 0x0b4)
243
+REG32(CM_TCNTCTL, 0x0c0)
244
+REG32(CM_TCNTCNT, 0x0c4)
245
+REG32(CM_TECCTL, 0x0c8)
246
+REG32(CM_TECDIV, 0x0cc)
247
+REG32(CM_TD0CTL, 0x0d0)
248
+REG32(CM_TD0DIV, 0x0d4)
249
+REG32(CM_TD1CTL, 0x0d8)
250
+REG32(CM_TD1DIV, 0x0dc)
251
+REG32(CM_TSENSCTL, 0x0e0)
252
+REG32(CM_TSENSDIV, 0x0e4)
253
+REG32(CM_TIMERCTL, 0x0e8)
254
+REG32(CM_TIMERDIV, 0x0ec)
255
+REG32(CM_UARTCTL, 0x0f0)
256
+REG32(CM_UARTDIV, 0x0f4)
257
+REG32(CM_VECCTL, 0x0f8)
258
+REG32(CM_VECDIV, 0x0fc)
259
+REG32(CM_PULSECTL, 0x190)
260
+REG32(CM_PULSEDIV, 0x194)
261
+REG32(CM_SDCCTL, 0x1a8)
262
+REG32(CM_SDCDIV, 0x1ac)
263
+REG32(CM_ARMCTL, 0x1b0)
264
+REG32(CM_AVEOCTL, 0x1b8)
265
+REG32(CM_AVEODIV, 0x1bc)
266
+REG32(CM_EMMCCTL, 0x1c0)
267
+REG32(CM_EMMCDIV, 0x1c4)
268
+REG32(CM_EMMC2CTL, 0x1d0)
269
+REG32(CM_EMMC2DIV, 0x1d4)
270
+
271
/* misc registers */
272
REG32(CM_LOCK, 0x114)
273
FIELD(CM_LOCK, FLOCKH, 12, 1)
274
@@ -XXX,XX +XXX,XX @@ static inline void set_pll_channel_init_info(BCM2835CprmanState *s,
275
channel->fixed_divider = PLL_CHANNEL_INIT_INFO[id].fixed_divider;
276
}
96
}
277
97
#endif /* CONFIG_TCG */
278
+/* Clock mux init info */
98
279
+typedef struct ClockMuxInitInfo {
280
+ const char *name;
281
+ size_t cm_offset; /* cm_offset[0]->CM_CTL, cm_offset[1]->CM_DIV */
282
+ int int_bits;
283
+ int frac_bits;
284
+
285
+ CprmanPllChannel src_mapping[CPRMAN_NUM_CLOCK_MUX_SRC];
286
+} ClockMuxInitInfo;
287
+
288
+/*
99
+/*
289
+ * Each clock mux can have up to 10 sources. Sources 0 to 3 are always the
100
+ * With SCTLR_ELx.NMI == 0, IRQ with Superpriority is masked identically with
290
+ * same (ground, xosc, td0, td1). Sources 4 to 9 are mux specific, and are not
101
+ * IRQ without Superpriority. Moreover, if the GIC is configured so that
291
+ * always populated. The following macros catch all those cases.
102
+ * FEAT_GICv3_NMI is only set if FEAT_NMI is set, then we won't ever see
103
+ * CPU_INTERRUPT_*NMI anyway. So we might as well accept NMI here
104
+ * unconditionally.
292
+ */
105
+ */
293
+
106
static bool arm_cpu_has_work(CPUState *cs)
294
+/* Unknown mapping. Connect everything to ground */
107
{
295
+#define SRC_MAPPING_INFO_unknown \
108
ARMCPU *cpu = ARM_CPU(cs);
296
+ .src_mapping = { \
109
@@ -XXX,XX +XXX,XX @@ static bool arm_cpu_has_work(CPUState *cs)
297
+ CPRMAN_CLOCK_SRC_FORCE_GROUND, /* gnd */ \
110
return (cpu->power_state != PSCI_OFF)
298
+ CPRMAN_CLOCK_SRC_FORCE_GROUND, /* xosc */ \
111
&& cs->interrupt_request &
299
+ CPRMAN_CLOCK_SRC_FORCE_GROUND, /* test debug 0 */ \
112
(CPU_INTERRUPT_FIQ | CPU_INTERRUPT_HARD
300
+ CPRMAN_CLOCK_SRC_FORCE_GROUND, /* test debug 1 */ \
113
+ | CPU_INTERRUPT_NMI | CPU_INTERRUPT_VINMI | CPU_INTERRUPT_VFNMI
301
+ CPRMAN_CLOCK_SRC_FORCE_GROUND, /* pll a */ \
114
| CPU_INTERRUPT_VFIQ | CPU_INTERRUPT_VIRQ | CPU_INTERRUPT_VSERR
302
+ CPRMAN_CLOCK_SRC_FORCE_GROUND, /* pll c */ \
115
| CPU_INTERRUPT_EXITTB);
303
+ CPRMAN_CLOCK_SRC_FORCE_GROUND, /* pll d */ \
116
}
304
+ CPRMAN_CLOCK_SRC_FORCE_GROUND, /* pll h */ \
117
@@ -XXX,XX +XXX,XX @@ static inline bool arm_excp_unmasked(CPUState *cs, unsigned int excp_idx,
305
+ CPRMAN_CLOCK_SRC_FORCE_GROUND, /* pll c, core1 */ \
118
CPUARMState *env = cpu_env(cs);
306
+ CPRMAN_CLOCK_SRC_FORCE_GROUND, /* pll c, core2 */ \
119
bool pstate_unmasked;
307
+ }
120
bool unmasked = false;
308
+
121
+ bool allIntMask = false;
309
+/* Only the oscillator and the two test debug clocks */
122
310
+#define SRC_MAPPING_INFO_xosc \
123
/*
311
+ .src_mapping = { \
124
* Don't take exceptions if they target a lower EL.
312
+ CPRMAN_CLOCK_SRC_NORMAL, \
125
@@ -XXX,XX +XXX,XX @@ static inline bool arm_excp_unmasked(CPUState *cs, unsigned int excp_idx,
313
+ CPRMAN_CLOCK_SRC_NORMAL, \
126
return false;
314
+ CPRMAN_CLOCK_SRC_NORMAL, \
127
}
315
+ CPRMAN_CLOCK_SRC_NORMAL, \
128
316
+ CPRMAN_CLOCK_SRC_FORCE_GROUND, \
129
+ if (cpu_isar_feature(aa64_nmi, env_archcpu(env)) &&
317
+ CPRMAN_CLOCK_SRC_FORCE_GROUND, \
130
+ env->cp15.sctlr_el[target_el] & SCTLR_NMI && cur_el == target_el) {
318
+ CPRMAN_CLOCK_SRC_FORCE_GROUND, \
131
+ allIntMask = env->pstate & PSTATE_ALLINT ||
319
+ CPRMAN_CLOCK_SRC_FORCE_GROUND, \
132
+ ((env->cp15.sctlr_el[target_el] & SCTLR_SPINTMASK) &&
320
+ CPRMAN_CLOCK_SRC_FORCE_GROUND, \
133
+ (env->pstate & PSTATE_SP));
321
+ CPRMAN_CLOCK_SRC_FORCE_GROUND, \
134
+ }
322
+ }
135
+
323
+
136
switch (excp_idx) {
324
+/* All the PLL "core" channels */
137
+ case EXCP_NMI:
325
+#define SRC_MAPPING_INFO_core \
138
+ pstate_unmasked = !allIntMask;
326
+ .src_mapping = { \
139
+ break;
327
+ CPRMAN_CLOCK_SRC_NORMAL, \
140
+
328
+ CPRMAN_CLOCK_SRC_NORMAL, \
141
+ case EXCP_VINMI:
329
+ CPRMAN_CLOCK_SRC_NORMAL, \
142
+ if (!(hcr_el2 & HCR_IMO) || (hcr_el2 & HCR_TGE)) {
330
+ CPRMAN_CLOCK_SRC_NORMAL, \
143
+ /* VINMIs are only taken when hypervized. */
331
+ CPRMAN_PLLA_CHANNEL_CORE, \
144
+ return false;
332
+ CPRMAN_PLLC_CHANNEL_CORE0, \
145
+ }
333
+ CPRMAN_PLLD_CHANNEL_CORE, \
146
+ return !allIntMask;
334
+ CPRMAN_PLLH_CHANNEL_AUX, \
147
+ case EXCP_VFNMI:
335
+ CPRMAN_PLLC_CHANNEL_CORE1, \
148
+ if (!(hcr_el2 & HCR_FMO) || (hcr_el2 & HCR_TGE)) {
336
+ CPRMAN_PLLC_CHANNEL_CORE2, \
149
+ /* VFNMIs are only taken when hypervized. */
337
+ }
150
+ return false;
338
+
151
+ }
339
+/* All the PLL "per" channels */
152
+ return !allIntMask;
340
+#define SRC_MAPPING_INFO_periph \
153
case EXCP_FIQ:
341
+ .src_mapping = { \
154
- pstate_unmasked = !(env->daif & PSTATE_F);
342
+ CPRMAN_CLOCK_SRC_NORMAL, \
155
+ pstate_unmasked = (!(env->daif & PSTATE_F)) && (!allIntMask);
343
+ CPRMAN_CLOCK_SRC_NORMAL, \
156
break;
344
+ CPRMAN_CLOCK_SRC_NORMAL, \
157
345
+ CPRMAN_CLOCK_SRC_NORMAL, \
158
case EXCP_IRQ:
346
+ CPRMAN_PLLA_CHANNEL_PER, \
159
- pstate_unmasked = !(env->daif & PSTATE_I);
347
+ CPRMAN_PLLC_CHANNEL_PER, \
160
+ pstate_unmasked = (!(env->daif & PSTATE_I)) && (!allIntMask);
348
+ CPRMAN_PLLD_CHANNEL_PER, \
161
break;
349
+ CPRMAN_CLOCK_SRC_FORCE_GROUND, \
162
350
+ CPRMAN_CLOCK_SRC_FORCE_GROUND, \
163
case EXCP_VFIQ:
351
+ CPRMAN_CLOCK_SRC_FORCE_GROUND, \
164
@@ -XXX,XX +XXX,XX @@ static inline bool arm_excp_unmasked(CPUState *cs, unsigned int excp_idx,
352
+ }
165
/* VFIQs are only taken when hypervized. */
353
+
166
return false;
354
+/*
167
}
355
+ * The DSI0 channels. This one got an intermediate mux between the PLL channels
168
- return !(env->daif & PSTATE_F);
356
+ * and the clock input.
169
+ return !(env->daif & PSTATE_F) && (!allIntMask);
357
+ */
170
case EXCP_VIRQ:
358
+#define SRC_MAPPING_INFO_dsi0 \
171
if (!(hcr_el2 & HCR_IMO) || (hcr_el2 & HCR_TGE)) {
359
+ .src_mapping = { \
172
/* VIRQs are only taken when hypervized. */
360
+ CPRMAN_CLOCK_SRC_NORMAL, \
173
return false;
361
+ CPRMAN_CLOCK_SRC_NORMAL, \
174
}
362
+ CPRMAN_CLOCK_SRC_NORMAL, \
175
- return !(env->daif & PSTATE_I);
363
+ CPRMAN_CLOCK_SRC_NORMAL, \
176
+ return !(env->daif & PSTATE_I) && (!allIntMask);
364
+ CPRMAN_CLOCK_SRC_DSI0HSCK, \
177
case EXCP_VSERR:
365
+ CPRMAN_CLOCK_SRC_FORCE_GROUND, \
178
if (!(hcr_el2 & HCR_AMO) || (hcr_el2 & HCR_TGE)) {
366
+ CPRMAN_CLOCK_SRC_FORCE_GROUND, \
179
/* VIRQs are only taken when hypervized. */
367
+ CPRMAN_CLOCK_SRC_FORCE_GROUND, \
180
@@ -XXX,XX +XXX,XX @@ static bool arm_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
368
+ CPRMAN_CLOCK_SRC_FORCE_GROUND, \
181
369
+ CPRMAN_CLOCK_SRC_FORCE_GROUND, \
182
/* The prioritization of interrupts is IMPLEMENTATION DEFINED. */
370
+ }
183
371
+
184
+ if (cpu_isar_feature(aa64_nmi, env_archcpu(env)) &&
372
+/* The DSI1 channel */
185
+ (arm_sctlr(env, cur_el) & SCTLR_NMI)) {
373
+#define SRC_MAPPING_INFO_dsi1 \
186
+ if (interrupt_request & CPU_INTERRUPT_NMI) {
374
+ .src_mapping = { \
187
+ excp_idx = EXCP_NMI;
375
+ CPRMAN_CLOCK_SRC_NORMAL, \
188
+ target_el = arm_phys_excp_target_el(cs, excp_idx, cur_el, secure);
376
+ CPRMAN_CLOCK_SRC_NORMAL, \
189
+ if (arm_excp_unmasked(cs, excp_idx, target_el,
377
+ CPRMAN_CLOCK_SRC_NORMAL, \
190
+ cur_el, secure, hcr_el2)) {
378
+ CPRMAN_CLOCK_SRC_NORMAL, \
191
+ goto found;
379
+ CPRMAN_PLLD_CHANNEL_DSI1, \
192
+ }
380
+ CPRMAN_CLOCK_SRC_FORCE_GROUND, \
193
+ }
381
+ CPRMAN_CLOCK_SRC_FORCE_GROUND, \
194
+ if (interrupt_request & CPU_INTERRUPT_VINMI) {
382
+ CPRMAN_CLOCK_SRC_FORCE_GROUND, \
195
+ excp_idx = EXCP_VINMI;
383
+ CPRMAN_CLOCK_SRC_FORCE_GROUND, \
196
+ target_el = 1;
384
+ CPRMAN_CLOCK_SRC_FORCE_GROUND, \
197
+ if (arm_excp_unmasked(cs, excp_idx, target_el,
385
+ }
198
+ cur_el, secure, hcr_el2)) {
386
+
199
+ goto found;
387
+#define FILL_CLOCK_MUX_SRC_MAPPING_INIT_INFO(kind_) \
200
+ }
388
+ SRC_MAPPING_INFO_ ## kind_
201
+ }
389
+
202
+ if (interrupt_request & CPU_INTERRUPT_VFNMI) {
390
+#define FILL_CLOCK_MUX_INIT_INFO(clock_, kind_) \
203
+ excp_idx = EXCP_VFNMI;
391
+ .cm_offset = R_CM_ ## clock_ ## CTL, \
204
+ target_el = 1;
392
+ FILL_CLOCK_MUX_SRC_MAPPING_INIT_INFO(kind_)
205
+ if (arm_excp_unmasked(cs, excp_idx, target_el,
393
+
206
+ cur_el, secure, hcr_el2)) {
394
+static ClockMuxInitInfo CLOCK_MUX_INIT_INFO[] = {
207
+ goto found;
395
+ [CPRMAN_CLOCK_GNRIC] = {
208
+ }
396
+ .name = "gnric",
209
+ }
397
+ FILL_CLOCK_MUX_INIT_INFO(GNRIC, unknown),
210
+ } else {
398
+ },
211
+ /*
399
+ [CPRMAN_CLOCK_VPU] = {
212
+ * NMI disabled: interrupts with superpriority are handled
400
+ .name = "vpu",
213
+ * as if they didn't have it
401
+ .int_bits = 12,
214
+ */
402
+ .frac_bits = 8,
215
+ if (interrupt_request & CPU_INTERRUPT_NMI) {
403
+ FILL_CLOCK_MUX_INIT_INFO(VPU, core),
216
+ interrupt_request |= CPU_INTERRUPT_HARD;
404
+ },
217
+ }
405
+ [CPRMAN_CLOCK_SYS] = {
218
+ if (interrupt_request & CPU_INTERRUPT_VINMI) {
406
+ .name = "sys",
219
+ interrupt_request |= CPU_INTERRUPT_VIRQ;
407
+ FILL_CLOCK_MUX_INIT_INFO(SYS, unknown),
220
+ }
408
+ },
221
+ if (interrupt_request & CPU_INTERRUPT_VFNMI) {
409
+ [CPRMAN_CLOCK_PERIA] = {
222
+ interrupt_request |= CPU_INTERRUPT_VFIQ;
410
+ .name = "peria",
223
+ }
411
+ FILL_CLOCK_MUX_INIT_INFO(PERIA, unknown),
224
+ }
412
+ },
225
+
413
+ [CPRMAN_CLOCK_PERII] = {
226
if (interrupt_request & CPU_INTERRUPT_FIQ) {
414
+ .name = "perii",
227
excp_idx = EXCP_FIQ;
415
+ FILL_CLOCK_MUX_INIT_INFO(PERII, unknown),
228
target_el = arm_phys_excp_target_el(cs, excp_idx, cur_el, secure);
416
+ },
229
@@ -XXX,XX +XXX,XX @@ void arm_cpu_update_virq(ARMCPU *cpu)
417
+ [CPRMAN_CLOCK_H264] = {
230
CPUARMState *env = &cpu->env;
418
+ .name = "h264",
231
CPUState *cs = CPU(cpu);
419
+ .int_bits = 4,
232
420
+ .frac_bits = 8,
233
- bool new_state = (env->cp15.hcr_el2 & HCR_VI) ||
421
+ FILL_CLOCK_MUX_INIT_INFO(H264, core),
234
+ bool new_state = ((arm_hcr_el2_eff(env) & HCR_VI) &&
422
+ },
235
+ !(arm_hcrx_el2_eff(env) & HCRX_VINMI)) ||
423
+ [CPRMAN_CLOCK_ISP] = {
236
(env->irq_line_state & CPU_INTERRUPT_VIRQ);
424
+ .name = "isp",
237
425
+ .int_bits = 4,
238
if (new_state != ((cs->interrupt_request & CPU_INTERRUPT_VIRQ) != 0)) {
426
+ .frac_bits = 8,
239
@@ -XXX,XX +XXX,XX @@ void arm_cpu_update_vfiq(ARMCPU *cpu)
427
+ FILL_CLOCK_MUX_INIT_INFO(ISP, core),
240
CPUARMState *env = &cpu->env;
428
+ },
241
CPUState *cs = CPU(cpu);
429
+ [CPRMAN_CLOCK_V3D] = {
242
430
+ .name = "v3d",
243
- bool new_state = (env->cp15.hcr_el2 & HCR_VF) ||
431
+ FILL_CLOCK_MUX_INIT_INFO(V3D, core),
244
+ bool new_state = ((arm_hcr_el2_eff(env) & HCR_VF) &&
432
+ },
245
+ !(arm_hcrx_el2_eff(env) & HCRX_VFNMI)) ||
433
+ [CPRMAN_CLOCK_CAM0] = {
246
(env->irq_line_state & CPU_INTERRUPT_VFIQ);
434
+ .name = "cam0",
247
435
+ .int_bits = 4,
248
if (new_state != ((cs->interrupt_request & CPU_INTERRUPT_VFIQ) != 0)) {
436
+ .frac_bits = 8,
249
@@ -XXX,XX +XXX,XX @@ void arm_cpu_update_vfiq(ARMCPU *cpu)
437
+ FILL_CLOCK_MUX_INIT_INFO(CAM0, periph),
438
+ },
439
+ [CPRMAN_CLOCK_CAM1] = {
440
+ .name = "cam1",
441
+ .int_bits = 4,
442
+ .frac_bits = 8,
443
+ FILL_CLOCK_MUX_INIT_INFO(CAM1, periph),
444
+ },
445
+ [CPRMAN_CLOCK_CCP2] = {
446
+ .name = "ccp2",
447
+ FILL_CLOCK_MUX_INIT_INFO(CCP2, unknown),
448
+ },
449
+ [CPRMAN_CLOCK_DSI0E] = {
450
+ .name = "dsi0e",
451
+ .int_bits = 4,
452
+ .frac_bits = 8,
453
+ FILL_CLOCK_MUX_INIT_INFO(DSI0E, dsi0),
454
+ },
455
+ [CPRMAN_CLOCK_DSI0P] = {
456
+ .name = "dsi0p",
457
+ .int_bits = 0,
458
+ .frac_bits = 0,
459
+ FILL_CLOCK_MUX_INIT_INFO(DSI0P, dsi0),
460
+ },
461
+ [CPRMAN_CLOCK_DPI] = {
462
+ .name = "dpi",
463
+ .int_bits = 4,
464
+ .frac_bits = 8,
465
+ FILL_CLOCK_MUX_INIT_INFO(DPI, periph),
466
+ },
467
+ [CPRMAN_CLOCK_GP0] = {
468
+ .name = "gp0",
469
+ .int_bits = 12,
470
+ .frac_bits = 12,
471
+ FILL_CLOCK_MUX_INIT_INFO(GP0, periph),
472
+ },
473
+ [CPRMAN_CLOCK_GP1] = {
474
+ .name = "gp1",
475
+ .int_bits = 12,
476
+ .frac_bits = 12,
477
+ FILL_CLOCK_MUX_INIT_INFO(GP1, periph),
478
+ },
479
+ [CPRMAN_CLOCK_GP2] = {
480
+ .name = "gp2",
481
+ .int_bits = 12,
482
+ .frac_bits = 12,
483
+ FILL_CLOCK_MUX_INIT_INFO(GP2, periph),
484
+ },
485
+ [CPRMAN_CLOCK_HSM] = {
486
+ .name = "hsm",
487
+ .int_bits = 4,
488
+ .frac_bits = 8,
489
+ FILL_CLOCK_MUX_INIT_INFO(HSM, periph),
490
+ },
491
+ [CPRMAN_CLOCK_OTP] = {
492
+ .name = "otp",
493
+ .int_bits = 4,
494
+ .frac_bits = 0,
495
+ FILL_CLOCK_MUX_INIT_INFO(OTP, xosc),
496
+ },
497
+ [CPRMAN_CLOCK_PCM] = {
498
+ .name = "pcm",
499
+ .int_bits = 12,
500
+ .frac_bits = 12,
501
+ FILL_CLOCK_MUX_INIT_INFO(PCM, periph),
502
+ },
503
+ [CPRMAN_CLOCK_PWM] = {
504
+ .name = "pwm",
505
+ .int_bits = 12,
506
+ .frac_bits = 12,
507
+ FILL_CLOCK_MUX_INIT_INFO(PWM, periph),
508
+ },
509
+ [CPRMAN_CLOCK_SLIM] = {
510
+ .name = "slim",
511
+ .int_bits = 12,
512
+ .frac_bits = 12,
513
+ FILL_CLOCK_MUX_INIT_INFO(SLIM, periph),
514
+ },
515
+ [CPRMAN_CLOCK_SMI] = {
516
+ .name = "smi",
517
+ .int_bits = 4,
518
+ .frac_bits = 8,
519
+ FILL_CLOCK_MUX_INIT_INFO(SMI, periph),
520
+ },
521
+ [CPRMAN_CLOCK_TEC] = {
522
+ .name = "tec",
523
+ .int_bits = 6,
524
+ .frac_bits = 0,
525
+ FILL_CLOCK_MUX_INIT_INFO(TEC, xosc),
526
+ },
527
+ [CPRMAN_CLOCK_TD0] = {
528
+ .name = "td0",
529
+ FILL_CLOCK_MUX_INIT_INFO(TD0, unknown),
530
+ },
531
+ [CPRMAN_CLOCK_TD1] = {
532
+ .name = "td1",
533
+ FILL_CLOCK_MUX_INIT_INFO(TD1, unknown),
534
+ },
535
+ [CPRMAN_CLOCK_TSENS] = {
536
+ .name = "tsens",
537
+ .int_bits = 5,
538
+ .frac_bits = 0,
539
+ FILL_CLOCK_MUX_INIT_INFO(TSENS, xosc),
540
+ },
541
+ [CPRMAN_CLOCK_TIMER] = {
542
+ .name = "timer",
543
+ .int_bits = 6,
544
+ .frac_bits = 12,
545
+ FILL_CLOCK_MUX_INIT_INFO(TIMER, xosc),
546
+ },
547
+ [CPRMAN_CLOCK_UART] = {
548
+ .name = "uart",
549
+ .int_bits = 10,
550
+ .frac_bits = 12,
551
+ FILL_CLOCK_MUX_INIT_INFO(UART, periph),
552
+ },
553
+ [CPRMAN_CLOCK_VEC] = {
554
+ .name = "vec",
555
+ .int_bits = 4,
556
+ .frac_bits = 0,
557
+ FILL_CLOCK_MUX_INIT_INFO(VEC, periph),
558
+ },
559
+ [CPRMAN_CLOCK_PULSE] = {
560
+ .name = "pulse",
561
+ FILL_CLOCK_MUX_INIT_INFO(PULSE, xosc),
562
+ },
563
+ [CPRMAN_CLOCK_SDC] = {
564
+ .name = "sdram",
565
+ .int_bits = 6,
566
+ .frac_bits = 0,
567
+ FILL_CLOCK_MUX_INIT_INFO(SDC, core),
568
+ },
569
+ [CPRMAN_CLOCK_ARM] = {
570
+ .name = "arm",
571
+ FILL_CLOCK_MUX_INIT_INFO(ARM, unknown),
572
+ },
573
+ [CPRMAN_CLOCK_AVEO] = {
574
+ .name = "aveo",
575
+ .int_bits = 4,
576
+ .frac_bits = 0,
577
+ FILL_CLOCK_MUX_INIT_INFO(AVEO, periph),
578
+ },
579
+ [CPRMAN_CLOCK_EMMC] = {
580
+ .name = "emmc",
581
+ .int_bits = 4,
582
+ .frac_bits = 8,
583
+ FILL_CLOCK_MUX_INIT_INFO(EMMC, periph),
584
+ },
585
+ [CPRMAN_CLOCK_EMMC2] = {
586
+ .name = "emmc2",
587
+ .int_bits = 4,
588
+ .frac_bits = 8,
589
+ FILL_CLOCK_MUX_INIT_INFO(EMMC2, unknown),
590
+ },
591
+};
592
+
593
+#undef FILL_CLOCK_MUX_INIT_INFO
594
+#undef FILL_CLOCK_MUX_SRC_MAPPING_INIT_INFO
595
+#undef SRC_MAPPING_INFO_dsi1
596
+#undef SRC_MAPPING_INFO_dsi0
597
+#undef SRC_MAPPING_INFO_periph
598
+#undef SRC_MAPPING_INFO_core
599
+#undef SRC_MAPPING_INFO_xosc
600
+#undef SRC_MAPPING_INFO_unknown
601
+
602
+static inline void set_clock_mux_init_info(BCM2835CprmanState *s,
603
+ CprmanClockMuxState *mux,
604
+ CprmanClockMux id)
605
+{
606
+ mux->id = id;
607
+ mux->reg_ctl = &s->regs[CLOCK_MUX_INIT_INFO[id].cm_offset];
608
+ mux->reg_div = &s->regs[CLOCK_MUX_INIT_INFO[id].cm_offset + 1];
609
+ mux->int_bits = CLOCK_MUX_INIT_INFO[id].int_bits;
610
+ mux->frac_bits = CLOCK_MUX_INIT_INFO[id].frac_bits;
611
+}
612
+
613
#endif
614
diff --git a/hw/misc/bcm2835_cprman.c b/hw/misc/bcm2835_cprman.c
615
index XXXXXXX..XXXXXXX 100644
616
--- a/hw/misc/bcm2835_cprman.c
617
+++ b/hw/misc/bcm2835_cprman.c
618
@@ -XXX,XX +XXX,XX @@
619
*
620
* The page at https://elinux.org/The_Undocumented_Pi gives the actual clock
621
* tree configuration.
622
+ *
623
+ * The CPRMAN exposes clock outputs with the name of the clock mux suffixed
624
+ * with "-out" (e.g. "uart-out", "h264-out", ...).
625
*/
626
627
#include "qemu/osdep.h"
628
@@ -XXX,XX +XXX,XX @@ static const TypeInfo cprman_pll_channel_info = {
629
};
630
631
632
+/* clock mux */
633
+
634
+static void clock_mux_update(CprmanClockMuxState *mux)
635
+{
636
+ clock_update(mux->out, 0);
637
+}
638
+
639
+static void clock_mux_src_update(void *opaque)
640
+{
641
+ CprmanClockMuxState **backref = opaque;
642
+ CprmanClockMuxState *s = *backref;
643
+
644
+ clock_mux_update(s);
645
+}
646
+
647
+static void clock_mux_init(Object *obj)
648
+{
649
+ CprmanClockMuxState *s = CPRMAN_CLOCK_MUX(obj);
650
+ size_t i;
651
+
652
+ for (i = 0; i < CPRMAN_NUM_CLOCK_MUX_SRC; i++) {
653
+ char *name = g_strdup_printf("srcs[%zu]", i);
654
+ s->backref[i] = s;
655
+ s->srcs[i] = qdev_init_clock_in(DEVICE(s), name,
656
+ clock_mux_src_update,
657
+ &s->backref[i]);
658
+ g_free(name);
659
+ }
660
+
661
+ s->out = qdev_init_clock_out(DEVICE(s), "out");
662
+}
663
+
664
+static const VMStateDescription clock_mux_vmstate = {
665
+ .name = TYPE_CPRMAN_CLOCK_MUX,
666
+ .version_id = 1,
667
+ .minimum_version_id = 1,
668
+ .fields = (VMStateField[]) {
669
+ VMSTATE_ARRAY_CLOCK(srcs, CprmanClockMuxState,
670
+ CPRMAN_NUM_CLOCK_MUX_SRC),
671
+ VMSTATE_END_OF_LIST()
672
+ }
673
+};
674
+
675
+static void clock_mux_class_init(ObjectClass *klass, void *data)
676
+{
677
+ DeviceClass *dc = DEVICE_CLASS(klass);
678
+
679
+ dc->vmsd = &clock_mux_vmstate;
680
+}
681
+
682
+static const TypeInfo cprman_clock_mux_info = {
683
+ .name = TYPE_CPRMAN_CLOCK_MUX,
684
+ .parent = TYPE_DEVICE,
685
+ .instance_size = sizeof(CprmanClockMuxState),
686
+ .class_init = clock_mux_class_init,
687
+ .instance_init = clock_mux_init,
688
+};
689
+
690
+
691
/* CPRMAN "top level" model */
692
693
static uint32_t get_cm_lock(const BCM2835CprmanState *s)
694
@@ -XXX,XX +XXX,XX @@ static inline void update_channel_from_a2w(BCM2835CprmanState *s, size_t idx)
695
}
250
}
696
}
251
}
697
252
698
+static inline void update_mux_from_cm(BCM2835CprmanState *s, size_t idx)
253
+void arm_cpu_update_vinmi(ARMCPU *cpu)
699
+{
254
+{
700
+ size_t i;
255
+ /*
701
+
256
+ * Update the interrupt level for VINMI, which is the logical OR of
702
+ for (i = 0; i < CPRMAN_NUM_CLOCK_MUX; i++) {
257
+ * the HCRX_EL2.VINMI bit and the input line level from the GIC.
703
+ if ((CLOCK_MUX_INIT_INFO[i].cm_offset == idx) ||
258
+ */
704
+ (CLOCK_MUX_INIT_INFO[i].cm_offset + 4 == idx)) {
259
+ CPUARMState *env = &cpu->env;
705
+ /* matches CM_CTL or CM_DIV mux register */
260
+ CPUState *cs = CPU(cpu);
706
+ clock_mux_update(&s->clock_muxes[i]);
261
+
707
+ return;
262
+ bool new_state = ((arm_hcr_el2_eff(env) & HCR_VI) &&
263
+ (arm_hcrx_el2_eff(env) & HCRX_VINMI)) ||
264
+ (env->irq_line_state & CPU_INTERRUPT_VINMI);
265
+
266
+ if (new_state != ((cs->interrupt_request & CPU_INTERRUPT_VINMI) != 0)) {
267
+ if (new_state) {
268
+ cpu_interrupt(cs, CPU_INTERRUPT_VINMI);
269
+ } else {
270
+ cpu_reset_interrupt(cs, CPU_INTERRUPT_VINMI);
708
+ }
271
+ }
709
+ }
272
+ }
710
+}
273
+}
711
+
274
+
712
#define CASE_PLL_A2W_REGS(pll_) \
275
+void arm_cpu_update_vfnmi(ARMCPU *cpu)
713
case R_A2W_ ## pll_ ## _CTRL: \
276
+{
714
case R_A2W_ ## pll_ ## _ANA0: \
277
+ /*
715
@@ -XXX,XX +XXX,XX @@ static void cprman_write(void *opaque, hwaddr offset,
278
+ * Update the interrupt level for VFNMI, which is the HCRX_EL2.VFNMI bit.
716
case R_A2W_PLLB_ARM:
279
+ */
717
update_channel_from_a2w(s, idx);
280
+ CPUARMState *env = &cpu->env;
281
+ CPUState *cs = CPU(cpu);
282
+
283
+ bool new_state = (arm_hcr_el2_eff(env) & HCR_VF) &&
284
+ (arm_hcrx_el2_eff(env) & HCRX_VFNMI);
285
+
286
+ if (new_state != ((cs->interrupt_request & CPU_INTERRUPT_VFNMI) != 0)) {
287
+ if (new_state) {
288
+ cpu_interrupt(cs, CPU_INTERRUPT_VFNMI);
289
+ } else {
290
+ cpu_reset_interrupt(cs, CPU_INTERRUPT_VFNMI);
291
+ }
292
+ }
293
+}
294
+
295
void arm_cpu_update_vserr(ARMCPU *cpu)
296
{
297
/*
298
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_set_irq(void *opaque, int irq, int level)
299
[ARM_CPU_IRQ] = CPU_INTERRUPT_HARD,
300
[ARM_CPU_FIQ] = CPU_INTERRUPT_FIQ,
301
[ARM_CPU_VIRQ] = CPU_INTERRUPT_VIRQ,
302
- [ARM_CPU_VFIQ] = CPU_INTERRUPT_VFIQ
303
+ [ARM_CPU_VFIQ] = CPU_INTERRUPT_VFIQ,
304
+ [ARM_CPU_NMI] = CPU_INTERRUPT_NMI,
305
+ [ARM_CPU_VINMI] = CPU_INTERRUPT_VINMI,
306
};
307
308
if (!arm_feature(env, ARM_FEATURE_EL2) &&
309
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_set_irq(void *opaque, int irq, int level)
310
case ARM_CPU_VFIQ:
311
arm_cpu_update_vfiq(cpu);
718
break;
312
break;
719
+
313
+ case ARM_CPU_VINMI:
720
+ case R_CM_GNRICCTL ... R_CM_SMIDIV:
314
+ arm_cpu_update_vinmi(cpu);
721
+ case R_CM_TCNTCNT ... R_CM_VECDIV:
722
+ case R_CM_PULSECTL ... R_CM_PULSEDIV:
723
+ case R_CM_SDCCTL ... R_CM_ARMCTL:
724
+ case R_CM_AVEOCTL ... R_CM_EMMCDIV:
725
+ case R_CM_EMMC2CTL ... R_CM_EMMC2DIV:
726
+ update_mux_from_cm(s, idx);
727
+ break;
315
+ break;
316
case ARM_CPU_IRQ:
317
case ARM_CPU_FIQ:
318
+ case ARM_CPU_NMI:
319
if (level) {
320
cpu_interrupt(cs, mask[irq]);
321
} else {
322
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_initfn(Object *obj)
323
#else
324
/* Our inbound IRQ and FIQ lines */
325
if (kvm_enabled()) {
326
- /* VIRQ and VFIQ are unused with KVM but we add them to maintain
327
- * the same interface as non-KVM CPUs.
328
+ /*
329
+ * VIRQ, VFIQ, NMI, VINMI are unused with KVM but we add
330
+ * them to maintain the same interface as non-KVM CPUs.
331
*/
332
- qdev_init_gpio_in(DEVICE(cpu), arm_cpu_kvm_set_irq, 4);
333
+ qdev_init_gpio_in(DEVICE(cpu), arm_cpu_kvm_set_irq, 6);
334
} else {
335
- qdev_init_gpio_in(DEVICE(cpu), arm_cpu_set_irq, 4);
336
+ qdev_init_gpio_in(DEVICE(cpu), arm_cpu_set_irq, 6);
728
}
337
}
338
339
qdev_init_gpio_out(DEVICE(cpu), cpu->gt_timer_outputs,
340
diff --git a/target/arm/helper.c b/target/arm/helper.c
341
index XXXXXXX..XXXXXXX 100644
342
--- a/target/arm/helper.c
343
+++ b/target/arm/helper.c
344
@@ -XXX,XX +XXX,XX @@ static void do_hcr_write(CPUARMState *env, uint64_t value, uint64_t valid_mask)
345
* and the state of the input lines from the GIC. (This requires
346
* that we have the BQL, which is done by marking the
347
* reginfo structs as ARM_CP_IO.)
348
- * Note that if a write to HCR pends a VIRQ or VFIQ it is never
349
- * possible for it to be taken immediately, because VIRQ and
350
- * VFIQ are masked unless running at EL0 or EL1, and HCR
351
- * can only be written at EL2.
352
+ * Note that if a write to HCR pends a VIRQ or VFIQ or VINMI or
353
+ * VFNMI, it is never possible for it to be taken immediately
354
+ * because VIRQ, VFIQ, VINMI and VFNMI are masked unless running
355
+ * at EL0 or EL1, and HCR can only be written at EL2.
356
*/
357
g_assert(bql_locked());
358
arm_cpu_update_virq(cpu);
359
arm_cpu_update_vfiq(cpu);
360
arm_cpu_update_vserr(cpu);
361
+ if (cpu_isar_feature(aa64_nmi, cpu)) {
362
+ arm_cpu_update_vinmi(cpu);
363
+ arm_cpu_update_vfnmi(cpu);
364
+ }
729
}
365
}
730
366
731
@@ -XXX,XX +XXX,XX @@ static void cprman_reset(DeviceState *dev)
367
static void hcr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
732
device_cold_reset(DEVICE(&s->channels[i]));
368
@@ -XXX,XX +XXX,XX @@ static void hcrx_write(CPUARMState *env, const ARMCPRegInfo *ri,
733
}
369
734
370
/* Clear RES0 bits. */
735
+ for (i = 0; i < CPRMAN_NUM_CLOCK_MUX; i++) {
371
env->cp15.hcrx_el2 = value & valid_mask;
736
+ device_cold_reset(DEVICE(&s->clock_muxes[i]));
372
+
737
+ }
373
+ /*
738
+
374
+ * Updates to VINMI and VFNMI require us to update the status of
739
clock_update_hz(s->xosc, s->xosc_freq);
375
+ * virtual NMI, which are the logical OR of these bits
376
+ * and the state of the input lines from the GIC. (This requires
377
+ * that we have the BQL, which is done by marking the
378
+ * reginfo structs as ARM_CP_IO.)
379
+ * Note that if a write to HCRX pends a VINMI or VFNMI it is never
380
+ * possible for it to be taken immediately, because VINMI and
381
+ * VFNMI are masked unless running at EL0 or EL1, and HCRX
382
+ * can only be written at EL2.
383
+ */
384
+ if (cpu_isar_feature(aa64_nmi, cpu)) {
385
+ g_assert(bql_locked());
386
+ arm_cpu_update_vinmi(cpu);
387
+ arm_cpu_update_vfnmi(cpu);
388
+ }
740
}
389
}
741
390
742
@@ -XXX,XX +XXX,XX @@ static void cprman_init(Object *obj)
391
static CPAccessResult access_hxen(CPUARMState *env, const ARMCPRegInfo *ri,
743
set_pll_channel_init_info(s, &s->channels[i], i);
392
@@ -XXX,XX +XXX,XX @@ static CPAccessResult access_hxen(CPUARMState *env, const ARMCPRegInfo *ri,
744
}
393
745
394
static const ARMCPRegInfo hcrx_el2_reginfo = {
746
+ for (i = 0; i < CPRMAN_NUM_CLOCK_MUX; i++) {
395
.name = "HCRX_EL2", .state = ARM_CP_STATE_AA64,
747
+ char *alias;
396
+ .type = ARM_CP_IO,
748
+
397
.opc0 = 3, .opc1 = 4, .crn = 1, .crm = 2, .opc2 = 2,
749
+ object_initialize_child(obj, CLOCK_MUX_INIT_INFO[i].name,
398
.access = PL2_RW, .writefn = hcrx_write, .accessfn = access_hxen,
750
+ &s->clock_muxes[i],
399
.nv2_redirect_offset = 0xa0,
751
+ TYPE_CPRMAN_CLOCK_MUX);
400
@@ -XXX,XX +XXX,XX @@ void arm_log_exception(CPUState *cs)
752
+ set_clock_mux_init_info(s, &s->clock_muxes[i], i);
401
[EXCP_DIVBYZERO] = "v7M DIVBYZERO UsageFault",
753
+
402
[EXCP_VSERR] = "Virtual SERR",
754
+ /* Expose muxes output as CPRMAN outputs */
403
[EXCP_GPC] = "Granule Protection Check",
755
+ alias = g_strdup_printf("%s-out", CLOCK_MUX_INIT_INFO[i].name);
404
+ [EXCP_NMI] = "NMI",
756
+ qdev_alias_clock(DEVICE(&s->clock_muxes[i]), "out", DEVICE(obj), alias);
405
+ [EXCP_VINMI] = "Virtual IRQ NMI",
757
+ g_free(alias);
406
+ [EXCP_VFNMI] = "Virtual FIQ NMI",
758
+ }
407
};
759
+
408
760
s->xosc = clock_new(obj, "xosc");
409
if (idx >= 0 && idx < ARRAY_SIZE(excnames)) {
761
+ s->gnd = clock_new(obj, "gnd");
762
+
763
+ clock_set(s->gnd, 0);
764
765
memory_region_init_io(&s->iomem, obj, &cprman_ops,
766
s, "bcm2835-cprman", 0x2000);
767
sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->iomem);
768
}
769
770
+static void connect_mux_sources(BCM2835CprmanState *s,
771
+ CprmanClockMuxState *mux,
772
+ const CprmanPllChannel *clk_mapping)
773
+{
774
+ size_t i;
775
+ Clock *td0 = s->clock_muxes[CPRMAN_CLOCK_TD0].out;
776
+ Clock *td1 = s->clock_muxes[CPRMAN_CLOCK_TD1].out;
777
+
778
+ /* For sources from 0 to 3. Source 4 to 9 are mux specific */
779
+ Clock * const CLK_SRC_MAPPING[] = {
780
+ [CPRMAN_CLOCK_SRC_GND] = s->gnd,
781
+ [CPRMAN_CLOCK_SRC_XOSC] = s->xosc,
782
+ [CPRMAN_CLOCK_SRC_TD0] = td0,
783
+ [CPRMAN_CLOCK_SRC_TD1] = td1,
784
+ };
785
+
786
+ for (i = 0; i < CPRMAN_NUM_CLOCK_MUX_SRC; i++) {
787
+ CprmanPllChannel mapping = clk_mapping[i];
788
+ Clock *src;
789
+
790
+ if (mapping == CPRMAN_CLOCK_SRC_FORCE_GROUND) {
791
+ src = s->gnd;
792
+ } else if (mapping == CPRMAN_CLOCK_SRC_DSI0HSCK) {
793
+ src = s->gnd; /* TODO */
794
+ } else if (i < CPRMAN_CLOCK_SRC_PLLA) {
795
+ src = CLK_SRC_MAPPING[i];
796
+ } else {
797
+ src = s->channels[mapping].out;
798
+ }
799
+
800
+ clock_set_source(mux->srcs[i], src);
801
+ }
802
+}
803
+
804
static void cprman_realize(DeviceState *dev, Error **errp)
805
{
806
BCM2835CprmanState *s = CPRMAN(dev);
807
@@ -XXX,XX +XXX,XX @@ static void cprman_realize(DeviceState *dev, Error **errp)
808
return;
809
}
810
}
811
+
812
+ for (i = 0; i < CPRMAN_NUM_CLOCK_MUX; i++) {
813
+ CprmanClockMuxState *clock_mux = &s->clock_muxes[i];
814
+
815
+ connect_mux_sources(s, clock_mux, CLOCK_MUX_INIT_INFO[i].src_mapping);
816
+
817
+ if (!qdev_realize(DEVICE(clock_mux), NULL, errp)) {
818
+ return;
819
+ }
820
+ }
821
}
822
823
static const VMStateDescription cprman_vmstate = {
824
@@ -XXX,XX +XXX,XX @@ static void cprman_register_types(void)
825
type_register_static(&cprman_info);
826
type_register_static(&cprman_pll_info);
827
type_register_static(&cprman_pll_channel_info);
828
+ type_register_static(&cprman_clock_mux_info);
829
}
830
831
type_init(cprman_register_types);
832
--
410
--
833
2.20.1
411
2.34.1
834
835
diff view generated by jsdifflib
1
From: Zenghui Yu <yuzenghui@huawei.com>
1
From: Jinjie Ruan <ruanjinjie@huawei.com>
2
2
3
Ensure the vSMMUv3 will be restored before all PCIe devices so that DMA
3
According to Arm GIC section 4.6.3 Interrupt superpriority, the interrupt
4
translation can work properly during migration.
4
with superpriority is always IRQ, never FIQ, so handle NMI same as IRQ in
5
arm_phys_excp_target_el().
5
6
6
Signed-off-by: Zenghui Yu <yuzenghui@huawei.com>
7
Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com>
7
Message-id: 20201019091508.197-1-yuzenghui@huawei.com
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Acked-by: Eric Auger <eric.auger@redhat.com>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Message-id: 20240407081733.3231820-8-ruanjinjie@huawei.com
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
12
---
11
hw/arm/smmuv3.c | 1 +
13
target/arm/helper.c | 1 +
12
1 file changed, 1 insertion(+)
14
1 file changed, 1 insertion(+)
13
15
14
diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c
16
diff --git a/target/arm/helper.c b/target/arm/helper.c
15
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/arm/smmuv3.c
18
--- a/target/arm/helper.c
17
+++ b/hw/arm/smmuv3.c
19
+++ b/target/arm/helper.c
18
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_smmuv3 = {
20
@@ -XXX,XX +XXX,XX @@ uint32_t arm_phys_excp_target_el(CPUState *cs, uint32_t excp_idx,
19
.name = "smmuv3",
21
hcr_el2 = arm_hcr_el2_eff(env);
20
.version_id = 1,
22
switch (excp_idx) {
21
.minimum_version_id = 1,
23
case EXCP_IRQ:
22
+ .priority = MIG_PRI_IOMMU,
24
+ case EXCP_NMI:
23
.fields = (VMStateField[]) {
25
scr = ((env->cp15.scr_el3 & SCR_IRQ) == SCR_IRQ);
24
VMSTATE_UINT32(features, SMMUv3State),
26
hcr = hcr_el2 & HCR_IMO;
25
VMSTATE_UINT8(sid_size, SMMUv3State),
27
break;
26
--
28
--
27
2.20.1
29
2.34.1
28
29
diff view generated by jsdifflib
1
From: Havard Skinnemoen <hskinnemoen@google.com>
1
From: Jinjie Ruan <ruanjinjie@huawei.com>
2
2
3
The NPCM730 and NPCM750 chips have a single USB host port shared between
3
Add IS and FS bit in ISR_EL1 and handle the read. With CPU_INTERRUPT_NMI or
4
a USB 2.0 EHCI host controller and a USB 1.1 OHCI host controller. This
4
CPU_INTERRUPT_VINMI, both CPSR_I and ISR_IS must be set. With
5
adds support for both of them.
5
CPU_INTERRUPT_VFNMI, both CPSR_F and ISR_FS must be set.
6
6
7
Testing notes:
7
Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com>
8
* With -device usb-kbd, qemu will automatically insert a full-speed
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
hub, and the keyboard becomes controlled by the OHCI controller.
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
* With -device usb-kbd,bus=usb-bus.0,port=1, the keyboard is directly
10
Message-id: 20240407081733.3231820-9-ruanjinjie@huawei.com
11
attached to the port without any hubs, and the device becomes
12
controlled by the EHCI controller since it's high speed capable.
13
* With -device usb-kbd,bus=usb-bus.0,port=1,usb_version=1, the
14
keyboard is directly attached to the port, but it only advertises
15
itself as full-speed capable, so it becomes controlled by the OHCI
16
controller.
17
18
In all cases, the keyboard device enumerates correctly.
19
20
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
21
Reviewed-by: Gerd Hoffmann <kraxel@redhat.com>
22
Signed-off-by: Havard Skinnemoen <hskinnemoen@google.com>
23
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
24
---
12
---
25
docs/system/arm/nuvoton.rst | 2 +-
13
target/arm/cpu.h | 2 ++
26
hw/usb/hcd-ehci.h | 1 +
14
target/arm/helper.c | 13 +++++++++++++
27
include/hw/arm/npcm7xx.h | 4 ++++
15
2 files changed, 15 insertions(+)
28
hw/arm/npcm7xx.c | 27 +++++++++++++++++++++++++--
29
hw/usb/hcd-ehci-sysbus.c | 19 +++++++++++++++++++
30
5 files changed, 50 insertions(+), 3 deletions(-)
31
16
32
diff --git a/docs/system/arm/nuvoton.rst b/docs/system/arm/nuvoton.rst
17
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
33
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
34
--- a/docs/system/arm/nuvoton.rst
19
--- a/target/arm/cpu.h
35
+++ b/docs/system/arm/nuvoton.rst
20
+++ b/target/arm/cpu.h
36
@@ -XXX,XX +XXX,XX @@ Supported devices
21
@@ -XXX,XX +XXX,XX @@ void pmu_init(ARMCPU *cpu);
37
* OTP controllers (no protection features)
22
#define CPSR_N (1U << 31)
38
* Flash Interface Unit (FIU; no protection features)
23
#define CPSR_NZCV (CPSR_N | CPSR_Z | CPSR_C | CPSR_V)
39
* Random Number Generator (RNG)
24
#define CPSR_AIF (CPSR_A | CPSR_I | CPSR_F)
40
+ * USB host (USBH)
25
+#define ISR_FS (1U << 9)
41
26
+#define ISR_IS (1U << 10)
42
Missing devices
27
43
---------------
28
#define CPSR_IT (CPSR_IT_0_1 | CPSR_IT_2_7)
44
@@ -XXX,XX +XXX,XX @@ Missing devices
29
#define CACHED_CPSR_BITS (CPSR_T | CPSR_AIF | CPSR_GE | CPSR_IT | CPSR_Q \
45
* eSPI slave interface
30
diff --git a/target/arm/helper.c b/target/arm/helper.c
46
47
* Ethernet controllers (GMAC and EMC)
48
- * USB host (USBH)
49
* USB device (USBD)
50
* SMBus controller (SMBF)
51
* Peripheral SPI controller (PSPI)
52
diff --git a/hw/usb/hcd-ehci.h b/hw/usb/hcd-ehci.h
53
index XXXXXXX..XXXXXXX 100644
31
index XXXXXXX..XXXXXXX 100644
54
--- a/hw/usb/hcd-ehci.h
32
--- a/target/arm/helper.c
55
+++ b/hw/usb/hcd-ehci.h
33
+++ b/target/arm/helper.c
56
@@ -XXX,XX +XXX,XX @@ struct EHCIPCIState {
34
@@ -XXX,XX +XXX,XX @@ static uint64_t isr_read(CPUARMState *env, const ARMCPRegInfo *ri)
57
#define TYPE_PLATFORM_EHCI "platform-ehci-usb"
35
if (cs->interrupt_request & CPU_INTERRUPT_VIRQ) {
58
#define TYPE_EXYNOS4210_EHCI "exynos4210-ehci-usb"
36
ret |= CPSR_I;
59
#define TYPE_AW_H3_EHCI "aw-h3-ehci-usb"
37
}
60
+#define TYPE_NPCM7XX_EHCI "npcm7xx-ehci-usb"
38
+ if (cs->interrupt_request & CPU_INTERRUPT_VINMI) {
61
#define TYPE_TEGRA2_EHCI "tegra2-ehci-usb"
39
+ ret |= ISR_IS;
62
#define TYPE_PPC4xx_EHCI "ppc4xx-ehci-usb"
40
+ ret |= CPSR_I;
63
#define TYPE_FUSBH200_EHCI "fusbh200-ehci-usb"
41
+ }
64
diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h
42
} else {
65
index XXXXXXX..XXXXXXX 100644
43
if (cs->interrupt_request & CPU_INTERRUPT_HARD) {
66
--- a/include/hw/arm/npcm7xx.h
44
ret |= CPSR_I;
67
+++ b/include/hw/arm/npcm7xx.h
45
}
68
@@ -XXX,XX +XXX,XX @@
69
#include "hw/nvram/npcm7xx_otp.h"
70
#include "hw/timer/npcm7xx_timer.h"
71
#include "hw/ssi/npcm7xx_fiu.h"
72
+#include "hw/usb/hcd-ehci.h"
73
+#include "hw/usb/hcd-ohci.h"
74
#include "target/arm/cpu.h"
75
76
#define NPCM7XX_MAX_NUM_CPUS (2)
77
@@ -XXX,XX +XXX,XX @@ typedef struct NPCM7xxState {
78
NPCM7xxOTPState fuse_array;
79
NPCM7xxMCState mc;
80
NPCM7xxRNGState rng;
81
+ EHCISysBusState ehci;
82
+ OHCISysBusState ohci;
83
NPCM7xxFIUState fiu[2];
84
} NPCM7xxState;
85
86
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
87
index XXXXXXX..XXXXXXX 100644
88
--- a/hw/arm/npcm7xx.c
89
+++ b/hw/arm/npcm7xx.c
90
@@ -XXX,XX +XXX,XX @@
91
#define NPCM7XX_MC_BA (0xf0824000)
92
#define NPCM7XX_RNG_BA (0xf000b000)
93
94
+/* USB Host modules */
95
+#define NPCM7XX_EHCI_BA (0xf0806000)
96
+#define NPCM7XX_OHCI_BA (0xf0807000)
97
+
46
+
98
/* Internal AHB SRAM */
47
+ if (cs->interrupt_request & CPU_INTERRUPT_NMI) {
99
#define NPCM7XX_RAM3_BA (0xc0008000)
48
+ ret |= ISR_IS;
100
#define NPCM7XX_RAM3_SZ (4 * KiB)
49
+ ret |= CPSR_I;
101
@@ -XXX,XX +XXX,XX @@ enum NPCM7xxInterrupt {
50
+ }
102
NPCM7XX_WDG0_IRQ = 47, /* Timer Module 0 Watchdog */
103
NPCM7XX_WDG1_IRQ, /* Timer Module 1 Watchdog */
104
NPCM7XX_WDG2_IRQ, /* Timer Module 2 Watchdog */
105
+ NPCM7XX_EHCI_IRQ = 61,
106
+ NPCM7XX_OHCI_IRQ = 62,
107
};
108
109
/* Total number of GIC interrupts, including internal Cortex-A9 interrupts. */
110
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_init(Object *obj)
111
object_initialize_child(obj, "tim[*]", &s->tim[i], TYPE_NPCM7XX_TIMER);
112
}
51
}
113
52
114
+ object_initialize_child(obj, "ehci", &s->ehci, TYPE_NPCM7XX_EHCI);
53
if (hcr_el2 & HCR_FMO) {
115
+ object_initialize_child(obj, "ohci", &s->ohci, TYPE_SYSBUS_OHCI);
54
if (cs->interrupt_request & CPU_INTERRUPT_VFIQ) {
116
+
55
ret |= CPSR_F;
117
QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_fiu) != ARRAY_SIZE(s->fiu));
56
}
118
for (i = 0; i < ARRAY_SIZE(s->fiu); i++) {
57
+ if (cs->interrupt_request & CPU_INTERRUPT_VFNMI) {
119
object_initialize_child(obj, npcm7xx_fiu[i].name, &s->fiu[i],
58
+ ret |= ISR_FS;
120
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
59
+ ret |= CPSR_F;
121
sysbus_realize(SYS_BUS_DEVICE(&s->rng), &error_abort);
60
+ }
122
sysbus_mmio_map(SYS_BUS_DEVICE(&s->rng), 0, NPCM7XX_RNG_BA);
61
} else {
123
62
if (cs->interrupt_request & CPU_INTERRUPT_FIQ) {
124
+ /* USB Host */
63
ret |= CPSR_F;
125
+ object_property_set_bool(OBJECT(&s->ehci), "companion-enable", true,
126
+ &error_abort);
127
+ sysbus_realize(SYS_BUS_DEVICE(&s->ehci), &error_abort);
128
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->ehci), 0, NPCM7XX_EHCI_BA);
129
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->ehci), 0,
130
+ npcm7xx_irq(s, NPCM7XX_EHCI_IRQ));
131
+
132
+ object_property_set_str(OBJECT(&s->ohci), "masterbus", "usb-bus.0",
133
+ &error_abort);
134
+ object_property_set_uint(OBJECT(&s->ohci), "num-ports", 1, &error_abort);
135
+ sysbus_realize(SYS_BUS_DEVICE(&s->ohci), &error_abort);
136
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->ohci), 0, NPCM7XX_OHCI_BA);
137
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->ohci), 0,
138
+ npcm7xx_irq(s, NPCM7XX_OHCI_IRQ));
139
+
140
/*
141
* Flash Interface Unit (FIU). Can fail if incorrect number of chip selects
142
* specified, but this is a programming error.
143
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
144
create_unimplemented_device("npcm7xx.mcphy", 0xf05f0000, 64 * KiB);
145
create_unimplemented_device("npcm7xx.gmac1", 0xf0802000, 8 * KiB);
146
create_unimplemented_device("npcm7xx.gmac2", 0xf0804000, 8 * KiB);
147
- create_unimplemented_device("npcm7xx.ehci", 0xf0806000, 4 * KiB);
148
- create_unimplemented_device("npcm7xx.ohci", 0xf0807000, 4 * KiB);
149
create_unimplemented_device("npcm7xx.vcd", 0xf0810000, 64 * KiB);
150
create_unimplemented_device("npcm7xx.ece", 0xf0820000, 8 * KiB);
151
create_unimplemented_device("npcm7xx.vdma", 0xf0822000, 8 * KiB);
152
diff --git a/hw/usb/hcd-ehci-sysbus.c b/hw/usb/hcd-ehci-sysbus.c
153
index XXXXXXX..XXXXXXX 100644
154
--- a/hw/usb/hcd-ehci-sysbus.c
155
+++ b/hw/usb/hcd-ehci-sysbus.c
156
@@ -XXX,XX +XXX,XX @@ static const TypeInfo ehci_aw_h3_type_info = {
157
.class_init = ehci_aw_h3_class_init,
158
};
159
160
+static void ehci_npcm7xx_class_init(ObjectClass *oc, void *data)
161
+{
162
+ SysBusEHCIClass *sec = SYS_BUS_EHCI_CLASS(oc);
163
+ DeviceClass *dc = DEVICE_CLASS(oc);
164
+
165
+ sec->capsbase = 0x0;
166
+ sec->opregbase = 0x10;
167
+ sec->portscbase = 0x44;
168
+ sec->portnr = 1;
169
+ set_bit(DEVICE_CATEGORY_USB, dc->categories);
170
+}
171
+
172
+static const TypeInfo ehci_npcm7xx_type_info = {
173
+ .name = TYPE_NPCM7XX_EHCI,
174
+ .parent = TYPE_SYS_BUS_EHCI,
175
+ .class_init = ehci_npcm7xx_class_init,
176
+};
177
+
178
static void ehci_tegra2_class_init(ObjectClass *oc, void *data)
179
{
180
SysBusEHCIClass *sec = SYS_BUS_EHCI_CLASS(oc);
181
@@ -XXX,XX +XXX,XX @@ static void ehci_sysbus_register_types(void)
182
type_register_static(&ehci_platform_type_info);
183
type_register_static(&ehci_exynos4210_type_info);
184
type_register_static(&ehci_aw_h3_type_info);
185
+ type_register_static(&ehci_npcm7xx_type_info);
186
type_register_static(&ehci_tegra2_type_info);
187
type_register_static(&ehci_ppc4xx_type_info);
188
type_register_static(&ehci_fusbh200_type_info);
189
--
64
--
190
2.20.1
65
2.34.1
191
192
diff view generated by jsdifflib
1
From: Hao Wu <wuhaotsh@google.com>
1
From: Jinjie Ruan <ruanjinjie@huawei.com>
2
2
3
The watchdog is part of NPCM7XX's timer module. Its behavior is
3
Set or clear PSTATE.ALLINT on taking an exception to ELx according to the
4
controlled by the WTCR register in the timer.
4
SCTLR_ELx.SPINTMASK bit.
5
5
6
When enabled, the watchdog issues an interrupt signal after a pre-set
6
Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com>
7
amount of cycles, and issues a reset signal shortly after that.
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
9
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
10
Signed-off-by: Hao Wu <wuhaotsh@google.com>
11
Signed-off-by: Havard Skinnemoen <hskinnemoen@google.com>
12
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
13
[PMM: deleted blank line at end of npcm_watchdog_timer-test.c]
9
Message-id: 20240407081733.3231820-10-ruanjinjie@huawei.com
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
---
11
---
16
include/hw/misc/npcm7xx_clk.h | 2 +
12
target/arm/helper.c | 8 ++++++++
17
include/hw/timer/npcm7xx_timer.h | 48 +++-
13
1 file changed, 8 insertions(+)
18
hw/arm/npcm7xx.c | 12 +
19
hw/misc/npcm7xx_clk.c | 28 ++
20
hw/timer/npcm7xx_timer.c | 266 ++++++++++++++----
21
tests/qtest/npcm7xx_watchdog_timer-test.c | 319 ++++++++++++++++++++++
22
MAINTAINERS | 1 +
23
tests/qtest/meson.build | 2 +-
24
8 files changed, 624 insertions(+), 54 deletions(-)
25
create mode 100644 tests/qtest/npcm7xx_watchdog_timer-test.c
26
14
27
diff --git a/include/hw/misc/npcm7xx_clk.h b/include/hw/misc/npcm7xx_clk.h
15
diff --git a/target/arm/helper.c b/target/arm/helper.c
28
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
29
--- a/include/hw/misc/npcm7xx_clk.h
17
--- a/target/arm/helper.c
30
+++ b/include/hw/misc/npcm7xx_clk.h
18
+++ b/target/arm/helper.c
31
@@ -XXX,XX +XXX,XX @@
19
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_do_interrupt_aarch64(CPUState *cs)
32
*/
33
#define NPCM7XX_CLK_NR_REGS (0x70 / sizeof(uint32_t))
34
35
+#define NPCM7XX_WATCHDOG_RESET_GPIO_IN "npcm7xx-clk-watchdog-reset-gpio-in"
36
+
37
typedef struct NPCM7xxCLKState {
38
SysBusDevice parent;
39
40
diff --git a/include/hw/timer/npcm7xx_timer.h b/include/hw/timer/npcm7xx_timer.h
41
index XXXXXXX..XXXXXXX 100644
42
--- a/include/hw/timer/npcm7xx_timer.h
43
+++ b/include/hw/timer/npcm7xx_timer.h
44
@@ -XXX,XX +XXX,XX @@
45
*/
46
#define NPCM7XX_TIMER_NR_REGS (0x54 / sizeof(uint32_t))
47
48
+/* The basic watchdog timer period is 2^14 clock cycles. */
49
+#define NPCM7XX_WATCHDOG_BASETIME_SHIFT 14
50
+
51
+#define NPCM7XX_WATCHDOG_RESET_GPIO_OUT "npcm7xx-clk-watchdog-reset-gpio-out"
52
+
53
typedef struct NPCM7xxTimerCtrlState NPCM7xxTimerCtrlState;
54
55
/**
56
- * struct NPCM7xxTimer - Individual timer state.
57
- * @irq: GIC interrupt line to fire on expiration (if enabled).
58
+ * struct NPCM7xxBaseTimer - Basic functionality that both regular timer and
59
+ * watchdog timer use.
60
* @qtimer: QEMU timer that notifies us on expiration.
61
* @expires_ns: Absolute virtual expiration time.
62
* @remaining_ns: Remaining time until expiration if timer is paused.
63
+ */
64
+typedef struct NPCM7xxBaseTimer {
65
+ QEMUTimer qtimer;
66
+ int64_t expires_ns;
67
+ int64_t remaining_ns;
68
+} NPCM7xxBaseTimer;
69
+
70
+/**
71
+ * struct NPCM7xxTimer - Individual timer state.
72
+ * @ctrl: The timer module that owns this timer.
73
+ * @irq: GIC interrupt line to fire on expiration (if enabled).
74
+ * @base_timer: The basic timer functionality for this timer.
75
* @tcsr: The Timer Control and Status Register.
76
* @ticr: The Timer Initial Count Register.
77
*/
78
@@ -XXX,XX +XXX,XX @@ typedef struct NPCM7xxTimer {
79
NPCM7xxTimerCtrlState *ctrl;
80
81
qemu_irq irq;
82
- QEMUTimer qtimer;
83
- int64_t expires_ns;
84
- int64_t remaining_ns;
85
+ NPCM7xxBaseTimer base_timer;
86
87
uint32_t tcsr;
88
uint32_t ticr;
89
} NPCM7xxTimer;
90
91
+/**
92
+ * struct NPCM7xxWatchdogTimer - The watchdog timer state.
93
+ * @ctrl: The timer module that owns this timer.
94
+ * @irq: GIC interrupt line to fire on expiration (if enabled).
95
+ * @reset_signal: The GPIO used to send a reset signal.
96
+ * @base_timer: The basic timer functionality for this timer.
97
+ * @wtcr: The Watchdog Timer Control Register.
98
+ */
99
+typedef struct NPCM7xxWatchdogTimer {
100
+ NPCM7xxTimerCtrlState *ctrl;
101
+
102
+ qemu_irq irq;
103
+ qemu_irq reset_signal;
104
+ NPCM7xxBaseTimer base_timer;
105
+
106
+ uint32_t wtcr;
107
+} NPCM7xxWatchdogTimer;
108
+
109
/**
110
* struct NPCM7xxTimerCtrlState - Timer Module device state.
111
* @parent: System bus device.
112
* @iomem: Memory region through which registers are accessed.
113
+ * @index: The index of this timer module.
114
* @tisr: The Timer Interrupt Status Register.
115
- * @wtcr: The Watchdog Timer Control Register.
116
* @timer: The five individual timers managed by this module.
117
+ * @watchdog_timer: The watchdog timer managed by this module.
118
*/
119
struct NPCM7xxTimerCtrlState {
120
SysBusDevice parent;
121
@@ -XXX,XX +XXX,XX @@ struct NPCM7xxTimerCtrlState {
122
MemoryRegion iomem;
123
124
uint32_t tisr;
125
- uint32_t wtcr;
126
127
NPCM7xxTimer timer[NPCM7XX_TIMERS_PER_CTRL];
128
+ NPCM7xxWatchdogTimer watchdog_timer;
129
};
130
131
#define TYPE_NPCM7XX_TIMER "npcm7xx-timer"
132
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
133
index XXXXXXX..XXXXXXX 100644
134
--- a/hw/arm/npcm7xx.c
135
+++ b/hw/arm/npcm7xx.c
136
@@ -XXX,XX +XXX,XX @@ enum NPCM7xxInterrupt {
137
NPCM7XX_TIMER12_IRQ,
138
NPCM7XX_TIMER13_IRQ,
139
NPCM7XX_TIMER14_IRQ,
140
+ NPCM7XX_WDG0_IRQ = 47, /* Timer Module 0 Watchdog */
141
+ NPCM7XX_WDG1_IRQ, /* Timer Module 1 Watchdog */
142
+ NPCM7XX_WDG2_IRQ, /* Timer Module 2 Watchdog */
143
};
144
145
/* Total number of GIC interrupts, including internal Cortex-A9 interrupts. */
146
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
147
qemu_irq irq = npcm7xx_irq(s, first_irq + j);
148
sysbus_connect_irq(sbd, j, irq);
149
}
150
+
151
+ /* IRQ for watchdogs */
152
+ sysbus_connect_irq(sbd, NPCM7XX_TIMERS_PER_CTRL,
153
+ npcm7xx_irq(s, NPCM7XX_WDG0_IRQ + i));
154
+ /* GPIO that connects clk module with watchdog */
155
+ qdev_connect_gpio_out_named(DEVICE(&s->tim[i]),
156
+ NPCM7XX_WATCHDOG_RESET_GPIO_OUT, 0,
157
+ qdev_get_gpio_in_named(DEVICE(&s->clk),
158
+ NPCM7XX_WATCHDOG_RESET_GPIO_IN, i));
159
}
160
161
/* UART0..3 (16550 compatible) */
162
diff --git a/hw/misc/npcm7xx_clk.c b/hw/misc/npcm7xx_clk.c
163
index XXXXXXX..XXXXXXX 100644
164
--- a/hw/misc/npcm7xx_clk.c
165
+++ b/hw/misc/npcm7xx_clk.c
166
@@ -XXX,XX +XXX,XX @@
167
#include "qemu/osdep.h"
168
169
#include "hw/misc/npcm7xx_clk.h"
170
+#include "hw/timer/npcm7xx_timer.h"
171
#include "migration/vmstate.h"
172
#include "qemu/error-report.h"
173
#include "qemu/log.h"
174
@@ -XXX,XX +XXX,XX @@
175
#include "qemu/timer.h"
176
#include "qemu/units.h"
177
#include "trace.h"
178
+#include "sysemu/watchdog.h"
179
180
#define PLLCON_LOKI BIT(31)
181
#define PLLCON_LOKS BIT(30)
182
@@ -XXX,XX +XXX,XX @@ static const uint32_t cold_reset_values[NPCM7XX_CLK_NR_REGS] = {
183
[NPCM7XX_CLK_AHBCKFI] = 0x000000c8,
184
};
185
186
+/* Register Field Definitions */
187
+#define NPCM7XX_CLK_WDRCR_CA9C BIT(0) /* Cortex A9 Cores */
188
+
189
+/* The number of watchdogs that can trigger a reset. */
190
+#define NPCM7XX_NR_WATCHDOGS (3)
191
+
192
static uint64_t npcm7xx_clk_read(void *opaque, hwaddr offset, unsigned size)
193
{
194
uint32_t reg = offset / sizeof(uint32_t);
195
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_clk_write(void *opaque, hwaddr offset,
196
s->regs[reg] = value;
197
}
198
199
+/* Perform reset action triggered by a watchdog */
200
+static void npcm7xx_clk_perform_watchdog_reset(void *opaque, int n,
201
+ int level)
202
+{
203
+ NPCM7xxCLKState *clk = NPCM7XX_CLK(opaque);
204
+ uint32_t rcr;
205
+
206
+ g_assert(n >= 0 && n <= NPCM7XX_NR_WATCHDOGS);
207
+ rcr = clk->regs[NPCM7XX_CLK_WD0RCR + n];
208
+ if (rcr & NPCM7XX_CLK_WDRCR_CA9C) {
209
+ watchdog_perform_action();
210
+ } else {
211
+ qemu_log_mask(LOG_UNIMP,
212
+ "%s: only CPU reset is implemented. (requested 0x%" PRIx32")\n",
213
+ __func__, rcr);
214
+ }
215
+}
216
+
217
static const struct MemoryRegionOps npcm7xx_clk_ops = {
218
.read = npcm7xx_clk_read,
219
.write = npcm7xx_clk_write,
220
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_clk_init(Object *obj)
221
memory_region_init_io(&s->iomem, obj, &npcm7xx_clk_ops, s,
222
TYPE_NPCM7XX_CLK, 4 * KiB);
223
sysbus_init_mmio(&s->parent, &s->iomem);
224
+ qdev_init_gpio_in_named(DEVICE(s), npcm7xx_clk_perform_watchdog_reset,
225
+ NPCM7XX_WATCHDOG_RESET_GPIO_IN, NPCM7XX_NR_WATCHDOGS);
226
}
227
228
static const VMStateDescription vmstate_npcm7xx_clk = {
229
diff --git a/hw/timer/npcm7xx_timer.c b/hw/timer/npcm7xx_timer.c
230
index XXXXXXX..XXXXXXX 100644
231
--- a/hw/timer/npcm7xx_timer.c
232
+++ b/hw/timer/npcm7xx_timer.c
233
@@ -XXX,XX +XXX,XX @@
234
#include "qemu/osdep.h"
235
236
#include "hw/irq.h"
237
+#include "hw/qdev-properties.h"
238
#include "hw/misc/npcm7xx_clk.h"
239
#include "hw/timer/npcm7xx_timer.h"
240
#include "migration/vmstate.h"
241
@@ -XXX,XX +XXX,XX @@ enum NPCM7xxTimerRegisters {
242
#define NPCM7XX_TCSR_PRESCALE_START 0
243
#define NPCM7XX_TCSR_PRESCALE_LEN 8
244
245
+#define NPCM7XX_WTCR_WTCLK(rv) extract32(rv, 10, 2)
246
+#define NPCM7XX_WTCR_FREEZE_EN BIT(9)
247
+#define NPCM7XX_WTCR_WTE BIT(7)
248
+#define NPCM7XX_WTCR_WTIE BIT(6)
249
+#define NPCM7XX_WTCR_WTIS(rv) extract32(rv, 4, 2)
250
+#define NPCM7XX_WTCR_WTIF BIT(3)
251
+#define NPCM7XX_WTCR_WTRF BIT(2)
252
+#define NPCM7XX_WTCR_WTRE BIT(1)
253
+#define NPCM7XX_WTCR_WTR BIT(0)
254
+
255
+/*
256
+ * The number of clock cycles between interrupt and reset in watchdog, used
257
+ * by the software to handle the interrupt before system is reset.
258
+ */
259
+#define NPCM7XX_WATCHDOG_INTERRUPT_TO_RESET_CYCLES 1024
260
+
261
+/* Start or resume the timer. */
262
+static void npcm7xx_timer_start(NPCM7xxBaseTimer *t)
263
+{
264
+ int64_t now;
265
+
266
+ now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
267
+ t->expires_ns = now + t->remaining_ns;
268
+ timer_mod(&t->qtimer, t->expires_ns);
269
+}
270
+
271
+/* Stop counting. Record the time remaining so we can continue later. */
272
+static void npcm7xx_timer_pause(NPCM7xxBaseTimer *t)
273
+{
274
+ int64_t now;
275
+
276
+ timer_del(&t->qtimer);
277
+ now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
278
+ t->remaining_ns = t->expires_ns - now;
279
+}
280
+
281
+/* Delete the timer and reset it to default state. */
282
+static void npcm7xx_timer_clear(NPCM7xxBaseTimer *t)
283
+{
284
+ timer_del(&t->qtimer);
285
+ t->expires_ns = 0;
286
+ t->remaining_ns = 0;
287
+}
288
+
289
/*
290
* Returns the index of timer in the tc->timer array. This can be used to
291
* locate the registers that belong to this timer.
292
@@ -XXX,XX +XXX,XX @@ static uint32_t npcm7xx_timer_ns_to_count(NPCM7xxTimer *t, int64_t ns)
293
return count;
294
}
295
296
+static uint32_t npcm7xx_watchdog_timer_prescaler(const NPCM7xxWatchdogTimer *t)
297
+{
298
+ switch (NPCM7XX_WTCR_WTCLK(t->wtcr)) {
299
+ case 0:
300
+ return 1;
301
+ case 1:
302
+ return 256;
303
+ case 2:
304
+ return 2048;
305
+ case 3:
306
+ return 65536;
307
+ default:
308
+ g_assert_not_reached();
309
+ }
310
+}
311
+
312
+static void npcm7xx_watchdog_timer_reset_cycles(NPCM7xxWatchdogTimer *t,
313
+ int64_t cycles)
314
+{
315
+ uint32_t prescaler = npcm7xx_watchdog_timer_prescaler(t);
316
+ int64_t ns = (NANOSECONDS_PER_SECOND / NPCM7XX_TIMER_REF_HZ) * cycles;
317
+
318
+ /*
319
+ * The reset function always clears the current timer. The caller of the
320
+ * this needs to decide whether to start the watchdog timer based on
321
+ * specific flag in WTCR.
322
+ */
323
+ npcm7xx_timer_clear(&t->base_timer);
324
+
325
+ ns *= prescaler;
326
+ t->base_timer.remaining_ns = ns;
327
+}
328
+
329
+static void npcm7xx_watchdog_timer_reset(NPCM7xxWatchdogTimer *t)
330
+{
331
+ int64_t cycles = 1;
332
+ uint32_t s = NPCM7XX_WTCR_WTIS(t->wtcr);
333
+
334
+ g_assert(s <= 3);
335
+
336
+ cycles <<= NPCM7XX_WATCHDOG_BASETIME_SHIFT;
337
+ cycles <<= 2 * s;
338
+
339
+ npcm7xx_watchdog_timer_reset_cycles(t, cycles);
340
+}
341
+
342
/*
343
* Raise the interrupt line if there's a pending interrupt and interrupts are
344
* enabled for this timer. If not, lower it.
345
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_timer_check_interrupt(NPCM7xxTimer *t)
346
trace_npcm7xx_timer_irq(DEVICE(tc)->canonical_path, index, pending);
347
}
348
349
-/* Start or resume the timer. */
350
-static void npcm7xx_timer_start(NPCM7xxTimer *t)
351
-{
352
- int64_t now;
353
-
354
- now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
355
- t->expires_ns = now + t->remaining_ns;
356
- timer_mod(&t->qtimer, t->expires_ns);
357
-}
358
-
359
/*
360
* Called when the counter reaches zero. Sets the interrupt flag, and either
361
* restarts or disables the timer.
362
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_timer_reached_zero(NPCM7xxTimer *t)
363
tc->tisr |= BIT(index);
364
365
if (t->tcsr & NPCM7XX_TCSR_PERIODIC) {
366
- t->remaining_ns = npcm7xx_timer_count_to_ns(t, t->ticr);
367
+ t->base_timer.remaining_ns = npcm7xx_timer_count_to_ns(t, t->ticr);
368
if (t->tcsr & NPCM7XX_TCSR_CEN) {
369
- npcm7xx_timer_start(t);
370
+ npcm7xx_timer_start(&t->base_timer);
371
}
372
} else {
373
t->tcsr &= ~(NPCM7XX_TCSR_CEN | NPCM7XX_TCSR_CACT);
374
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_timer_reached_zero(NPCM7xxTimer *t)
375
npcm7xx_timer_check_interrupt(t);
376
}
377
378
-/* Stop counting. Record the time remaining so we can continue later. */
379
-static void npcm7xx_timer_pause(NPCM7xxTimer *t)
380
-{
381
- int64_t now;
382
-
383
- timer_del(&t->qtimer);
384
- now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
385
- t->remaining_ns = t->expires_ns - now;
386
-}
387
388
/*
389
* Restart the timer from its initial value. If the timer was enabled and stays
390
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_timer_pause(NPCM7xxTimer *t)
391
*/
392
static void npcm7xx_timer_restart(NPCM7xxTimer *t, uint32_t old_tcsr)
393
{
394
- t->remaining_ns = npcm7xx_timer_count_to_ns(t, t->ticr);
395
+ t->base_timer.remaining_ns = npcm7xx_timer_count_to_ns(t, t->ticr);
396
397
if (old_tcsr & t->tcsr & NPCM7XX_TCSR_CEN) {
398
- npcm7xx_timer_start(t);
399
+ npcm7xx_timer_start(&t->base_timer);
400
}
401
}
402
403
@@ -XXX,XX +XXX,XX @@ static uint32_t npcm7xx_timer_read_tdr(NPCM7xxTimer *t)
404
if (t->tcsr & NPCM7XX_TCSR_CEN) {
405
int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
406
407
- return npcm7xx_timer_ns_to_count(t, t->expires_ns - now);
408
+ return npcm7xx_timer_ns_to_count(t, t->base_timer.expires_ns - now);
409
}
410
411
- return npcm7xx_timer_ns_to_count(t, t->remaining_ns);
412
+ return npcm7xx_timer_ns_to_count(t, t->base_timer.remaining_ns);
413
}
414
415
static void npcm7xx_timer_write_tcsr(NPCM7xxTimer *t, uint32_t new_tcsr)
416
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_timer_write_tcsr(NPCM7xxTimer *t, uint32_t new_tcsr)
417
418
if (npcm7xx_tcsr_prescaler(old_tcsr) != npcm7xx_tcsr_prescaler(new_tcsr)) {
419
/* Recalculate time remaining based on the current TDR value. */
420
- t->remaining_ns = npcm7xx_timer_count_to_ns(t, tdr);
421
+ t->base_timer.remaining_ns = npcm7xx_timer_count_to_ns(t, tdr);
422
if (old_tcsr & t->tcsr & NPCM7XX_TCSR_CEN) {
423
- npcm7xx_timer_start(t);
424
+ npcm7xx_timer_start(&t->base_timer);
425
}
20
}
426
}
21
}
427
22
428
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_timer_write_tcsr(NPCM7xxTimer *t, uint32_t new_tcsr)
23
+ if (cpu_isar_feature(aa64_nmi, cpu)) {
429
if ((old_tcsr ^ new_tcsr) & NPCM7XX_TCSR_CEN) {
24
+ if (!(env->cp15.sctlr_el[new_el] & SCTLR_SPINTMASK)) {
430
if (new_tcsr & NPCM7XX_TCSR_CEN) {
25
+ new_mode |= PSTATE_ALLINT;
431
t->tcsr |= NPCM7XX_TCSR_CACT;
432
- npcm7xx_timer_start(t);
433
+ npcm7xx_timer_start(&t->base_timer);
434
} else {
435
t->tcsr &= ~NPCM7XX_TCSR_CACT;
436
- npcm7xx_timer_pause(t);
437
- if (t->remaining_ns <= 0) {
438
+ npcm7xx_timer_pause(&t->base_timer);
439
+ if (t->base_timer.remaining_ns <= 0) {
440
npcm7xx_timer_reached_zero(t);
441
}
442
}
443
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_timer_write_tisr(NPCM7xxTimerCtrlState *s, uint32_t value)
444
if (value & (1U << i)) {
445
npcm7xx_timer_check_interrupt(&s->timer[i]);
446
}
447
+
448
}
449
}
450
451
+static void npcm7xx_timer_write_wtcr(NPCM7xxWatchdogTimer *t, uint32_t new_wtcr)
452
+{
453
+ uint32_t old_wtcr = t->wtcr;
454
+
455
+ /*
456
+ * WTIF and WTRF are cleared by writing 1. Writing 0 makes these bits
457
+ * unchanged.
458
+ */
459
+ if (new_wtcr & NPCM7XX_WTCR_WTIF) {
460
+ new_wtcr &= ~NPCM7XX_WTCR_WTIF;
461
+ } else if (old_wtcr & NPCM7XX_WTCR_WTIF) {
462
+ new_wtcr |= NPCM7XX_WTCR_WTIF;
463
+ }
464
+ if (new_wtcr & NPCM7XX_WTCR_WTRF) {
465
+ new_wtcr &= ~NPCM7XX_WTCR_WTRF;
466
+ } else if (old_wtcr & NPCM7XX_WTCR_WTRF) {
467
+ new_wtcr |= NPCM7XX_WTCR_WTRF;
468
+ }
469
+
470
+ t->wtcr = new_wtcr;
471
+
472
+ if (new_wtcr & NPCM7XX_WTCR_WTR) {
473
+ t->wtcr &= ~NPCM7XX_WTCR_WTR;
474
+ npcm7xx_watchdog_timer_reset(t);
475
+ if (new_wtcr & NPCM7XX_WTCR_WTE) {
476
+ npcm7xx_timer_start(&t->base_timer);
477
+ }
478
+ } else if ((old_wtcr ^ new_wtcr) & NPCM7XX_WTCR_WTE) {
479
+ if (new_wtcr & NPCM7XX_WTCR_WTE) {
480
+ npcm7xx_timer_start(&t->base_timer);
481
+ } else {
26
+ } else {
482
+ npcm7xx_timer_pause(&t->base_timer);
27
+ new_mode &= ~PSTATE_ALLINT;
483
+ }
28
+ }
484
+ }
29
+ }
485
+
30
+
486
+}
31
pstate_write(env, PSTATE_DAIF | new_mode);
487
+
32
env->aarch64 = true;
488
static hwaddr npcm7xx_tcsr_index(hwaddr reg)
33
aarch64_restore_sp(env, new_el);
489
{
490
switch (reg) {
491
@@ -XXX,XX +XXX,XX @@ static uint64_t npcm7xx_timer_read(void *opaque, hwaddr offset, unsigned size)
492
break;
493
494
case NPCM7XX_TIMER_WTCR:
495
- value = s->wtcr;
496
+ value = s->watchdog_timer.wtcr;
497
break;
498
499
default:
500
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_timer_write(void *opaque, hwaddr offset,
501
return;
502
503
case NPCM7XX_TIMER_WTCR:
504
- qemu_log_mask(LOG_UNIMP, "%s: WTCR write not implemented: 0x%08x\n",
505
- __func__, value);
506
+ npcm7xx_timer_write_wtcr(&s->watchdog_timer, value);
507
return;
508
}
509
510
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_timer_enter_reset(Object *obj, ResetType type)
511
for (i = 0; i < NPCM7XX_TIMERS_PER_CTRL; i++) {
512
NPCM7xxTimer *t = &s->timer[i];
513
514
- timer_del(&t->qtimer);
515
- t->expires_ns = 0;
516
- t->remaining_ns = 0;
517
+ npcm7xx_timer_clear(&t->base_timer);
518
t->tcsr = 0x00000005;
519
t->ticr = 0x00000000;
520
}
521
522
s->tisr = 0x00000000;
523
- s->wtcr = 0x00000400;
524
+ /*
525
+ * Set WTCLK to 1(default) and reset all flags except WTRF.
526
+ * WTRF is not reset during a core domain reset.
527
+ */
528
+ s->watchdog_timer.wtcr = 0x00000400 | (s->watchdog_timer.wtcr &
529
+ NPCM7XX_WTCR_WTRF);
530
+}
531
+
532
+static void npcm7xx_watchdog_timer_expired(void *opaque)
533
+{
534
+ NPCM7xxWatchdogTimer *t = opaque;
535
+
536
+ if (t->wtcr & NPCM7XX_WTCR_WTE) {
537
+ if (t->wtcr & NPCM7XX_WTCR_WTIF) {
538
+ if (t->wtcr & NPCM7XX_WTCR_WTRE) {
539
+ t->wtcr |= NPCM7XX_WTCR_WTRF;
540
+ /* send reset signal to CLK module*/
541
+ qemu_irq_raise(t->reset_signal);
542
+ }
543
+ } else {
544
+ t->wtcr |= NPCM7XX_WTCR_WTIF;
545
+ if (t->wtcr & NPCM7XX_WTCR_WTIE) {
546
+ /* send interrupt */
547
+ qemu_irq_raise(t->irq);
548
+ }
549
+ npcm7xx_watchdog_timer_reset_cycles(t,
550
+ NPCM7XX_WATCHDOG_INTERRUPT_TO_RESET_CYCLES);
551
+ npcm7xx_timer_start(&t->base_timer);
552
+ }
553
+ }
554
}
555
556
static void npcm7xx_timer_hold_reset(Object *obj)
557
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_timer_hold_reset(Object *obj)
558
for (i = 0; i < NPCM7XX_TIMERS_PER_CTRL; i++) {
559
qemu_irq_lower(s->timer[i].irq);
560
}
561
+ qemu_irq_lower(s->watchdog_timer.irq);
562
}
563
564
static void npcm7xx_timer_realize(DeviceState *dev, Error **errp)
565
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_timer_realize(DeviceState *dev, Error **errp)
566
NPCM7xxTimerCtrlState *s = NPCM7XX_TIMER(dev);
567
SysBusDevice *sbd = &s->parent;
568
int i;
569
+ NPCM7xxWatchdogTimer *w;
570
571
for (i = 0; i < NPCM7XX_TIMERS_PER_CTRL; i++) {
572
NPCM7xxTimer *t = &s->timer[i];
573
t->ctrl = s;
574
- timer_init_ns(&t->qtimer, QEMU_CLOCK_VIRTUAL, npcm7xx_timer_expired, t);
575
+ timer_init_ns(&t->base_timer.qtimer, QEMU_CLOCK_VIRTUAL,
576
+ npcm7xx_timer_expired, t);
577
sysbus_init_irq(sbd, &t->irq);
578
}
579
580
+ w = &s->watchdog_timer;
581
+ w->ctrl = s;
582
+ timer_init_ns(&w->base_timer.qtimer, QEMU_CLOCK_VIRTUAL,
583
+ npcm7xx_watchdog_timer_expired, w);
584
+ sysbus_init_irq(sbd, &w->irq);
585
+
586
memory_region_init_io(&s->iomem, OBJECT(s), &npcm7xx_timer_ops, s,
587
TYPE_NPCM7XX_TIMER, 4 * KiB);
588
sysbus_init_mmio(sbd, &s->iomem);
589
+ qdev_init_gpio_out_named(dev, &w->reset_signal,
590
+ NPCM7XX_WATCHDOG_RESET_GPIO_OUT, 1);
591
}
592
593
-static const VMStateDescription vmstate_npcm7xx_timer = {
594
- .name = "npcm7xx-timer",
595
+static const VMStateDescription vmstate_npcm7xx_base_timer = {
596
+ .name = "npcm7xx-base-timer",
597
.version_id = 0,
598
.minimum_version_id = 0,
599
.fields = (VMStateField[]) {
600
- VMSTATE_TIMER(qtimer, NPCM7xxTimer),
601
- VMSTATE_INT64(expires_ns, NPCM7xxTimer),
602
- VMSTATE_INT64(remaining_ns, NPCM7xxTimer),
603
+ VMSTATE_TIMER(qtimer, NPCM7xxBaseTimer),
604
+ VMSTATE_INT64(expires_ns, NPCM7xxBaseTimer),
605
+ VMSTATE_INT64(remaining_ns, NPCM7xxBaseTimer),
606
+ VMSTATE_END_OF_LIST(),
607
+ },
608
+};
609
+
610
+static const VMStateDescription vmstate_npcm7xx_timer = {
611
+ .name = "npcm7xx-timer",
612
+ .version_id = 1,
613
+ .minimum_version_id = 1,
614
+ .fields = (VMStateField[]) {
615
+ VMSTATE_STRUCT(base_timer, NPCM7xxTimer,
616
+ 0, vmstate_npcm7xx_base_timer,
617
+ NPCM7xxBaseTimer),
618
VMSTATE_UINT32(tcsr, NPCM7xxTimer),
619
VMSTATE_UINT32(ticr, NPCM7xxTimer),
620
VMSTATE_END_OF_LIST(),
621
},
622
};
623
624
-static const VMStateDescription vmstate_npcm7xx_timer_ctrl = {
625
- .name = "npcm7xx-timer-ctrl",
626
+static const VMStateDescription vmstate_npcm7xx_watchdog_timer = {
627
+ .name = "npcm7xx-watchdog-timer",
628
.version_id = 0,
629
.minimum_version_id = 0,
630
+ .fields = (VMStateField[]) {
631
+ VMSTATE_STRUCT(base_timer, NPCM7xxWatchdogTimer,
632
+ 0, vmstate_npcm7xx_base_timer,
633
+ NPCM7xxBaseTimer),
634
+ VMSTATE_UINT32(wtcr, NPCM7xxWatchdogTimer),
635
+ VMSTATE_END_OF_LIST(),
636
+ },
637
+};
638
+
639
+static const VMStateDescription vmstate_npcm7xx_timer_ctrl = {
640
+ .name = "npcm7xx-timer-ctrl",
641
+ .version_id = 1,
642
+ .minimum_version_id = 1,
643
.fields = (VMStateField[]) {
644
VMSTATE_UINT32(tisr, NPCM7xxTimerCtrlState),
645
- VMSTATE_UINT32(wtcr, NPCM7xxTimerCtrlState),
646
VMSTATE_STRUCT_ARRAY(timer, NPCM7xxTimerCtrlState,
647
NPCM7XX_TIMERS_PER_CTRL, 0, vmstate_npcm7xx_timer,
648
NPCM7xxTimer),
649
+ VMSTATE_STRUCT(watchdog_timer, NPCM7xxTimerCtrlState,
650
+ 0, vmstate_npcm7xx_watchdog_timer,
651
+ NPCM7xxWatchdogTimer),
652
VMSTATE_END_OF_LIST(),
653
},
654
};
655
diff --git a/tests/qtest/npcm7xx_watchdog_timer-test.c b/tests/qtest/npcm7xx_watchdog_timer-test.c
656
new file mode 100644
657
index XXXXXXX..XXXXXXX
658
--- /dev/null
659
+++ b/tests/qtest/npcm7xx_watchdog_timer-test.c
660
@@ -XXX,XX +XXX,XX @@
661
+/*
662
+ * QTests for Nuvoton NPCM7xx Timer Watchdog Modules.
663
+ *
664
+ * Copyright 2020 Google LLC
665
+ *
666
+ * This program is free software; you can redistribute it and/or modify it
667
+ * under the terms of the GNU General Public License as published by the
668
+ * Free Software Foundation; either version 2 of the License, or
669
+ * (at your option) any later version.
670
+ *
671
+ * This program is distributed in the hope that it will be useful, but WITHOUT
672
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
673
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
674
+ * for more details.
675
+ */
676
+
677
+#include "qemu/osdep.h"
678
+#include "qemu/timer.h"
679
+
680
+#include "libqos/libqtest.h"
681
+#include "qapi/qmp/qdict.h"
682
+
683
+#define WTCR_OFFSET 0x1c
684
+#define REF_HZ (25000000)
685
+
686
+/* WTCR bit fields */
687
+#define WTCLK(rv) ((rv) << 10)
688
+#define WTE BIT(7)
689
+#define WTIE BIT(6)
690
+#define WTIS(rv) ((rv) << 4)
691
+#define WTIF BIT(3)
692
+#define WTRF BIT(2)
693
+#define WTRE BIT(1)
694
+#define WTR BIT(0)
695
+
696
+typedef struct Watchdog {
697
+ int irq;
698
+ uint64_t base_addr;
699
+} Watchdog;
700
+
701
+static const Watchdog watchdog_list[] = {
702
+ {
703
+ .irq = 47,
704
+ .base_addr = 0xf0008000
705
+ },
706
+ {
707
+ .irq = 48,
708
+ .base_addr = 0xf0009000
709
+ },
710
+ {
711
+ .irq = 49,
712
+ .base_addr = 0xf000a000
713
+ }
714
+};
715
+
716
+static int watchdog_index(const Watchdog *wd)
717
+{
718
+ ptrdiff_t diff = wd - watchdog_list;
719
+
720
+ g_assert(diff >= 0 && diff < ARRAY_SIZE(watchdog_list));
721
+
722
+ return diff;
723
+}
724
+
725
+static uint32_t watchdog_read_wtcr(QTestState *qts, const Watchdog *wd)
726
+{
727
+ return qtest_readl(qts, wd->base_addr + WTCR_OFFSET);
728
+}
729
+
730
+static void watchdog_write_wtcr(QTestState *qts, const Watchdog *wd,
731
+ uint32_t value)
732
+{
733
+ qtest_writel(qts, wd->base_addr + WTCR_OFFSET, value);
734
+}
735
+
736
+static uint32_t watchdog_prescaler(QTestState *qts, const Watchdog *wd)
737
+{
738
+ switch (extract32(watchdog_read_wtcr(qts, wd), 10, 2)) {
739
+ case 0:
740
+ return 1;
741
+ case 1:
742
+ return 256;
743
+ case 2:
744
+ return 2048;
745
+ case 3:
746
+ return 65536;
747
+ default:
748
+ g_assert_not_reached();
749
+ }
750
+}
751
+
752
+static QDict *get_watchdog_action(QTestState *qts)
753
+{
754
+ QDict *ev = qtest_qmp_eventwait_ref(qts, "WATCHDOG");
755
+ QDict *data;
756
+
757
+ data = qdict_get_qdict(ev, "data");
758
+ qobject_ref(data);
759
+ qobject_unref(ev);
760
+ return data;
761
+}
762
+
763
+#define RESET_CYCLES 1024
764
+static uint32_t watchdog_interrupt_cycles(QTestState *qts, const Watchdog *wd)
765
+{
766
+ uint32_t wtis = extract32(watchdog_read_wtcr(qts, wd), 4, 2);
767
+ return 1 << (14 + 2 * wtis);
768
+}
769
+
770
+static int64_t watchdog_calculate_steps(uint32_t count, uint32_t prescale)
771
+{
772
+ return (NANOSECONDS_PER_SECOND / REF_HZ) * count * prescale;
773
+}
774
+
775
+static int64_t watchdog_interrupt_steps(QTestState *qts, const Watchdog *wd)
776
+{
777
+ return watchdog_calculate_steps(watchdog_interrupt_cycles(qts, wd),
778
+ watchdog_prescaler(qts, wd));
779
+}
780
+
781
+/* Check wtcr can be reset to default value */
782
+static void test_init(gconstpointer watchdog)
783
+{
784
+ const Watchdog *wd = watchdog;
785
+ QTestState *qts = qtest_init("-machine quanta-gsj");
786
+
787
+ qtest_irq_intercept_in(qts, "/machine/soc/a9mpcore/gic");
788
+
789
+ watchdog_write_wtcr(qts, wd, WTCLK(1) | WTRF | WTIF | WTR);
790
+ g_assert_cmphex(watchdog_read_wtcr(qts, wd), ==, WTCLK(1));
791
+
792
+ qtest_quit(qts);
793
+}
794
+
795
+/* Check a watchdog can generate interrupt and reset actions */
796
+static void test_reset_action(gconstpointer watchdog)
797
+{
798
+ const Watchdog *wd = watchdog;
799
+ QTestState *qts = qtest_init("-machine quanta-gsj");
800
+ QDict *ad;
801
+
802
+ qtest_irq_intercept_in(qts, "/machine/soc/a9mpcore/gic");
803
+
804
+ watchdog_write_wtcr(qts, wd,
805
+ WTCLK(0) | WTE | WTRF | WTRE | WTIF | WTIE | WTR);
806
+ g_assert_cmphex(watchdog_read_wtcr(qts, wd), ==,
807
+ WTCLK(0) | WTE | WTRE | WTIE);
808
+
809
+ /* Check a watchdog can generate an interrupt */
810
+ qtest_clock_step(qts, watchdog_interrupt_steps(qts, wd));
811
+ g_assert_cmphex(watchdog_read_wtcr(qts, wd), ==,
812
+ WTCLK(0) | WTE | WTIF | WTIE | WTRE);
813
+ g_assert_true(qtest_get_irq(qts, wd->irq));
814
+
815
+ /* Check a watchdog can generate a reset signal */
816
+ qtest_clock_step(qts, watchdog_calculate_steps(RESET_CYCLES,
817
+ watchdog_prescaler(qts, wd)));
818
+ ad = get_watchdog_action(qts);
819
+ /* The signal is a reset signal */
820
+ g_assert_false(strcmp(qdict_get_str(ad, "action"), "reset"));
821
+ qobject_unref(ad);
822
+ qtest_qmp_eventwait(qts, "RESET");
823
+ /*
824
+ * Make sure WTCR is reset to default except for WTRF bit which shouldn't
825
+ * be reset.
826
+ */
827
+ g_assert_cmphex(watchdog_read_wtcr(qts, wd), ==, WTCLK(1) | WTRF);
828
+ qtest_quit(qts);
829
+}
830
+
831
+/* Check a watchdog works with all possible WTCLK prescalers and WTIS cycles */
832
+static void test_prescaler(gconstpointer watchdog)
833
+{
834
+ const Watchdog *wd = watchdog;
835
+
836
+ for (int wtclk = 0; wtclk < 4; ++wtclk) {
837
+ for (int wtis = 0; wtis < 4; ++wtis) {
838
+ QTestState *qts = qtest_init("-machine quanta-gsj");
839
+
840
+ qtest_irq_intercept_in(qts, "/machine/soc/a9mpcore/gic");
841
+ watchdog_write_wtcr(qts, wd,
842
+ WTCLK(wtclk) | WTE | WTIF | WTIS(wtis) | WTIE | WTR);
843
+ /*
844
+ * The interrupt doesn't fire until watchdog_interrupt_steps()
845
+ * cycles passed
846
+ */
847
+ qtest_clock_step(qts, watchdog_interrupt_steps(qts, wd) - 1);
848
+ g_assert_false(watchdog_read_wtcr(qts, wd) & WTIF);
849
+ g_assert_false(qtest_get_irq(qts, wd->irq));
850
+ qtest_clock_step(qts, 1);
851
+ g_assert_true(watchdog_read_wtcr(qts, wd) & WTIF);
852
+ g_assert_true(qtest_get_irq(qts, wd->irq));
853
+
854
+ qtest_quit(qts);
855
+ }
856
+ }
857
+}
858
+
859
+/*
860
+ * Check a watchdog doesn't fire if corresponding flags (WTIE and WTRE) are not
861
+ * set.
862
+ */
863
+static void test_enabling_flags(gconstpointer watchdog)
864
+{
865
+ const Watchdog *wd = watchdog;
866
+ QTestState *qts;
867
+
868
+ /* Neither WTIE or WTRE is set, no interrupt or reset should happen */
869
+ qts = qtest_init("-machine quanta-gsj");
870
+ qtest_irq_intercept_in(qts, "/machine/soc/a9mpcore/gic");
871
+ watchdog_write_wtcr(qts, wd, WTCLK(0) | WTE | WTIF | WTRF | WTR);
872
+ qtest_clock_step(qts, watchdog_interrupt_steps(qts, wd));
873
+ g_assert_true(watchdog_read_wtcr(qts, wd) & WTIF);
874
+ g_assert_false(qtest_get_irq(qts, wd->irq));
875
+ qtest_clock_step(qts, watchdog_calculate_steps(RESET_CYCLES,
876
+ watchdog_prescaler(qts, wd)));
877
+ g_assert_true(watchdog_read_wtcr(qts, wd) & WTIF);
878
+ g_assert_false(watchdog_read_wtcr(qts, wd) & WTRF);
879
+ qtest_quit(qts);
880
+
881
+ /* Only WTIE is set, interrupt is triggered but reset should not happen */
882
+ qts = qtest_init("-machine quanta-gsj");
883
+ qtest_irq_intercept_in(qts, "/machine/soc/a9mpcore/gic");
884
+ watchdog_write_wtcr(qts, wd, WTCLK(0) | WTE | WTIF | WTIE | WTRF | WTR);
885
+ qtest_clock_step(qts, watchdog_interrupt_steps(qts, wd));
886
+ g_assert_true(watchdog_read_wtcr(qts, wd) & WTIF);
887
+ g_assert_true(qtest_get_irq(qts, wd->irq));
888
+ qtest_clock_step(qts, watchdog_calculate_steps(RESET_CYCLES,
889
+ watchdog_prescaler(qts, wd)));
890
+ g_assert_true(watchdog_read_wtcr(qts, wd) & WTIF);
891
+ g_assert_false(watchdog_read_wtcr(qts, wd) & WTRF);
892
+ qtest_quit(qts);
893
+
894
+ /* Only WTRE is set, interrupt is triggered but reset should not happen */
895
+ qts = qtest_init("-machine quanta-gsj");
896
+ qtest_irq_intercept_in(qts, "/machine/soc/a9mpcore/gic");
897
+ watchdog_write_wtcr(qts, wd, WTCLK(0) | WTE | WTIF | WTRE | WTRF | WTR);
898
+ qtest_clock_step(qts, watchdog_interrupt_steps(qts, wd));
899
+ g_assert_true(watchdog_read_wtcr(qts, wd) & WTIF);
900
+ g_assert_false(qtest_get_irq(qts, wd->irq));
901
+ qtest_clock_step(qts, watchdog_calculate_steps(RESET_CYCLES,
902
+ watchdog_prescaler(qts, wd)));
903
+ g_assert_false(strcmp(qdict_get_str(get_watchdog_action(qts), "action"),
904
+ "reset"));
905
+ qtest_qmp_eventwait(qts, "RESET");
906
+ qtest_quit(qts);
907
+
908
+ /*
909
+ * The case when both flags are set is already tested in
910
+ * test_reset_action().
911
+ */
912
+}
913
+
914
+/* Check a watchdog can pause and resume by setting WTE bits */
915
+static void test_pause(gconstpointer watchdog)
916
+{
917
+ const Watchdog *wd = watchdog;
918
+ QTestState *qts;
919
+ int64_t remaining_steps, steps;
920
+
921
+ qts = qtest_init("-machine quanta-gsj");
922
+ qtest_irq_intercept_in(qts, "/machine/soc/a9mpcore/gic");
923
+ watchdog_write_wtcr(qts, wd, WTCLK(0) | WTE | WTIF | WTIE | WTRF | WTR);
924
+ remaining_steps = watchdog_interrupt_steps(qts, wd);
925
+ g_assert_cmphex(watchdog_read_wtcr(qts, wd), ==, WTCLK(0) | WTE | WTIE);
926
+
927
+ /* Run for half of the execution period. */
928
+ steps = remaining_steps / 2;
929
+ remaining_steps -= steps;
930
+ qtest_clock_step(qts, steps);
931
+
932
+ /* Pause the watchdog */
933
+ watchdog_write_wtcr(qts, wd, WTCLK(0) | WTIE);
934
+ g_assert_cmphex(watchdog_read_wtcr(qts, wd), ==, WTCLK(0) | WTIE);
935
+
936
+ /* Run for a long period of time, the watchdog shouldn't fire */
937
+ qtest_clock_step(qts, steps << 4);
938
+ g_assert_cmphex(watchdog_read_wtcr(qts, wd), ==, WTCLK(0) | WTIE);
939
+ g_assert_false(qtest_get_irq(qts, wd->irq));
940
+
941
+ /* Resume the watchdog */
942
+ watchdog_write_wtcr(qts, wd, WTCLK(0) | WTE | WTIE);
943
+ g_assert_cmphex(watchdog_read_wtcr(qts, wd), ==, WTCLK(0) | WTE | WTIE);
944
+
945
+ /* Run for the reset of the execution period, the watchdog should fire */
946
+ qtest_clock_step(qts, remaining_steps);
947
+ g_assert_cmphex(watchdog_read_wtcr(qts, wd), ==,
948
+ WTCLK(0) | WTE | WTIF | WTIE);
949
+ g_assert_true(qtest_get_irq(qts, wd->irq));
950
+
951
+ qtest_quit(qts);
952
+}
953
+
954
+static void watchdog_add_test(const char *name, const Watchdog* wd,
955
+ GTestDataFunc fn)
956
+{
957
+ g_autofree char *full_name = g_strdup_printf(
958
+ "npcm7xx_watchdog_timer[%d]/%s", watchdog_index(wd), name);
959
+ qtest_add_data_func(full_name, wd, fn);
960
+}
961
+#define add_test(name, td) watchdog_add_test(#name, td, test_##name)
962
+
963
+int main(int argc, char **argv)
964
+{
965
+ g_test_init(&argc, &argv, NULL);
966
+ g_test_set_nonfatal_assertions();
967
+
968
+ for (int i = 0; i < ARRAY_SIZE(watchdog_list); ++i) {
969
+ const Watchdog *wd = &watchdog_list[i];
970
+
971
+ add_test(init, wd);
972
+ add_test(reset_action, wd);
973
+ add_test(prescaler, wd);
974
+ add_test(enabling_flags, wd);
975
+ add_test(pause, wd);
976
+ }
977
+
978
+ return g_test_run();
979
+}
980
diff --git a/MAINTAINERS b/MAINTAINERS
981
index XXXXXXX..XXXXXXX 100644
982
--- a/MAINTAINERS
983
+++ b/MAINTAINERS
984
@@ -XXX,XX +XXX,XX @@ L: qemu-arm@nongnu.org
985
S: Supported
986
F: hw/*/npcm7xx*
987
F: include/hw/*/npcm7xx*
988
+F: tests/qtest/npcm7xx*
989
F: pc-bios/npcm7xx_bootrom.bin
990
F: roms/vbootrom
991
992
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
993
index XXXXXXX..XXXXXXX 100644
994
--- a/tests/qtest/meson.build
995
+++ b/tests/qtest/meson.build
996
@@ -XXX,XX +XXX,XX @@ qtests_sparc64 = \
997
(config_all_devices.has_key('CONFIG_ISA_TESTDEV') ? ['endianness-test'] : []) + \
998
['prom-env-test', 'boot-serial-test']
999
1000
-qtests_npcm7xx = ['npcm7xx_timer-test']
1001
+qtests_npcm7xx = ['npcm7xx_timer-test', 'npcm7xx_watchdog_timer-test']
1002
qtests_arm = \
1003
(config_all_devices.has_key('CONFIG_PFLASH_CFI02') ? ['pflash-cfi02-test'] : []) + \
1004
(config_all_devices.has_key('CONFIG_NPCM7XX') ? qtests_npcm7xx : []) + \
1005
--
34
--
1006
2.20.1
35
2.34.1
1007
1008
diff view generated by jsdifflib
1
From: Luc Michel <luc@lmichel.fr>
1
From: Jinjie Ruan <ruanjinjie@huawei.com>
2
2
3
Connect the 'uart-out' clock from the CPRMAN to the PL011 instance.
3
Augment the GICv3's QOM device interface by adding one
4
new set of sysbus IRQ line, to signal NMI to each CPU.
4
5
5
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com>
6
Signed-off-by: Luc Michel <luc@lmichel.fr>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Tested-by: Guenter Roeck <linux@roeck-us.net>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Message-id: 20240407081733.3231820-11-ruanjinjie@huawei.com
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
---
11
hw/arm/bcm2835_peripherals.c | 2 ++
12
include/hw/intc/arm_gic_common.h | 2 ++
12
1 file changed, 2 insertions(+)
13
include/hw/intc/arm_gicv3_common.h | 2 ++
14
hw/intc/arm_gicv3_common.c | 6 ++++++
15
3 files changed, 10 insertions(+)
13
16
14
diff --git a/hw/arm/bcm2835_peripherals.c b/hw/arm/bcm2835_peripherals.c
17
diff --git a/include/hw/intc/arm_gic_common.h b/include/hw/intc/arm_gic_common.h
15
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/arm/bcm2835_peripherals.c
19
--- a/include/hw/intc/arm_gic_common.h
17
+++ b/hw/arm/bcm2835_peripherals.c
20
+++ b/include/hw/intc/arm_gic_common.h
18
@@ -XXX,XX +XXX,XX @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
21
@@ -XXX,XX +XXX,XX @@ struct GICState {
22
qemu_irq parent_fiq[GIC_NCPU];
23
qemu_irq parent_virq[GIC_NCPU];
24
qemu_irq parent_vfiq[GIC_NCPU];
25
+ qemu_irq parent_nmi[GIC_NCPU];
26
+ qemu_irq parent_vnmi[GIC_NCPU];
27
qemu_irq maintenance_irq[GIC_NCPU];
28
29
/* GICD_CTLR; for a GIC with the security extensions the NS banked version
30
diff --git a/include/hw/intc/arm_gicv3_common.h b/include/hw/intc/arm_gicv3_common.h
31
index XXXXXXX..XXXXXXX 100644
32
--- a/include/hw/intc/arm_gicv3_common.h
33
+++ b/include/hw/intc/arm_gicv3_common.h
34
@@ -XXX,XX +XXX,XX @@ struct GICv3CPUState {
35
qemu_irq parent_fiq;
36
qemu_irq parent_virq;
37
qemu_irq parent_vfiq;
38
+ qemu_irq parent_nmi;
39
+ qemu_irq parent_vnmi;
40
41
/* Redistributor */
42
uint32_t level; /* Current IRQ level */
43
diff --git a/hw/intc/arm_gicv3_common.c b/hw/intc/arm_gicv3_common.c
44
index XXXXXXX..XXXXXXX 100644
45
--- a/hw/intc/arm_gicv3_common.c
46
+++ b/hw/intc/arm_gicv3_common.c
47
@@ -XXX,XX +XXX,XX @@ void gicv3_init_irqs_and_mmio(GICv3State *s, qemu_irq_handler handler,
48
for (i = 0; i < s->num_cpu; i++) {
49
sysbus_init_irq(sbd, &s->cpu[i].parent_vfiq);
19
}
50
}
20
memory_region_add_subregion(&s->peri_mr, CPRMAN_OFFSET,
51
+ for (i = 0; i < s->num_cpu; i++) {
21
sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->cprman), 0));
52
+ sysbus_init_irq(sbd, &s->cpu[i].parent_nmi);
22
+ qdev_connect_clock_in(DEVICE(&s->uart0), "clk",
53
+ }
23
+ qdev_get_clock_out(DEVICE(&s->cprman), "uart-out"));
54
+ for (i = 0; i < s->num_cpu; i++) {
24
55
+ sysbus_init_irq(sbd, &s->cpu[i].parent_vnmi);
25
memory_region_add_subregion(&s->peri_mr, ARMCTRL_IC_OFFSET,
56
+ }
26
sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->ic), 0));
57
58
memory_region_init_io(&s->iomem_dist, OBJECT(s), ops, s,
59
"gicv3_dist", 0x10000);
27
--
60
--
28
2.20.1
61
2.34.1
29
30
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Jinjie Ruan <ruanjinjie@huawei.com>
2
2
3
The second loop uses a loop induction variable, and the first
3
Wire the new NMI and VINMI interrupt line from the GIC to each CPU if it
4
does not. Transform the first to match the second, to simplify
4
is not GICv2.
5
a following patch moving code between them.
6
5
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com>
8
Message-id: 20201021173749.111103-7-richard.henderson@linaro.org
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Message-id: 20240407081733.3231820-12-ruanjinjie@huawei.com
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
10
---
12
linux-user/elfload.c | 9 +++++----
11
hw/arm/virt.c | 10 +++++++++-
13
1 file changed, 5 insertions(+), 4 deletions(-)
12
1 file changed, 9 insertions(+), 1 deletion(-)
14
13
15
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
14
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
16
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
17
--- a/linux-user/elfload.c
16
--- a/hw/arm/virt.c
18
+++ b/linux-user/elfload.c
17
+++ b/hw/arm/virt.c
19
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
18
@@ -XXX,XX +XXX,XX @@ static void create_gic(VirtMachineState *vms, MemoryRegion *mem)
20
loaddr = -1, hiaddr = 0;
19
21
info->alignment = 0;
20
/* Wire the outputs from each CPU's generic timer and the GICv3
22
for (i = 0; i < ehdr->e_phnum; ++i) {
21
* maintenance interrupt signal to the appropriate GIC PPI inputs,
23
- if (phdr[i].p_type == PT_LOAD) {
22
- * and the GIC's IRQ/FIQ/VIRQ/VFIQ interrupt outputs to the CPU's inputs.
24
- abi_ulong a = phdr[i].p_vaddr - phdr[i].p_offset;
23
+ * and the GIC's IRQ/FIQ/VIRQ/VFIQ/NMI/VINMI interrupt outputs to the
25
+ struct elf_phdr *eppnt = phdr + i;
24
+ * CPU's inputs.
26
+ if (eppnt->p_type == PT_LOAD) {
25
*/
27
+ abi_ulong a = eppnt->p_vaddr - eppnt->p_offset;
26
for (i = 0; i < smp_cpus; i++) {
28
if (a < loaddr) {
27
DeviceState *cpudev = DEVICE(qemu_get_cpu(i));
29
loaddr = a;
28
@@ -XXX,XX +XXX,XX @@ static void create_gic(VirtMachineState *vms, MemoryRegion *mem)
30
}
29
qdev_get_gpio_in(cpudev, ARM_CPU_VIRQ));
31
- a = phdr[i].p_vaddr + phdr[i].p_memsz;
30
sysbus_connect_irq(gicbusdev, i + 3 * smp_cpus,
32
+ a = eppnt->p_vaddr + eppnt->p_memsz;
31
qdev_get_gpio_in(cpudev, ARM_CPU_VFIQ));
33
if (a > hiaddr) {
32
+
34
hiaddr = a;
33
+ if (vms->gic_version != VIRT_GIC_VERSION_2) {
35
}
34
+ sysbus_connect_irq(gicbusdev, i + 4 * smp_cpus,
36
++info->nsegs;
35
+ qdev_get_gpio_in(cpudev, ARM_CPU_NMI));
37
- info->alignment |= phdr[i].p_align;
36
+ sysbus_connect_irq(gicbusdev, i + 5 * smp_cpus,
38
+ info->alignment |= eppnt->p_align;
37
+ qdev_get_gpio_in(cpudev, ARM_CPU_VINMI));
39
}
38
+ }
40
}
39
}
41
40
41
fdt_add_gic_node(vms);
42
--
42
--
43
2.20.1
43
2.34.1
44
45
diff view generated by jsdifflib
1
From: Luc Michel <luc@lmichel.fr>
1
From: Jinjie Ruan <ruanjinjie@huawei.com>
2
2
3
The CPRMAN (clock controller) was mapped at the watchdog/power manager
3
According to Arm GIC section 4.6.3 Interrupt superpriority, the interrupt
4
address. It was also split into two unimplemented peripherals (CM and
4
with superpriority is always IRQ, never FIQ, so the NMI exception trap entry
5
A2W) but this is really the same one, as shown by this extract of the
5
behave like IRQ. And VINMI(vIRQ with Superpriority) can be raised from the
6
Raspberry Pi 3 Linux device tree:
6
GIC or come from the hcrx_el2.HCRX_VINMI bit, VFNMI(vFIQ with Superpriority)
7
come from the hcrx_el2.HCRX_VFNMI bit.
7
8
8
watchdog@7e100000 {
9
Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com>
9
compatible = "brcm,bcm2835-pm\0brcm,bcm2835-pm-wdt";
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
[...]
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
reg = <0x7e100000 0x114 0x7e00a000 0x24>;
12
Message-id: 20240407081733.3231820-13-ruanjinjie@huawei.com
12
[...]
13
};
14
15
[...]
16
cprman@7e101000 {
17
compatible = "brcm,bcm2835-cprman";
18
[...]
19
reg = <0x7e101000 0x2000>;
20
[...]
21
};
22
23
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
24
Signed-off-by: Luc Michel <luc@lmichel.fr>
25
Tested-by: Guenter Roeck <linux@roeck-us.net>
26
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
27
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
28
---
14
---
29
include/hw/arm/bcm2835_peripherals.h | 2 +-
15
target/arm/helper.c | 3 +++
30
include/hw/arm/raspi_platform.h | 5 ++---
16
1 file changed, 3 insertions(+)
31
hw/arm/bcm2835_peripherals.c | 4 ++--
32
3 files changed, 5 insertions(+), 6 deletions(-)
33
17
34
diff --git a/include/hw/arm/bcm2835_peripherals.h b/include/hw/arm/bcm2835_peripherals.h
18
diff --git a/target/arm/helper.c b/target/arm/helper.c
35
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
36
--- a/include/hw/arm/bcm2835_peripherals.h
20
--- a/target/arm/helper.c
37
+++ b/include/hw/arm/bcm2835_peripherals.h
21
+++ b/target/arm/helper.c
38
@@ -XXX,XX +XXX,XX @@ struct BCM2835PeripheralState {
22
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_do_interrupt_aarch64(CPUState *cs)
39
BCM2835MphiState mphi;
23
break;
40
UnimplementedDeviceState txp;
24
case EXCP_IRQ:
41
UnimplementedDeviceState armtmr;
25
case EXCP_VIRQ:
42
+ UnimplementedDeviceState powermgt;
26
+ case EXCP_NMI:
43
UnimplementedDeviceState cprman;
27
+ case EXCP_VINMI:
44
- UnimplementedDeviceState a2w;
28
addr += 0x80;
45
PL011State uart0;
29
break;
46
BCM2835AuxState aux;
30
case EXCP_FIQ:
47
BCM2835FBState fb;
31
case EXCP_VFIQ:
48
diff --git a/include/hw/arm/raspi_platform.h b/include/hw/arm/raspi_platform.h
32
+ case EXCP_VFNMI:
49
index XXXXXXX..XXXXXXX 100644
33
addr += 0x100;
50
--- a/include/hw/arm/raspi_platform.h
34
break;
51
+++ b/include/hw/arm/raspi_platform.h
35
case EXCP_VSERR:
52
@@ -XXX,XX +XXX,XX @@
53
#define ARMCTRL_TIMER0_1_OFFSET (ARM_OFFSET + 0x400) /* Timer 0 and 1 (SP804) */
54
#define ARMCTRL_0_SBM_OFFSET (ARM_OFFSET + 0x800) /* User 0 (ARM) Semaphores
55
* Doorbells & Mailboxes */
56
-#define CPRMAN_OFFSET 0x100000 /* Power Management, Watchdog */
57
-#define CM_OFFSET 0x101000 /* Clock Management */
58
-#define A2W_OFFSET 0x102000 /* Reset controller */
59
+#define PM_OFFSET 0x100000 /* Power Management */
60
+#define CPRMAN_OFFSET 0x101000 /* Clock Management */
61
#define AVS_OFFSET 0x103000 /* Audio Video Standard */
62
#define RNG_OFFSET 0x104000
63
#define GPIO_OFFSET 0x200000
64
diff --git a/hw/arm/bcm2835_peripherals.c b/hw/arm/bcm2835_peripherals.c
65
index XXXXXXX..XXXXXXX 100644
66
--- a/hw/arm/bcm2835_peripherals.c
67
+++ b/hw/arm/bcm2835_peripherals.c
68
@@ -XXX,XX +XXX,XX @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
69
70
create_unimp(s, &s->txp, "bcm2835-txp", TXP_OFFSET, 0x1000);
71
create_unimp(s, &s->armtmr, "bcm2835-sp804", ARMCTRL_TIMER0_1_OFFSET, 0x40);
72
- create_unimp(s, &s->cprman, "bcm2835-cprman", CPRMAN_OFFSET, 0x1000);
73
- create_unimp(s, &s->a2w, "bcm2835-a2w", A2W_OFFSET, 0x1000);
74
+ create_unimp(s, &s->powermgt, "bcm2835-powermgt", PM_OFFSET, 0x114);
75
+ create_unimp(s, &s->cprman, "bcm2835-cprman", CPRMAN_OFFSET, 0x2000);
76
create_unimp(s, &s->i2s, "bcm2835-i2s", I2S_OFFSET, 0x100);
77
create_unimp(s, &s->smi, "bcm2835-smi", SMI_OFFSET, 0x100);
78
create_unimp(s, &s->spi[0], "bcm2835-spi0", SPI0_OFFSET, 0x20);
79
--
36
--
80
2.20.1
37
2.34.1
81
82
diff view generated by jsdifflib
1
From: Luc Michel <luc@lmichel.fr>
1
From: Jinjie Ruan <ruanjinjie@huawei.com>
2
2
3
The nanosecond unit greatly limits the dynamic range we can display in
3
Add a property has-nmi to the GICv3 device, and use this to set
4
clock value traces, for values in the order of 1GHz and more. The
4
the NMI bit in the GICD_TYPER register. This isn't visible to
5
internal representation can go way beyond this value and it is quite
5
guests yet because the property defaults to false and we won't
6
common for today's clocks to be within those ranges.
6
set it in the board code until we've landed all of the changes
7
needed to implement FEAT_GICV3_NMI.
7
8
8
For example, a frequency between 500MHz+ and 1GHz will be displayed as
9
Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com>
9
1ns. Beyond 1GHz, it will show up as 0ns.
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Replace nanosecond periods traces with frequencies in the Hz unit
12
Message-id: 20240407081733.3231820-14-ruanjinjie@huawei.com
12
to have more dynamic range in the trace output.
13
14
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
15
Reviewed-by: Damien Hedde <damien.hedde@greensocs.com>
16
Signed-off-by: Luc Michel <luc@lmichel.fr>
17
Tested-by: Guenter Roeck <linux@roeck-us.net>
18
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
19
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
20
---
14
---
21
hw/core/clock.c | 6 +++---
15
hw/intc/gicv3_internal.h | 1 +
22
hw/core/trace-events | 4 ++--
16
include/hw/intc/arm_gicv3_common.h | 1 +
23
2 files changed, 5 insertions(+), 5 deletions(-)
17
hw/intc/arm_gicv3_common.c | 1 +
18
hw/intc/arm_gicv3_dist.c | 2 ++
19
4 files changed, 5 insertions(+)
24
20
25
diff --git a/hw/core/clock.c b/hw/core/clock.c
21
diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h
26
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
27
--- a/hw/core/clock.c
23
--- a/hw/intc/gicv3_internal.h
28
+++ b/hw/core/clock.c
24
+++ b/hw/intc/gicv3_internal.h
29
@@ -XXX,XX +XXX,XX @@ bool clock_set(Clock *clk, uint64_t period)
25
@@ -XXX,XX +XXX,XX @@
30
if (clk->period == period) {
26
#define GICD_CTLR_E1NWF (1U << 7)
31
return false;
27
#define GICD_CTLR_RWP (1U << 31)
32
}
28
33
- trace_clock_set(CLOCK_PATH(clk), CLOCK_PERIOD_TO_NS(clk->period),
29
+#define GICD_TYPER_NMI_SHIFT 9
34
- CLOCK_PERIOD_TO_NS(period));
30
#define GICD_TYPER_LPIS_SHIFT 17
35
+ trace_clock_set(CLOCK_PATH(clk), CLOCK_PERIOD_TO_HZ(clk->period),
31
36
+ CLOCK_PERIOD_TO_HZ(period));
32
/* 16 bits EventId */
37
clk->period = period;
33
diff --git a/include/hw/intc/arm_gicv3_common.h b/include/hw/intc/arm_gicv3_common.h
38
39
return true;
40
@@ -XXX,XX +XXX,XX @@ static void clock_propagate_period(Clock *clk, bool call_callbacks)
41
if (child->period != clk->period) {
42
child->period = clk->period;
43
trace_clock_update(CLOCK_PATH(child), CLOCK_PATH(clk),
44
- CLOCK_PERIOD_TO_NS(clk->period),
45
+ CLOCK_PERIOD_TO_HZ(clk->period),
46
call_callbacks);
47
if (call_callbacks && child->callback) {
48
child->callback(child->callback_opaque);
49
diff --git a/hw/core/trace-events b/hw/core/trace-events
50
index XXXXXXX..XXXXXXX 100644
34
index XXXXXXX..XXXXXXX 100644
51
--- a/hw/core/trace-events
35
--- a/include/hw/intc/arm_gicv3_common.h
52
+++ b/hw/core/trace-events
36
+++ b/include/hw/intc/arm_gicv3_common.h
53
@@ -XXX,XX +XXX,XX @@ resettable_transitional_function(void *obj, const char *objtype) "obj=%p(%s)"
37
@@ -XXX,XX +XXX,XX @@ struct GICv3State {
54
# clock.c
38
uint32_t num_irq;
55
clock_set_source(const char *clk, const char *src) "'%s', src='%s'"
39
uint32_t revision;
56
clock_disconnect(const char *clk) "'%s'"
40
bool lpi_enable;
57
-clock_set(const char *clk, uint64_t old, uint64_t new) "'%s', ns=%"PRIu64"->%"PRIu64
41
+ bool nmi_support;
58
+clock_set(const char *clk, uint64_t old, uint64_t new) "'%s', %"PRIu64"Hz->%"PRIu64"Hz"
42
bool security_extn;
59
clock_propagate(const char *clk) "'%s'"
43
bool force_8bit_prio;
60
-clock_update(const char *clk, const char *src, uint64_t val, int cb) "'%s', src='%s', ns=%"PRIu64", cb=%d"
44
bool irq_reset_nonsecure;
61
+clock_update(const char *clk, const char *src, uint64_t hz, int cb) "'%s', src='%s', val=%"PRIu64"Hz cb=%d"
45
diff --git a/hw/intc/arm_gicv3_common.c b/hw/intc/arm_gicv3_common.c
46
index XXXXXXX..XXXXXXX 100644
47
--- a/hw/intc/arm_gicv3_common.c
48
+++ b/hw/intc/arm_gicv3_common.c
49
@@ -XXX,XX +XXX,XX @@ static Property arm_gicv3_common_properties[] = {
50
DEFINE_PROP_UINT32("num-irq", GICv3State, num_irq, 32),
51
DEFINE_PROP_UINT32("revision", GICv3State, revision, 3),
52
DEFINE_PROP_BOOL("has-lpi", GICv3State, lpi_enable, 0),
53
+ DEFINE_PROP_BOOL("has-nmi", GICv3State, nmi_support, 0),
54
DEFINE_PROP_BOOL("has-security-extensions", GICv3State, security_extn, 0),
55
/*
56
* Compatibility property: force 8 bits of physical priority, even
57
diff --git a/hw/intc/arm_gicv3_dist.c b/hw/intc/arm_gicv3_dist.c
58
index XXXXXXX..XXXXXXX 100644
59
--- a/hw/intc/arm_gicv3_dist.c
60
+++ b/hw/intc/arm_gicv3_dist.c
61
@@ -XXX,XX +XXX,XX @@ static bool gicd_readl(GICv3State *s, hwaddr offset,
62
* by GICD_TYPER.IDbits)
63
* MBIS == 0 (message-based SPIs not supported)
64
* SecurityExtn == 1 if security extns supported
65
+ * NMI = 1 if Non-maskable interrupt property is supported
66
* CPUNumber == 0 since for us ARE is always 1
67
* ITLinesNumber == (((max SPI IntID + 1) / 32) - 1)
68
*/
69
@@ -XXX,XX +XXX,XX @@ static bool gicd_readl(GICv3State *s, hwaddr offset,
70
bool dvis = s->revision >= 4;
71
72
*data = (1 << 25) | (1 << 24) | (dvis << 18) | (sec_extn << 10) |
73
+ (s->nmi_support << GICD_TYPER_NMI_SHIFT) |
74
(s->lpi_enable << GICD_TYPER_LPIS_SHIFT) |
75
(0xf << 19) | itlinesnumber;
76
return true;
62
--
77
--
63
2.20.1
78
2.34.1
64
65
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
From: Jinjie Ruan <ruanjinjie@huawei.com>
2
2
3
The realize() function is clearly composed of two parts,
3
So far, there is no FEAT_GICv3_NMI support in the in-kernel GIC, so make it
4
each described by a comment:
4
an error to try to set has-nmi=true for the KVM GICv3.
5
5
6
void realize()
6
Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com>
7
{
7
Message-id: 20240407081733.3231820-15-ruanjinjie@huawei.com
8
/* common peripherals from bcm2835 */
8
Suggested-by: Peter Maydell <peter.maydell@linaro.org>
9
...
10
/* bcm2836 interrupt controller (and mailboxes, etc.) */
11
...
12
}
13
14
Split the two part, so we can reuse the common part with other
15
SoCs from this family.
16
17
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
18
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
19
Message-id: 20201024170127.3592182-6-f4bug@amsat.org
20
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
---
10
---
22
hw/arm/bcm2836.c | 22 ++++++++++++++++++----
11
hw/intc/arm_gicv3_kvm.c | 5 +++++
23
1 file changed, 18 insertions(+), 4 deletions(-)
12
1 file changed, 5 insertions(+)
24
13
25
diff --git a/hw/arm/bcm2836.c b/hw/arm/bcm2836.c
14
diff --git a/hw/intc/arm_gicv3_kvm.c b/hw/intc/arm_gicv3_kvm.c
26
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
27
--- a/hw/arm/bcm2836.c
16
--- a/hw/intc/arm_gicv3_kvm.c
28
+++ b/hw/arm/bcm2836.c
17
+++ b/hw/intc/arm_gicv3_kvm.c
29
@@ -XXX,XX +XXX,XX @@ static void bcm2836_init(Object *obj)
18
@@ -XXX,XX +XXX,XX @@ static void kvm_arm_gicv3_realize(DeviceState *dev, Error **errp)
30
qdev_prop_set_uint32(DEVICE(obj), "enabled-cpus", bc->core_count);
19
return;
31
}
20
}
32
21
33
- object_initialize_child(obj, "control", &s->control, TYPE_BCM2836_CONTROL);
22
+ if (s->nmi_support) {
34
+ if (bc->ctrl_base) {
23
+ error_setg(errp, "NMI is not supported with the in-kernel GIC");
35
+ object_initialize_child(obj, "control", &s->control,
36
+ TYPE_BCM2836_CONTROL);
37
+ }
38
39
object_initialize_child(obj, "peripherals", &s->peripherals,
40
TYPE_BCM2835_PERIPHERALS);
41
@@ -XXX,XX +XXX,XX @@ static void bcm2836_init(Object *obj)
42
"vcram-size");
43
}
44
45
-static void bcm2836_realize(DeviceState *dev, Error **errp)
46
+static bool bcm283x_common_realize(DeviceState *dev, Error **errp)
47
{
48
BCM283XState *s = BCM283X(dev);
49
BCM283XClass *bc = BCM283X_GET_CLASS(dev);
50
Object *obj;
51
- int n;
52
53
/* common peripherals from bcm2835 */
54
55
@@ -XXX,XX +XXX,XX @@ static void bcm2836_realize(DeviceState *dev, Error **errp)
56
object_property_add_const_link(OBJECT(&s->peripherals), "ram", obj);
57
58
if (!sysbus_realize(SYS_BUS_DEVICE(&s->peripherals), errp)) {
59
- return;
60
+ return false;
61
}
62
63
object_property_add_alias(OBJECT(s), "sd-bus", OBJECT(&s->peripherals),
64
@@ -XXX,XX +XXX,XX @@ static void bcm2836_realize(DeviceState *dev, Error **errp)
65
66
sysbus_mmio_map_overlap(SYS_BUS_DEVICE(&s->peripherals), 0,
67
bc->peri_base, 1);
68
+ return true;
69
+}
70
+
71
+static void bcm2836_realize(DeviceState *dev, Error **errp)
72
+{
73
+ BCM283XState *s = BCM283X(dev);
74
+ BCM283XClass *bc = BCM283X_GET_CLASS(dev);
75
+ int n;
76
+
77
+ if (!bcm283x_common_realize(dev, errp)) {
78
+ return;
24
+ return;
79
+ }
25
+ }
80
26
+
81
/* bcm2836 interrupt controller (and mailboxes, etc.) */
27
gicv3_init_irqs_and_mmio(s, kvm_arm_gicv3_set_irq, NULL);
82
if (!sysbus_realize(SYS_BUS_DEVICE(&s->control), errp)) {
28
29
for (i = 0; i < s->num_cpu; i++) {
83
--
30
--
84
2.20.1
31
2.34.1
85
86
diff view generated by jsdifflib
1
From: Luc Michel <luc@lmichel.fr>
1
From: Jinjie Ruan <ruanjinjie@huawei.com>
2
2
3
There are 5 PLLs in the CPRMAN, namely PLL A, C, D, H and B. All of them
3
A SPI, PPI or SGI interrupt can have non-maskable property. So maintain
4
take the xosc clock as input and produce a new clock.
4
non-maskable property in PendingIrq and GICR/GICD. Since add new device
5
state, it also needs to be migrated, so also save NMI info in
6
vmstate_gicv3_cpu and vmstate_gicv3.
5
7
6
This commit adds a skeleton implementation for the PLLs as sub-devices
8
Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com>
7
of the CPRMAN. The PLLs are instantiated and connected internally to the
9
Acked-by: Richard Henderson <richard.henderson@linaro.org>
8
main oscillator.
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
11
Message-id: 20240407081733.3231820-16-ruanjinjie@huawei.com
10
Each PLL has 6 registers : CM, A2W_CTRL, A2W_ANA[0,1,2,3], A2W_FRAC. A
11
write to any of them triggers a call to the (not yet implemented)
12
pll_update function.
13
14
If the main oscillator changes frequency, an update is also triggered.
15
16
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
17
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
18
Signed-off-by: Luc Michel <luc@lmichel.fr>
19
Tested-by: Guenter Roeck <linux@roeck-us.net>
20
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
---
13
---
22
include/hw/misc/bcm2835_cprman.h | 29 +++++
14
include/hw/intc/arm_gicv3_common.h | 4 ++++
23
include/hw/misc/bcm2835_cprman_internals.h | 144 +++++++++++++++++++++
15
hw/intc/arm_gicv3_common.c | 38 ++++++++++++++++++++++++++++++
24
hw/misc/bcm2835_cprman.c | 108 ++++++++++++++++
16
2 files changed, 42 insertions(+)
25
3 files changed, 281 insertions(+)
26
17
27
diff --git a/include/hw/misc/bcm2835_cprman.h b/include/hw/misc/bcm2835_cprman.h
18
diff --git a/include/hw/intc/arm_gicv3_common.h b/include/hw/intc/arm_gicv3_common.h
28
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
29
--- a/include/hw/misc/bcm2835_cprman.h
20
--- a/include/hw/intc/arm_gicv3_common.h
30
+++ b/include/hw/misc/bcm2835_cprman.h
21
+++ b/include/hw/intc/arm_gicv3_common.h
31
@@ -XXX,XX +XXX,XX @@ DECLARE_INSTANCE_CHECKER(BCM2835CprmanState, CPRMAN,
22
@@ -XXX,XX +XXX,XX @@ typedef struct {
32
23
int irq;
33
#define CPRMAN_NUM_REGS (0x2000 / sizeof(uint32_t))
24
uint8_t prio;
34
25
int grp;
35
+typedef enum CprmanPll {
26
+ bool nmi;
36
+ CPRMAN_PLLA = 0,
27
} PendingIrq;
37
+ CPRMAN_PLLC,
28
38
+ CPRMAN_PLLD,
29
struct GICv3CPUState {
39
+ CPRMAN_PLLH,
30
@@ -XXX,XX +XXX,XX @@ struct GICv3CPUState {
40
+ CPRMAN_PLLB,
31
uint32_t gicr_ienabler0;
32
uint32_t gicr_ipendr0;
33
uint32_t gicr_iactiver0;
34
+ uint32_t gicr_inmir0;
35
uint32_t edge_trigger; /* ICFGR0 and ICFGR1 even bits */
36
uint32_t gicr_igrpmodr0;
37
uint32_t gicr_nsacr;
38
@@ -XXX,XX +XXX,XX @@ struct GICv3State {
39
GIC_DECLARE_BITMAP(active); /* GICD_ISACTIVER */
40
GIC_DECLARE_BITMAP(level); /* Current level */
41
GIC_DECLARE_BITMAP(edge_trigger); /* GICD_ICFGR even bits */
42
+ GIC_DECLARE_BITMAP(nmi); /* GICD_INMIR */
43
uint8_t gicd_ipriority[GICV3_MAXIRQ];
44
uint64_t gicd_irouter[GICV3_MAXIRQ];
45
/* Cached information: pointer to the cpu i/f for the CPUs specified
46
@@ -XXX,XX +XXX,XX @@ GICV3_BITMAP_ACCESSORS(pending)
47
GICV3_BITMAP_ACCESSORS(active)
48
GICV3_BITMAP_ACCESSORS(level)
49
GICV3_BITMAP_ACCESSORS(edge_trigger)
50
+GICV3_BITMAP_ACCESSORS(nmi)
51
52
#define TYPE_ARM_GICV3_COMMON "arm-gicv3-common"
53
typedef struct ARMGICv3CommonClass ARMGICv3CommonClass;
54
diff --git a/hw/intc/arm_gicv3_common.c b/hw/intc/arm_gicv3_common.c
55
index XXXXXXX..XXXXXXX 100644
56
--- a/hw/intc/arm_gicv3_common.c
57
+++ b/hw/intc/arm_gicv3_common.c
58
@@ -XXX,XX +XXX,XX @@ const VMStateDescription vmstate_gicv3_gicv4 = {
59
}
60
};
61
62
+static bool gicv3_cpu_nmi_needed(void *opaque)
63
+{
64
+ GICv3CPUState *cs = opaque;
41
+
65
+
42
+ CPRMAN_NUM_PLL
66
+ return cs->gic->nmi_support;
43
+} CprmanPll;
44
+
45
+typedef struct CprmanPllState {
46
+ /*< private >*/
47
+ DeviceState parent_obj;
48
+
49
+ /*< public >*/
50
+ CprmanPll id;
51
+
52
+ uint32_t *reg_cm;
53
+ uint32_t *reg_a2w_ctrl;
54
+ uint32_t *reg_a2w_ana; /* ANA[0] .. ANA[3] */
55
+ uint32_t prediv_mask; /* prediv bit in ana[1] */
56
+ uint32_t *reg_a2w_frac;
57
+
58
+ Clock *xosc_in;
59
+ Clock *out;
60
+} CprmanPllState;
61
+
62
struct BCM2835CprmanState {
63
/*< private >*/
64
SysBusDevice parent_obj;
65
@@ -XXX,XX +XXX,XX @@ struct BCM2835CprmanState {
66
/*< public >*/
67
MemoryRegion iomem;
68
69
+ CprmanPllState plls[CPRMAN_NUM_PLL];
70
+
71
uint32_t regs[CPRMAN_NUM_REGS];
72
uint32_t xosc_freq;
73
74
diff --git a/include/hw/misc/bcm2835_cprman_internals.h b/include/hw/misc/bcm2835_cprman_internals.h
75
index XXXXXXX..XXXXXXX 100644
76
--- a/include/hw/misc/bcm2835_cprman_internals.h
77
+++ b/include/hw/misc/bcm2835_cprman_internals.h
78
@@ -XXX,XX +XXX,XX @@
79
#include "hw/registerfields.h"
80
#include "hw/misc/bcm2835_cprman.h"
81
82
+#define TYPE_CPRMAN_PLL "bcm2835-cprman-pll"
83
+
84
+DECLARE_INSTANCE_CHECKER(CprmanPllState, CPRMAN_PLL,
85
+ TYPE_CPRMAN_PLL)
86
+
87
/* Register map */
88
89
+/* PLLs */
90
+REG32(CM_PLLA, 0x104)
91
+ FIELD(CM_PLLA, LOADDSI0, 0, 1)
92
+ FIELD(CM_PLLA, HOLDDSI0, 1, 1)
93
+ FIELD(CM_PLLA, LOADCCP2, 2, 1)
94
+ FIELD(CM_PLLA, HOLDCCP2, 3, 1)
95
+ FIELD(CM_PLLA, LOADCORE, 4, 1)
96
+ FIELD(CM_PLLA, HOLDCORE, 5, 1)
97
+ FIELD(CM_PLLA, LOADPER, 6, 1)
98
+ FIELD(CM_PLLA, HOLDPER, 7, 1)
99
+ FIELD(CM_PLLx, ANARST, 8, 1)
100
+REG32(CM_PLLC, 0x108)
101
+ FIELD(CM_PLLC, LOADCORE0, 0, 1)
102
+ FIELD(CM_PLLC, HOLDCORE0, 1, 1)
103
+ FIELD(CM_PLLC, LOADCORE1, 2, 1)
104
+ FIELD(CM_PLLC, HOLDCORE1, 3, 1)
105
+ FIELD(CM_PLLC, LOADCORE2, 4, 1)
106
+ FIELD(CM_PLLC, HOLDCORE2, 5, 1)
107
+ FIELD(CM_PLLC, LOADPER, 6, 1)
108
+ FIELD(CM_PLLC, HOLDPER, 7, 1)
109
+REG32(CM_PLLD, 0x10c)
110
+ FIELD(CM_PLLD, LOADDSI0, 0, 1)
111
+ FIELD(CM_PLLD, HOLDDSI0, 1, 1)
112
+ FIELD(CM_PLLD, LOADDSI1, 2, 1)
113
+ FIELD(CM_PLLD, HOLDDSI1, 3, 1)
114
+ FIELD(CM_PLLD, LOADCORE, 4, 1)
115
+ FIELD(CM_PLLD, HOLDCORE, 5, 1)
116
+ FIELD(CM_PLLD, LOADPER, 6, 1)
117
+ FIELD(CM_PLLD, HOLDPER, 7, 1)
118
+REG32(CM_PLLH, 0x110)
119
+ FIELD(CM_PLLH, LOADPIX, 0, 1)
120
+ FIELD(CM_PLLH, LOADAUX, 1, 1)
121
+ FIELD(CM_PLLH, LOADRCAL, 2, 1)
122
+REG32(CM_PLLB, 0x170)
123
+ FIELD(CM_PLLB, LOADARM, 0, 1)
124
+ FIELD(CM_PLLB, HOLDARM, 1, 1)
125
+
126
+REG32(A2W_PLLA_CTRL, 0x1100)
127
+ FIELD(A2W_PLLx_CTRL, NDIV, 0, 10)
128
+ FIELD(A2W_PLLx_CTRL, PDIV, 12, 3)
129
+ FIELD(A2W_PLLx_CTRL, PWRDN, 16, 1)
130
+ FIELD(A2W_PLLx_CTRL, PRST_DISABLE, 17, 1)
131
+REG32(A2W_PLLC_CTRL, 0x1120)
132
+REG32(A2W_PLLD_CTRL, 0x1140)
133
+REG32(A2W_PLLH_CTRL, 0x1160)
134
+REG32(A2W_PLLB_CTRL, 0x11e0)
135
+
136
+REG32(A2W_PLLA_ANA0, 0x1010)
137
+REG32(A2W_PLLA_ANA1, 0x1014)
138
+ FIELD(A2W_PLLx_ANA1, FB_PREDIV, 14, 1)
139
+REG32(A2W_PLLA_ANA2, 0x1018)
140
+REG32(A2W_PLLA_ANA3, 0x101c)
141
+
142
+REG32(A2W_PLLC_ANA0, 0x1030)
143
+REG32(A2W_PLLC_ANA1, 0x1034)
144
+REG32(A2W_PLLC_ANA2, 0x1038)
145
+REG32(A2W_PLLC_ANA3, 0x103c)
146
+
147
+REG32(A2W_PLLD_ANA0, 0x1050)
148
+REG32(A2W_PLLD_ANA1, 0x1054)
149
+REG32(A2W_PLLD_ANA2, 0x1058)
150
+REG32(A2W_PLLD_ANA3, 0x105c)
151
+
152
+REG32(A2W_PLLH_ANA0, 0x1070)
153
+REG32(A2W_PLLH_ANA1, 0x1074)
154
+ FIELD(A2W_PLLH_ANA1, FB_PREDIV, 11, 1)
155
+REG32(A2W_PLLH_ANA2, 0x1078)
156
+REG32(A2W_PLLH_ANA3, 0x107c)
157
+
158
+REG32(A2W_PLLB_ANA0, 0x10f0)
159
+REG32(A2W_PLLB_ANA1, 0x10f4)
160
+REG32(A2W_PLLB_ANA2, 0x10f8)
161
+REG32(A2W_PLLB_ANA3, 0x10fc)
162
+
163
+REG32(A2W_PLLA_FRAC, 0x1200)
164
+ FIELD(A2W_PLLx_FRAC, FRAC, 0, 20)
165
+REG32(A2W_PLLC_FRAC, 0x1220)
166
+REG32(A2W_PLLD_FRAC, 0x1240)
167
+REG32(A2W_PLLH_FRAC, 0x1260)
168
+REG32(A2W_PLLB_FRAC, 0x12e0)
169
+
170
/*
171
* This field is common to all registers. Each register write value must match
172
* the CPRMAN_PASSWORD magic value in its 8 MSB.
173
@@ -XXX,XX +XXX,XX @@
174
FIELD(CPRMAN, PASSWORD, 24, 8)
175
#define CPRMAN_PASSWORD 0x5a
176
177
+/* PLL init info */
178
+typedef struct PLLInitInfo {
179
+ const char *name;
180
+ size_t cm_offset;
181
+ size_t a2w_ctrl_offset;
182
+ size_t a2w_ana_offset;
183
+ uint32_t prediv_mask; /* Prediv bit in ana[1] */
184
+ size_t a2w_frac_offset;
185
+} PLLInitInfo;
186
+
187
+#define FILL_PLL_INIT_INFO(pll_) \
188
+ .cm_offset = R_CM_ ## pll_, \
189
+ .a2w_ctrl_offset = R_A2W_ ## pll_ ## _CTRL, \
190
+ .a2w_ana_offset = R_A2W_ ## pll_ ## _ANA0, \
191
+ .a2w_frac_offset = R_A2W_ ## pll_ ## _FRAC
192
+
193
+static const PLLInitInfo PLL_INIT_INFO[] = {
194
+ [CPRMAN_PLLA] = {
195
+ .name = "plla",
196
+ .prediv_mask = R_A2W_PLLx_ANA1_FB_PREDIV_MASK,
197
+ FILL_PLL_INIT_INFO(PLLA),
198
+ },
199
+ [CPRMAN_PLLC] = {
200
+ .name = "pllc",
201
+ .prediv_mask = R_A2W_PLLx_ANA1_FB_PREDIV_MASK,
202
+ FILL_PLL_INIT_INFO(PLLC),
203
+ },
204
+ [CPRMAN_PLLD] = {
205
+ .name = "plld",
206
+ .prediv_mask = R_A2W_PLLx_ANA1_FB_PREDIV_MASK,
207
+ FILL_PLL_INIT_INFO(PLLD),
208
+ },
209
+ [CPRMAN_PLLH] = {
210
+ .name = "pllh",
211
+ .prediv_mask = R_A2W_PLLH_ANA1_FB_PREDIV_MASK,
212
+ FILL_PLL_INIT_INFO(PLLH),
213
+ },
214
+ [CPRMAN_PLLB] = {
215
+ .name = "pllb",
216
+ .prediv_mask = R_A2W_PLLx_ANA1_FB_PREDIV_MASK,
217
+ FILL_PLL_INIT_INFO(PLLB),
218
+ },
219
+};
220
+
221
+#undef FILL_PLL_CHANNEL_INIT_INFO
222
+
223
+static inline void set_pll_init_info(BCM2835CprmanState *s,
224
+ CprmanPllState *pll,
225
+ CprmanPll id)
226
+{
227
+ pll->id = id;
228
+ pll->reg_cm = &s->regs[PLL_INIT_INFO[id].cm_offset];
229
+ pll->reg_a2w_ctrl = &s->regs[PLL_INIT_INFO[id].a2w_ctrl_offset];
230
+ pll->reg_a2w_ana = &s->regs[PLL_INIT_INFO[id].a2w_ana_offset];
231
+ pll->prediv_mask = PLL_INIT_INFO[id].prediv_mask;
232
+ pll->reg_a2w_frac = &s->regs[PLL_INIT_INFO[id].a2w_frac_offset];
233
+}
67
+}
234
+
68
+
235
#endif
69
+static const VMStateDescription vmstate_gicv3_cpu_nmi = {
236
diff --git a/hw/misc/bcm2835_cprman.c b/hw/misc/bcm2835_cprman.c
70
+ .name = "arm_gicv3_cpu/nmi",
237
index XXXXXXX..XXXXXXX 100644
238
--- a/hw/misc/bcm2835_cprman.c
239
+++ b/hw/misc/bcm2835_cprman.c
240
@@ -XXX,XX +XXX,XX @@
241
#include "hw/misc/bcm2835_cprman_internals.h"
242
#include "trace.h"
243
244
+/* PLL */
245
+
246
+static void pll_update(CprmanPllState *pll)
247
+{
248
+ clock_update(pll->out, 0);
249
+}
250
+
251
+static void pll_xosc_update(void *opaque)
252
+{
253
+ pll_update(CPRMAN_PLL(opaque));
254
+}
255
+
256
+static void pll_init(Object *obj)
257
+{
258
+ CprmanPllState *s = CPRMAN_PLL(obj);
259
+
260
+ s->xosc_in = qdev_init_clock_in(DEVICE(s), "xosc-in", pll_xosc_update, s);
261
+ s->out = qdev_init_clock_out(DEVICE(s), "out");
262
+}
263
+
264
+static const VMStateDescription pll_vmstate = {
265
+ .name = TYPE_CPRMAN_PLL,
266
+ .version_id = 1,
71
+ .version_id = 1,
267
+ .minimum_version_id = 1,
72
+ .minimum_version_id = 1,
268
+ .fields = (VMStateField[]) {
73
+ .needed = gicv3_cpu_nmi_needed,
269
+ VMSTATE_CLOCK(xosc_in, CprmanPllState),
74
+ .fields = (const VMStateField[]) {
75
+ VMSTATE_UINT32(gicr_inmir0, GICv3CPUState),
270
+ VMSTATE_END_OF_LIST()
76
+ VMSTATE_END_OF_LIST()
271
+ }
77
+ }
272
+};
78
+};
273
+
79
+
274
+static void pll_class_init(ObjectClass *klass, void *data)
80
static const VMStateDescription vmstate_gicv3_cpu = {
81
.name = "arm_gicv3_cpu",
82
.version_id = 1,
83
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_gicv3_cpu = {
84
&vmstate_gicv3_cpu_virt,
85
&vmstate_gicv3_cpu_sre_el1,
86
&vmstate_gicv3_gicv4,
87
+ &vmstate_gicv3_cpu_nmi,
88
NULL
89
}
90
};
91
@@ -XXX,XX +XXX,XX @@ const VMStateDescription vmstate_gicv3_gicd_no_migration_shift_bug = {
92
}
93
};
94
95
+static bool gicv3_nmi_needed(void *opaque)
275
+{
96
+{
276
+ DeviceClass *dc = DEVICE_CLASS(klass);
97
+ GICv3State *cs = opaque;
277
+
98
+
278
+ dc->vmsd = &pll_vmstate;
99
+ return cs->nmi_support;
279
+}
100
+}
280
+
101
+
281
+static const TypeInfo cprman_pll_info = {
102
+const VMStateDescription vmstate_gicv3_gicd_nmi = {
282
+ .name = TYPE_CPRMAN_PLL,
103
+ .name = "arm_gicv3/gicd_nmi",
283
+ .parent = TYPE_DEVICE,
104
+ .version_id = 1,
284
+ .instance_size = sizeof(CprmanPllState),
105
+ .minimum_version_id = 1,
285
+ .class_init = pll_class_init,
106
+ .needed = gicv3_nmi_needed,
286
+ .instance_init = pll_init,
107
+ .fields = (const VMStateField[]) {
108
+ VMSTATE_UINT32_ARRAY(nmi, GICv3State, GICV3_BMP_SIZE),
109
+ VMSTATE_END_OF_LIST()
110
+ }
287
+};
111
+};
288
+
112
+
289
+
113
static const VMStateDescription vmstate_gicv3 = {
290
/* CPRMAN "top level" model */
114
.name = "arm_gicv3",
291
292
static uint64_t cprman_read(void *opaque, hwaddr offset,
293
@@ -XXX,XX +XXX,XX @@ static uint64_t cprman_read(void *opaque, hwaddr offset,
294
return r;
295
}
296
297
+#define CASE_PLL_REGS(pll_) \
298
+ case R_CM_ ## pll_: \
299
+ case R_A2W_ ## pll_ ## _CTRL: \
300
+ case R_A2W_ ## pll_ ## _ANA0: \
301
+ case R_A2W_ ## pll_ ## _ANA1: \
302
+ case R_A2W_ ## pll_ ## _ANA2: \
303
+ case R_A2W_ ## pll_ ## _ANA3: \
304
+ case R_A2W_ ## pll_ ## _FRAC
305
+
306
static void cprman_write(void *opaque, hwaddr offset,
307
uint64_t value, unsigned size)
308
{
309
@@ -XXX,XX +XXX,XX @@ static void cprman_write(void *opaque, hwaddr offset,
310
trace_bcm2835_cprman_write(offset, value);
311
s->regs[idx] = value;
312
313
+ switch (idx) {
314
+ CASE_PLL_REGS(PLLA) :
315
+ pll_update(&s->plls[CPRMAN_PLLA]);
316
+ break;
317
+
318
+ CASE_PLL_REGS(PLLC) :
319
+ pll_update(&s->plls[CPRMAN_PLLC]);
320
+ break;
321
+
322
+ CASE_PLL_REGS(PLLD) :
323
+ pll_update(&s->plls[CPRMAN_PLLD]);
324
+ break;
325
+
326
+ CASE_PLL_REGS(PLLH) :
327
+ pll_update(&s->plls[CPRMAN_PLLH]);
328
+ break;
329
+
330
+ CASE_PLL_REGS(PLLB) :
331
+ pll_update(&s->plls[CPRMAN_PLLB]);
332
+ break;
333
+ }
334
}
335
336
+#undef CASE_PLL_REGS
337
+
338
static const MemoryRegionOps cprman_ops = {
339
.read = cprman_read,
340
.write = cprman_write,
341
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps cprman_ops = {
342
static void cprman_reset(DeviceState *dev)
343
{
344
BCM2835CprmanState *s = CPRMAN(dev);
345
+ size_t i;
346
347
memset(s->regs, 0, sizeof(s->regs));
348
349
+ for (i = 0; i < CPRMAN_NUM_PLL; i++) {
350
+ device_cold_reset(DEVICE(&s->plls[i]));
351
+ }
352
+
353
clock_update_hz(s->xosc, s->xosc_freq);
354
}
355
356
static void cprman_init(Object *obj)
357
{
358
BCM2835CprmanState *s = CPRMAN(obj);
359
+ size_t i;
360
+
361
+ for (i = 0; i < CPRMAN_NUM_PLL; i++) {
362
+ object_initialize_child(obj, PLL_INIT_INFO[i].name,
363
+ &s->plls[i], TYPE_CPRMAN_PLL);
364
+ set_pll_init_info(s, &s->plls[i], i);
365
+ }
366
367
s->xosc = clock_new(obj, "xosc");
368
369
@@ -XXX,XX +XXX,XX @@ static void cprman_init(Object *obj)
370
sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->iomem);
371
}
372
373
+static void cprman_realize(DeviceState *dev, Error **errp)
374
+{
375
+ BCM2835CprmanState *s = CPRMAN(dev);
376
+ size_t i;
377
+
378
+ for (i = 0; i < CPRMAN_NUM_PLL; i++) {
379
+ CprmanPllState *pll = &s->plls[i];
380
+
381
+ clock_set_source(pll->xosc_in, s->xosc);
382
+
383
+ if (!qdev_realize(DEVICE(pll), NULL, errp)) {
384
+ return;
385
+ }
386
+ }
387
+}
388
+
389
static const VMStateDescription cprman_vmstate = {
390
.name = TYPE_BCM2835_CPRMAN,
391
.version_id = 1,
115
.version_id = 1,
392
@@ -XXX,XX +XXX,XX @@ static void cprman_class_init(ObjectClass *klass, void *data)
116
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_gicv3 = {
393
{
117
},
394
DeviceClass *dc = DEVICE_CLASS(klass);
118
.subsections = (const VMStateDescription * const []) {
395
119
&vmstate_gicv3_gicd_no_migration_shift_bug,
396
+ dc->realize = cprman_realize;
120
+ &vmstate_gicv3_gicd_nmi,
397
dc->reset = cprman_reset;
121
NULL
398
dc->vmsd = &cprman_vmstate;
122
}
399
device_class_set_props(dc, cprman_properties);
123
};
400
@@ -XXX,XX +XXX,XX @@ static const TypeInfo cprman_info = {
401
static void cprman_register_types(void)
402
{
403
type_register_static(&cprman_info);
404
+ type_register_static(&cprman_pll_info);
405
}
406
407
type_init(cprman_register_types);
408
--
124
--
409
2.20.1
125
2.34.1
410
411
diff view generated by jsdifflib
1
From: Shashi Mallela <shashi.mallela@linaro.org>
1
From: Jinjie Ruan <ruanjinjie@huawei.com>
2
2
3
Included the newly implemented SBSA generic watchdog device model into
3
Add GICR_INMIR0 register and support access GICR_INMIR0.
4
SBSA platform
5
4
6
Signed-off-by: Shashi Mallela <shashi.mallela@linaro.org>
5
Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Message-id: 20201027015927.29495-3-shashi.mallela@linaro.org
8
Message-id: 20240407081733.3231820-17-ruanjinjie@huawei.com
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
10
---
11
hw/arm/sbsa-ref.c | 23 +++++++++++++++++++++++
11
hw/intc/gicv3_internal.h | 1 +
12
1 file changed, 23 insertions(+)
12
hw/intc/arm_gicv3_redist.c | 19 +++++++++++++++++++
13
2 files changed, 20 insertions(+)
13
14
14
diff --git a/hw/arm/sbsa-ref.c b/hw/arm/sbsa-ref.c
15
diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h
15
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/arm/sbsa-ref.c
17
--- a/hw/intc/gicv3_internal.h
17
+++ b/hw/arm/sbsa-ref.c
18
+++ b/hw/intc/gicv3_internal.h
18
@@ -XXX,XX +XXX,XX @@
19
@@ -XXX,XX +XXX,XX @@
19
#include "hw/qdev-properties.h"
20
#define GICR_ICFGR1 (GICR_SGI_OFFSET + 0x0C04)
20
#include "hw/usb.h"
21
#define GICR_IGRPMODR0 (GICR_SGI_OFFSET + 0x0D00)
21
#include "hw/char/pl011.h"
22
#define GICR_NSACR (GICR_SGI_OFFSET + 0x0E00)
22
+#include "hw/watchdog/sbsa_gwdt.h"
23
+#define GICR_INMIR0 (GICR_SGI_OFFSET + 0x0F80)
23
#include "net/net.h"
24
24
#include "qom/object.h"
25
/* VLPI redistributor registers, offsets from VLPI_base */
25
26
#define GICR_VPROPBASER (GICR_VLPI_OFFSET + 0x70)
26
@@ -XXX,XX +XXX,XX @@ enum {
27
diff --git a/hw/intc/arm_gicv3_redist.c b/hw/intc/arm_gicv3_redist.c
27
SBSA_GIC_DIST,
28
index XXXXXXX..XXXXXXX 100644
28
SBSA_GIC_REDIST,
29
--- a/hw/intc/arm_gicv3_redist.c
29
SBSA_SECURE_EC,
30
+++ b/hw/intc/arm_gicv3_redist.c
30
+ SBSA_GWDT,
31
@@ -XXX,XX +XXX,XX @@ static int gicr_ns_access(GICv3CPUState *cs, int irq)
31
+ SBSA_GWDT_REFRESH,
32
return extract32(cs->gicr_nsacr, irq * 2, 2);
32
+ SBSA_GWDT_CONTROL,
33
SBSA_SMMU,
34
SBSA_UART,
35
SBSA_RTC,
36
@@ -XXX,XX +XXX,XX @@ static const MemMapEntry sbsa_ref_memmap[] = {
37
[SBSA_GIC_DIST] = { 0x40060000, 0x00010000 },
38
[SBSA_GIC_REDIST] = { 0x40080000, 0x04000000 },
39
[SBSA_SECURE_EC] = { 0x50000000, 0x00001000 },
40
+ [SBSA_GWDT_REFRESH] = { 0x50010000, 0x00001000 },
41
+ [SBSA_GWDT_CONTROL] = { 0x50011000, 0x00001000 },
42
[SBSA_UART] = { 0x60000000, 0x00001000 },
43
[SBSA_RTC] = { 0x60010000, 0x00001000 },
44
[SBSA_GPIO] = { 0x60020000, 0x00001000 },
45
@@ -XXX,XX +XXX,XX @@ static const int sbsa_ref_irqmap[] = {
46
[SBSA_AHCI] = 10,
47
[SBSA_EHCI] = 11,
48
[SBSA_SMMU] = 12, /* ... to 15 */
49
+ [SBSA_GWDT] = 16,
50
};
51
52
static uint64_t sbsa_ref_cpu_mp_affinity(SBSAMachineState *sms, int idx)
53
@@ -XXX,XX +XXX,XX @@ static void create_rtc(const SBSAMachineState *sms)
54
sysbus_create_simple("pl031", base, qdev_get_gpio_in(sms->gic, irq));
55
}
33
}
56
34
57
+static void create_wdt(const SBSAMachineState *sms)
35
+static void gicr_write_bitmap_reg(GICv3CPUState *cs, MemTxAttrs attrs,
36
+ uint32_t *reg, uint32_t val)
58
+{
37
+{
59
+ hwaddr rbase = sbsa_ref_memmap[SBSA_GWDT_REFRESH].base;
38
+ /* Helper routine to implement writing to a "set" register */
60
+ hwaddr cbase = sbsa_ref_memmap[SBSA_GWDT_CONTROL].base;
39
+ val &= mask_group(cs, attrs);
61
+ DeviceState *dev = qdev_new(TYPE_WDT_SBSA);
40
+ *reg = val;
62
+ SysBusDevice *s = SYS_BUS_DEVICE(dev);
41
+ gicv3_redist_update(cs);
63
+ int irq = sbsa_ref_irqmap[SBSA_GWDT];
64
+
65
+ sysbus_realize_and_unref(s, &error_fatal);
66
+ sysbus_mmio_map(s, 0, rbase);
67
+ sysbus_mmio_map(s, 1, cbase);
68
+ sysbus_connect_irq(s, 0, qdev_get_gpio_in(sms->gic, irq));
69
+}
42
+}
70
+
43
+
71
static DeviceState *gpio_key_dev;
44
static void gicr_write_set_bitmap_reg(GICv3CPUState *cs, MemTxAttrs attrs,
72
static void sbsa_ref_powerdown_req(Notifier *n, void *opaque)
45
uint32_t *reg, uint32_t val)
73
{
46
{
74
@@ -XXX,XX +XXX,XX @@ static void sbsa_ref_init(MachineState *machine)
47
@@ -XXX,XX +XXX,XX @@ static MemTxResult gicr_readl(GICv3CPUState *cs, hwaddr offset,
75
48
*data = value;
76
create_rtc(sms);
49
return MEMTX_OK;
77
50
}
78
+ create_wdt(sms);
51
+ case GICR_INMIR0:
52
+ *data = cs->gic->nmi_support ?
53
+ gicr_read_bitmap_reg(cs, attrs, cs->gicr_inmir0) : 0;
54
+ return MEMTX_OK;
55
case GICR_ICFGR0:
56
case GICR_ICFGR1:
57
{
58
@@ -XXX,XX +XXX,XX @@ static MemTxResult gicr_writel(GICv3CPUState *cs, hwaddr offset,
59
gicv3_redist_update(cs);
60
return MEMTX_OK;
61
}
62
+ case GICR_INMIR0:
63
+ if (cs->gic->nmi_support) {
64
+ gicr_write_bitmap_reg(cs, attrs, &cs->gicr_inmir0, value);
65
+ }
66
+ return MEMTX_OK;
79
+
67
+
80
create_gpio(sms);
68
case GICR_ICFGR0:
81
69
/* Register is all RAZ/WI or RAO/WI bits */
82
create_ahci(sms);
70
return MEMTX_OK;
83
--
71
--
84
2.20.1
72
2.34.1
85
86
diff view generated by jsdifflib
1
From: Luc Michel <luc@lmichel.fr>
1
From: Jinjie Ruan <ruanjinjie@huawei.com>
2
2
3
A PLL channel is able to further divide the generated PLL frequency.
3
Add GICD_INMIR, GICD_INMIRnE register and support access GICD_INMIR0.
4
The divider is given in the CTRL_A2W register. Some channels have an
5
additional fixed divider which is always applied to the signal.
6
4
7
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
5
Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Signed-off-by: Luc Michel <luc@lmichel.fr>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Tested-by: Guenter Roeck <linux@roeck-us.net>
8
Message-id: 20240407081733.3231820-18-ruanjinjie@huawei.com
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
10
---
13
hw/misc/bcm2835_cprman.c | 33 ++++++++++++++++++++++++++++++++-
11
hw/intc/gicv3_internal.h | 2 ++
14
1 file changed, 32 insertions(+), 1 deletion(-)
12
hw/intc/arm_gicv3_dist.c | 34 ++++++++++++++++++++++++++++++++++
13
2 files changed, 36 insertions(+)
15
14
16
diff --git a/hw/misc/bcm2835_cprman.c b/hw/misc/bcm2835_cprman.c
15
diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h
17
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/misc/bcm2835_cprman.c
17
--- a/hw/intc/gicv3_internal.h
19
+++ b/hw/misc/bcm2835_cprman.c
18
+++ b/hw/intc/gicv3_internal.h
20
@@ -XXX,XX +XXX,XX @@ static const TypeInfo cprman_pll_info = {
19
@@ -XXX,XX +XXX,XX @@
21
20
#define GICD_SGIR 0x0F00
22
/* PLL channel */
21
#define GICD_CPENDSGIR 0x0F10
23
22
#define GICD_SPENDSGIR 0x0F20
24
+static bool pll_channel_is_enabled(CprmanPllChannelState *channel)
23
+#define GICD_INMIR 0x0F80
24
+#define GICD_INMIRnE 0x3B00
25
#define GICD_IROUTER 0x6000
26
#define GICD_IDREGS 0xFFD0
27
28
diff --git a/hw/intc/arm_gicv3_dist.c b/hw/intc/arm_gicv3_dist.c
29
index XXXXXXX..XXXXXXX 100644
30
--- a/hw/intc/arm_gicv3_dist.c
31
+++ b/hw/intc/arm_gicv3_dist.c
32
@@ -XXX,XX +XXX,XX @@ static int gicd_ns_access(GICv3State *s, int irq)
33
return extract32(s->gicd_nsacr[irq / 16], (irq % 16) * 2, 2);
34
}
35
36
+static void gicd_write_bitmap_reg(GICv3State *s, MemTxAttrs attrs,
37
+ uint32_t *bmp, maskfn *maskfn,
38
+ int offset, uint32_t val)
25
+{
39
+{
26
+ /*
40
+ /*
27
+ * XXX I'm not sure of the purpose of the LOAD field. The Linux driver does
41
+ * Helper routine to implement writing to a "set" register
28
+ * not set it when enabling the channel, but does clear it when disabling
42
+ * (GICD_INMIR, etc).
29
+ * it.
43
+ * Semantics implemented here:
44
+ * RAZ/WI for SGIs, PPIs, unimplemented IRQs
45
+ * Bits corresponding to Group 0 or Secure Group 1 interrupts RAZ/WI.
46
+ * offset should be the offset in bytes of the register from the start
47
+ * of its group.
30
+ */
48
+ */
31
+ return !FIELD_EX32(*channel->reg_a2w_ctrl, A2W_PLLx_CHANNELy, DISABLE)
49
+ int irq = offset * 8;
32
+ && !(*channel->reg_cm & channel->hold_mask);
50
+
51
+ if (irq < GIC_INTERNAL || irq >= s->num_irq) {
52
+ return;
53
+ }
54
+ val &= mask_group_and_nsacr(s, attrs, maskfn, irq);
55
+ *gic_bmp_ptr32(bmp, irq) = val;
56
+ gicv3_update(s, irq, 32);
33
+}
57
+}
34
+
58
+
35
static void pll_channel_update(CprmanPllChannelState *channel)
59
static void gicd_write_set_bitmap_reg(GICv3State *s, MemTxAttrs attrs,
36
{
60
uint32_t *bmp,
37
- clock_update(channel->out, 0);
61
maskfn *maskfn,
38
+ uint64_t freq, div;
62
@@ -XXX,XX +XXX,XX @@ static bool gicd_readl(GICv3State *s, hwaddr offset,
39
+
63
/* RAZ/WI since affinity routing is always enabled */
40
+ if (!pll_channel_is_enabled(channel)) {
64
*data = 0;
41
+ clock_update(channel->out, 0);
65
return true;
42
+ return;
66
+ case GICD_INMIR ... GICD_INMIR + 0x7f:
43
+ }
67
+ *data = (!s->nmi_support) ? 0 :
44
+
68
+ gicd_read_bitmap_reg(s, attrs, s->nmi, NULL,
45
+ div = FIELD_EX32(*channel->reg_a2w_ctrl, A2W_PLLx_CHANNELy, DIV);
69
+ offset - GICD_INMIR);
46
+
70
+ return true;
47
+ if (!div) {
71
case GICD_IROUTER ... GICD_IROUTER + 0x1fdf:
48
+ /*
72
{
49
+ * It seems that when the divider value is 0, it is considered as
73
uint64_t r;
50
+ * being maximum by the hardware (see the Linux driver).
74
@@ -XXX,XX +XXX,XX @@ static bool gicd_writel(GICv3State *s, hwaddr offset,
51
+ */
75
case GICD_SPENDSGIR ... GICD_SPENDSGIR + 0xf:
52
+ div = R_A2W_PLLx_CHANNELy_DIV_MASK;
76
/* RAZ/WI since affinity routing is always enabled */
53
+ }
77
return true;
54
+
78
+ case GICD_INMIR ... GICD_INMIR + 0x7f:
55
+ /* Some channels have an additional fixed divider */
79
+ if (s->nmi_support) {
56
+ freq = clock_get_hz(channel->pll_in) / (div * channel->fixed_divider);
80
+ gicd_write_bitmap_reg(s, attrs, s->nmi, NULL,
57
+
81
+ offset - GICD_INMIR, value);
58
+ clock_update_hz(channel->out, freq);
82
+ }
59
}
83
+ return true;
60
84
case GICD_IROUTER ... GICD_IROUTER + 0x1fdf:
61
/* Update a PLL and all its channels */
85
{
86
uint64_t r;
62
--
87
--
63
2.20.1
88
2.34.1
64
65
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
Add the NMIAR CPU interface registers which deal with acknowledging NMI.
2
2
3
Remove usage of TypeInfo::class_data. Instead fill the fields in
3
When introduce NMI interrupt, there are some updates to the semantics for the
4
the corresponding class_init().
4
register ICC_IAR1_EL1 and ICC_HPPIR1_EL1. For ICC_IAR1_EL1 register, it
5
should return 1022 if the intid has non-maskable property. And for
6
ICC_NMIAR1_EL1 register, it should return 1023 if the intid do not have
7
non-maskable property. Howerever, these are not necessary for ICC_HPPIR1_EL1
8
register.
5
9
6
So far all children use the same values for almost all fields,
10
And the APR and RPR has NMI bits which should be handled correctly.
7
but we are going to add the BCM2711/BCM2838 SoC for the raspi4
8
machine which use different fields.
9
11
10
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
12
Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com>
11
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
13
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20201024170127.3592182-3-f4bug@amsat.org
14
[PMM: Separate out whether cpuif supports NMI from whether the
15
GIC proper (IRI) supports NMI]
16
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
17
Message-id: 20240407081733.3231820-19-ruanjinjie@huawei.com
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
19
---
15
hw/arm/bcm2836.c | 108 ++++++++++++++++++++++-------------------------
20
hw/intc/gicv3_internal.h | 5 +
16
1 file changed, 51 insertions(+), 57 deletions(-)
21
include/hw/intc/arm_gicv3_common.h | 7 ++
22
hw/intc/arm_gicv3_cpuif.c | 147 ++++++++++++++++++++++++++++-
23
hw/intc/trace-events | 1 +
24
4 files changed, 155 insertions(+), 5 deletions(-)
17
25
18
diff --git a/hw/arm/bcm2836.c b/hw/arm/bcm2836.c
26
diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h
19
index XXXXXXX..XXXXXXX 100644
27
index XXXXXXX..XXXXXXX 100644
20
--- a/hw/arm/bcm2836.c
28
--- a/hw/intc/gicv3_internal.h
21
+++ b/hw/arm/bcm2836.c
29
+++ b/hw/intc/gicv3_internal.h
30
@@ -XXX,XX +XXX,XX @@ FIELD(GICR_VPENDBASER, VALID, 63, 1)
31
#define ICC_CTLR_EL3_A3V (1U << 15)
32
#define ICC_CTLR_EL3_NDS (1U << 17)
33
34
+#define ICC_AP1R_EL1_NMI (1ULL << 63)
35
+#define ICC_RPR_EL1_NSNMI (1ULL << 62)
36
+#define ICC_RPR_EL1_NMI (1ULL << 63)
37
+
38
#define ICH_VMCR_EL2_VENG0_SHIFT 0
39
#define ICH_VMCR_EL2_VENG0 (1U << ICH_VMCR_EL2_VENG0_SHIFT)
40
#define ICH_VMCR_EL2_VENG1_SHIFT 1
41
@@ -XXX,XX +XXX,XX @@ FIELD(VTE, RDBASE, 42, RDBASE_PROCNUM_LENGTH)
42
/* Special interrupt IDs */
43
#define INTID_SECURE 1020
44
#define INTID_NONSECURE 1021
45
+#define INTID_NMI 1022
46
#define INTID_SPURIOUS 1023
47
48
/* Functions internal to the emulated GICv3 */
49
diff --git a/include/hw/intc/arm_gicv3_common.h b/include/hw/intc/arm_gicv3_common.h
50
index XXXXXXX..XXXXXXX 100644
51
--- a/include/hw/intc/arm_gicv3_common.h
52
+++ b/include/hw/intc/arm_gicv3_common.h
53
@@ -XXX,XX +XXX,XX @@ struct GICv3CPUState {
54
55
/* This is temporary working state, to avoid a malloc in gicv3_update() */
56
bool seenbetter;
57
+
58
+ /*
59
+ * Whether the CPU interface has NMI support (FEAT_GICv3_NMI). The
60
+ * CPU interface may support NMIs even when the GIC proper (what the
61
+ * spec calls the IRI; the redistributors and distributor) does not.
62
+ */
63
+ bool nmi_support;
64
};
65
66
/*
67
diff --git a/hw/intc/arm_gicv3_cpuif.c b/hw/intc/arm_gicv3_cpuif.c
68
index XXXXXXX..XXXXXXX 100644
69
--- a/hw/intc/arm_gicv3_cpuif.c
70
+++ b/hw/intc/arm_gicv3_cpuif.c
22
@@ -XXX,XX +XXX,XX @@
71
@@ -XXX,XX +XXX,XX @@
23
#include "hw/arm/raspi_platform.h"
72
#include "hw/irq.h"
24
#include "hw/sysbus.h"
73
#include "cpu.h"
25
74
#include "target/arm/cpregs.h"
26
-typedef struct BCM283XInfo BCM283XInfo;
75
+#include "target/arm/cpu-features.h"
27
-
76
#include "sysemu/tcg.h"
28
typedef struct BCM283XClass {
77
#include "sysemu/qtest.h"
29
/*< private >*/
78
30
DeviceClass parent_class;
79
@@ -XXX,XX +XXX,XX @@ static uint64_t icv_iar_read(CPUARMState *env, const ARMCPRegInfo *ri)
31
/*< public >*/
80
return intid;
32
- const BCM283XInfo *info;
81
}
33
-} BCM283XClass;
82
34
-
83
+static uint64_t icv_nmiar1_read(CPUARMState *env, const ARMCPRegInfo *ri)
35
-struct BCM283XInfo {
84
+{
36
const char *name;
85
+ /* todo */
37
const char *cpu_type;
86
+ uint64_t intid = INTID_SPURIOUS;
38
hwaddr peri_base; /* Peripheral base address seen by the CPU */
87
+ return intid;
39
hwaddr ctrl_base; /* Interrupt controller and mailboxes etc. */
88
+}
40
int clusterid;
89
+
41
-};
90
static uint32_t icc_fullprio_mask(GICv3CPUState *cs)
42
+} BCM283XClass;
91
{
43
92
/*
44
#define BCM283X_CLASS(klass) \
93
@@ -XXX,XX +XXX,XX @@ static int icc_highest_active_prio(GICv3CPUState *cs)
45
OBJECT_CLASS_CHECK(BCM283XClass, (klass), TYPE_BCM283X)
94
*/
46
#define BCM283X_GET_CLASS(obj) \
95
int i;
47
OBJECT_GET_CLASS(BCM283XClass, (obj), TYPE_BCM283X)
96
48
97
+ if (cs->nmi_support) {
49
-static const BCM283XInfo bcm283x_socs[] = {
98
+ /*
50
- {
99
+ * If an NMI is active this takes precedence over anything else
51
- .name = TYPE_BCM2836,
100
+ * for priority purposes; the NMI bit is only in the AP1R0 bit.
52
- .cpu_type = ARM_CPU_TYPE_NAME("cortex-a7"),
101
+ * We return here the effective priority of the NMI, which is
53
- .peri_base = 0x3f000000,
102
+ * either 0x0 or 0x80. Callers will need to check NMI again for
54
- .ctrl_base = 0x40000000,
103
+ * purposes of either setting the RPR register bits or for
55
- .clusterid = 0xf,
104
+ * prioritization of NMI vs non-NMI.
56
- },
105
+ */
57
-#ifdef TARGET_AARCH64
106
+ if (cs->icc_apr[GICV3_G1][0] & ICC_AP1R_EL1_NMI) {
58
- {
107
+ return 0;
59
- .name = TYPE_BCM2837,
108
+ }
60
- .cpu_type = ARM_CPU_TYPE_NAME("cortex-a53"),
109
+ if (cs->icc_apr[GICV3_G1NS][0] & ICC_AP1R_EL1_NMI) {
61
- .peri_base = 0x3f000000,
110
+ return (cs->gic->gicd_ctlr & GICD_CTLR_DS) ? 0 : 0x80;
62
- .ctrl_base = 0x40000000,
111
+ }
63
- .clusterid = 0x0,
112
+ }
64
- },
113
+
65
-#endif
114
for (i = 0; i < icc_num_aprs(cs); i++) {
66
-};
115
uint32_t apr = cs->icc_apr[GICV3_G0][i] |
67
-
116
cs->icc_apr[GICV3_G1][i] | cs->icc_apr[GICV3_G1NS][i];
68
static void bcm2836_init(Object *obj)
117
@@ -XXX,XX +XXX,XX @@ static bool icc_hppi_can_preempt(GICv3CPUState *cs)
69
{
118
*/
70
BCM283XState *s = BCM283X(obj);
119
int rprio;
71
BCM283XClass *bc = BCM283X_GET_CLASS(obj);
120
uint32_t mask;
72
- const BCM283XInfo *info = bc->info;
121
+ ARMCPU *cpu = ARM_CPU(cs->cpu);
73
int n;
122
+ CPUARMState *env = &cpu->env;
74
123
75
for (n = 0; n < BCM283X_NCPUS; n++) {
124
if (icc_no_enabled_hppi(cs)) {
76
object_initialize_child(obj, "cpu[*]", &s->cpu[n].core,
125
return false;
77
- info->cpu_type);
126
}
78
+ bc->cpu_type);
127
79
}
128
- if (cs->hppi.prio >= cs->icc_pmr_el1) {
80
129
+ if (cs->hppi.nmi) {
81
object_initialize_child(obj, "control", &s->control, TYPE_BCM2836_CONTROL);
130
+ if (!(cs->gic->gicd_ctlr & GICD_CTLR_DS) &&
82
@@ -XXX,XX +XXX,XX @@ static void bcm2836_realize(DeviceState *dev, Error **errp)
131
+ cs->hppi.grp == GICV3_G1NS) {
83
{
132
+ if (cs->icc_pmr_el1 < 0x80) {
84
BCM283XState *s = BCM283X(dev);
133
+ return false;
85
BCM283XClass *bc = BCM283X_GET_CLASS(dev);
134
+ }
86
- const BCM283XInfo *info = bc->info;
135
+ if (arm_is_secure(env) && cs->icc_pmr_el1 == 0x80) {
87
Object *obj;
136
+ return false;
88
int n;
137
+ }
89
138
+ }
90
@@ -XXX,XX +XXX,XX @@ static void bcm2836_realize(DeviceState *dev, Error **errp)
139
+ } else if (cs->hppi.prio >= cs->icc_pmr_el1) {
91
"sd-bus");
140
/* Priority mask masks this interrupt */
92
141
return false;
93
sysbus_mmio_map_overlap(SYS_BUS_DEVICE(&s->peripherals), 0,
142
}
94
- info->peri_base, 1);
143
@@ -XXX,XX +XXX,XX @@ static bool icc_hppi_can_preempt(GICv3CPUState *cs)
95
+ bc->peri_base, 1);
144
return true;
96
145
}
97
/* bcm2836 interrupt controller (and mailboxes, etc.) */
146
98
if (!sysbus_realize(SYS_BUS_DEVICE(&s->control), errp)) {
147
+ if (cs->hppi.nmi && (cs->hppi.prio & mask) == (rprio & mask)) {
148
+ if (!(cs->icc_apr[cs->hppi.grp][0] & ICC_AP1R_EL1_NMI)) {
149
+ return true;
150
+ }
151
+ }
152
+
153
return false;
154
}
155
156
@@ -XXX,XX +XXX,XX @@ static void icc_activate_irq(GICv3CPUState *cs, int irq)
157
int aprbit = prio >> (8 - cs->prebits);
158
int regno = aprbit / 32;
159
int regbit = aprbit % 32;
160
+ bool nmi = cs->hppi.nmi;
161
162
- cs->icc_apr[cs->hppi.grp][regno] |= (1 << regbit);
163
+ if (nmi) {
164
+ cs->icc_apr[cs->hppi.grp][regno] |= ICC_AP1R_EL1_NMI;
165
+ } else {
166
+ cs->icc_apr[cs->hppi.grp][regno] |= (1 << regbit);
167
+ }
168
169
if (irq < GIC_INTERNAL) {
170
cs->gicr_iactiver0 = deposit32(cs->gicr_iactiver0, irq, 1, 1);
171
@@ -XXX,XX +XXX,XX @@ static uint64_t icc_iar0_read(CPUARMState *env, const ARMCPRegInfo *ri)
172
static uint64_t icc_iar1_read(CPUARMState *env, const ARMCPRegInfo *ri)
173
{
174
GICv3CPUState *cs = icc_cs_from_env(env);
175
+ int el = arm_current_el(env);
176
uint64_t intid;
177
178
if (icv_access(env, HCR_IMO)) {
179
@@ -XXX,XX +XXX,XX @@ static uint64_t icc_iar1_read(CPUARMState *env, const ARMCPRegInfo *ri)
180
}
181
182
if (!gicv3_intid_is_special(intid)) {
183
- icc_activate_irq(cs, intid);
184
+ if (cs->hppi.nmi && env->cp15.sctlr_el[el] & SCTLR_NMI) {
185
+ intid = INTID_NMI;
186
+ } else {
187
+ icc_activate_irq(cs, intid);
188
+ }
189
}
190
191
trace_gicv3_icc_iar1_read(gicv3_redist_affid(cs), intid);
192
return intid;
193
}
194
195
+static uint64_t icc_nmiar1_read(CPUARMState *env, const ARMCPRegInfo *ri)
196
+{
197
+ GICv3CPUState *cs = icc_cs_from_env(env);
198
+ uint64_t intid;
199
+
200
+ if (icv_access(env, HCR_IMO)) {
201
+ return icv_nmiar1_read(env, ri);
202
+ }
203
+
204
+ if (!icc_hppi_can_preempt(cs)) {
205
+ intid = INTID_SPURIOUS;
206
+ } else {
207
+ intid = icc_hppir1_value(cs, env);
208
+ }
209
+
210
+ if (!gicv3_intid_is_special(intid)) {
211
+ if (!cs->hppi.nmi) {
212
+ intid = INTID_SPURIOUS;
213
+ } else {
214
+ icc_activate_irq(cs, intid);
215
+ }
216
+ }
217
+
218
+ trace_gicv3_icc_nmiar1_read(gicv3_redist_affid(cs), intid);
219
+ return intid;
220
+}
221
+
222
static void icc_drop_prio(GICv3CPUState *cs, int grp)
223
{
224
/* Drop the priority of the currently active interrupt in
225
@@ -XXX,XX +XXX,XX @@ static void icc_drop_prio(GICv3CPUState *cs, int grp)
226
if (!*papr) {
227
continue;
228
}
229
+
230
+ if (i == 0 && cs->nmi_support && (*papr & ICC_AP1R_EL1_NMI)) {
231
+ *papr &= (~ICC_AP1R_EL1_NMI);
232
+ break;
233
+ }
234
+
235
/* Clear the lowest set bit */
236
*papr &= *papr - 1;
237
break;
238
@@ -XXX,XX +XXX,XX @@ static int icc_highest_active_group(GICv3CPUState *cs)
239
*/
240
int i;
241
242
+ if (cs->nmi_support) {
243
+ if (cs->icc_apr[GICV3_G1][0] & ICC_AP1R_EL1_NMI) {
244
+ return GICV3_G1;
245
+ }
246
+ if (cs->icc_apr[GICV3_G1NS][0] & ICC_AP1R_EL1_NMI) {
247
+ return GICV3_G1NS;
248
+ }
249
+ }
250
+
251
for (i = 0; i < ARRAY_SIZE(cs->icc_apr[0]); i++) {
252
int g0ctz = ctz32(cs->icc_apr[GICV3_G0][i]);
253
int g1ctz = ctz32(cs->icc_apr[GICV3_G1][i]);
254
@@ -XXX,XX +XXX,XX @@ static void icc_ap_write(CPUARMState *env, const ARMCPRegInfo *ri,
99
return;
255
return;
100
}
256
}
101
257
102
- sysbus_mmio_map(SYS_BUS_DEVICE(&s->control), 0, info->ctrl_base);
258
- cs->icc_apr[grp][regno] = value & 0xFFFFFFFFU;
103
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->control), 0, bc->ctrl_base);
259
+ if (cs->nmi_support) {
104
260
+ cs->icc_apr[grp][regno] = value & (0xFFFFFFFFU | ICC_AP1R_EL1_NMI);
105
sysbus_connect_irq(SYS_BUS_DEVICE(&s->peripherals), 0,
261
+ } else {
106
qdev_get_gpio_in_named(DEVICE(&s->control), "gpu-irq", 0));
262
+ cs->icc_apr[grp][regno] = value & 0xFFFFFFFFU;
107
@@ -XXX,XX +XXX,XX @@ static void bcm2836_realize(DeviceState *dev, Error **errp)
263
+ }
108
264
gicv3_cpuif_update(cs);
109
for (n = 0; n < BCM283X_NCPUS; n++) {
265
}
110
/* TODO: this should be converted to a property of ARM_CPU */
266
111
- s->cpu[n].core.mp_affinity = (info->clusterid << 8) | n;
267
@@ -XXX,XX +XXX,XX @@ static void icc_dir_write(CPUARMState *env, const ARMCPRegInfo *ri,
112
+ s->cpu[n].core.mp_affinity = (bc->clusterid << 8) | n;
268
static uint64_t icc_rpr_read(CPUARMState *env, const ARMCPRegInfo *ri)
113
269
{
114
/* set periphbase/CBAR value for CPU-local registers */
270
GICv3CPUState *cs = icc_cs_from_env(env);
115
if (!object_property_set_int(OBJECT(&s->cpu[n].core), "reset-cbar",
271
- int prio;
116
- info->peri_base, errp)) {
272
+ uint64_t prio;
117
+ bc->peri_base, errp)) {
273
118
return;
274
if (icv_access(env, HCR_FMO | HCR_IMO)) {
275
return icv_rpr_read(env, ri);
276
@@ -XXX,XX +XXX,XX @@ static uint64_t icc_rpr_read(CPUARMState *env, const ARMCPRegInfo *ri)
119
}
277
}
120
278
}
121
@@ -XXX,XX +XXX,XX @@ static Property bcm2836_props[] = {
279
122
static void bcm283x_class_init(ObjectClass *oc, void *data)
280
+ if (cs->nmi_support) {
123
{
281
+ /* NMI info is reported in the high bits of RPR */
124
DeviceClass *dc = DEVICE_CLASS(oc);
282
+ if (arm_feature(env, ARM_FEATURE_EL3) && !arm_is_secure(env)) {
125
- BCM283XClass *bc = BCM283X_CLASS(oc);
283
+ if (cs->icc_apr[GICV3_G1NS][0] & ICC_AP1R_EL1_NMI) {
126
284
+ prio |= ICC_RPR_EL1_NMI;
127
- bc->info = data;
285
+ }
128
- dc->realize = bcm2836_realize;
286
+ } else {
129
- device_class_set_props(dc, bcm2836_props);
287
+ if (cs->icc_apr[GICV3_G1NS][0] & ICC_AP1R_EL1_NMI) {
130
/* Reason: Must be wired up in code (see raspi_init() function) */
288
+ prio |= ICC_RPR_EL1_NSNMI;
131
dc->user_creatable = false;
289
+ }
132
}
290
+ if (cs->icc_apr[GICV3_G1][0] & ICC_AP1R_EL1_NMI) {
133
291
+ prio |= ICC_RPR_EL1_NMI;
134
-static const TypeInfo bcm283x_type_info = {
292
+ }
135
- .name = TYPE_BCM283X,
293
+ }
136
- .parent = TYPE_DEVICE,
294
+ }
137
- .instance_size = sizeof(BCM283XState),
295
+
138
- .instance_init = bcm2836_init,
296
trace_gicv3_icc_rpr_read(gicv3_redist_affid(cs), prio);
139
- .class_size = sizeof(BCM283XClass),
297
return prio;
140
- .abstract = true,
298
}
141
+static void bcm2836_class_init(ObjectClass *oc, void *data)
299
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo gicv3_cpuif_icc_apxr23_reginfo[] = {
142
+{
300
},
143
+ DeviceClass *dc = DEVICE_CLASS(oc);
144
+ BCM283XClass *bc = BCM283X_CLASS(oc);
145
+
146
+ bc->cpu_type = ARM_CPU_TYPE_NAME("cortex-a7");
147
+ bc->peri_base = 0x3f000000;
148
+ bc->ctrl_base = 0x40000000;
149
+ bc->clusterid = 0xf;
150
+ dc->realize = bcm2836_realize;
151
+ device_class_set_props(dc, bcm2836_props);
152
};
301
};
153
302
154
-static void bcm2836_register_types(void)
303
+static const ARMCPRegInfo gicv3_cpuif_gicv3_nmi_reginfo[] = {
155
+#ifdef TARGET_AARCH64
304
+ { .name = "ICC_NMIAR1_EL1", .state = ARM_CP_STATE_BOTH,
156
+static void bcm2837_class_init(ObjectClass *oc, void *data)
305
+ .opc0 = 3, .opc1 = 0, .crn = 12, .crm = 9, .opc2 = 5,
157
{
306
+ .type = ARM_CP_IO | ARM_CP_NO_RAW,
158
- int i;
307
+ .access = PL1_R, .accessfn = gicv3_irq_access,
159
+ DeviceClass *dc = DEVICE_CLASS(oc);
308
+ .readfn = icc_nmiar1_read,
160
+ BCM283XClass *bc = BCM283X_CLASS(oc);
309
+ },
161
162
- type_register_static(&bcm283x_type_info);
163
- for (i = 0; i < ARRAY_SIZE(bcm283x_socs); i++) {
164
- TypeInfo ti = {
165
- .name = bcm283x_socs[i].name,
166
- .parent = TYPE_BCM283X,
167
- .class_init = bcm283x_class_init,
168
- .class_data = (void *) &bcm283x_socs[i],
169
- };
170
- type_register(&ti);
171
+ bc->cpu_type = ARM_CPU_TYPE_NAME("cortex-a53");
172
+ bc->peri_base = 0x3f000000;
173
+ bc->ctrl_base = 0x40000000;
174
+ bc->clusterid = 0x0;
175
+ dc->realize = bcm2836_realize;
176
+ device_class_set_props(dc, bcm2836_props);
177
+};
310
+};
178
+#endif
311
+
179
+
312
static uint64_t ich_ap_read(CPUARMState *env, const ARMCPRegInfo *ri)
180
+static const TypeInfo bcm283x_types[] = {
313
{
181
+ {
314
GICv3CPUState *cs = icc_cs_from_env(env);
182
+ .name = TYPE_BCM2836,
315
@@ -XXX,XX +XXX,XX @@ void gicv3_init_cpuif(GICv3State *s)
183
+ .parent = TYPE_BCM283X,
316
*/
184
+ .class_init = bcm2836_class_init,
317
define_arm_cp_regs(cpu, gicv3_cpuif_reginfo);
185
+#ifdef TARGET_AARCH64
318
186
+ }, {
319
+ /*
187
+ .name = TYPE_BCM2837,
320
+ * If the CPU implements FEAT_NMI and FEAT_GICv3 it must also
188
+ .parent = TYPE_BCM283X,
321
+ * implement FEAT_GICv3_NMI, which is the CPU interface part
189
+ .class_init = bcm2837_class_init,
322
+ * of NMI support. This is distinct from whether the GIC proper
190
+#endif
323
+ * (redistributors and distributor) have NMI support. In QEMU
191
+ }, {
324
+ * that is a property of the GIC device in s->nmi_support;
192
+ .name = TYPE_BCM283X,
325
+ * cs->nmi_support indicates the CPU interface's support.
193
+ .parent = TYPE_DEVICE,
326
+ */
194
+ .instance_size = sizeof(BCM283XState),
327
+ if (cpu_isar_feature(aa64_nmi, cpu)) {
195
+ .instance_init = bcm2836_init,
328
+ cs->nmi_support = true;
196
+ .class_size = sizeof(BCM283XClass),
329
+ define_arm_cp_regs(cpu, gicv3_cpuif_gicv3_nmi_reginfo);
197
+ .class_init = bcm283x_class_init,
330
+ }
198
+ .abstract = true,
331
+
199
}
332
/*
200
-}
333
* The CPU implementation specifies the number of supported
201
+};
334
* bits of physical priority. For backwards compatibility
202
335
diff --git a/hw/intc/trace-events b/hw/intc/trace-events
203
-type_init(bcm2836_register_types)
336
index XXXXXXX..XXXXXXX 100644
204
+DEFINE_TYPES(bcm283x_types)
337
--- a/hw/intc/trace-events
338
+++ b/hw/intc/trace-events
339
@@ -XXX,XX +XXX,XX @@ gicv3_cpuif_set_irqs(uint32_t cpuid, int fiqlevel, int irqlevel) "GICv3 CPU i/f
340
gicv3_icc_generate_sgi(uint32_t cpuid, int irq, int irm, uint32_t aff, uint32_t targetlist) "GICv3 CPU i/f 0x%x generating SGI %d IRM %d target affinity 0x%xxx targetlist 0x%x"
341
gicv3_icc_iar0_read(uint32_t cpu, uint64_t val) "GICv3 ICC_IAR0 read cpu 0x%x value 0x%" PRIx64
342
gicv3_icc_iar1_read(uint32_t cpu, uint64_t val) "GICv3 ICC_IAR1 read cpu 0x%x value 0x%" PRIx64
343
+gicv3_icc_nmiar1_read(uint32_t cpu, uint64_t val) "GICv3 ICC_NMIAR1 read cpu 0x%x value 0x%" PRIx64
344
gicv3_icc_eoir_write(int grp, uint32_t cpu, uint64_t val) "GICv3 ICC_EOIR%d write cpu 0x%x value 0x%" PRIx64
345
gicv3_icc_hppir0_read(uint32_t cpu, uint64_t val) "GICv3 ICC_HPPIR0 read cpu 0x%x value 0x%" PRIx64
346
gicv3_icc_hppir1_read(uint32_t cpu, uint64_t val) "GICv3 ICC_HPPIR1 read cpu 0x%x value 0x%" PRIx64
205
--
347
--
206
2.20.1
348
2.34.1
207
208
diff view generated by jsdifflib
1
From: Havard Skinnemoen <hskinnemoen@google.com>
1
Implement icv_nmiar1_read() for icc_nmiar1_read(), so add definition for
2
2
ICH_LR_EL2.NMI and ICH_AP1R_EL2.NMI bit.
3
The NPCM7xx chips have multiple GPIO controllers that are mostly
3
4
identical except for some minor differences like the reset values of
4
If FEAT_GICv3_NMI is supported, ich_ap_write() should consider ICV_AP1R_EL1.NMI
5
some registers. Each controller controls up to 32 pins.
5
bit. In icv_activate_irq() and icv_eoir_write(), the ICV_AP1R_EL1.NMI bit
6
6
should be set or clear according to the Non-maskable property. And the RPR
7
Each individual pin is modeled as a pair of unnamed GPIOs -- one for
7
priority should also update the NMI bit according to the APR priority NMI bit.
8
emitting the actual pin state, and one for driving the pin externally.
8
9
Like the nRF51 GPIO controller, a gpio level may be negative, which
9
By the way, add gicv3_icv_nmiar1_read trace event.
10
means the pin is not driven, or floating.
10
11
11
If the hpp irq is a NMI, the icv iar read should return 1022 and trap for
12
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
12
NMI again
13
Signed-off-by: Havard Skinnemoen <hskinnemoen@google.com>
13
14
Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com>
15
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
16
[PMM: use cs->nmi_support instead of cs->gic->nmi_support]
14
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
17
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
18
Message-id: 20240407081733.3231820-20-ruanjinjie@huawei.com
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
---
20
---
17
docs/system/arm/nuvoton.rst | 2 +-
21
hw/intc/gicv3_internal.h | 4 ++
18
include/hw/arm/npcm7xx.h | 2 +
22
hw/intc/arm_gicv3_cpuif.c | 105 +++++++++++++++++++++++++++++++++-----
19
include/hw/gpio/npcm7xx_gpio.h | 55 +++++
23
hw/intc/trace-events | 1 +
20
hw/arm/npcm7xx.c | 80 ++++++
24
3 files changed, 98 insertions(+), 12 deletions(-)
21
hw/gpio/npcm7xx_gpio.c | 424 ++++++++++++++++++++++++++++++++
25
22
tests/qtest/npcm7xx_gpio-test.c | 385 +++++++++++++++++++++++++++++
26
diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h
23
hw/gpio/meson.build | 1 +
24
hw/gpio/trace-events | 7 +
25
tests/qtest/meson.build | 3 +-
26
9 files changed, 957 insertions(+), 2 deletions(-)
27
create mode 100644 include/hw/gpio/npcm7xx_gpio.h
28
create mode 100644 hw/gpio/npcm7xx_gpio.c
29
create mode 100644 tests/qtest/npcm7xx_gpio-test.c
30
31
diff --git a/docs/system/arm/nuvoton.rst b/docs/system/arm/nuvoton.rst
32
index XXXXXXX..XXXXXXX 100644
27
index XXXXXXX..XXXXXXX 100644
33
--- a/docs/system/arm/nuvoton.rst
28
--- a/hw/intc/gicv3_internal.h
34
+++ b/docs/system/arm/nuvoton.rst
29
+++ b/hw/intc/gicv3_internal.h
35
@@ -XXX,XX +XXX,XX @@ Supported devices
30
@@ -XXX,XX +XXX,XX @@ FIELD(GICR_VPENDBASER, VALID, 63, 1)
36
* Flash Interface Unit (FIU; no protection features)
31
#define ICH_LR_EL2_PRIORITY_SHIFT 48
37
* Random Number Generator (RNG)
32
#define ICH_LR_EL2_PRIORITY_LENGTH 8
38
* USB host (USBH)
33
#define ICH_LR_EL2_PRIORITY_MASK (0xffULL << ICH_LR_EL2_PRIORITY_SHIFT)
39
+ * GPIO controller
34
+#define ICH_LR_EL2_NMI (1ULL << 59)
40
35
#define ICH_LR_EL2_GROUP (1ULL << 60)
41
Missing devices
36
#define ICH_LR_EL2_HW (1ULL << 61)
42
---------------
37
#define ICH_LR_EL2_STATE_SHIFT 62
43
38
@@ -XXX,XX +XXX,XX @@ FIELD(GICR_VPENDBASER, VALID, 63, 1)
44
- * GPIO controller
39
#define ICH_VTR_EL2_PREBITS_SHIFT 26
45
* LPC/eSPI host-to-BMC interface, including
40
#define ICH_VTR_EL2_PRIBITS_SHIFT 29
46
41
47
* Keyboard and mouse controller interface (KBCI)
42
+#define ICV_AP1R_EL1_NMI (1ULL << 63)
48
diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h
43
+#define ICV_RPR_EL1_NMI (1ULL << 63)
44
+
45
/* ITS Registers */
46
47
FIELD(GITS_BASER, SIZE, 0, 8)
48
diff --git a/hw/intc/arm_gicv3_cpuif.c b/hw/intc/arm_gicv3_cpuif.c
49
index XXXXXXX..XXXXXXX 100644
49
index XXXXXXX..XXXXXXX 100644
50
--- a/include/hw/arm/npcm7xx.h
50
--- a/hw/intc/arm_gicv3_cpuif.c
51
+++ b/include/hw/arm/npcm7xx.h
51
+++ b/hw/intc/arm_gicv3_cpuif.c
52
@@ -XXX,XX +XXX,XX @@
52
@@ -XXX,XX +XXX,XX @@ static int ich_highest_active_virt_prio(GICv3CPUState *cs)
53
53
int i;
54
#include "hw/boards.h"
54
int aprmax = ich_num_aprs(cs);
55
#include "hw/cpu/a9mpcore.h"
55
56
+#include "hw/gpio/npcm7xx_gpio.h"
56
+ if (cs->ich_apr[GICV3_G1NS][0] & ICV_AP1R_EL1_NMI) {
57
#include "hw/mem/npcm7xx_mc.h"
57
+ return 0x0;
58
#include "hw/misc/npcm7xx_clk.h"
58
+ }
59
#include "hw/misc/npcm7xx_gcr.h"
59
+
60
@@ -XXX,XX +XXX,XX @@ typedef struct NPCM7xxState {
60
for (i = 0; i < aprmax; i++) {
61
NPCM7xxOTPState fuse_array;
61
uint32_t apr = cs->ich_apr[GICV3_G0][i] |
62
NPCM7xxMCState mc;
62
cs->ich_apr[GICV3_G1NS][i];
63
NPCM7xxRNGState rng;
63
@@ -XXX,XX +XXX,XX @@ static int hppvi_index(GICv3CPUState *cs)
64
+ NPCM7xxGPIOState gpio[8];
64
* correct behaviour.
65
EHCISysBusState ehci;
65
*/
66
OHCISysBusState ohci;
66
int prio = 0xff;
67
NPCM7xxFIUState fiu[2];
67
+ bool nmi = false;
68
diff --git a/include/hw/gpio/npcm7xx_gpio.h b/include/hw/gpio/npcm7xx_gpio.h
68
69
new file mode 100644
69
if (!(cs->ich_vmcr_el2 & (ICH_VMCR_EL2_VENG0 | ICH_VMCR_EL2_VENG1))) {
70
index XXXXXXX..XXXXXXX
70
/* Both groups disabled, definitely nothing to do */
71
--- /dev/null
71
@@ -XXX,XX +XXX,XX @@ static int hppvi_index(GICv3CPUState *cs)
72
+++ b/include/hw/gpio/npcm7xx_gpio.h
72
73
@@ -XXX,XX +XXX,XX @@
73
for (i = 0; i < cs->num_list_regs; i++) {
74
+/*
74
uint64_t lr = cs->ich_lr_el2[i];
75
+ * Nuvoton NPCM7xx General Purpose Input / Output (GPIO)
75
+ bool thisnmi;
76
+ *
76
int thisprio;
77
+ * Copyright 2020 Google LLC
77
78
+ *
78
if (ich_lr_state(lr) != ICH_LR_EL2_STATE_PENDING) {
79
+ * This program is free software; you can redistribute it and/or
79
@@ -XXX,XX +XXX,XX @@ static int hppvi_index(GICv3CPUState *cs)
80
+ * modify it under the terms of the GNU General Public License
80
}
81
+ * version 2 as published by the Free Software Foundation.
81
}
82
+ *
82
83
+ * This program is distributed in the hope that it will be useful,
83
+ thisnmi = lr & ICH_LR_EL2_NMI;
84
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
84
thisprio = ich_lr_prio(lr);
85
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
85
86
+ * GNU General Public License for more details.
86
- if (thisprio < prio) {
87
+ */
87
+ if ((thisprio < prio) || ((thisprio == prio) && (thisnmi & (!nmi)))) {
88
+#ifndef NPCM7XX_GPIO_H
88
prio = thisprio;
89
+#define NPCM7XX_GPIO_H
89
+ nmi = thisnmi;
90
+
90
idx = i;
91
+#include "exec/memory.h"
91
}
92
+#include "hw/sysbus.h"
93
+
94
+/* Number of pins managed by each controller. */
95
+#define NPCM7XX_GPIO_NR_PINS (32)
96
+
97
+/*
98
+ * Number of registers in our device state structure. Don't change this without
99
+ * incrementing the version_id in the vmstate.
100
+ */
101
+#define NPCM7XX_GPIO_NR_REGS (0x80 / sizeof(uint32_t))
102
+
103
+typedef struct NPCM7xxGPIOState {
104
+ SysBusDevice parent;
105
+
106
+ /* Properties to be defined by the SoC */
107
+ uint32_t reset_pu;
108
+ uint32_t reset_pd;
109
+ uint32_t reset_osrc;
110
+ uint32_t reset_odsc;
111
+
112
+ MemoryRegion mmio;
113
+
114
+ qemu_irq irq;
115
+ qemu_irq output[NPCM7XX_GPIO_NR_PINS];
116
+
117
+ uint32_t pin_level;
118
+ uint32_t ext_level;
119
+ uint32_t ext_driven;
120
+
121
+ uint32_t regs[NPCM7XX_GPIO_NR_REGS];
122
+} NPCM7xxGPIOState;
123
+
124
+#define TYPE_NPCM7XX_GPIO "npcm7xx-gpio"
125
+#define NPCM7XX_GPIO(obj) \
126
+ OBJECT_CHECK(NPCM7xxGPIOState, (obj), TYPE_NPCM7XX_GPIO)
127
+
128
+#endif /* NPCM7XX_GPIO_H */
129
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
130
index XXXXXXX..XXXXXXX 100644
131
--- a/hw/arm/npcm7xx.c
132
+++ b/hw/arm/npcm7xx.c
133
@@ -XXX,XX +XXX,XX @@ enum NPCM7xxInterrupt {
134
NPCM7XX_WDG2_IRQ, /* Timer Module 2 Watchdog */
135
NPCM7XX_EHCI_IRQ = 61,
136
NPCM7XX_OHCI_IRQ = 62,
137
+ NPCM7XX_GPIO0_IRQ = 116,
138
+ NPCM7XX_GPIO1_IRQ,
139
+ NPCM7XX_GPIO2_IRQ,
140
+ NPCM7XX_GPIO3_IRQ,
141
+ NPCM7XX_GPIO4_IRQ,
142
+ NPCM7XX_GPIO5_IRQ,
143
+ NPCM7XX_GPIO6_IRQ,
144
+ NPCM7XX_GPIO7_IRQ,
145
};
146
147
/* Total number of GIC interrupts, including internal Cortex-A9 interrupts. */
148
@@ -XXX,XX +XXX,XX @@ static const hwaddr npcm7xx_fiu3_flash_addr[] = {
149
0xb8000000, /* CS3 */
150
};
151
152
+static const struct {
153
+ hwaddr regs_addr;
154
+ uint32_t unconnected_pins;
155
+ uint32_t reset_pu;
156
+ uint32_t reset_pd;
157
+ uint32_t reset_osrc;
158
+ uint32_t reset_odsc;
159
+} npcm7xx_gpio[] = {
160
+ {
161
+ .regs_addr = 0xf0010000,
162
+ .reset_pu = 0xff03ffff,
163
+ .reset_pd = 0x00fc0000,
164
+ }, {
165
+ .regs_addr = 0xf0011000,
166
+ .unconnected_pins = 0x0000001e,
167
+ .reset_pu = 0xfefffe07,
168
+ .reset_pd = 0x010001e0,
169
+ }, {
170
+ .regs_addr = 0xf0012000,
171
+ .reset_pu = 0x780fffff,
172
+ .reset_pd = 0x07f00000,
173
+ .reset_odsc = 0x00700000,
174
+ }, {
175
+ .regs_addr = 0xf0013000,
176
+ .reset_pu = 0x00fc0000,
177
+ .reset_pd = 0xff000000,
178
+ }, {
179
+ .regs_addr = 0xf0014000,
180
+ .reset_pu = 0xffffffff,
181
+ }, {
182
+ .regs_addr = 0xf0015000,
183
+ .reset_pu = 0xbf83f801,
184
+ .reset_pd = 0x007c0000,
185
+ .reset_osrc = 0x000000f1,
186
+ .reset_odsc = 0x3f9f80f1,
187
+ }, {
188
+ .regs_addr = 0xf0016000,
189
+ .reset_pu = 0xfc00f801,
190
+ .reset_pd = 0x000007fe,
191
+ .reset_odsc = 0x00000800,
192
+ }, {
193
+ .regs_addr = 0xf0017000,
194
+ .unconnected_pins = 0xffffff00,
195
+ .reset_pu = 0x0000007f,
196
+ .reset_osrc = 0x0000007f,
197
+ .reset_odsc = 0x0000007f,
198
+ },
199
+};
200
+
201
static const struct {
202
const char *name;
203
hwaddr regs_addr;
204
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_init(Object *obj)
205
object_initialize_child(obj, "tim[*]", &s->tim[i], TYPE_NPCM7XX_TIMER);
206
}
92
}
207
93
@@ -XXX,XX +XXX,XX @@ static bool icv_hppi_can_preempt(GICv3CPUState *cs, uint64_t lr)
208
+ for (i = 0; i < ARRAY_SIZE(s->gpio); i++) {
94
* equivalent of these checks.
209
+ object_initialize_child(obj, "gpio[*]", &s->gpio[i], TYPE_NPCM7XX_GPIO);
95
*/
210
+ }
96
int grp;
211
+
97
+ bool is_nmi;
212
object_initialize_child(obj, "ehci", &s->ehci, TYPE_NPCM7XX_EHCI);
98
uint32_t mask, prio, rprio, vpmr;
213
object_initialize_child(obj, "ohci", &s->ohci, TYPE_SYSBUS_OHCI);
99
214
100
if (!(cs->ich_hcr_el2 & ICH_HCR_EL2_EN)) {
215
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
101
@@ -XXX,XX +XXX,XX @@ static bool icv_hppi_can_preempt(GICv3CPUState *cs, uint64_t lr)
216
sysbus_realize(SYS_BUS_DEVICE(&s->rng), &error_abort);
102
*/
217
sysbus_mmio_map(SYS_BUS_DEVICE(&s->rng), 0, NPCM7XX_RNG_BA);
103
218
104
prio = ich_lr_prio(lr);
219
+ /* GPIO modules. Cannot fail. */
105
+ is_nmi = lr & ICH_LR_EL2_NMI;
220
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_gpio) != ARRAY_SIZE(s->gpio));
106
vpmr = extract64(cs->ich_vmcr_el2, ICH_VMCR_EL2_VPMR_SHIFT,
221
+ for (i = 0; i < ARRAY_SIZE(s->gpio); i++) {
107
ICH_VMCR_EL2_VPMR_LENGTH);
222
+ Object *obj = OBJECT(&s->gpio[i]);
108
223
+
109
- if (prio >= vpmr) {
224
+ object_property_set_uint(obj, "reset-pullup",
110
+ if (!is_nmi && prio >= vpmr) {
225
+ npcm7xx_gpio[i].reset_pu, &error_abort);
111
/* Priority mask masks this interrupt */
226
+ object_property_set_uint(obj, "reset-pulldown",
112
return false;
227
+ npcm7xx_gpio[i].reset_pd, &error_abort);
113
}
228
+ object_property_set_uint(obj, "reset-osrc",
114
@@ -XXX,XX +XXX,XX @@ static bool icv_hppi_can_preempt(GICv3CPUState *cs, uint64_t lr)
229
+ npcm7xx_gpio[i].reset_osrc, &error_abort);
115
return true;
230
+ object_property_set_uint(obj, "reset-odsc",
116
}
231
+ npcm7xx_gpio[i].reset_odsc, &error_abort);
117
232
+ sysbus_realize(SYS_BUS_DEVICE(obj), &error_abort);
118
+ if ((prio & mask) == (rprio & mask) && is_nmi &&
233
+ sysbus_mmio_map(SYS_BUS_DEVICE(obj), 0, npcm7xx_gpio[i].regs_addr);
119
+ !(cs->ich_apr[GICV3_G1NS][0] & ICV_AP1R_EL1_NMI)) {
234
+ sysbus_connect_irq(SYS_BUS_DEVICE(obj), 0,
120
+ return true;
235
+ npcm7xx_irq(s, NPCM7XX_GPIO0_IRQ + i));
121
+ }
236
+ }
122
+
237
+
123
return false;
238
/* USB Host */
124
}
239
object_property_set_bool(OBJECT(&s->ehci), "companion-enable", true,
125
240
&error_abort);
126
@@ -XXX,XX +XXX,XX @@ static void icv_ap_write(CPUARMState *env, const ARMCPRegInfo *ri,
241
diff --git a/hw/gpio/npcm7xx_gpio.c b/hw/gpio/npcm7xx_gpio.c
127
242
new file mode 100644
128
trace_gicv3_icv_ap_write(ri->crm & 1, regno, gicv3_redist_affid(cs), value);
243
index XXXXXXX..XXXXXXX
129
244
--- /dev/null
130
- cs->ich_apr[grp][regno] = value & 0xFFFFFFFFU;
245
+++ b/hw/gpio/npcm7xx_gpio.c
131
+ if (cs->nmi_support) {
246
@@ -XXX,XX +XXX,XX @@
132
+ cs->ich_apr[grp][regno] = value & (0xFFFFFFFFU | ICV_AP1R_EL1_NMI);
247
+/*
133
+ } else {
248
+ * Nuvoton NPCM7xx General Purpose Input / Output (GPIO)
134
+ cs->ich_apr[grp][regno] = value & 0xFFFFFFFFU;
249
+ *
135
+ }
250
+ * Copyright 2020 Google LLC
136
251
+ *
137
gicv3_cpuif_virt_irq_fiq_update(cs);
252
+ * This program is free software; you can redistribute it and/or
138
return;
253
+ * modify it under the terms of the GNU General Public License
139
@@ -XXX,XX +XXX,XX @@ static void icv_ctlr_write(CPUARMState *env, const ARMCPRegInfo *ri,
254
+ * version 2 as published by the Free Software Foundation.
140
static uint64_t icv_rpr_read(CPUARMState *env, const ARMCPRegInfo *ri)
255
+ *
141
{
256
+ * This program is distributed in the hope that it will be useful,
142
GICv3CPUState *cs = icc_cs_from_env(env);
257
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
143
- int prio = ich_highest_active_virt_prio(cs);
258
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
144
+ uint64_t prio = ich_highest_active_virt_prio(cs);
259
+ * GNU General Public License for more details.
145
+
260
+ */
146
+ if (cs->ich_apr[GICV3_G1NS][0] & ICV_AP1R_EL1_NMI) {
261
+
147
+ prio |= ICV_RPR_EL1_NMI;
262
+#include "qemu/osdep.h"
148
+ }
263
+
149
264
+#include "hw/gpio/npcm7xx_gpio.h"
150
trace_gicv3_icv_rpr_read(gicv3_redist_affid(cs), prio);
265
+#include "hw/irq.h"
151
return prio;
266
+#include "hw/qdev-properties.h"
152
@@ -XXX,XX +XXX,XX @@ static void icv_activate_irq(GICv3CPUState *cs, int idx, int grp)
267
+#include "migration/vmstate.h"
153
*/
268
+#include "qapi/error.h"
154
uint32_t mask = icv_gprio_mask(cs, grp);
269
+#include "qemu/log.h"
155
int prio = ich_lr_prio(cs->ich_lr_el2[idx]) & mask;
270
+#include "qemu/module.h"
156
+ bool nmi = cs->ich_lr_el2[idx] & ICH_LR_EL2_NMI;
271
+#include "qemu/units.h"
157
int aprbit = prio >> (8 - cs->vprebits);
272
+#include "trace.h"
158
int regno = aprbit / 32;
273
+
159
int regbit = aprbit % 32;
274
+/* 32-bit register indices. */
160
275
+enum NPCM7xxGPIORegister {
161
cs->ich_lr_el2[idx] &= ~ICH_LR_EL2_STATE_PENDING_BIT;
276
+ NPCM7XX_GPIO_TLOCK1,
162
cs->ich_lr_el2[idx] |= ICH_LR_EL2_STATE_ACTIVE_BIT;
277
+ NPCM7XX_GPIO_DIN,
163
- cs->ich_apr[grp][regno] |= (1 << regbit);
278
+ NPCM7XX_GPIO_POL,
164
+
279
+ NPCM7XX_GPIO_DOUT,
165
+ if (nmi) {
280
+ NPCM7XX_GPIO_OE,
166
+ cs->ich_apr[grp][regno] |= ICV_AP1R_EL1_NMI;
281
+ NPCM7XX_GPIO_OTYP,
167
+ } else {
282
+ NPCM7XX_GPIO_MP,
168
+ cs->ich_apr[grp][regno] |= (1 << regbit);
283
+ NPCM7XX_GPIO_PU,
169
+ }
284
+ NPCM7XX_GPIO_PD,
170
}
285
+ NPCM7XX_GPIO_DBNC,
171
286
+ NPCM7XX_GPIO_EVTYP,
172
static void icv_activate_vlpi(GICv3CPUState *cs)
287
+ NPCM7XX_GPIO_EVBE,
173
@@ -XXX,XX +XXX,XX @@ static uint64_t icv_iar_read(CPUARMState *env, const ARMCPRegInfo *ri)
288
+ NPCM7XX_GPIO_OBL0,
174
int grp = ri->crm == 8 ? GICV3_G0 : GICV3_G1NS;
289
+ NPCM7XX_GPIO_OBL1,
175
int idx = hppvi_index(cs);
290
+ NPCM7XX_GPIO_OBL2,
176
uint64_t intid = INTID_SPURIOUS;
291
+ NPCM7XX_GPIO_OBL3,
177
+ int el = arm_current_el(env);
292
+ NPCM7XX_GPIO_EVEN,
178
293
+ NPCM7XX_GPIO_EVENS,
179
if (idx == HPPVI_INDEX_VLPI) {
294
+ NPCM7XX_GPIO_EVENC,
180
if (cs->hppvlpi.grp == grp && icv_hppvlpi_can_preempt(cs)) {
295
+ NPCM7XX_GPIO_EVST,
181
@@ -XXX,XX +XXX,XX @@ static uint64_t icv_iar_read(CPUARMState *env, const ARMCPRegInfo *ri)
296
+ NPCM7XX_GPIO_SPLCK,
182
} else if (idx >= 0) {
297
+ NPCM7XX_GPIO_MPLCK,
183
uint64_t lr = cs->ich_lr_el2[idx];
298
+ NPCM7XX_GPIO_IEM,
184
int thisgrp = (lr & ICH_LR_EL2_GROUP) ? GICV3_G1NS : GICV3_G0;
299
+ NPCM7XX_GPIO_OSRC,
185
+ bool nmi = env->cp15.sctlr_el[el] & SCTLR_NMI && lr & ICH_LR_EL2_NMI;
300
+ NPCM7XX_GPIO_ODSC,
186
301
+ NPCM7XX_GPIO_DOS = 0x68 / sizeof(uint32_t),
187
if (thisgrp == grp && icv_hppi_can_preempt(cs, lr)) {
302
+ NPCM7XX_GPIO_DOC,
188
intid = ich_lr_vintid(lr);
303
+ NPCM7XX_GPIO_OES,
189
if (!gicv3_intid_is_special(intid)) {
304
+ NPCM7XX_GPIO_OEC,
190
- icv_activate_irq(cs, idx, grp);
305
+ NPCM7XX_GPIO_TLOCK2 = 0x7c / sizeof(uint32_t),
191
+ if (!nmi) {
306
+ NPCM7XX_GPIO_REGS_END,
192
+ icv_activate_irq(cs, idx, grp);
307
+};
193
+ } else {
308
+
194
+ intid = INTID_NMI;
309
+#define NPCM7XX_GPIO_REGS_SIZE (4 * KiB)
195
+ }
310
+
196
} else {
311
+#define NPCM7XX_GPIO_LOCK_MAGIC1 (0xc0defa73)
197
/* Interrupt goes from Pending to Invalid */
312
+#define NPCM7XX_GPIO_LOCK_MAGIC2 (0xc0de1248)
198
cs->ich_lr_el2[idx] &= ~ICH_LR_EL2_STATE_PENDING_BIT;
313
+
199
@@ -XXX,XX +XXX,XX @@ static uint64_t icv_iar_read(CPUARMState *env, const ARMCPRegInfo *ri)
314
+static void npcm7xx_gpio_update_events(NPCM7xxGPIOState *s, uint32_t din_diff)
200
315
+{
201
static uint64_t icv_nmiar1_read(CPUARMState *env, const ARMCPRegInfo *ri)
316
+ uint32_t din_new = s->regs[NPCM7XX_GPIO_DIN];
202
{
317
+
203
- /* todo */
318
+ /* Trigger on high level */
204
+ GICv3CPUState *cs = icc_cs_from_env(env);
319
+ s->regs[NPCM7XX_GPIO_EVST] |= din_new & ~s->regs[NPCM7XX_GPIO_EVTYP];
205
+ int idx = hppvi_index(cs);
320
+ /* Trigger on both edges */
206
uint64_t intid = INTID_SPURIOUS;
321
+ s->regs[NPCM7XX_GPIO_EVST] |= (din_diff & s->regs[NPCM7XX_GPIO_EVTYP]
207
+
322
+ & s->regs[NPCM7XX_GPIO_EVBE]);
208
+ if (idx >= 0 && idx != HPPVI_INDEX_VLPI) {
323
+ /* Trigger on rising edge */
209
+ uint64_t lr = cs->ich_lr_el2[idx];
324
+ s->regs[NPCM7XX_GPIO_EVST] |= (din_diff & din_new
210
+ int thisgrp = (lr & ICH_LR_EL2_GROUP) ? GICV3_G1NS : GICV3_G0;
325
+ & s->regs[NPCM7XX_GPIO_EVTYP]);
211
+
326
+
212
+ if ((thisgrp == GICV3_G1NS) && icv_hppi_can_preempt(cs, lr)) {
327
+ trace_npcm7xx_gpio_update_events(DEVICE(s)->canonical_path,
213
+ intid = ich_lr_vintid(lr);
328
+ s->regs[NPCM7XX_GPIO_EVST],
214
+ if (!gicv3_intid_is_special(intid)) {
329
+ s->regs[NPCM7XX_GPIO_EVEN]);
215
+ if (lr & ICH_LR_EL2_NMI) {
330
+ qemu_set_irq(s->irq, !!(s->regs[NPCM7XX_GPIO_EVST]
216
+ icv_activate_irq(cs, idx, GICV3_G1NS);
331
+ & s->regs[NPCM7XX_GPIO_EVEN]));
217
+ } else {
332
+}
218
+ intid = INTID_SPURIOUS;
333
+
219
+ }
334
+static void npcm7xx_gpio_update_pins(NPCM7xxGPIOState *s, uint32_t diff)
220
+ } else {
335
+{
221
+ /* Interrupt goes from Pending to Invalid */
336
+ uint32_t drive_en;
222
+ cs->ich_lr_el2[idx] &= ~ICH_LR_EL2_STATE_PENDING_BIT;
337
+ uint32_t drive_lvl;
223
+ /*
338
+ uint32_t not_driven;
224
+ * We will now return the (bogus) ID from the list register,
339
+ uint32_t undefined;
225
+ * as per the pseudocode.
340
+ uint32_t pin_diff;
226
+ */
341
+ uint32_t din_old;
342
+
343
+ /* Calculate level of each pin driven by GPIO controller. */
344
+ drive_lvl = s->regs[NPCM7XX_GPIO_DOUT] ^ s->regs[NPCM7XX_GPIO_POL];
345
+ /* If OTYP=1, only drive low (open drain) */
346
+ drive_en = s->regs[NPCM7XX_GPIO_OE] & ~(s->regs[NPCM7XX_GPIO_OTYP]
347
+ & drive_lvl);
348
+ /*
349
+ * If a pin is driven to opposite levels by the GPIO controller and the
350
+ * external driver, the result is undefined.
351
+ */
352
+ undefined = drive_en & s->ext_driven & (drive_lvl ^ s->ext_level);
353
+ if (undefined) {
354
+ qemu_log_mask(LOG_GUEST_ERROR,
355
+ "%s: pins have multiple drivers: 0x%" PRIx32 "\n",
356
+ DEVICE(s)->canonical_path, undefined);
357
+ }
358
+
359
+ not_driven = ~(drive_en | s->ext_driven);
360
+ pin_diff = s->pin_level;
361
+
362
+ /* Set pins to externally driven level. */
363
+ s->pin_level = s->ext_level & s->ext_driven;
364
+ /* Set internally driven pins, ignoring any conflicts. */
365
+ s->pin_level |= drive_lvl & drive_en;
366
+ /* Pull up undriven pins with internal pull-up enabled. */
367
+ s->pin_level |= not_driven & s->regs[NPCM7XX_GPIO_PU];
368
+ /* Pins not driven, pulled up or pulled down are undefined */
369
+ undefined |= not_driven & ~(s->regs[NPCM7XX_GPIO_PU]
370
+ | s->regs[NPCM7XX_GPIO_PD]);
371
+
372
+ /* If any pins changed state, update the outgoing GPIOs. */
373
+ pin_diff ^= s->pin_level;
374
+ pin_diff |= undefined & diff;
375
+ if (pin_diff) {
376
+ int i;
377
+
378
+ for (i = 0; i < NPCM7XX_GPIO_NR_PINS; i++) {
379
+ uint32_t mask = BIT(i);
380
+ if (pin_diff & mask) {
381
+ int level = (undefined & mask) ? -1 : !!(s->pin_level & mask);
382
+ trace_npcm7xx_gpio_set_output(DEVICE(s)->canonical_path,
383
+ i, level);
384
+ qemu_set_irq(s->output[i], level);
385
+ }
227
+ }
386
+ }
228
+ }
387
+ }
229
+ }
388
+
230
+
389
+ /* Calculate new value of DIN after masking and polarity setting. */
231
+ trace_gicv3_icv_nmiar1_read(gicv3_redist_affid(cs), intid);
390
+ din_old = s->regs[NPCM7XX_GPIO_DIN];
232
+
391
+ s->regs[NPCM7XX_GPIO_DIN] = ((s->pin_level & s->regs[NPCM7XX_GPIO_IEM])
233
+ gicv3_cpuif_virt_update(cs);
392
+ ^ s->regs[NPCM7XX_GPIO_POL]);
234
+
393
+
235
return intid;
394
+ /* See if any new events triggered because of all this. */
236
}
395
+ npcm7xx_gpio_update_events(s, din_old ^ s->regs[NPCM7XX_GPIO_DIN]);
237
396
+}
238
@@ -XXX,XX +XXX,XX @@ static void icv_increment_eoicount(GICv3CPUState *cs)
397
+
239
ICH_HCR_EL2_EOICOUNT_LENGTH, eoicount + 1);
398
+static bool npcm7xx_gpio_is_locked(NPCM7xxGPIOState *s)
240
}
399
+{
241
400
+ return s->regs[NPCM7XX_GPIO_TLOCK1] == 1;
242
-static int icv_drop_prio(GICv3CPUState *cs)
401
+}
243
+static int icv_drop_prio(GICv3CPUState *cs, bool *nmi)
402
+
244
{
403
+static uint64_t npcm7xx_gpio_regs_read(void *opaque, hwaddr addr,
245
/* Drop the priority of the currently active virtual interrupt
404
+ unsigned int size)
246
* (favouring group 0 if there is a set active bit at
405
+{
247
@@ -XXX,XX +XXX,XX @@ static int icv_drop_prio(GICv3CPUState *cs)
406
+ hwaddr reg = addr / sizeof(uint32_t);
248
continue;
407
+ NPCM7xxGPIOState *s = opaque;
249
}
408
+ uint64_t value = 0;
250
409
+
251
+ if (i == 0 && cs->nmi_support && (*papr1 & ICV_AP1R_EL1_NMI)) {
410
+ switch (reg) {
252
+ *papr1 &= (~ICV_AP1R_EL1_NMI);
411
+ case NPCM7XX_GPIO_TLOCK1 ... NPCM7XX_GPIO_EVEN:
253
+ *nmi = true;
412
+ case NPCM7XX_GPIO_EVST ... NPCM7XX_GPIO_ODSC:
254
+ return 0xff;
413
+ value = s->regs[reg];
414
+ break;
415
+
416
+ case NPCM7XX_GPIO_EVENS ... NPCM7XX_GPIO_EVENC:
417
+ case NPCM7XX_GPIO_DOS ... NPCM7XX_GPIO_TLOCK2:
418
+ qemu_log_mask(LOG_GUEST_ERROR,
419
+ "%s: read from write-only register 0x%" HWADDR_PRIx "\n",
420
+ DEVICE(s)->canonical_path, addr);
421
+ break;
422
+
423
+ default:
424
+ qemu_log_mask(LOG_GUEST_ERROR,
425
+ "%s: read from invalid offset 0x%" HWADDR_PRIx "\n",
426
+ DEVICE(s)->canonical_path, addr);
427
+ break;
428
+ }
429
+
430
+ trace_npcm7xx_gpio_read(DEVICE(s)->canonical_path, addr, value);
431
+
432
+ return value;
433
+}
434
+
435
+static void npcm7xx_gpio_regs_write(void *opaque, hwaddr addr, uint64_t v,
436
+ unsigned int size)
437
+{
438
+ hwaddr reg = addr / sizeof(uint32_t);
439
+ NPCM7xxGPIOState *s = opaque;
440
+ uint32_t value = v;
441
+ uint32_t diff;
442
+
443
+ trace_npcm7xx_gpio_write(DEVICE(s)->canonical_path, addr, v);
444
+
445
+ if (npcm7xx_gpio_is_locked(s)) {
446
+ switch (reg) {
447
+ case NPCM7XX_GPIO_TLOCK1:
448
+ if (s->regs[NPCM7XX_GPIO_TLOCK2] == NPCM7XX_GPIO_LOCK_MAGIC2 &&
449
+ value == NPCM7XX_GPIO_LOCK_MAGIC1) {
450
+ s->regs[NPCM7XX_GPIO_TLOCK1] = 0;
451
+ s->regs[NPCM7XX_GPIO_TLOCK2] = 0;
452
+ }
453
+ break;
454
+
455
+ case NPCM7XX_GPIO_TLOCK2:
456
+ s->regs[reg] = value;
457
+ break;
458
+
459
+ default:
460
+ qemu_log_mask(LOG_GUEST_ERROR,
461
+ "%s: write to locked register @ 0x%" HWADDR_PRIx "\n",
462
+ DEVICE(s)->canonical_path, addr);
463
+ break;
464
+ }
255
+ }
465
+
256
+
466
+ return;
257
/* We can't just use the bit-twiddling hack icc_drop_prio() does
467
+ }
258
* because we need to return the bit number we cleared so
468
+
259
* it can be compared against the list register's priority field.
469
+ diff = s->regs[reg] ^ value;
260
@@ -XXX,XX +XXX,XX @@ static void icv_eoir_write(CPUARMState *env, const ARMCPRegInfo *ri,
470
+
261
int irq = value & 0xffffff;
471
+ switch (reg) {
262
int grp = ri->crm == 8 ? GICV3_G0 : GICV3_G1NS;
472
+ case NPCM7XX_GPIO_TLOCK1:
263
int idx, dropprio;
473
+ case NPCM7XX_GPIO_TLOCK2:
264
+ bool nmi = false;
474
+ s->regs[NPCM7XX_GPIO_TLOCK1] = 1;
265
475
+ s->regs[NPCM7XX_GPIO_TLOCK2] = 0;
266
trace_gicv3_icv_eoir_write(ri->crm == 8 ? 0 : 1,
476
+ break;
267
gicv3_redist_affid(cs), value);
477
+
268
@@ -XXX,XX +XXX,XX @@ static void icv_eoir_write(CPUARMState *env, const ARMCPRegInfo *ri,
478
+ case NPCM7XX_GPIO_DIN:
269
* error checks" (because that lets us avoid scanning the AP
479
+ qemu_log_mask(LOG_GUEST_ERROR,
270
* registers twice).
480
+ "%s: write to read-only register @ 0x%" HWADDR_PRIx "\n",
271
*/
481
+ DEVICE(s)->canonical_path, addr);
272
- dropprio = icv_drop_prio(cs);
482
+ break;
273
- if (dropprio == 0xff) {
483
+
274
+ dropprio = icv_drop_prio(cs, &nmi);
484
+ case NPCM7XX_GPIO_POL:
275
+ if (dropprio == 0xff && !nmi) {
485
+ case NPCM7XX_GPIO_DOUT:
276
/* No active interrupt. It is CONSTRAINED UNPREDICTABLE
486
+ case NPCM7XX_GPIO_OE:
277
* whether the list registers are checked in this
487
+ case NPCM7XX_GPIO_OTYP:
278
* situation; we choose not to.
488
+ case NPCM7XX_GPIO_PU:
279
@@ -XXX,XX +XXX,XX @@ static void icv_eoir_write(CPUARMState *env, const ARMCPRegInfo *ri,
489
+ case NPCM7XX_GPIO_PD:
280
uint64_t lr = cs->ich_lr_el2[idx];
490
+ case NPCM7XX_GPIO_IEM:
281
int thisgrp = (lr & ICH_LR_EL2_GROUP) ? GICV3_G1NS : GICV3_G0;
491
+ s->regs[reg] = value;
282
int lr_gprio = ich_lr_prio(lr) & icv_gprio_mask(cs, grp);
492
+ npcm7xx_gpio_update_pins(s, diff);
283
+ bool thisnmi = lr & ICH_LR_EL2_NMI;
493
+ break;
284
494
+
285
- if (thisgrp == grp && lr_gprio == dropprio) {
495
+ case NPCM7XX_GPIO_DOS:
286
+ if (thisgrp == grp && (lr_gprio == dropprio || (thisnmi & nmi))) {
496
+ s->regs[NPCM7XX_GPIO_DOUT] |= value;
287
if (!icv_eoi_split(env, cs) || irq >= GICV3_LPI_INTID_START) {
497
+ npcm7xx_gpio_update_pins(s, value);
288
/*
498
+ break;
289
* Priority drop and deactivate not split: deactivate irq now.
499
+ case NPCM7XX_GPIO_DOC:
290
@@ -XXX,XX +XXX,XX @@ static void ich_ap_write(CPUARMState *env, const ARMCPRegInfo *ri,
500
+ s->regs[NPCM7XX_GPIO_DOUT] &= ~value;
291
501
+ npcm7xx_gpio_update_pins(s, value);
292
trace_gicv3_ich_ap_write(ri->crm & 1, regno, gicv3_redist_affid(cs), value);
502
+ break;
293
503
+ case NPCM7XX_GPIO_OES:
294
- cs->ich_apr[grp][regno] = value & 0xFFFFFFFFU;
504
+ s->regs[NPCM7XX_GPIO_OE] |= value;
295
+ if (cs->nmi_support) {
505
+ npcm7xx_gpio_update_pins(s, value);
296
+ cs->ich_apr[grp][regno] = value & (0xFFFFFFFFU | ICV_AP1R_EL1_NMI);
506
+ break;
297
+ } else {
507
+ case NPCM7XX_GPIO_OEC:
298
+ cs->ich_apr[grp][regno] = value & 0xFFFFFFFFU;
508
+ s->regs[NPCM7XX_GPIO_OE] &= ~value;
299
+ }
509
+ npcm7xx_gpio_update_pins(s, value);
300
gicv3_cpuif_virt_irq_fiq_update(cs);
510
+ break;
301
}
511
+
302
512
+ case NPCM7XX_GPIO_EVTYP:
303
@@ -XXX,XX +XXX,XX @@ static void ich_lr_write(CPUARMState *env, const ARMCPRegInfo *ri,
513
+ case NPCM7XX_GPIO_EVBE:
304
8 - cs->vpribits, 0);
514
+ case NPCM7XX_GPIO_EVEN:
305
}
515
+ s->regs[reg] = value;
306
516
+ npcm7xx_gpio_update_events(s, 0);
307
+ /* Enforce RES0 bit in NMI field when FEAT_GICv3_NMI is not implemented */
517
+ break;
308
+ if (!cs->nmi_support) {
518
+
309
+ value &= ~ICH_LR_EL2_NMI;
519
+ case NPCM7XX_GPIO_EVENS:
310
+ }
520
+ s->regs[NPCM7XX_GPIO_EVEN] |= value;
311
+
521
+ npcm7xx_gpio_update_events(s, 0);
312
cs->ich_lr_el2[regno] = value;
522
+ break;
313
gicv3_cpuif_virt_update(cs);
523
+ case NPCM7XX_GPIO_EVENC:
314
}
524
+ s->regs[NPCM7XX_GPIO_EVEN] &= ~value;
315
diff --git a/hw/intc/trace-events b/hw/intc/trace-events
525
+ npcm7xx_gpio_update_events(s, 0);
526
+ break;
527
+
528
+ case NPCM7XX_GPIO_EVST:
529
+ s->regs[reg] &= ~value;
530
+ npcm7xx_gpio_update_events(s, 0);
531
+ break;
532
+
533
+ case NPCM7XX_GPIO_MP:
534
+ case NPCM7XX_GPIO_DBNC:
535
+ case NPCM7XX_GPIO_OSRC:
536
+ case NPCM7XX_GPIO_ODSC:
537
+ /* Nothing to do; just store the value. */
538
+ s->regs[reg] = value;
539
+ break;
540
+
541
+ case NPCM7XX_GPIO_OBL0:
542
+ case NPCM7XX_GPIO_OBL1:
543
+ case NPCM7XX_GPIO_OBL2:
544
+ case NPCM7XX_GPIO_OBL3:
545
+ s->regs[reg] = value;
546
+ qemu_log_mask(LOG_UNIMP, "%s: Blinking is not implemented\n",
547
+ __func__);
548
+ break;
549
+
550
+ case NPCM7XX_GPIO_SPLCK:
551
+ case NPCM7XX_GPIO_MPLCK:
552
+ qemu_log_mask(LOG_UNIMP, "%s: Per-pin lock is not implemented\n",
553
+ __func__);
554
+ break;
555
+
556
+ default:
557
+ qemu_log_mask(LOG_GUEST_ERROR,
558
+ "%s: write to invalid offset 0x%" HWADDR_PRIx "\n",
559
+ DEVICE(s)->canonical_path, addr);
560
+ break;
561
+ }
562
+}
563
+
564
+static const MemoryRegionOps npcm7xx_gpio_regs_ops = {
565
+ .read = npcm7xx_gpio_regs_read,
566
+ .write = npcm7xx_gpio_regs_write,
567
+ .endianness = DEVICE_NATIVE_ENDIAN,
568
+ .valid = {
569
+ .min_access_size = 4,
570
+ .max_access_size = 4,
571
+ .unaligned = false,
572
+ },
573
+};
574
+
575
+static void npcm7xx_gpio_set_input(void *opaque, int line, int level)
576
+{
577
+ NPCM7xxGPIOState *s = opaque;
578
+
579
+ trace_npcm7xx_gpio_set_input(DEVICE(s)->canonical_path, line, level);
580
+
581
+ g_assert(line >= 0 && line < NPCM7XX_GPIO_NR_PINS);
582
+
583
+ s->ext_driven = deposit32(s->ext_driven, line, 1, level >= 0);
584
+ s->ext_level = deposit32(s->ext_level, line, 1, level > 0);
585
+
586
+ npcm7xx_gpio_update_pins(s, BIT(line));
587
+}
588
+
589
+static void npcm7xx_gpio_enter_reset(Object *obj, ResetType type)
590
+{
591
+ NPCM7xxGPIOState *s = NPCM7XX_GPIO(obj);
592
+
593
+ memset(s->regs, 0, sizeof(s->regs));
594
+
595
+ s->regs[NPCM7XX_GPIO_PU] = s->reset_pu;
596
+ s->regs[NPCM7XX_GPIO_PD] = s->reset_pd;
597
+ s->regs[NPCM7XX_GPIO_OSRC] = s->reset_osrc;
598
+ s->regs[NPCM7XX_GPIO_ODSC] = s->reset_odsc;
599
+}
600
+
601
+static void npcm7xx_gpio_hold_reset(Object *obj)
602
+{
603
+ NPCM7xxGPIOState *s = NPCM7XX_GPIO(obj);
604
+
605
+ npcm7xx_gpio_update_pins(s, -1);
606
+}
607
+
608
+static void npcm7xx_gpio_init(Object *obj)
609
+{
610
+ NPCM7xxGPIOState *s = NPCM7XX_GPIO(obj);
611
+ DeviceState *dev = DEVICE(obj);
612
+
613
+ memory_region_init_io(&s->mmio, obj, &npcm7xx_gpio_regs_ops, s,
614
+ "regs", NPCM7XX_GPIO_REGS_SIZE);
615
+ sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio);
616
+ sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->irq);
617
+
618
+ qdev_init_gpio_in(dev, npcm7xx_gpio_set_input, NPCM7XX_GPIO_NR_PINS);
619
+ qdev_init_gpio_out(dev, s->output, NPCM7XX_GPIO_NR_PINS);
620
+}
621
+
622
+static const VMStateDescription vmstate_npcm7xx_gpio = {
623
+ .name = "npcm7xx-gpio",
624
+ .version_id = 0,
625
+ .minimum_version_id = 0,
626
+ .fields = (VMStateField[]) {
627
+ VMSTATE_UINT32(pin_level, NPCM7xxGPIOState),
628
+ VMSTATE_UINT32(ext_level, NPCM7xxGPIOState),
629
+ VMSTATE_UINT32(ext_driven, NPCM7xxGPIOState),
630
+ VMSTATE_UINT32_ARRAY(regs, NPCM7xxGPIOState, NPCM7XX_GPIO_NR_REGS),
631
+ VMSTATE_END_OF_LIST(),
632
+ },
633
+};
634
+
635
+static Property npcm7xx_gpio_properties[] = {
636
+ /* Bit n set => pin n has pullup enabled by default. */
637
+ DEFINE_PROP_UINT32("reset-pullup", NPCM7xxGPIOState, reset_pu, 0),
638
+ /* Bit n set => pin n has pulldown enabled by default. */
639
+ DEFINE_PROP_UINT32("reset-pulldown", NPCM7xxGPIOState, reset_pd, 0),
640
+ /* Bit n set => pin n has high slew rate by default. */
641
+ DEFINE_PROP_UINT32("reset-osrc", NPCM7xxGPIOState, reset_osrc, 0),
642
+ /* Bit n set => pin n has high drive strength by default. */
643
+ DEFINE_PROP_UINT32("reset-odsc", NPCM7xxGPIOState, reset_odsc, 0),
644
+ DEFINE_PROP_END_OF_LIST(),
645
+};
646
+
647
+static void npcm7xx_gpio_class_init(ObjectClass *klass, void *data)
648
+{
649
+ ResettableClass *reset = RESETTABLE_CLASS(klass);
650
+ DeviceClass *dc = DEVICE_CLASS(klass);
651
+
652
+ QEMU_BUILD_BUG_ON(NPCM7XX_GPIO_REGS_END > NPCM7XX_GPIO_NR_REGS);
653
+
654
+ dc->desc = "NPCM7xx GPIO Controller";
655
+ dc->vmsd = &vmstate_npcm7xx_gpio;
656
+ reset->phases.enter = npcm7xx_gpio_enter_reset;
657
+ reset->phases.hold = npcm7xx_gpio_hold_reset;
658
+ device_class_set_props(dc, npcm7xx_gpio_properties);
659
+}
660
+
661
+static const TypeInfo npcm7xx_gpio_types[] = {
662
+ {
663
+ .name = TYPE_NPCM7XX_GPIO,
664
+ .parent = TYPE_SYS_BUS_DEVICE,
665
+ .instance_size = sizeof(NPCM7xxGPIOState),
666
+ .class_init = npcm7xx_gpio_class_init,
667
+ .instance_init = npcm7xx_gpio_init,
668
+ },
669
+};
670
+DEFINE_TYPES(npcm7xx_gpio_types);
671
diff --git a/tests/qtest/npcm7xx_gpio-test.c b/tests/qtest/npcm7xx_gpio-test.c
672
new file mode 100644
673
index XXXXXXX..XXXXXXX
674
--- /dev/null
675
+++ b/tests/qtest/npcm7xx_gpio-test.c
676
@@ -XXX,XX +XXX,XX @@
677
+/*
678
+ * QTest testcase for the Nuvoton NPCM7xx GPIO modules.
679
+ *
680
+ * Copyright 2020 Google LLC
681
+ *
682
+ * This program is free software; you can redistribute it and/or modify it
683
+ * under the terms of the GNU General Public License as published by the
684
+ * Free Software Foundation; either version 2 of the License, or
685
+ * (at your option) any later version.
686
+ *
687
+ * This program is distributed in the hope that it will be useful, but WITHOUT
688
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
689
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
690
+ * for more details.
691
+ */
692
+
693
+#include "qemu/osdep.h"
694
+#include "libqtest-single.h"
695
+
696
+#define NR_GPIO_DEVICES (8)
697
+#define GPIO(x) (0xf0010000 + (x) * 0x1000)
698
+#define GPIO_IRQ(x) (116 + (x))
699
+
700
+/* GPIO registers */
701
+#define GP_N_TLOCK1 0x00
702
+#define GP_N_DIN 0x04 /* Data IN */
703
+#define GP_N_POL 0x08 /* Polarity */
704
+#define GP_N_DOUT 0x0c /* Data OUT */
705
+#define GP_N_OE 0x10 /* Output Enable */
706
+#define GP_N_OTYP 0x14
707
+#define GP_N_MP 0x18
708
+#define GP_N_PU 0x1c /* Pull-up */
709
+#define GP_N_PD 0x20 /* Pull-down */
710
+#define GP_N_DBNC 0x24 /* Debounce */
711
+#define GP_N_EVTYP 0x28 /* Event Type */
712
+#define GP_N_EVBE 0x2c /* Event Both Edge */
713
+#define GP_N_OBL0 0x30
714
+#define GP_N_OBL1 0x34
715
+#define GP_N_OBL2 0x38
716
+#define GP_N_OBL3 0x3c
717
+#define GP_N_EVEN 0x40 /* Event Enable */
718
+#define GP_N_EVENS 0x44 /* Event Set (enable) */
719
+#define GP_N_EVENC 0x48 /* Event Clear (disable) */
720
+#define GP_N_EVST 0x4c /* Event Status */
721
+#define GP_N_SPLCK 0x50
722
+#define GP_N_MPLCK 0x54
723
+#define GP_N_IEM 0x58 /* Input Enable */
724
+#define GP_N_OSRC 0x5c
725
+#define GP_N_ODSC 0x60
726
+#define GP_N_DOS 0x68 /* Data OUT Set */
727
+#define GP_N_DOC 0x6c /* Data OUT Clear */
728
+#define GP_N_OES 0x70 /* Output Enable Set */
729
+#define GP_N_OEC 0x74 /* Output Enable Clear */
730
+#define GP_N_TLOCK2 0x7c
731
+
732
+static void gpio_unlock(int n)
733
+{
734
+ if (readl(GPIO(n) + GP_N_TLOCK1) != 0) {
735
+ writel(GPIO(n) + GP_N_TLOCK2, 0xc0de1248);
736
+ writel(GPIO(n) + GP_N_TLOCK1, 0xc0defa73);
737
+ }
738
+}
739
+
740
+/* Restore the GPIO controller to a sensible default state. */
741
+static void gpio_reset(int n)
742
+{
743
+ gpio_unlock(0);
744
+
745
+ writel(GPIO(n) + GP_N_EVEN, 0x00000000);
746
+ writel(GPIO(n) + GP_N_EVST, 0xffffffff);
747
+ writel(GPIO(n) + GP_N_POL, 0x00000000);
748
+ writel(GPIO(n) + GP_N_DOUT, 0x00000000);
749
+ writel(GPIO(n) + GP_N_OE, 0x00000000);
750
+ writel(GPIO(n) + GP_N_OTYP, 0x00000000);
751
+ writel(GPIO(n) + GP_N_PU, 0xffffffff);
752
+ writel(GPIO(n) + GP_N_PD, 0x00000000);
753
+ writel(GPIO(n) + GP_N_IEM, 0xffffffff);
754
+}
755
+
756
+static void test_dout_to_din(void)
757
+{
758
+ gpio_reset(0);
759
+
760
+ /* When output is enabled, DOUT should be reflected on DIN. */
761
+ writel(GPIO(0) + GP_N_OE, 0xffffffff);
762
+ /* PU and PD shouldn't have any impact on DIN. */
763
+ writel(GPIO(0) + GP_N_PU, 0xffff0000);
764
+ writel(GPIO(0) + GP_N_PD, 0x0000ffff);
765
+ writel(GPIO(0) + GP_N_DOUT, 0x12345678);
766
+ g_assert_cmphex(readl(GPIO(0) + GP_N_DOUT), ==, 0x12345678);
767
+ g_assert_cmphex(readl(GPIO(0) + GP_N_DIN), ==, 0x12345678);
768
+}
769
+
770
+static void test_pullup_pulldown(void)
771
+{
772
+ gpio_reset(0);
773
+
774
+ /*
775
+ * When output is disabled, and PD is the inverse of PU, PU should be
776
+ * reflected on DIN. If PD is not the inverse of PU, the state of DIN is
777
+ * undefined, so we don't test that.
778
+ */
779
+ writel(GPIO(0) + GP_N_OE, 0x00000000);
780
+ /* DOUT shouldn't have any impact on DIN. */
781
+ writel(GPIO(0) + GP_N_DOUT, 0xffff0000);
782
+ writel(GPIO(0) + GP_N_PU, 0x23456789);
783
+ writel(GPIO(0) + GP_N_PD, ~0x23456789U);
784
+ g_assert_cmphex(readl(GPIO(0) + GP_N_PU), ==, 0x23456789);
785
+ g_assert_cmphex(readl(GPIO(0) + GP_N_PD), ==, ~0x23456789U);
786
+ g_assert_cmphex(readl(GPIO(0) + GP_N_DIN), ==, 0x23456789);
787
+}
788
+
789
+static void test_output_enable(void)
790
+{
791
+ gpio_reset(0);
792
+
793
+ /*
794
+ * With all pins weakly pulled down, and DOUT all-ones, OE should be
795
+ * reflected on DIN.
796
+ */
797
+ writel(GPIO(0) + GP_N_DOUT, 0xffffffff);
798
+ writel(GPIO(0) + GP_N_PU, 0x00000000);
799
+ writel(GPIO(0) + GP_N_PD, 0xffffffff);
800
+ writel(GPIO(0) + GP_N_OE, 0x3456789a);
801
+ g_assert_cmphex(readl(GPIO(0) + GP_N_OE), ==, 0x3456789a);
802
+ g_assert_cmphex(readl(GPIO(0) + GP_N_DIN), ==, 0x3456789a);
803
+
804
+ writel(GPIO(0) + GP_N_OEC, 0x00030002);
805
+ g_assert_cmphex(readl(GPIO(0) + GP_N_OE), ==, 0x34547898);
806
+ g_assert_cmphex(readl(GPIO(0) + GP_N_DIN), ==, 0x34547898);
807
+
808
+ writel(GPIO(0) + GP_N_OES, 0x0000f001);
809
+ g_assert_cmphex(readl(GPIO(0) + GP_N_OE), ==, 0x3454f899);
810
+ g_assert_cmphex(readl(GPIO(0) + GP_N_DIN), ==, 0x3454f899);
811
+}
812
+
813
+static void test_open_drain(void)
814
+{
815
+ gpio_reset(0);
816
+
817
+ /*
818
+ * Upper half of DOUT drives a 1 only if the corresponding bit in OTYP is
819
+ * not set. If OTYP is set, DIN is determined by PU/PD. Lower half of
820
+ * DOUT always drives a 0 regardless of OTYP; PU/PD have no effect. When
821
+ * OE is 0, output is determined by PU/PD; OTYP has no effect.
822
+ */
823
+ writel(GPIO(0) + GP_N_OTYP, 0x456789ab);
824
+ writel(GPIO(0) + GP_N_OE, 0xf0f0f0f0);
825
+ writel(GPIO(0) + GP_N_DOUT, 0xffff0000);
826
+ writel(GPIO(0) + GP_N_PU, 0xff00ff00);
827
+ writel(GPIO(0) + GP_N_PD, 0x00ff00ff);
828
+ g_assert_cmphex(readl(GPIO(0) + GP_N_OTYP), ==, 0x456789ab);
829
+ g_assert_cmphex(readl(GPIO(0) + GP_N_DIN), ==, 0xff900f00);
830
+}
831
+
832
+static void test_polarity(void)
833
+{
834
+ gpio_reset(0);
835
+
836
+ /*
837
+ * In push-pull mode, DIN should reflect DOUT because the signal is
838
+ * inverted in both directions.
839
+ */
840
+ writel(GPIO(0) + GP_N_OTYP, 0x00000000);
841
+ writel(GPIO(0) + GP_N_OE, 0xffffffff);
842
+ writel(GPIO(0) + GP_N_DOUT, 0x56789abc);
843
+ writel(GPIO(0) + GP_N_POL, 0x6789abcd);
844
+ g_assert_cmphex(readl(GPIO(0) + GP_N_POL), ==, 0x6789abcd);
845
+ g_assert_cmphex(readl(GPIO(0) + GP_N_DIN), ==, 0x56789abc);
846
+
847
+ /*
848
+ * When turning off the drivers, DIN should reflect the inverse of the
849
+ * pulled-up lines.
850
+ */
851
+ writel(GPIO(0) + GP_N_OE, 0x00000000);
852
+ writel(GPIO(0) + GP_N_POL, 0xffffffff);
853
+ writel(GPIO(0) + GP_N_PU, 0x789abcde);
854
+ writel(GPIO(0) + GP_N_PD, ~0x789abcdeU);
855
+ g_assert_cmphex(readl(GPIO(0) + GP_N_DIN), ==, ~0x789abcdeU);
856
+
857
+ /*
858
+ * In open-drain mode, DOUT=1 will appear to drive the pin high (since DIN
859
+ * is inverted), while DOUT=0 will leave the pin floating.
860
+ */
861
+ writel(GPIO(0) + GP_N_OTYP, 0xffffffff);
862
+ writel(GPIO(0) + GP_N_OE, 0xffffffff);
863
+ writel(GPIO(0) + GP_N_PU, 0xffff0000);
864
+ writel(GPIO(0) + GP_N_PD, 0x0000ffff);
865
+ writel(GPIO(0) + GP_N_DOUT, 0xff00ff00);
866
+ g_assert_cmphex(readl(GPIO(0) + GP_N_DIN), ==, 0xff00ffff);
867
+}
868
+
869
+static void test_input_mask(void)
870
+{
871
+ gpio_reset(0);
872
+
873
+ /* IEM=0 forces the input to zero before polarity inversion. */
874
+ writel(GPIO(0) + GP_N_OE, 0xffffffff);
875
+ writel(GPIO(0) + GP_N_DOUT, 0xff00ff00);
876
+ writel(GPIO(0) + GP_N_POL, 0xffff0000);
877
+ writel(GPIO(0) + GP_N_IEM, 0x87654321);
878
+ g_assert_cmphex(readl(GPIO(0) + GP_N_DIN), ==, 0xff9a4300);
879
+}
880
+
881
+static void test_temp_lock(void)
882
+{
883
+ gpio_reset(0);
884
+
885
+ writel(GPIO(0) + GP_N_DOUT, 0x98765432);
886
+
887
+ /* Make sure we're unlocked initially. */
888
+ g_assert_cmphex(readl(GPIO(0) + GP_N_TLOCK1), ==, 0);
889
+ /* Writing any value to TLOCK1 will lock. */
890
+ writel(GPIO(0) + GP_N_TLOCK1, 0);
891
+ g_assert_cmphex(readl(GPIO(0) + GP_N_TLOCK1), ==, 1);
892
+ writel(GPIO(0) + GP_N_DOUT, 0xa9876543);
893
+ g_assert_cmphex(readl(GPIO(0) + GP_N_DOUT), ==, 0x98765432);
894
+ /* Now, try to unlock. */
895
+ gpio_unlock(0);
896
+ g_assert_cmphex(readl(GPIO(0) + GP_N_TLOCK1), ==, 0);
897
+ writel(GPIO(0) + GP_N_DOUT, 0xa9876543);
898
+ g_assert_cmphex(readl(GPIO(0) + GP_N_DOUT), ==, 0xa9876543);
899
+
900
+ /* Try it again, but write TLOCK2 to lock. */
901
+ writel(GPIO(0) + GP_N_TLOCK2, 0);
902
+ g_assert_cmphex(readl(GPIO(0) + GP_N_TLOCK1), ==, 1);
903
+ writel(GPIO(0) + GP_N_DOUT, 0x98765432);
904
+ g_assert_cmphex(readl(GPIO(0) + GP_N_DOUT), ==, 0xa9876543);
905
+ /* Now, try to unlock. */
906
+ gpio_unlock(0);
907
+ g_assert_cmphex(readl(GPIO(0) + GP_N_TLOCK1), ==, 0);
908
+ writel(GPIO(0) + GP_N_DOUT, 0x98765432);
909
+ g_assert_cmphex(readl(GPIO(0) + GP_N_DOUT), ==, 0x98765432);
910
+}
911
+
912
+static void test_events_level(void)
913
+{
914
+ gpio_reset(0);
915
+
916
+ writel(GPIO(0) + GP_N_EVTYP, 0x00000000);
917
+ writel(GPIO(0) + GP_N_DOUT, 0xba987654);
918
+ writel(GPIO(0) + GP_N_OE, 0xffffffff);
919
+ writel(GPIO(0) + GP_N_EVST, 0xffffffff);
920
+
921
+ g_assert_cmphex(readl(GPIO(0) + GP_N_EVST), ==, 0xba987654);
922
+ g_assert_false(qtest_get_irq(global_qtest, GPIO_IRQ(0)));
923
+ writel(GPIO(0) + GP_N_DOUT, 0x00000000);
924
+ g_assert_cmphex(readl(GPIO(0) + GP_N_EVST), ==, 0xba987654);
925
+ g_assert_false(qtest_get_irq(global_qtest, GPIO_IRQ(0)));
926
+ writel(GPIO(0) + GP_N_EVST, 0x00007654);
927
+ g_assert_cmphex(readl(GPIO(0) + GP_N_EVST), ==, 0xba980000);
928
+ g_assert_false(qtest_get_irq(global_qtest, GPIO_IRQ(0)));
929
+ writel(GPIO(0) + GP_N_EVST, 0xba980000);
930
+ g_assert_cmphex(readl(GPIO(0) + GP_N_EVST), ==, 0x00000000);
931
+ g_assert_false(qtest_get_irq(global_qtest, GPIO_IRQ(0)));
932
+}
933
+
934
+static void test_events_rising_edge(void)
935
+{
936
+ gpio_reset(0);
937
+
938
+ writel(GPIO(0) + GP_N_EVTYP, 0xffffffff);
939
+ writel(GPIO(0) + GP_N_EVBE, 0x00000000);
940
+ writel(GPIO(0) + GP_N_DOUT, 0xffff0000);
941
+ writel(GPIO(0) + GP_N_OE, 0xffffffff);
942
+ writel(GPIO(0) + GP_N_EVST, 0xffffffff);
943
+
944
+ g_assert_cmphex(readl(GPIO(0) + GP_N_EVST), ==, 0x00000000);
945
+ g_assert_false(qtest_get_irq(global_qtest, GPIO_IRQ(0)));
946
+ writel(GPIO(0) + GP_N_DOUT, 0xff00ff00);
947
+ g_assert_cmphex(readl(GPIO(0) + GP_N_EVST), ==, 0x0000ff00);
948
+ g_assert_false(qtest_get_irq(global_qtest, GPIO_IRQ(0)));
949
+ writel(GPIO(0) + GP_N_DOUT, 0x00ff0000);
950
+ g_assert_cmphex(readl(GPIO(0) + GP_N_EVST), ==, 0x00ffff00);
951
+ g_assert_false(qtest_get_irq(global_qtest, GPIO_IRQ(0)));
952
+ writel(GPIO(0) + GP_N_EVST, 0x0000f000);
953
+ g_assert_cmphex(readl(GPIO(0) + GP_N_EVST), ==, 0x00ff0f00);
954
+ g_assert_false(qtest_get_irq(global_qtest, GPIO_IRQ(0)));
955
+ writel(GPIO(0) + GP_N_EVST, 0x00ff0f00);
956
+ g_assert_cmphex(readl(GPIO(0) + GP_N_EVST), ==, 0x00000000);
957
+ g_assert_false(qtest_get_irq(global_qtest, GPIO_IRQ(0)));
958
+}
959
+
960
+static void test_events_both_edges(void)
961
+{
962
+ gpio_reset(0);
963
+
964
+ writel(GPIO(0) + GP_N_EVTYP, 0xffffffff);
965
+ writel(GPIO(0) + GP_N_EVBE, 0xffffffff);
966
+ writel(GPIO(0) + GP_N_DOUT, 0xffff0000);
967
+ writel(GPIO(0) + GP_N_OE, 0xffffffff);
968
+ writel(GPIO(0) + GP_N_EVST, 0xffffffff);
969
+
970
+ g_assert_cmphex(readl(GPIO(0) + GP_N_EVST), ==, 0x00000000);
971
+ g_assert_false(qtest_get_irq(global_qtest, GPIO_IRQ(0)));
972
+ writel(GPIO(0) + GP_N_DOUT, 0xff00ff00);
973
+ g_assert_cmphex(readl(GPIO(0) + GP_N_EVST), ==, 0x00ffff00);
974
+ g_assert_false(qtest_get_irq(global_qtest, GPIO_IRQ(0)));
975
+ writel(GPIO(0) + GP_N_DOUT, 0xef00ff08);
976
+ g_assert_cmphex(readl(GPIO(0) + GP_N_EVST), ==, 0x10ffff08);
977
+ g_assert_false(qtest_get_irq(global_qtest, GPIO_IRQ(0)));
978
+ writel(GPIO(0) + GP_N_EVST, 0x0000f000);
979
+ g_assert_cmphex(readl(GPIO(0) + GP_N_EVST), ==, 0x10ff0f08);
980
+ g_assert_false(qtest_get_irq(global_qtest, GPIO_IRQ(0)));
981
+ writel(GPIO(0) + GP_N_EVST, 0x10ff0f08);
982
+ g_assert_cmphex(readl(GPIO(0) + GP_N_EVST), ==, 0x00000000);
983
+ g_assert_false(qtest_get_irq(global_qtest, GPIO_IRQ(0)));
984
+}
985
+
986
+static void test_gpion_irq(gconstpointer test_data)
987
+{
988
+ intptr_t n = (intptr_t)test_data;
989
+
990
+ gpio_reset(n);
991
+
992
+ writel(GPIO(n) + GP_N_EVTYP, 0x00000000);
993
+ writel(GPIO(n) + GP_N_DOUT, 0x00000000);
994
+ writel(GPIO(n) + GP_N_OE, 0xffffffff);
995
+ writel(GPIO(n) + GP_N_EVST, 0xffffffff);
996
+ writel(GPIO(n) + GP_N_EVEN, 0x00000000);
997
+
998
+ /* Trigger an event; interrupts are masked. */
999
+ g_assert_cmphex(readl(GPIO(n) + GP_N_EVST), ==, 0x00000000);
1000
+ g_assert_false(qtest_get_irq(global_qtest, GPIO_IRQ(n)));
1001
+ writel(GPIO(n) + GP_N_DOS, 0x00008000);
1002
+ g_assert_cmphex(readl(GPIO(n) + GP_N_EVST), ==, 0x00008000);
1003
+ g_assert_false(qtest_get_irq(global_qtest, GPIO_IRQ(n)));
1004
+
1005
+ /* Unmask all event interrupts; verify that the interrupt fired. */
1006
+ writel(GPIO(n) + GP_N_EVEN, 0xffffffff);
1007
+ g_assert_true(qtest_get_irq(global_qtest, GPIO_IRQ(n)));
1008
+
1009
+ /* Clear the current bit, set a new bit, irq stays asserted. */
1010
+ writel(GPIO(n) + GP_N_DOC, 0x00008000);
1011
+ g_assert_true(qtest_get_irq(global_qtest, GPIO_IRQ(n)));
1012
+ writel(GPIO(n) + GP_N_DOS, 0x00000200);
1013
+ g_assert_true(qtest_get_irq(global_qtest, GPIO_IRQ(n)));
1014
+ writel(GPIO(n) + GP_N_EVST, 0x00008000);
1015
+ g_assert_true(qtest_get_irq(global_qtest, GPIO_IRQ(n)));
1016
+
1017
+ /* Mask/unmask the event that's currently active. */
1018
+ writel(GPIO(n) + GP_N_EVENC, 0x00000200);
1019
+ g_assert_false(qtest_get_irq(global_qtest, GPIO_IRQ(n)));
1020
+ writel(GPIO(n) + GP_N_EVENS, 0x00000200);
1021
+ g_assert_true(qtest_get_irq(global_qtest, GPIO_IRQ(n)));
1022
+
1023
+ /* Clear the input and the status bit, irq is deasserted. */
1024
+ writel(GPIO(n) + GP_N_DOC, 0x00000200);
1025
+ g_assert_true(qtest_get_irq(global_qtest, GPIO_IRQ(n)));
1026
+ writel(GPIO(n) + GP_N_EVST, 0x00000200);
1027
+ g_assert_false(qtest_get_irq(global_qtest, GPIO_IRQ(n)));
1028
+}
1029
+
1030
+int main(int argc, char **argv)
1031
+{
1032
+ int ret;
1033
+ int i;
1034
+
1035
+ g_test_init(&argc, &argv, NULL);
1036
+ g_test_set_nonfatal_assertions();
1037
+
1038
+ qtest_add_func("/npcm7xx_gpio/dout_to_din", test_dout_to_din);
1039
+ qtest_add_func("/npcm7xx_gpio/pullup_pulldown", test_pullup_pulldown);
1040
+ qtest_add_func("/npcm7xx_gpio/output_enable", test_output_enable);
1041
+ qtest_add_func("/npcm7xx_gpio/open_drain", test_open_drain);
1042
+ qtest_add_func("/npcm7xx_gpio/polarity", test_polarity);
1043
+ qtest_add_func("/npcm7xx_gpio/input_mask", test_input_mask);
1044
+ qtest_add_func("/npcm7xx_gpio/temp_lock", test_temp_lock);
1045
+ qtest_add_func("/npcm7xx_gpio/events/level", test_events_level);
1046
+ qtest_add_func("/npcm7xx_gpio/events/rising_edge", test_events_rising_edge);
1047
+ qtest_add_func("/npcm7xx_gpio/events/both_edges", test_events_both_edges);
1048
+
1049
+ for (i = 0; i < NR_GPIO_DEVICES; i++) {
1050
+ g_autofree char *test_name =
1051
+ g_strdup_printf("/npcm7xx_gpio/gpio[%d]/irq", i);
1052
+ qtest_add_data_func(test_name, (void *)(intptr_t)i, test_gpion_irq);
1053
+ }
1054
+
1055
+ qtest_start("-machine npcm750-evb");
1056
+ qtest_irq_intercept_in(global_qtest, "/machine/soc/a9mpcore/gic");
1057
+ ret = g_test_run();
1058
+ qtest_end();
1059
+
1060
+ return ret;
1061
+}
1062
diff --git a/hw/gpio/meson.build b/hw/gpio/meson.build
1063
index XXXXXXX..XXXXXXX 100644
316
index XXXXXXX..XXXXXXX 100644
1064
--- a/hw/gpio/meson.build
317
--- a/hw/intc/trace-events
1065
+++ b/hw/gpio/meson.build
318
+++ b/hw/intc/trace-events
1066
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_PUV3', if_true: files('puv3_gpio.c'))
319
@@ -XXX,XX +XXX,XX @@ gicv3_icv_rpr_read(uint32_t cpu, uint64_t val) "GICv3 ICV_RPR read cpu 0x%x valu
1067
softmmu_ss.add(when: 'CONFIG_ZAURUS', if_true: files('zaurus.c'))
320
gicv3_icv_hppir_read(int grp, uint32_t cpu, uint64_t val) "GICv3 ICV_HPPIR%d read cpu 0x%x value 0x%" PRIx64
1068
321
gicv3_icv_dir_write(uint32_t cpu, uint64_t val) "GICv3 ICV_DIR write cpu 0x%x value 0x%" PRIx64
1069
softmmu_ss.add(when: 'CONFIG_IMX', if_true: files('imx_gpio.c'))
322
gicv3_icv_iar_read(int grp, uint32_t cpu, uint64_t val) "GICv3 ICV_IAR%d read cpu 0x%x value 0x%" PRIx64
1070
+softmmu_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx_gpio.c'))
323
+gicv3_icv_nmiar1_read(uint32_t cpu, uint64_t val) "GICv3 ICV_NMIAR1 read cpu 0x%x value 0x%" PRIx64
1071
softmmu_ss.add(when: 'CONFIG_NRF51_SOC', if_true: files('nrf51_gpio.c'))
324
gicv3_icv_eoir_write(int grp, uint32_t cpu, uint64_t val) "GICv3 ICV_EOIR%d write cpu 0x%x value 0x%" PRIx64
1072
softmmu_ss.add(when: 'CONFIG_OMAP', if_true: files('omap_gpio.c'))
325
gicv3_cpuif_virt_update(uint32_t cpuid, int idx, int hppvlpi, int grp, int prio) "GICv3 CPU i/f 0x%x virt HPPI update LR index %d HPPVLPI %d grp %d prio %d"
1073
softmmu_ss.add(when: 'CONFIG_RASPI', if_true: files('bcm2835_gpio.c'))
326
gicv3_cpuif_virt_set_irqs(uint32_t cpuid, int fiqlevel, int irqlevel) "GICv3 CPU i/f 0x%x virt HPPI update: setting FIQ %d IRQ %d"
1074
diff --git a/hw/gpio/trace-events b/hw/gpio/trace-events
1075
index XXXXXXX..XXXXXXX 100644
1076
--- a/hw/gpio/trace-events
1077
+++ b/hw/gpio/trace-events
1078
@@ -XXX,XX +XXX,XX @@
1079
# See docs/devel/tracing.txt for syntax documentation.
1080
1081
+# npcm7xx_gpio.c
1082
+npcm7xx_gpio_read(const char *id, uint64_t offset, uint64_t value) " %s offset: 0x%04" PRIx64 " value 0x%08" PRIx64
1083
+npcm7xx_gpio_write(const char *id, uint64_t offset, uint64_t value) "%s offset: 0x%04" PRIx64 " value 0x%08" PRIx64
1084
+npcm7xx_gpio_set_input(const char *id, int32_t line, int32_t level) "%s line: %" PRIi32 " level: %" PRIi32
1085
+npcm7xx_gpio_set_output(const char *id, int32_t line, int32_t level) "%s line: %" PRIi32 " level: %" PRIi32
1086
+npcm7xx_gpio_update_events(const char *id, uint32_t evst, uint32_t even) "%s evst: 0x%08" PRIx32 " even: 0x%08" PRIx32
1087
+
1088
# nrf51_gpio.c
1089
nrf51_gpio_read(uint64_t offset, uint64_t r) "offset 0x%" PRIx64 " value 0x%" PRIx64
1090
nrf51_gpio_write(uint64_t offset, uint64_t value) "offset 0x%" PRIx64 " value 0x%" PRIx64
1091
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
1092
index XXXXXXX..XXXXXXX 100644
1093
--- a/tests/qtest/meson.build
1094
+++ b/tests/qtest/meson.build
1095
@@ -XXX,XX +XXX,XX @@ qtests_sparc64 = \
1096
['prom-env-test', 'boot-serial-test']
1097
1098
qtests_npcm7xx = \
1099
- ['npcm7xx_rng-test',
1100
+ ['npcm7xx_gpio-test',
1101
+ 'npcm7xx_rng-test',
1102
'npcm7xx_timer-test',
1103
'npcm7xx_watchdog_timer-test']
1104
qtests_arm = \
1105
--
327
--
1106
2.20.1
328
2.34.1
1107
1108
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Jinjie Ruan <ruanjinjie@huawei.com>
2
2
3
This is generic support, with the code disabled for all targets.
3
If GICD_CTLR_DS bit is zero and the NMI is non-secure, the NMI priority is
4
higher than 0x80, otherwise it is higher than 0x0. And save the interrupt
5
non-maskable property in hppi.nmi to deliver NMI exception. Since both GICR
6
and GICD can deliver NMI, it is both necessary to check whether the pending
7
irq is NMI in gicv3_redist_update_noirqset and gicv3_update_noirqset.
4
8
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com>
6
Message-id: 20201021173749.111103-11-richard.henderson@linaro.org
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
Message-id: 20240407081733.3231820-21-ruanjinjie@huawei.com
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
14
---
10
linux-user/qemu.h | 4 ++
15
hw/intc/arm_gicv3.c | 67 +++++++++++++++++++++++++++++++++-----
11
linux-user/elfload.c | 157 +++++++++++++++++++++++++++++++++++++++++++
16
hw/intc/arm_gicv3_common.c | 3 ++
12
2 files changed, 161 insertions(+)
17
hw/intc/arm_gicv3_redist.c | 3 ++
18
3 files changed, 64 insertions(+), 9 deletions(-)
13
19
14
diff --git a/linux-user/qemu.h b/linux-user/qemu.h
20
diff --git a/hw/intc/arm_gicv3.c b/hw/intc/arm_gicv3.c
15
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
16
--- a/linux-user/qemu.h
22
--- a/hw/intc/arm_gicv3.c
17
+++ b/linux-user/qemu.h
23
+++ b/hw/intc/arm_gicv3.c
18
@@ -XXX,XX +XXX,XX @@ struct image_info {
24
@@ -XXX,XX +XXX,XX @@
19
abi_ulong interpreter_loadmap_addr;
25
#include "hw/intc/arm_gicv3.h"
20
abi_ulong interpreter_pt_dynamic_addr;
26
#include "gicv3_internal.h"
21
struct image_info *other_info;
27
22
+
28
-static bool irqbetter(GICv3CPUState *cs, int irq, uint8_t prio)
23
+ /* For target-specific processing of NT_GNU_PROPERTY_TYPE_0. */
29
+static bool irqbetter(GICv3CPUState *cs, int irq, uint8_t prio, bool nmi)
24
+ uint32_t note_flags;
30
{
25
+
31
/* Return true if this IRQ at this priority should take
26
#ifdef TARGET_MIPS
32
* precedence over the current recorded highest priority
27
int fp_abi;
33
@@ -XXX,XX +XXX,XX @@ static bool irqbetter(GICv3CPUState *cs, int irq, uint8_t prio)
28
int interp_fp_abi;
34
* is the same as this one (a property which the calling code
29
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
35
* relies on).
30
index XXXXXXX..XXXXXXX 100644
36
*/
31
--- a/linux-user/elfload.c
37
- if (prio < cs->hppi.prio) {
32
+++ b/linux-user/elfload.c
38
- return true;
33
@@ -XXX,XX +XXX,XX @@ static void elf_core_copy_regs(target_elf_gregset_t *regs,
39
+ if (prio != cs->hppi.prio) {
34
40
+ return prio < cs->hppi.prio;
35
#include "elf.h"
41
}
36
42
+
37
+static bool arch_parse_elf_property(uint32_t pr_type, uint32_t pr_datasz,
43
+ /*
38
+ const uint32_t *data,
44
+ * The same priority IRQ with non-maskable property should signal to
39
+ struct image_info *info,
45
+ * the CPU as it have the priority higher than the labelled 0x80 or 0x00.
40
+ Error **errp)
46
+ */
47
+ if (nmi != cs->hppi.nmi) {
48
+ return nmi;
49
+ }
50
+
51
/* If multiple pending interrupts have the same priority then it is an
52
* IMPDEF choice which of them to signal to the CPU. We choose to
53
* signal the one with the lowest interrupt number.
54
*/
55
- if (prio == cs->hppi.prio && irq <= cs->hppi.irq) {
56
+ if (irq <= cs->hppi.irq) {
57
return true;
58
}
59
return false;
60
@@ -XXX,XX +XXX,XX @@ static uint32_t gicr_int_pending(GICv3CPUState *cs)
61
return pend;
62
}
63
64
+static bool gicv3_get_priority(GICv3CPUState *cs, bool is_redist, int irq,
65
+ uint8_t *prio)
41
+{
66
+{
42
+ g_assert_not_reached();
67
+ uint32_t nmi = 0x0;
43
+}
68
+
44
+#define ARCH_USE_GNU_PROPERTY 0
69
+ if (is_redist) {
45
+
70
+ nmi = extract32(cs->gicr_inmir0, irq, 1);
46
struct exec
71
+ } else {
47
{
72
+ nmi = *gic_bmp_ptr32(cs->gic->nmi, irq);
48
unsigned int a_info; /* Use macros N_MAGIC, etc for access */
73
+ nmi = nmi & (1 << (irq & 0x1f));
49
@@ -XXX,XX +XXX,XX @@ void probe_guest_base(const char *image_name, abi_ulong guest_loaddr,
74
+ }
50
"@ 0x%" PRIx64 "\n", (uint64_t)guest_base);
75
+
51
}
76
+ if (nmi) {
52
77
+ /* DS = 0 & Non-secure NMI */
53
+enum {
78
+ if (!(cs->gic->gicd_ctlr & GICD_CTLR_DS) &&
54
+ /* The string "GNU\0" as a magic number. */
79
+ ((is_redist && extract32(cs->gicr_igroupr0, irq, 1)) ||
55
+ GNU0_MAGIC = const_le32('G' | 'N' << 8 | 'U' << 16),
80
+ (!is_redist && gicv3_gicd_group_test(cs->gic, irq)))) {
56
+ NOTE_DATA_SZ = 1 * KiB,
81
+ *prio = 0x80;
57
+ NOTE_NAME_SZ = 4,
58
+ ELF_GNU_PROPERTY_ALIGN = ELF_CLASS == ELFCLASS32 ? 4 : 8,
59
+};
60
+
61
+/*
62
+ * Process a single gnu_property entry.
63
+ * Return false for error.
64
+ */
65
+static bool parse_elf_property(const uint32_t *data, int *off, int datasz,
66
+ struct image_info *info, bool have_prev_type,
67
+ uint32_t *prev_type, Error **errp)
68
+{
69
+ uint32_t pr_type, pr_datasz, step;
70
+
71
+ if (*off > datasz || !QEMU_IS_ALIGNED(*off, ELF_GNU_PROPERTY_ALIGN)) {
72
+ goto error_data;
73
+ }
74
+ datasz -= *off;
75
+ data += *off / sizeof(uint32_t);
76
+
77
+ if (datasz < 2 * sizeof(uint32_t)) {
78
+ goto error_data;
79
+ }
80
+ pr_type = data[0];
81
+ pr_datasz = data[1];
82
+ data += 2;
83
+ datasz -= 2 * sizeof(uint32_t);
84
+ step = ROUND_UP(pr_datasz, ELF_GNU_PROPERTY_ALIGN);
85
+ if (step > datasz) {
86
+ goto error_data;
87
+ }
88
+
89
+ /* Properties are supposed to be unique and sorted on pr_type. */
90
+ if (have_prev_type && pr_type <= *prev_type) {
91
+ if (pr_type == *prev_type) {
92
+ error_setg(errp, "Duplicate property in PT_GNU_PROPERTY");
93
+ } else {
82
+ } else {
94
+ error_setg(errp, "Unsorted property in PT_GNU_PROPERTY");
83
+ *prio = 0x0;
95
+ }
84
+ }
96
+ return false;
85
+
97
+ }
86
+ return true;
98
+ *prev_type = pr_type;
87
+ }
99
+
88
+
100
+ if (!arch_parse_elf_property(pr_type, pr_datasz, data, info, errp)) {
89
+ if (is_redist) {
101
+ return false;
90
+ *prio = cs->gicr_ipriorityr[irq];
102
+ }
91
+ } else {
103
+
92
+ *prio = cs->gic->gicd_ipriority[irq];
104
+ *off += 2 * sizeof(uint32_t) + step;
93
+ }
105
+ return true;
94
+
106
+
107
+ error_data:
108
+ error_setg(errp, "Ill-formed property in PT_GNU_PROPERTY");
109
+ return false;
95
+ return false;
110
+}
96
+}
111
+
97
+
112
+/* Process NT_GNU_PROPERTY_TYPE_0. */
98
/* Update the interrupt status after state in a redistributor
113
+static bool parse_elf_properties(int image_fd,
99
* or CPU interface has changed, but don't tell the CPU i/f.
114
+ struct image_info *info,
100
*/
115
+ const struct elf_phdr *phdr,
101
@@ -XXX,XX +XXX,XX @@ static void gicv3_redist_update_noirqset(GICv3CPUState *cs)
116
+ char bprm_buf[BPRM_BUF_SIZE],
102
uint8_t prio;
117
+ Error **errp)
103
int i;
118
+{
104
uint32_t pend;
119
+ union {
105
+ bool nmi = false;
120
+ struct elf_note nhdr;
106
121
+ uint32_t data[NOTE_DATA_SZ / sizeof(uint32_t)];
107
/* Find out which redistributor interrupts are eligible to be
122
+ } note;
108
* signaled to the CPU interface.
123
+
109
@@ -XXX,XX +XXX,XX @@ static void gicv3_redist_update_noirqset(GICv3CPUState *cs)
124
+ int n, off, datasz;
110
if (!(pend & (1 << i))) {
125
+ bool have_prev_type;
111
continue;
126
+ uint32_t prev_type;
127
+
128
+ /* Unless the arch requires properties, ignore them. */
129
+ if (!ARCH_USE_GNU_PROPERTY) {
130
+ return true;
131
+ }
132
+
133
+ /* If the properties are crazy large, that's too bad. */
134
+ n = phdr->p_filesz;
135
+ if (n > sizeof(note)) {
136
+ error_setg(errp, "PT_GNU_PROPERTY too large");
137
+ return false;
138
+ }
139
+ if (n < sizeof(note.nhdr)) {
140
+ error_setg(errp, "PT_GNU_PROPERTY too small");
141
+ return false;
142
+ }
143
+
144
+ if (phdr->p_offset + n <= BPRM_BUF_SIZE) {
145
+ memcpy(&note, bprm_buf + phdr->p_offset, n);
146
+ } else {
147
+ ssize_t len = pread(image_fd, &note, n, phdr->p_offset);
148
+ if (len != n) {
149
+ error_setg_errno(errp, errno, "Error reading file header");
150
+ return false;
151
+ }
152
+ }
153
+
154
+ /*
155
+ * The contents of a valid PT_GNU_PROPERTY is a sequence
156
+ * of uint32_t -- swap them all now.
157
+ */
158
+#ifdef BSWAP_NEEDED
159
+ for (int i = 0; i < n / 4; i++) {
160
+ bswap32s(note.data + i);
161
+ }
162
+#endif
163
+
164
+ /*
165
+ * Note that nhdr is 3 words, and that the "name" described by namesz
166
+ * immediately follows nhdr and is thus at the 4th word. Further, all
167
+ * of the inputs to the kernel's round_up are multiples of 4.
168
+ */
169
+ if (note.nhdr.n_type != NT_GNU_PROPERTY_TYPE_0 ||
170
+ note.nhdr.n_namesz != NOTE_NAME_SZ ||
171
+ note.data[3] != GNU0_MAGIC) {
172
+ error_setg(errp, "Invalid note in PT_GNU_PROPERTY");
173
+ return false;
174
+ }
175
+ off = sizeof(note.nhdr) + NOTE_NAME_SZ;
176
+
177
+ datasz = note.nhdr.n_descsz + off;
178
+ if (datasz > n) {
179
+ error_setg(errp, "Invalid note size in PT_GNU_PROPERTY");
180
+ return false;
181
+ }
182
+
183
+ have_prev_type = false;
184
+ prev_type = 0;
185
+ while (1) {
186
+ if (off == datasz) {
187
+ return true; /* end, exit ok */
188
+ }
189
+ if (!parse_elf_property(note.data, &off, datasz, info,
190
+ have_prev_type, &prev_type, errp)) {
191
+ return false;
192
+ }
193
+ have_prev_type = true;
194
+ }
195
+}
196
+
197
/* Load an ELF image into the address space.
198
199
IMAGE_NAME is the filename of the image, to use in error messages.
200
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
201
goto exit_errmsg;
202
}
112
}
203
*pinterp_name = g_steal_pointer(&interp_name);
113
- prio = cs->gicr_ipriorityr[i];
204
+ } else if (eppnt->p_type == PT_GNU_PROPERTY) {
114
- if (irqbetter(cs, i, prio)) {
205
+ if (!parse_elf_properties(image_fd, info, eppnt, bprm_buf, &err)) {
115
+ nmi = gicv3_get_priority(cs, true, i, &prio);
206
+ goto exit_errmsg;
116
+ if (irqbetter(cs, i, prio, nmi)) {
207
+ }
117
cs->hppi.irq = i;
208
}
118
cs->hppi.prio = prio;
209
}
119
+ cs->hppi.nmi = nmi;
120
seenbetter = true;
121
}
122
}
123
@@ -XXX,XX +XXX,XX @@ static void gicv3_redist_update_noirqset(GICv3CPUState *cs)
124
if ((cs->gicr_ctlr & GICR_CTLR_ENABLE_LPIS) && cs->gic->lpi_enable &&
125
(cs->gic->gicd_ctlr & GICD_CTLR_EN_GRP1NS) &&
126
(cs->hpplpi.prio != 0xff)) {
127
- if (irqbetter(cs, cs->hpplpi.irq, cs->hpplpi.prio)) {
128
+ if (irqbetter(cs, cs->hpplpi.irq, cs->hpplpi.prio, cs->hpplpi.nmi)) {
129
cs->hppi.irq = cs->hpplpi.irq;
130
cs->hppi.prio = cs->hpplpi.prio;
131
+ cs->hppi.nmi = cs->hpplpi.nmi;
132
cs->hppi.grp = cs->hpplpi.grp;
133
seenbetter = true;
134
}
135
@@ -XXX,XX +XXX,XX @@ static void gicv3_update_noirqset(GICv3State *s, int start, int len)
136
int i;
137
uint8_t prio;
138
uint32_t pend = 0;
139
+ bool nmi = false;
140
141
assert(start >= GIC_INTERNAL);
142
assert(len > 0);
143
@@ -XXX,XX +XXX,XX @@ static void gicv3_update_noirqset(GICv3State *s, int start, int len)
144
*/
145
continue;
146
}
147
- prio = s->gicd_ipriority[i];
148
- if (irqbetter(cs, i, prio)) {
149
+ nmi = gicv3_get_priority(cs, false, i, &prio);
150
+ if (irqbetter(cs, i, prio, nmi)) {
151
cs->hppi.irq = i;
152
cs->hppi.prio = prio;
153
+ cs->hppi.nmi = nmi;
154
cs->seenbetter = true;
155
}
156
}
157
@@ -XXX,XX +XXX,XX @@ void gicv3_full_update_noirqset(GICv3State *s)
158
159
for (i = 0; i < s->num_cpu; i++) {
160
s->cpu[i].hppi.prio = 0xff;
161
+ s->cpu[i].hppi.nmi = false;
162
}
163
164
/* Note that we can guarantee that these functions will not
165
diff --git a/hw/intc/arm_gicv3_common.c b/hw/intc/arm_gicv3_common.c
166
index XXXXXXX..XXXXXXX 100644
167
--- a/hw/intc/arm_gicv3_common.c
168
+++ b/hw/intc/arm_gicv3_common.c
169
@@ -XXX,XX +XXX,XX @@ static void arm_gicv3_common_reset_hold(Object *obj)
170
memset(cs->gicr_ipriorityr, 0, sizeof(cs->gicr_ipriorityr));
171
172
cs->hppi.prio = 0xff;
173
+ cs->hppi.nmi = false;
174
cs->hpplpi.prio = 0xff;
175
+ cs->hpplpi.nmi = false;
176
cs->hppvlpi.prio = 0xff;
177
+ cs->hppvlpi.nmi = false;
178
179
/* State in the CPU interface must *not* be reset here, because it
180
* is part of the CPU's reset domain, not the GIC device's.
181
diff --git a/hw/intc/arm_gicv3_redist.c b/hw/intc/arm_gicv3_redist.c
182
index XXXXXXX..XXXXXXX 100644
183
--- a/hw/intc/arm_gicv3_redist.c
184
+++ b/hw/intc/arm_gicv3_redist.c
185
@@ -XXX,XX +XXX,XX @@ static void update_for_one_lpi(GICv3CPUState *cs, int irq,
186
((prio == hpp->prio) && (irq <= hpp->irq))) {
187
hpp->irq = irq;
188
hpp->prio = prio;
189
+ hpp->nmi = false;
190
/* LPIs and vLPIs are always non-secure Grp1 interrupts */
191
hpp->grp = GICV3_G1NS;
192
}
193
@@ -XXX,XX +XXX,XX @@ static void update_for_all_lpis(GICv3CPUState *cs, uint64_t ptbase,
194
int i, bit;
195
196
hpp->prio = 0xff;
197
+ hpp->nmi = false;
198
199
for (i = GICV3_LPI_INTID_START / 8; i < pendt_size / 8; i++) {
200
address_space_read(as, ptbase + i, MEMTXATTRS_UNSPECIFIED, &pend, 1);
201
@@ -XXX,XX +XXX,XX @@ static void gicv3_redist_update_vlpi_only(GICv3CPUState *cs)
202
203
if (!FIELD_EX64(cs->gicr_vpendbaser, GICR_VPENDBASER, VALID)) {
204
cs->hppvlpi.prio = 0xff;
205
+ cs->hppvlpi.nmi = false;
206
return;
207
}
210
208
211
--
209
--
212
2.20.1
210
2.34.1
213
214
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Jinjie Ruan <ruanjinjie@huawei.com>
2
2
3
This is a bit clearer than open-coding some of this
3
In CPU Interface, if the IRQ has the non-maskable property, report NMI to
4
with a bare c string.
4
the corresponding PE.
5
5
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com>
7
Message-id: 20201021173749.111103-9-richard.henderson@linaro.org
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Message-id: 20240407081733.3231820-22-ruanjinjie@huawei.com
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
---
11
linux-user/elfload.c | 37 ++++++++++++++++++++-----------------
12
hw/intc/arm_gicv3_cpuif.c | 4 ++++
12
1 file changed, 20 insertions(+), 17 deletions(-)
13
1 file changed, 4 insertions(+)
13
14
14
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
15
diff --git a/hw/intc/arm_gicv3_cpuif.c b/hw/intc/arm_gicv3_cpuif.c
15
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
16
--- a/linux-user/elfload.c
17
--- a/hw/intc/arm_gicv3_cpuif.c
17
+++ b/linux-user/elfload.c
18
+++ b/hw/intc/arm_gicv3_cpuif.c
18
@@ -XXX,XX +XXX,XX @@
19
@@ -XXX,XX +XXX,XX @@ void gicv3_cpuif_update(GICv3CPUState *cs)
19
#include "qemu/guest-random.h"
20
/* Tell the CPU about its highest priority pending interrupt */
20
#include "qemu/units.h"
21
int irqlevel = 0;
21
#include "qemu/selfmap.h"
22
int fiqlevel = 0;
22
+#include "qapi/error.h"
23
+ int nmilevel = 0;
23
24
ARMCPU *cpu = ARM_CPU(cs->cpu);
24
#ifdef _ARCH_PPC64
25
CPUARMState *env = &cpu->env;
25
#undef ARCH_DLINFO
26
26
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
27
@@ -XXX,XX +XXX,XX @@ void gicv3_cpuif_update(GICv3CPUState *cs)
27
struct elf_phdr *phdr;
28
28
abi_ulong load_addr, load_bias, loaddr, hiaddr, error;
29
if (isfiq) {
29
int i, retval;
30
fiqlevel = 1;
30
- const char *errmsg;
31
+ } else if (cs->hppi.nmi) {
31
+ Error *err = NULL;
32
+ nmilevel = 1;
32
33
} else {
33
/* First of all, some simple consistency checks */
34
irqlevel = 1;
34
- errmsg = "Invalid ELF image for this architecture";
35
}
35
if (!elf_check_ident(ehdr)) {
36
@@ -XXX,XX +XXX,XX @@ void gicv3_cpuif_update(GICv3CPUState *cs)
36
+ error_setg(&err, "Invalid ELF image for this architecture");
37
37
goto exit_errmsg;
38
qemu_set_irq(cs->parent_fiq, fiqlevel);
38
}
39
qemu_set_irq(cs->parent_irq, irqlevel);
39
bswap_ehdr(ehdr);
40
+ qemu_set_irq(cs->parent_nmi, nmilevel);
40
if (!elf_check_ehdr(ehdr)) {
41
+ error_setg(&err, "Invalid ELF image for this architecture");
42
goto exit_errmsg;
43
}
44
45
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
46
g_autofree char *interp_name = NULL;
47
48
if (*pinterp_name) {
49
- errmsg = "Multiple PT_INTERP entries";
50
+ error_setg(&err, "Multiple PT_INTERP entries");
51
goto exit_errmsg;
52
}
53
+
54
interp_name = g_malloc(eppnt->p_filesz);
55
- if (!interp_name) {
56
- goto exit_perror;
57
- }
58
59
if (eppnt->p_offset + eppnt->p_filesz <= BPRM_BUF_SIZE) {
60
memcpy(interp_name, bprm_buf + eppnt->p_offset,
61
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
62
retval = pread(image_fd, interp_name, eppnt->p_filesz,
63
eppnt->p_offset);
64
if (retval != eppnt->p_filesz) {
65
- goto exit_perror;
66
+ goto exit_read;
67
}
68
}
69
if (interp_name[eppnt->p_filesz - 1] != 0) {
70
- errmsg = "Invalid PT_INTERP entry";
71
+ error_setg(&err, "Invalid PT_INTERP entry");
72
goto exit_errmsg;
73
}
74
*pinterp_name = g_steal_pointer(&interp_name);
75
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
76
(ehdr->e_type == ET_EXEC ? MAP_FIXED : 0),
77
-1, 0);
78
if (load_addr == -1) {
79
- goto exit_perror;
80
+ goto exit_mmap;
81
}
82
load_bias = load_addr - loaddr;
83
84
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
85
image_fd, eppnt->p_offset - vaddr_po);
86
87
if (error == -1) {
88
- goto exit_perror;
89
+ goto exit_mmap;
90
}
91
}
92
93
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
94
} else if (eppnt->p_type == PT_MIPS_ABIFLAGS) {
95
Mips_elf_abiflags_v0 abiflags;
96
if (eppnt->p_filesz < sizeof(Mips_elf_abiflags_v0)) {
97
- errmsg = "Invalid PT_MIPS_ABIFLAGS entry";
98
+ error_setg(&err, "Invalid PT_MIPS_ABIFLAGS entry");
99
goto exit_errmsg;
100
}
101
if (eppnt->p_offset + eppnt->p_filesz <= BPRM_BUF_SIZE) {
102
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
103
retval = pread(image_fd, &abiflags, sizeof(Mips_elf_abiflags_v0),
104
eppnt->p_offset);
105
if (retval != sizeof(Mips_elf_abiflags_v0)) {
106
- goto exit_perror;
107
+ goto exit_read;
108
}
109
}
110
bswap_mips_abiflags(&abiflags);
111
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
112
113
exit_read:
114
if (retval >= 0) {
115
- errmsg = "Incomplete read of file header";
116
- goto exit_errmsg;
117
+ error_setg(&err, "Incomplete read of file header");
118
+ } else {
119
+ error_setg_errno(&err, errno, "Error reading file header");
120
}
121
- exit_perror:
122
- errmsg = strerror(errno);
123
+ goto exit_errmsg;
124
+ exit_mmap:
125
+ error_setg_errno(&err, errno, "Error mapping file");
126
+ goto exit_errmsg;
127
exit_errmsg:
128
- fprintf(stderr, "%s: %s\n", image_name, errmsg);
129
+ error_reportf_err(err, "%s: ", image_name);
130
exit(-1);
131
}
41
}
132
42
43
static uint64_t icc_pmr_read(CPUARMState *env, const ARMCPRegInfo *ri)
133
--
44
--
134
2.20.1
45
2.34.1
135
136
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Jinjie Ruan <ruanjinjie@huawei.com>
2
2
3
This is slightly clearer than just using strerror, though
3
In vCPU Interface, if the vIRQ has the non-maskable property, report
4
the different forms produced by error_setg_file_open and
4
vINMI to the corresponding vPE.
5
error_setg_errno isn't entirely convenient.
6
5
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com>
8
Message-id: 20201021173749.111103-10-richard.henderson@linaro.org
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Message-id: 20240407081733.3231820-23-ruanjinjie@huawei.com
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
11
---
12
linux-user/elfload.c | 15 ++++++++-------
12
hw/intc/arm_gicv3_cpuif.c | 14 ++++++++++++--
13
1 file changed, 8 insertions(+), 7 deletions(-)
13
1 file changed, 12 insertions(+), 2 deletions(-)
14
14
15
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
15
diff --git a/hw/intc/arm_gicv3_cpuif.c b/hw/intc/arm_gicv3_cpuif.c
16
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
17
--- a/linux-user/elfload.c
17
--- a/hw/intc/arm_gicv3_cpuif.c
18
+++ b/linux-user/elfload.c
18
+++ b/hw/intc/arm_gicv3_cpuif.c
19
@@ -XXX,XX +XXX,XX @@ static void load_elf_interp(const char *filename, struct image_info *info,
19
@@ -XXX,XX +XXX,XX @@ void gicv3_cpuif_virt_irq_fiq_update(GICv3CPUState *cs)
20
char bprm_buf[BPRM_BUF_SIZE])
20
int idx;
21
{
21
int irqlevel = 0;
22
int fd, retval;
22
int fiqlevel = 0;
23
+ Error *err = NULL;
23
+ int nmilevel = 0;
24
24
25
fd = open(path(filename), O_RDONLY);
25
idx = hppvi_index(cs);
26
if (fd < 0) {
26
trace_gicv3_cpuif_virt_update(gicv3_redist_affid(cs), idx,
27
- goto exit_perror;
27
@@ -XXX,XX +XXX,XX @@ void gicv3_cpuif_virt_irq_fiq_update(GICv3CPUState *cs)
28
+ error_setg_file_open(&err, errno, filename);
28
uint64_t lr = cs->ich_lr_el2[idx];
29
+ error_report_err(err);
29
30
+ exit(-1);
30
if (icv_hppi_can_preempt(cs, lr)) {
31
}
31
- /* Virtual interrupts are simple: G0 are always FIQ, and G1 IRQ */
32
32
+ /*
33
retval = read(fd, bprm_buf, BPRM_BUF_SIZE);
33
+ * Virtual interrupts are simple: G0 are always FIQ, and G1 are
34
if (retval < 0) {
34
+ * IRQ or NMI which depends on the ICH_LR<n>_EL2.NMI to have
35
- goto exit_perror;
35
+ * non-maskable property.
36
+ error_setg_errno(&err, errno, "Error reading file header");
36
+ */
37
+ error_reportf_err(err, "%s: ", filename);
37
if (lr & ICH_LR_EL2_GROUP) {
38
+ exit(-1);
38
- irqlevel = 1;
39
}
39
+ if (lr & ICH_LR_EL2_NMI) {
40
+
40
+ nmilevel = 1;
41
if (retval < BPRM_BUF_SIZE) {
41
+ } else {
42
memset(bprm_buf + retval, 0, BPRM_BUF_SIZE - retval);
42
+ irqlevel = 1;
43
}
43
+ }
44
44
} else {
45
load_elf_image(filename, fd, info, NULL, bprm_buf);
45
fiqlevel = 1;
46
- return;
46
}
47
-
47
@@ -XXX,XX +XXX,XX @@ void gicv3_cpuif_virt_irq_fiq_update(GICv3CPUState *cs)
48
- exit_perror:
48
trace_gicv3_cpuif_virt_set_irqs(gicv3_redist_affid(cs), fiqlevel, irqlevel);
49
- fprintf(stderr, "%s: %s\n", filename, strerror(errno));
49
qemu_set_irq(cs->parent_vfiq, fiqlevel);
50
- exit(-1);
50
qemu_set_irq(cs->parent_virq, irqlevel);
51
+ qemu_set_irq(cs->parent_vnmi, nmilevel);
51
}
52
}
52
53
53
static int symfind(const void *s0, const void *s1)
54
static void gicv3_cpuif_virt_update(GICv3CPUState *cs)
54
--
55
--
55
2.20.1
56
2.34.1
56
57
diff view generated by jsdifflib
1
From: Luc Michel <luc@lmichel.fr>
1
From: Jinjie Ruan <ruanjinjie@huawei.com>
2
2
3
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
3
Enable FEAT_NMI on the 'max' CPU.
4
Reviewed-by: Damien Hedde <damien.hedde@greensocs.com>
4
5
Signed-off-by: Luc Michel <luc@lmichel.fr>
5
Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com>
6
Tested-by: Guenter Roeck <linux@roeck-us.net>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Message-id: 20240407081733.3231820-24-ruanjinjie@huawei.com
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
---
10
include/hw/clock.h | 5 +++++
11
docs/system/arm/emulation.rst | 1 +
11
1 file changed, 5 insertions(+)
12
target/arm/tcg/cpu64.c | 1 +
13
2 files changed, 2 insertions(+)
12
14
13
diff --git a/include/hw/clock.h b/include/hw/clock.h
15
diff --git a/docs/system/arm/emulation.rst b/docs/system/arm/emulation.rst
14
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
15
--- a/include/hw/clock.h
17
--- a/docs/system/arm/emulation.rst
16
+++ b/include/hw/clock.h
18
+++ b/docs/system/arm/emulation.rst
17
@@ -XXX,XX +XXX,XX @@ extern const VMStateDescription vmstate_clock;
19
@@ -XXX,XX +XXX,XX @@ the following architecture extensions:
18
VMSTATE_CLOCK_V(field, state, 0)
20
- FEAT_MTE (Memory Tagging Extension)
19
#define VMSTATE_CLOCK_V(field, state, version) \
21
- FEAT_MTE2 (Memory Tagging Extension)
20
VMSTATE_STRUCT_POINTER_V(field, state, version, vmstate_clock, Clock)
22
- FEAT_MTE3 (MTE Asymmetric Fault Handling)
21
+#define VMSTATE_ARRAY_CLOCK(field, state, num) \
23
+- FEAT_NMI (Non-maskable Interrupt)
22
+ VMSTATE_ARRAY_CLOCK_V(field, state, num, 0)
24
- FEAT_NV (Nested Virtualization)
23
+#define VMSTATE_ARRAY_CLOCK_V(field, state, num, version) \
25
- FEAT_NV2 (Enhanced nested virtualization support)
24
+ VMSTATE_ARRAY_OF_POINTER_TO_STRUCT(field, state, num, version, \
26
- FEAT_PACIMP (Pointer authentication - IMPLEMENTATION DEFINED algorithm)
25
+ vmstate_clock, Clock)
27
diff --git a/target/arm/tcg/cpu64.c b/target/arm/tcg/cpu64.c
26
28
index XXXXXXX..XXXXXXX 100644
27
/**
29
--- a/target/arm/tcg/cpu64.c
28
* clock_setup_canonical_path:
30
+++ b/target/arm/tcg/cpu64.c
31
@@ -XXX,XX +XXX,XX @@ void aarch64_max_tcg_initfn(Object *obj)
32
t = FIELD_DP64(t, ID_AA64PFR1, RAS_FRAC, 0); /* FEAT_RASv1p1 + FEAT_DoubleFault */
33
t = FIELD_DP64(t, ID_AA64PFR1, SME, 1); /* FEAT_SME */
34
t = FIELD_DP64(t, ID_AA64PFR1, CSV2_FRAC, 0); /* FEAT_CSV2_2 */
35
+ t = FIELD_DP64(t, ID_AA64PFR1, NMI, 1); /* FEAT_NMI */
36
cpu->isar.id_aa64pfr1 = t;
37
38
t = cpu->isar.id_aa64mmfr0;
29
--
39
--
30
2.20.1
40
2.34.1
31
32
diff view generated by jsdifflib
1
From: Luc Michel <luc@lmichel.fr>
1
From: Jinjie Ruan <ruanjinjie@huawei.com>
2
2
3
This simple mux sits between the PLL channels and the DSI0E and DSI0P
3
If the CPU implements FEAT_NMI, then turn on the NMI support in the
4
clock muxes. This mux selects between PLLA-DSI0 and PLLD-DSI0 channel
4
GICv3 too. It's permitted to have a configuration with FEAT_NMI in
5
and outputs the selected signal to source number 4 of DSI0E/P clock
5
the CPU (and thus NMI support in the CPU interfaces too) but no NMI
6
muxes. It is controlled by the cm_dsi0hsck register.
6
support in the distributor and redistributor, but this isn't a very
7
useful setup as it's close to having no NMI support at all.
7
8
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
We don't need to gate the enabling of NMI in the GIC behind a
9
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
machine version property, because none of our current CPUs
10
Signed-off-by: Luc Michel <luc@lmichel.fr>
11
implement FEAT_NMI, and '-cpu max' is not something we maintain
11
Tested-by: Guenter Roeck <linux@roeck-us.net>
12
migration compatibility across versions for. So we can always
13
enable the GIC NMI support when the CPU has it.
14
15
Neither hvf nor KVM support NMI in the GIC yet, so we don't enable
16
it unless we're using TCG.
17
18
Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com>
19
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
20
Message-id: 20240407081733.3231820-25-ruanjinjie@huawei.com
21
[PMM: Update comment and commit message]
22
Suggested-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
23
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
24
---
14
include/hw/misc/bcm2835_cprman.h | 15 +++++
25
hw/arm/virt.c | 19 +++++++++++++++++++
15
include/hw/misc/bcm2835_cprman_internals.h | 6 ++
26
1 file changed, 19 insertions(+)
16
hw/misc/bcm2835_cprman.c | 74 +++++++++++++++++++++-
17
3 files changed, 94 insertions(+), 1 deletion(-)
18
27
19
diff --git a/include/hw/misc/bcm2835_cprman.h b/include/hw/misc/bcm2835_cprman.h
28
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
20
index XXXXXXX..XXXXXXX 100644
29
index XXXXXXX..XXXXXXX 100644
21
--- a/include/hw/misc/bcm2835_cprman.h
30
--- a/hw/arm/virt.c
22
+++ b/include/hw/misc/bcm2835_cprman.h
31
+++ b/hw/arm/virt.c
23
@@ -XXX,XX +XXX,XX @@ typedef struct CprmanClockMuxState {
32
@@ -XXX,XX +XXX,XX @@ static void create_v2m(VirtMachineState *vms)
24
struct CprmanClockMuxState *backref[CPRMAN_NUM_CLOCK_MUX_SRC];
33
vms->msi_controller = VIRT_MSI_CTRL_GICV2M;
25
} CprmanClockMuxState;
34
}
26
35
27
+typedef struct CprmanDsi0HsckMuxState {
36
+/*
28
+ /*< private >*/
37
+ * If the CPU has FEAT_NMI, then turn on the NMI support in the GICv3 too.
29
+ DeviceState parent_obj;
38
+ * It's permitted to have a configuration with NMI in the CPU (and thus the
39
+ * GICv3 CPU interface) but not in the distributor/redistributors, but it's
40
+ * not very useful.
41
+ */
42
+static bool gicv3_nmi_present(VirtMachineState *vms)
43
+{
44
+ ARMCPU *cpu = ARM_CPU(qemu_get_cpu(0));
30
+
45
+
31
+ /*< public >*/
46
+ return tcg_enabled() && cpu_isar_feature(aa64_nmi, cpu) &&
32
+ CprmanClockMux id;
47
+ (vms->gic_version != VIRT_GIC_VERSION_2);
33
+
34
+ uint32_t *reg_cm;
35
+
36
+ Clock *plla_in;
37
+ Clock *plld_in;
38
+ Clock *out;
39
+} CprmanDsi0HsckMuxState;
40
+
41
struct BCM2835CprmanState {
42
/*< private >*/
43
SysBusDevice parent_obj;
44
@@ -XXX,XX +XXX,XX @@ struct BCM2835CprmanState {
45
CprmanPllState plls[CPRMAN_NUM_PLL];
46
CprmanPllChannelState channels[CPRMAN_NUM_PLL_CHANNEL];
47
CprmanClockMuxState clock_muxes[CPRMAN_NUM_CLOCK_MUX];
48
+ CprmanDsi0HsckMuxState dsi0hsck_mux;
49
50
uint32_t regs[CPRMAN_NUM_REGS];
51
uint32_t xosc_freq;
52
diff --git a/include/hw/misc/bcm2835_cprman_internals.h b/include/hw/misc/bcm2835_cprman_internals.h
53
index XXXXXXX..XXXXXXX 100644
54
--- a/include/hw/misc/bcm2835_cprman_internals.h
55
+++ b/include/hw/misc/bcm2835_cprman_internals.h
56
@@ -XXX,XX +XXX,XX @@
57
#define TYPE_CPRMAN_PLL "bcm2835-cprman-pll"
58
#define TYPE_CPRMAN_PLL_CHANNEL "bcm2835-cprman-pll-channel"
59
#define TYPE_CPRMAN_CLOCK_MUX "bcm2835-cprman-clock-mux"
60
+#define TYPE_CPRMAN_DSI0HSCK_MUX "bcm2835-cprman-dsi0hsck-mux"
61
62
DECLARE_INSTANCE_CHECKER(CprmanPllState, CPRMAN_PLL,
63
TYPE_CPRMAN_PLL)
64
@@ -XXX,XX +XXX,XX @@ DECLARE_INSTANCE_CHECKER(CprmanPllChannelState, CPRMAN_PLL_CHANNEL,
65
TYPE_CPRMAN_PLL_CHANNEL)
66
DECLARE_INSTANCE_CHECKER(CprmanClockMuxState, CPRMAN_CLOCK_MUX,
67
TYPE_CPRMAN_CLOCK_MUX)
68
+DECLARE_INSTANCE_CHECKER(CprmanDsi0HsckMuxState, CPRMAN_DSI0HSCK_MUX,
69
+ TYPE_CPRMAN_DSI0HSCK_MUX)
70
71
/* Register map */
72
73
@@ -XXX,XX +XXX,XX @@ REG32(CM_LOCK, 0x114)
74
FIELD(CM_LOCK, FLOCKB, 9, 1)
75
FIELD(CM_LOCK, FLOCKA, 8, 1)
76
77
+REG32(CM_DSI0HSCK, 0x120)
78
+ FIELD(CM_DSI0HSCK, SELPLLD, 0, 1)
79
+
80
/*
81
* This field is common to all registers. Each register write value must match
82
* the CPRMAN_PASSWORD magic value in its 8 MSB.
83
diff --git a/hw/misc/bcm2835_cprman.c b/hw/misc/bcm2835_cprman.c
84
index XXXXXXX..XXXXXXX 100644
85
--- a/hw/misc/bcm2835_cprman.c
86
+++ b/hw/misc/bcm2835_cprman.c
87
@@ -XXX,XX +XXX,XX @@ static const TypeInfo cprman_clock_mux_info = {
88
};
89
90
91
+/* DSI0HSCK mux */
92
+
93
+static void dsi0hsck_mux_update(CprmanDsi0HsckMuxState *s)
94
+{
95
+ bool src_is_plld = FIELD_EX32(*s->reg_cm, CM_DSI0HSCK, SELPLLD);
96
+ Clock *src = src_is_plld ? s->plld_in : s->plla_in;
97
+
98
+ clock_update(s->out, clock_get(src));
99
+}
48
+}
100
+
49
+
101
+static void dsi0hsck_mux_in_update(void *opaque)
50
static void create_gic(VirtMachineState *vms, MemoryRegion *mem)
102
+{
51
{
103
+ dsi0hsck_mux_update(CPRMAN_DSI0HSCK_MUX(opaque));
52
MachineState *ms = MACHINE(vms);
104
+}
53
@@ -XXX,XX +XXX,XX @@ static void create_gic(VirtMachineState *vms, MemoryRegion *mem)
105
+
54
vms->virt);
106
+static void dsi0hsck_mux_init(Object *obj)
107
+{
108
+ CprmanDsi0HsckMuxState *s = CPRMAN_DSI0HSCK_MUX(obj);
109
+ DeviceState *dev = DEVICE(obj);
110
+
111
+ s->plla_in = qdev_init_clock_in(dev, "plla-in", dsi0hsck_mux_in_update, s);
112
+ s->plld_in = qdev_init_clock_in(dev, "plld-in", dsi0hsck_mux_in_update, s);
113
+ s->out = qdev_init_clock_out(DEVICE(s), "out");
114
+}
115
+
116
+static const VMStateDescription dsi0hsck_mux_vmstate = {
117
+ .name = TYPE_CPRMAN_DSI0HSCK_MUX,
118
+ .version_id = 1,
119
+ .minimum_version_id = 1,
120
+ .fields = (VMStateField[]) {
121
+ VMSTATE_CLOCK(plla_in, CprmanDsi0HsckMuxState),
122
+ VMSTATE_CLOCK(plld_in, CprmanDsi0HsckMuxState),
123
+ VMSTATE_END_OF_LIST()
124
+ }
125
+};
126
+
127
+static void dsi0hsck_mux_class_init(ObjectClass *klass, void *data)
128
+{
129
+ DeviceClass *dc = DEVICE_CLASS(klass);
130
+
131
+ dc->vmsd = &dsi0hsck_mux_vmstate;
132
+}
133
+
134
+static const TypeInfo cprman_dsi0hsck_mux_info = {
135
+ .name = TYPE_CPRMAN_DSI0HSCK_MUX,
136
+ .parent = TYPE_DEVICE,
137
+ .instance_size = sizeof(CprmanDsi0HsckMuxState),
138
+ .class_init = dsi0hsck_mux_class_init,
139
+ .instance_init = dsi0hsck_mux_init,
140
+};
141
+
142
+
143
/* CPRMAN "top level" model */
144
145
static uint32_t get_cm_lock(const BCM2835CprmanState *s)
146
@@ -XXX,XX +XXX,XX @@ static void cprman_write(void *opaque, hwaddr offset,
147
case R_CM_EMMC2CTL ... R_CM_EMMC2DIV:
148
update_mux_from_cm(s, idx);
149
break;
150
+
151
+ case R_CM_DSI0HSCK:
152
+ dsi0hsck_mux_update(&s->dsi0hsck_mux);
153
+ break;
154
}
155
}
156
157
@@ -XXX,XX +XXX,XX @@ static void cprman_reset(DeviceState *dev)
158
device_cold_reset(DEVICE(&s->channels[i]));
159
}
160
161
+ device_cold_reset(DEVICE(&s->dsi0hsck_mux));
162
+
163
for (i = 0; i < CPRMAN_NUM_CLOCK_MUX; i++) {
164
device_cold_reset(DEVICE(&s->clock_muxes[i]));
165
}
166
@@ -XXX,XX +XXX,XX @@ static void cprman_init(Object *obj)
167
set_pll_channel_init_info(s, &s->channels[i], i);
168
}
169
170
+ object_initialize_child(obj, "dsi0hsck-mux",
171
+ &s->dsi0hsck_mux, TYPE_CPRMAN_DSI0HSCK_MUX);
172
+ s->dsi0hsck_mux.reg_cm = &s->regs[R_CM_DSI0HSCK];
173
+
174
for (i = 0; i < CPRMAN_NUM_CLOCK_MUX; i++) {
175
char *alias;
176
177
@@ -XXX,XX +XXX,XX @@ static void connect_mux_sources(BCM2835CprmanState *s,
178
if (mapping == CPRMAN_CLOCK_SRC_FORCE_GROUND) {
179
src = s->gnd;
180
} else if (mapping == CPRMAN_CLOCK_SRC_DSI0HSCK) {
181
- src = s->gnd; /* TODO */
182
+ src = s->dsi0hsck_mux.out;
183
} else if (i < CPRMAN_CLOCK_SRC_PLLA) {
184
src = CLK_SRC_MAPPING[i];
185
} else {
186
@@ -XXX,XX +XXX,XX @@ static void cprman_realize(DeviceState *dev, Error **errp)
187
}
55
}
188
}
56
}
189
190
+ clock_set_source(s->dsi0hsck_mux.plla_in,
191
+ s->channels[CPRMAN_PLLA_CHANNEL_DSI0].out);
192
+ clock_set_source(s->dsi0hsck_mux.plld_in,
193
+ s->channels[CPRMAN_PLLD_CHANNEL_DSI0].out);
194
+
57
+
195
+ if (!qdev_realize(DEVICE(&s->dsi0hsck_mux), NULL, errp)) {
58
+ if (gicv3_nmi_present(vms)) {
196
+ return;
59
+ qdev_prop_set_bit(vms->gic, "has-nmi", true);
197
+ }
60
+ }
198
+
61
+
199
for (i = 0; i < CPRMAN_NUM_CLOCK_MUX; i++) {
62
gicbusdev = SYS_BUS_DEVICE(vms->gic);
200
CprmanClockMuxState *clock_mux = &s->clock_muxes[i];
63
sysbus_realize_and_unref(gicbusdev, &error_fatal);
201
64
sysbus_mmio_map(gicbusdev, 0, vms->memmap[VIRT_GIC_DIST].base);
202
@@ -XXX,XX +XXX,XX @@ static void cprman_register_types(void)
203
type_register_static(&cprman_pll_info);
204
type_register_static(&cprman_pll_channel_info);
205
type_register_static(&cprman_clock_mux_info);
206
+ type_register_static(&cprman_dsi0hsck_mux_info);
207
}
208
209
type_init(cprman_register_types);
210
--
65
--
211
2.20.1
66
2.34.1
212
213
diff view generated by jsdifflib
1
From: Thomas Huth <thuth@redhat.com>
1
From: Anastasia Belova <abelova@astralinux.ru>
2
2
3
When compiling with -Werror=implicit-fallthrough, gcc complains about
3
In soc_dma_set_request() we try to set a bit in a uint64_t, but we
4
missing fallthrough annotations in this file. Looking at the code,
4
do it with "1 << ch->num", which can't set any bits past 31;
5
the fallthrough is very likely intended here, so add some comments
5
any use for a channel number of 32 or more would fail due to
6
to silence the compiler warnings.
6
integer overflow.
7
7
8
Signed-off-by: Thomas Huth <thuth@redhat.com>
8
This doesn't happen in practice for our current use of this code,
9
Message-id: 20201020105938.23209-1-thuth@redhat.com
9
because the worst case is when we call soc_dma_init() with an
10
argument of 32 for the number of channels, and QEMU builds with
11
-fwrapv so the shift into the sign bit is well-defined. However,
12
it's obviously not the intended behaviour of the code.
13
14
Add casts to force the shift to be done as 64-bit arithmetic,
15
allowing up to 64 channels.
16
17
Found by Linux Verification Center (linuxtesting.org) with SVACE.
18
19
Fixes: afbb5194d4 ("Handle on-chip DMA controllers in one place, convert OMAP DMA to use it.")
20
Signed-off-by: Anastasia Belova <abelova@astralinux.ru>
21
Message-id: 20240409115301.21829-1-abelova@astralinux.ru
22
[PMM: Edit commit message to clarify that this doesn't actually
23
bite us in our current usage of this code.]
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
24
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
25
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
26
---
13
hw/arm/highbank.c | 2 ++
27
hw/dma/soc_dma.c | 4 ++--
14
1 file changed, 2 insertions(+)
28
1 file changed, 2 insertions(+), 2 deletions(-)
15
29
16
diff --git a/hw/arm/highbank.c b/hw/arm/highbank.c
30
diff --git a/hw/dma/soc_dma.c b/hw/dma/soc_dma.c
17
index XXXXXXX..XXXXXXX 100644
31
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/arm/highbank.c
32
--- a/hw/dma/soc_dma.c
19
+++ b/hw/arm/highbank.c
33
+++ b/hw/dma/soc_dma.c
20
@@ -XXX,XX +XXX,XX @@ static void hb_reset_secondary(ARMCPU *cpu, const struct arm_boot_info *info)
34
@@ -XXX,XX +XXX,XX @@ void soc_dma_set_request(struct soc_dma_ch_s *ch, int level)
21
address_space_stl_notdirty(&address_space_memory,
35
dma->enabled_count += level - ch->enable;
22
SMP_BOOT_REG + 0x30, 0,
36
23
MEMTXATTRS_UNSPECIFIED, NULL);
37
if (level)
24
+ /* fallthrough */
38
- dma->ch_enable_mask |= 1 << ch->num;
25
case 3:
39
+ dma->ch_enable_mask |= (uint64_t)1 << ch->num;
26
address_space_stl_notdirty(&address_space_memory,
40
else
27
SMP_BOOT_REG + 0x20, 0,
41
- dma->ch_enable_mask &= ~(1 << ch->num);
28
MEMTXATTRS_UNSPECIFIED, NULL);
42
+ dma->ch_enable_mask &= ~((uint64_t)1 << ch->num);
29
+ /* fallthrough */
43
30
case 2:
44
if (level != ch->enable) {
31
address_space_stl_notdirty(&address_space_memory,
45
soc_dma_ch_freq_update(dma);
32
SMP_BOOT_REG + 0x10, 0,
33
--
46
--
34
2.20.1
47
2.34.1
35
36
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
Ever since the bFLT format support was added in 2006, there has been
2
2
a chunk of code in the file guarded by CONFIG_BINFMT_SHARED_FLAT
3
The Pi 3A+ is a stripped down version of the 3B:
3
which is supposedly for shared library support. This is not enabled
4
- 512 MiB of RAM instead of 1 GiB
4
and it's not possible to enable it, because if you do you'll run into
5
- no on-board ethernet chipset
5
the "#error needs checking" in the calc_reloc() function.
6
6
7
Add it as it is a closer match to what we model.
7
Similarly, CONFIG_BINFMT_ZFLAT exists but can't be enabled because of
8
8
an "#error code needs checking" in load_flat_file().
9
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
9
10
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
This code is obviously unfinished and has never been used; nobody in
11
Message-id: 20201024170127.3592182-10-f4bug@amsat.org
11
the intervening 18 years has complained about this or fixed it, so
12
just delete the dead code. If anybody ever wants the feature they
13
can always pull it out of git, or (perhaps better) write it from
14
scratch based on the current Linux bFLT loader rather than the one of
15
18 years ago.
16
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
19
Message-id: 20240411115313.680433-1-peter.maydell@linaro.org
13
---
20
---
14
hw/arm/raspi.c | 13 +++++++++++++
21
linux-user/flat.h | 5 +-
15
1 file changed, 13 insertions(+)
22
linux-user/flatload.c | 293 ++----------------------------------------
16
23
2 files changed, 11 insertions(+), 287 deletions(-)
17
diff --git a/hw/arm/raspi.c b/hw/arm/raspi.c
24
25
diff --git a/linux-user/flat.h b/linux-user/flat.h
18
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/arm/raspi.c
27
--- a/linux-user/flat.h
20
+++ b/hw/arm/raspi.c
28
+++ b/linux-user/flat.h
21
@@ -XXX,XX +XXX,XX @@ static void raspi2b_machine_class_init(ObjectClass *oc, void *data)
29
@@ -XXX,XX +XXX,XX @@
30
31
#define    FLAT_VERSION            0x00000004L
32
33
-#ifdef CONFIG_BINFMT_SHARED_FLAT
34
-#define    MAX_SHARED_LIBS            (4)
35
-#else
36
+/* QEMU doesn't support bflt shared libraries */
37
#define    MAX_SHARED_LIBS            (1)
38
-#endif
39
40
/*
41
* To make everything easier to port and manage cross platform
42
diff --git a/linux-user/flatload.c b/linux-user/flatload.c
43
index XXXXXXX..XXXXXXX 100644
44
--- a/linux-user/flatload.c
45
+++ b/linux-user/flatload.c
46
@@ -XXX,XX +XXX,XX @@
47
*    JAN/99 -- coded full program relocation (gerg@snapgear.com)
48
*/
49
50
-/* ??? ZFLAT and shared library support is currently disabled. */
51
-
52
/****************************************************************************/
53
54
#include "qemu/osdep.h"
55
@@ -XXX,XX +XXX,XX @@ struct lib_info {
56
short loaded;        /* Has this library been loaded? */
22
};
57
};
23
58
24
#ifdef TARGET_AARCH64
59
-#ifdef CONFIG_BINFMT_SHARED_FLAT
25
+static void raspi3ap_machine_class_init(ObjectClass *oc, void *data)
60
-static int load_flat_shared_library(int id, struct lib_info *p);
26
+{
61
-#endif
27
+ MachineClass *mc = MACHINE_CLASS(oc);
62
-
28
+ RaspiMachineClass *rmc = RASPI_MACHINE_CLASS(oc);
63
struct linux_binprm;
29
+
64
30
+ rmc->board_rev = 0x9020e0; /* Revision 1.0 */
65
/****************************************************************************/
31
+ raspi_machine_class_common_init(mc, rmc->board_rev);
66
@@ -XXX,XX +XXX,XX @@ static int target_pread(int fd, abi_ulong ptr, abi_ulong len,
32
+};
67
unlock_user(buf, ptr, len);
33
+
68
return ret;
34
static void raspi3b_machine_class_init(ObjectClass *oc, void *data)
69
}
70
-/****************************************************************************/
71
-
72
-#ifdef CONFIG_BINFMT_ZFLAT
73
-
74
-#include <linux/zlib.h>
75
-
76
-#define LBUFSIZE    4000
77
-
78
-/* gzip flag byte */
79
-#define ASCII_FLAG 0x01 /* bit 0 set: file probably ASCII text */
80
-#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */
81
-#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */
82
-#define ORIG_NAME 0x08 /* bit 3 set: original file name present */
83
-#define COMMENT 0x10 /* bit 4 set: file comment present */
84
-#define ENCRYPTED 0x20 /* bit 5 set: file is encrypted */
85
-#define RESERVED 0xC0 /* bit 6,7: reserved */
86
-
87
-static int decompress_exec(
88
-    struct linux_binprm *bprm,
89
-    unsigned long offset,
90
-    char *dst,
91
-    long len,
92
-    int fd)
93
-{
94
-    unsigned char *buf;
95
-    z_stream strm;
96
-    loff_t fpos;
97
-    int ret, retval;
98
-
99
-    DBG_FLT("decompress_exec(offset=%x,buf=%x,len=%x)\n",(int)offset, (int)dst, (int)len);
100
-
101
-    memset(&strm, 0, sizeof(strm));
102
-    strm.workspace = kmalloc(zlib_inflate_workspacesize(), GFP_KERNEL);
103
-    if (strm.workspace == NULL) {
104
-        DBG_FLT("binfmt_flat: no memory for decompress workspace\n");
105
-        return -ENOMEM;
106
-    }
107
-    buf = kmalloc(LBUFSIZE, GFP_KERNEL);
108
-    if (buf == NULL) {
109
-        DBG_FLT("binfmt_flat: no memory for read buffer\n");
110
-        retval = -ENOMEM;
111
-        goto out_free;
112
-    }
113
-
114
-    /* Read in first chunk of data and parse gzip header. */
115
-    fpos = offset;
116
-    ret = bprm->file->f_op->read(bprm->file, buf, LBUFSIZE, &fpos);
117
-
118
-    strm.next_in = buf;
119
-    strm.avail_in = ret;
120
-    strm.total_in = 0;
121
-
122
-    retval = -ENOEXEC;
123
-
124
-    /* Check minimum size -- gzip header */
125
-    if (ret < 10) {
126
-        DBG_FLT("binfmt_flat: file too small?\n");
127
-        goto out_free_buf;
128
-    }
129
-
130
-    /* Check gzip magic number */
131
-    if ((buf[0] != 037) || ((buf[1] != 0213) && (buf[1] != 0236))) {
132
-        DBG_FLT("binfmt_flat: unknown compression magic?\n");
133
-        goto out_free_buf;
134
-    }
135
-
136
-    /* Check gzip method */
137
-    if (buf[2] != 8) {
138
-        DBG_FLT("binfmt_flat: unknown compression method?\n");
139
-        goto out_free_buf;
140
-    }
141
-    /* Check gzip flags */
142
-    if ((buf[3] & ENCRYPTED) || (buf[3] & CONTINUATION) ||
143
-     (buf[3] & RESERVED)) {
144
-        DBG_FLT("binfmt_flat: unknown flags?\n");
145
-        goto out_free_buf;
146
-    }
147
-
148
-    ret = 10;
149
-    if (buf[3] & EXTRA_FIELD) {
150
-        ret += 2 + buf[10] + (buf[11] << 8);
151
-        if (unlikely(LBUFSIZE == ret)) {
152
-            DBG_FLT("binfmt_flat: buffer overflow (EXTRA)?\n");
153
-            goto out_free_buf;
154
-        }
155
-    }
156
-    if (buf[3] & ORIG_NAME) {
157
-        for (; ret < LBUFSIZE && (buf[ret] != 0); ret++)
158
-            ;
159
-        if (unlikely(LBUFSIZE == ret)) {
160
-            DBG_FLT("binfmt_flat: buffer overflow (ORIG_NAME)?\n");
161
-            goto out_free_buf;
162
-        }
163
-    }
164
-    if (buf[3] & COMMENT) {
165
-        for (; ret < LBUFSIZE && (buf[ret] != 0); ret++)
166
-            ;
167
-        if (unlikely(LBUFSIZE == ret)) {
168
-            DBG_FLT("binfmt_flat: buffer overflow (COMMENT)?\n");
169
-            goto out_free_buf;
170
-        }
171
-    }
172
-
173
-    strm.next_in += ret;
174
-    strm.avail_in -= ret;
175
-
176
-    strm.next_out = dst;
177
-    strm.avail_out = len;
178
-    strm.total_out = 0;
179
-
180
-    if (zlib_inflateInit2(&strm, -MAX_WBITS) != Z_OK) {
181
-        DBG_FLT("binfmt_flat: zlib init failed?\n");
182
-        goto out_free_buf;
183
-    }
184
-
185
-    while ((ret = zlib_inflate(&strm, Z_NO_FLUSH)) == Z_OK) {
186
-        ret = bprm->file->f_op->read(bprm->file, buf, LBUFSIZE, &fpos);
187
-        if (ret <= 0)
188
-            break;
189
- if (is_error(ret)) {
190
-            break;
191
- }
192
-        len -= ret;
193
-
194
-        strm.next_in = buf;
195
-        strm.avail_in = ret;
196
-        strm.total_in = 0;
197
-    }
198
-
199
-    if (ret < 0) {
200
-        DBG_FLT("binfmt_flat: decompression failed (%d), %s\n",
201
-            ret, strm.msg);
202
-        goto out_zlib;
203
-    }
204
-
205
-    retval = 0;
206
-out_zlib:
207
-    zlib_inflateEnd(&strm);
208
-out_free_buf:
209
-    kfree(buf);
210
-out_free:
211
-    kfree(strm.workspace);
212
-out:
213
-    return retval;
214
-}
215
-
216
-#endif /* CONFIG_BINFMT_ZFLAT */
217
218
/****************************************************************************/
219
220
@@ -XXX,XX +XXX,XX @@ calc_reloc(abi_ulong r, struct lib_info *p, int curid, int internalp)
221
abi_ulong text_len;
222
abi_ulong start_code;
223
224
-#ifdef CONFIG_BINFMT_SHARED_FLAT
225
-#error needs checking
226
- if (r == 0)
227
- id = curid;    /* Relocs of 0 are always self referring */
228
- else {
229
- id = (r >> 24) & 0xff;    /* Find ID for this reloc */
230
- r &= 0x00ffffff;    /* Trim ID off here */
231
- }
232
- if (id >= MAX_SHARED_LIBS) {
233
- fprintf(stderr, "BINFMT_FLAT: reference 0x%x to shared library %d\n",
234
- (unsigned) r, id);
235
- goto failed;
236
- }
237
- if (curid != id) {
238
- if (internalp) {
239
- fprintf(stderr, "BINFMT_FLAT: reloc address 0x%x not "
240
- "in same module (%d != %d)\n",
241
- (unsigned) r, curid, id);
242
- goto failed;
243
- } else if (!p[id].loaded && is_error(load_flat_shared_library(id, p))) {
244
- fprintf(stderr, "BINFMT_FLAT: failed to load library %d\n", id);
245
- goto failed;
246
- }
247
- /* Check versioning information (i.e. time stamps) */
248
- if (p[id].build_date && p[curid].build_date
249
- && p[curid].build_date < p[id].build_date) {
250
- fprintf(stderr, "BINFMT_FLAT: library %d is younger than %d\n",
251
- id, curid);
252
- goto failed;
253
- }
254
- }
255
-#else
256
id = 0;
257
-#endif
258
259
start_brk = p[id].start_brk;
260
start_data = p[id].start_data;
261
@@ -XXX,XX +XXX,XX @@ static int load_flat_file(struct linux_binprm * bprm,
262
if (rev == OLD_FLAT_VERSION && flat_old_ram_flag(flags))
263
flags = FLAT_FLAG_RAM;
264
265
-#ifndef CONFIG_BINFMT_ZFLAT
266
if (flags & (FLAT_FLAG_GZIP|FLAT_FLAG_GZDATA)) {
267
- fprintf(stderr, "Support for ZFLAT executables is not enabled\n");
268
+ fprintf(stderr, "ZFLAT executables are not supported\n");
269
return -ENOEXEC;
270
}
271
-#endif
272
273
/*
274
* calculate the extra space we need to map in
275
@@ -XXX,XX +XXX,XX @@ static int load_flat_file(struct linux_binprm * bprm,
276
(int)(data_len + bss_len + stack_len), (int)datapos);
277
278
fpos = ntohl(hdr->data_start);
279
-#ifdef CONFIG_BINFMT_ZFLAT
280
- if (flags & FLAT_FLAG_GZDATA) {
281
- result = decompress_exec(bprm, fpos, (char *) datapos,
282
- data_len + (relocs * sizeof(abi_ulong)))
283
- } else
284
-#endif
285
- {
286
- result = target_pread(bprm->src.fd, datapos,
287
- data_len + (relocs * sizeof(abi_ulong)),
288
- fpos);
289
- }
290
+ result = target_pread(bprm->src.fd, datapos,
291
+ data_len + (relocs * sizeof(abi_ulong)),
292
+ fpos);
293
if (result < 0) {
294
fprintf(stderr, "Unable to read data+bss\n");
295
return result;
296
@@ -XXX,XX +XXX,XX @@ static int load_flat_file(struct linux_binprm * bprm,
297
datapos = realdatastart + indx_len;
298
reloc = (textpos + ntohl(hdr->reloc_start) + indx_len);
299
300
-#ifdef CONFIG_BINFMT_ZFLAT
301
-#error code needs checking
302
- /*
303
- * load it all in and treat it like a RAM load from now on
304
- */
305
- if (flags & FLAT_FLAG_GZIP) {
306
- result = decompress_exec(bprm, sizeof (struct flat_hdr),
307
- (((char *) textpos) + sizeof (struct flat_hdr)),
308
- (text_len + data_len + (relocs * sizeof(unsigned long))
309
- - sizeof (struct flat_hdr)),
310
- 0);
311
- memmove((void *) datapos, (void *) realdatastart,
312
- data_len + (relocs * sizeof(unsigned long)));
313
- } else if (flags & FLAT_FLAG_GZDATA) {
314
- fpos = 0;
315
- result = bprm->file->f_op->read(bprm->file,
316
- (char *) textpos, text_len, &fpos);
317
- if (!is_error(result)) {
318
- result = decompress_exec(bprm, text_len, (char *) datapos,
319
- data_len + (relocs * sizeof(unsigned long)), 0);
320
- }
321
- }
322
- else
323
-#endif
324
- {
325
- result = target_pread(bprm->src.fd, textpos,
326
- text_len, 0);
327
- if (result >= 0) {
328
- result = target_pread(bprm->src.fd, datapos,
329
- data_len + (relocs * sizeof(abi_ulong)),
330
- ntohl(hdr->data_start));
331
- }
332
+ result = target_pread(bprm->src.fd, textpos,
333
+ text_len, 0);
334
+ if (result >= 0) {
335
+ result = target_pread(bprm->src.fd, datapos,
336
+ data_len + (relocs * sizeof(abi_ulong)),
337
+ ntohl(hdr->data_start));
338
}
339
if (result < 0) {
340
fprintf(stderr, "Unable to read code+data+bss\n");
341
@@ -XXX,XX +XXX,XX @@ static int load_flat_file(struct linux_binprm * bprm,
342
343
344
/****************************************************************************/
345
-#ifdef CONFIG_BINFMT_SHARED_FLAT
346
-
347
-/*
348
- * Load a shared library into memory. The library gets its own data
349
- * segment (including bss) but not argv/argc/environ.
350
- */
351
-
352
-static int load_flat_shared_library(int id, struct lib_info *libs)
353
-{
354
-    struct linux_binprm bprm;
355
-    int res;
356
-    char buf[16];
357
-
358
-    /* Create the file name */
359
-    sprintf(buf, "/lib/lib%d.so", id);
360
-
361
-    /* Open the file up */
362
-    bprm.filename = buf;
363
-    bprm.file = open_exec(bprm.filename);
364
-    res = PTR_ERR(bprm.file);
365
-    if (IS_ERR(bprm.file))
366
-        return res;
367
-
368
-    res = prepare_binprm(&bprm);
369
-
370
- if (!is_error(res)) {
371
-        res = load_flat_file(&bprm, libs, id, NULL);
372
- }
373
-    if (bprm.file) {
374
-        allow_write_access(bprm.file);
375
-        fput(bprm.file);
376
-        bprm.file = NULL;
377
-    }
378
-    return(res);
379
-}
380
-
381
-#endif /* CONFIG_BINFMT_SHARED_FLAT */
382
-
383
int load_flt_binary(struct linux_binprm *bprm, struct image_info *info)
35
{
384
{
36
MachineClass *mc = MACHINE_CLASS(oc);
385
struct lib_info libinfo[MAX_SHARED_LIBS];
37
@@ -XXX,XX +XXX,XX @@ static const TypeInfo raspi_machine_types[] = {
386
@@ -XXX,XX +XXX,XX @@ int load_flt_binary(struct linux_binprm *bprm, struct image_info *info)
38
.parent = TYPE_RASPI_MACHINE,
387
*/
39
.class_init = raspi2b_machine_class_init,
388
start_addr = libinfo[0].entry;
40
#ifdef TARGET_AARCH64
389
41
+ }, {
390
-#ifdef CONFIG_BINFMT_SHARED_FLAT
42
+ .name = MACHINE_TYPE_NAME("raspi3ap"),
391
-#error here
43
+ .parent = TYPE_RASPI_MACHINE,
392
- for (i = MAX_SHARED_LIBS-1; i>0; i--) {
44
+ .class_init = raspi3ap_machine_class_init,
393
- if (libinfo[i].loaded) {
45
}, {
394
- /* Push previous first to call address */
46
.name = MACHINE_TYPE_NAME("raspi3b"),
395
- --sp;
47
.parent = TYPE_RASPI_MACHINE,
396
- if (put_user_ual(start_addr, sp))
397
- return -EFAULT;
398
- start_addr = libinfo[i].entry;
399
- }
400
- }
401
-#endif
402
-
403
/* Stash our initial stack pointer into the mm structure */
404
info->start_code = libinfo[0].start_code;
405
info->end_code = libinfo[0].start_code + libinfo[0].text_len;
48
--
406
--
49
2.20.1
407
2.34.1
50
408
51
409
diff view generated by jsdifflib
1
The armv7m systick timer is a 24-bit decrementing, wrap-on-zero,
1
The npcm7xx_clk and npcm7xx_gcr device reset methods look at
2
clear-on-write counter. Our current implementation has various
2
the ResetType argument and only handle RESET_TYPE_COLD,
3
bugs and dubious workarounds in it (for instance see
3
producing a warning if another reset type is passed. This
4
https://bugs.launchpad.net/qemu/+bug/1872237).
4
is different from how every other three-phase-reset method
5
we have works, and makes it difficult to add new reset types.
5
6
6
We have an implementation of a simple decrementing counter
7
A better pattern is "assume that any reset type you don't know
7
and we put a lot of effort into making sure it handles the
8
about should be handled like RESET_TYPE_COLD"; switch these
8
interesting corner cases (like "spend a cycle at 0 before
9
devices to do that. Then adding a new reset type will only
9
reloading") -- ptimer.
10
need to touch those devices where its behaviour really needs
10
11
to be different from the standard cold reset.
11
Rewrite the systick timer to use a ptimer rather than
12
a raw QEMU timer.
13
14
Unfortunately this is a migration compatibility break,
15
which will affect all M-profile boards.
16
17
Among other bugs, this fixes
18
https://bugs.launchpad.net/qemu/+bug/1872237 :
19
now writes to SYST_CVR when the timer is enabled correctly
20
do nothing; when the timer is enabled via SYST_CSR.ENABLE,
21
the ptimer code will (because of POLICY_NO_IMMEDIATE_RELOAD)
22
arrange that after one timer tick the counter is reloaded
23
from SYST_RVR and then counts down from there, as the
24
architecture requires.
25
12
26
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
27
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
28
Message-id: 20201015151829.14656-3-peter.maydell@linaro.org
15
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
16
Reviewed-by: Luc Michel <luc.michel@amd.com>
17
Message-id: 20240412160809.1260625-2-peter.maydell@linaro.org
29
---
18
---
30
include/hw/timer/armv7m_systick.h | 3 +-
19
hw/misc/npcm7xx_clk.c | 13 +++----------
31
hw/timer/armv7m_systick.c | 124 +++++++++++++-----------------
20
hw/misc/npcm7xx_gcr.c | 12 ++++--------
32
2 files changed, 54 insertions(+), 73 deletions(-)
21
2 files changed, 7 insertions(+), 18 deletions(-)
33
22
34
diff --git a/include/hw/timer/armv7m_systick.h b/include/hw/timer/armv7m_systick.h
23
diff --git a/hw/misc/npcm7xx_clk.c b/hw/misc/npcm7xx_clk.c
35
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
36
--- a/include/hw/timer/armv7m_systick.h
25
--- a/hw/misc/npcm7xx_clk.c
37
+++ b/include/hw/timer/armv7m_systick.h
26
+++ b/hw/misc/npcm7xx_clk.c
38
@@ -XXX,XX +XXX,XX @@
27
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_clk_enter_reset(Object *obj, ResetType type)
39
28
40
#include "hw/sysbus.h"
29
QEMU_BUILD_BUG_ON(sizeof(s->regs) != sizeof(cold_reset_values));
41
#include "qom/object.h"
30
42
+#include "hw/ptimer.h"
31
- switch (type) {
43
32
- case RESET_TYPE_COLD:
44
#define TYPE_SYSTICK "armv7m_systick"
33
- memcpy(s->regs, cold_reset_values, sizeof(cold_reset_values));
45
34
- s->ref_ns = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
46
@@ -XXX,XX +XXX,XX @@ struct SysTickState {
35
- npcm7xx_clk_update_all_clocks(s);
47
uint32_t control;
48
uint32_t reload;
49
int64_t tick;
50
- QEMUTimer *timer;
51
+ ptimer_state *ptimer;
52
MemoryRegion iomem;
53
qemu_irq irq;
54
};
55
diff --git a/hw/timer/armv7m_systick.c b/hw/timer/armv7m_systick.c
56
index XXXXXXX..XXXXXXX 100644
57
--- a/hw/timer/armv7m_systick.c
58
+++ b/hw/timer/armv7m_systick.c
59
@@ -XXX,XX +XXX,XX @@ static inline int64_t systick_scale(SysTickState *s)
60
}
61
}
62
63
-static void systick_reload(SysTickState *s, int reset)
64
-{
65
- /* The Cortex-M3 Devices Generic User Guide says that "When the
66
- * ENABLE bit is set to 1, the counter loads the RELOAD value from the
67
- * SYST RVR register and then counts down". So, we need to check the
68
- * ENABLE bit before reloading the value.
69
- */
70
- trace_systick_reload();
71
-
72
- if ((s->control & SYSTICK_ENABLE) == 0) {
73
- return;
36
- return;
74
- }
37
- }
75
-
38
-
76
- if (reset) {
39
+ memcpy(s->regs, cold_reset_values, sizeof(cold_reset_values));
77
- s->tick = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
40
+ s->ref_ns = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
41
+ npcm7xx_clk_update_all_clocks(s);
42
/*
43
* A small number of registers need to be reset on a core domain reset,
44
* but no such reset type exists yet.
45
*/
46
- qemu_log_mask(LOG_UNIMP, "%s: reset type %d not implemented.",
47
- __func__, type);
48
}
49
50
static void npcm7xx_clk_init_clock_hierarchy(NPCM7xxCLKState *s)
51
diff --git a/hw/misc/npcm7xx_gcr.c b/hw/misc/npcm7xx_gcr.c
52
index XXXXXXX..XXXXXXX 100644
53
--- a/hw/misc/npcm7xx_gcr.c
54
+++ b/hw/misc/npcm7xx_gcr.c
55
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_gcr_enter_reset(Object *obj, ResetType type)
56
57
QEMU_BUILD_BUG_ON(sizeof(s->regs) != sizeof(cold_reset_values));
58
59
- switch (type) {
60
- case RESET_TYPE_COLD:
61
- memcpy(s->regs, cold_reset_values, sizeof(s->regs));
62
- s->regs[NPCM7XX_GCR_PWRON] = s->reset_pwron;
63
- s->regs[NPCM7XX_GCR_MDLR] = s->reset_mdlr;
64
- s->regs[NPCM7XX_GCR_INTCR3] = s->reset_intcr3;
65
- break;
78
- }
66
- }
79
- s->tick += (s->reload + 1) * systick_scale(s);
67
+ memcpy(s->regs, cold_reset_values, sizeof(s->regs));
80
- timer_mod(s->timer, s->tick);
68
+ s->regs[NPCM7XX_GCR_PWRON] = s->reset_pwron;
81
-}
69
+ s->regs[NPCM7XX_GCR_MDLR] = s->reset_mdlr;
82
-
70
+ s->regs[NPCM7XX_GCR_INTCR3] = s->reset_intcr3;
83
static void systick_timer_tick(void *opaque)
84
{
85
SysTickState *s = (SysTickState *)opaque;
86
@@ -XXX,XX +XXX,XX @@ static void systick_timer_tick(void *opaque)
87
/* Tell the NVIC to pend the SysTick exception */
88
qemu_irq_pulse(s->irq);
89
}
90
- if (s->reload == 0) {
91
- s->control &= ~SYSTICK_ENABLE;
92
- } else {
93
- systick_reload(s, 0);
94
+ if (ptimer_get_limit(s->ptimer) == 0) {
95
+ /*
96
+ * Timer expiry with SYST_RVR zero disables the timer
97
+ * (but doesn't clear SYST_CSR.ENABLE)
98
+ */
99
+ ptimer_stop(s->ptimer);
100
}
101
}
71
}
102
72
103
@@ -XXX,XX +XXX,XX @@ static MemTxResult systick_read(void *opaque, hwaddr addr, uint64_t *data,
73
static void npcm7xx_gcr_realize(DeviceState *dev, Error **errp)
104
s->control &= ~SYSTICK_COUNTFLAG;
105
break;
106
case 0x4: /* SysTick Reload Value. */
107
- val = s->reload;
108
+ val = ptimer_get_limit(s->ptimer);
109
break;
110
case 0x8: /* SysTick Current Value. */
111
- {
112
- int64_t t;
113
-
114
- if ((s->control & SYSTICK_ENABLE) == 0) {
115
- val = 0;
116
- break;
117
- }
118
- t = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
119
- if (t >= s->tick) {
120
- val = 0;
121
- break;
122
- }
123
- val = ((s->tick - (t + 1)) / systick_scale(s)) + 1;
124
- /* The interrupt in triggered when the timer reaches zero.
125
- However the counter is not reloaded until the next clock
126
- tick. This is a hack to return zero during the first tick. */
127
- if (val > s->reload) {
128
- val = 0;
129
- }
130
+ val = ptimer_get_count(s->ptimer);
131
break;
132
- }
133
case 0xc: /* SysTick Calibration Value. */
134
val = 10000;
135
break;
136
@@ -XXX,XX +XXX,XX @@ static MemTxResult systick_write(void *opaque, hwaddr addr,
137
switch (addr) {
138
case 0x0: /* SysTick Control and Status. */
139
{
140
- uint32_t oldval = s->control;
141
+ uint32_t oldval;
142
143
+ ptimer_transaction_begin(s->ptimer);
144
+ oldval = s->control;
145
s->control &= 0xfffffff8;
146
s->control |= value & 7;
147
+
148
if ((oldval ^ value) & SYSTICK_ENABLE) {
149
- int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
150
if (value & SYSTICK_ENABLE) {
151
- if (s->tick) {
152
- s->tick += now;
153
- timer_mod(s->timer, s->tick);
154
- } else {
155
- systick_reload(s, 1);
156
- }
157
+ /*
158
+ * Always reload the period in case board code has
159
+ * changed system_clock_scale. If we ever replace that
160
+ * global with a more sensible API then we might be able
161
+ * to set the period only when it actually changes.
162
+ */
163
+ ptimer_set_period(s->ptimer, systick_scale(s));
164
+ ptimer_run(s->ptimer, 0);
165
} else {
166
- timer_del(s->timer);
167
- s->tick -= now;
168
- if (s->tick < 0) {
169
- s->tick = 0;
170
- }
171
+ ptimer_stop(s->ptimer);
172
}
173
} else if ((oldval ^ value) & SYSTICK_CLKSOURCE) {
174
- /* This is a hack. Force the timer to be reloaded
175
- when the reference clock is changed. */
176
- systick_reload(s, 1);
177
+ ptimer_set_period(s->ptimer, systick_scale(s));
178
}
179
+ ptimer_transaction_commit(s->ptimer);
180
break;
181
}
182
case 0x4: /* SysTick Reload Value. */
183
- s->reload = value;
184
+ ptimer_transaction_begin(s->ptimer);
185
+ ptimer_set_limit(s->ptimer, value & 0xffffff, 0);
186
+ ptimer_transaction_commit(s->ptimer);
187
break;
188
- case 0x8: /* SysTick Current Value. Writes reload the timer. */
189
- systick_reload(s, 1);
190
+ case 0x8: /* SysTick Current Value. */
191
+ /*
192
+ * Writing any value clears SYST_CVR to zero and clears
193
+ * SYST_CSR.COUNTFLAG. The counter will then reload from SYST_RVR
194
+ * on the next clock edge unless SYST_RVR is zero.
195
+ */
196
+ ptimer_transaction_begin(s->ptimer);
197
+ if (ptimer_get_limit(s->ptimer) == 0) {
198
+ ptimer_stop(s->ptimer);
199
+ }
200
+ ptimer_set_count(s->ptimer, 0);
201
s->control &= ~SYSTICK_COUNTFLAG;
202
+ ptimer_transaction_commit(s->ptimer);
203
break;
204
default:
205
qemu_log_mask(LOG_GUEST_ERROR,
206
@@ -XXX,XX +XXX,XX @@ static void systick_reset(DeviceState *dev)
207
*/
208
assert(system_clock_scale != 0);
209
210
+ ptimer_transaction_begin(s->ptimer);
211
s->control = 0;
212
- s->reload = 0;
213
- s->tick = 0;
214
- timer_del(s->timer);
215
+ ptimer_stop(s->ptimer);
216
+ ptimer_set_count(s->ptimer, 0);
217
+ ptimer_set_limit(s->ptimer, 0, 0);
218
+ ptimer_set_period(s->ptimer, systick_scale(s));
219
+ ptimer_transaction_commit(s->ptimer);
220
}
221
222
static void systick_instance_init(Object *obj)
223
@@ -XXX,XX +XXX,XX @@ static void systick_instance_init(Object *obj)
224
static void systick_realize(DeviceState *dev, Error **errp)
225
{
226
SysTickState *s = SYSTICK(dev);
227
- s->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, systick_timer_tick, s);
228
+ s->ptimer = ptimer_init(systick_timer_tick, s,
229
+ PTIMER_POLICY_WRAP_AFTER_ONE_PERIOD |
230
+ PTIMER_POLICY_NO_COUNTER_ROUND_DOWN |
231
+ PTIMER_POLICY_NO_IMMEDIATE_RELOAD |
232
+ PTIMER_POLICY_TRIGGER_ONLY_ON_DECREMENT);
233
}
234
235
static const VMStateDescription vmstate_systick = {
236
.name = "armv7m_systick",
237
- .version_id = 1,
238
- .minimum_version_id = 1,
239
+ .version_id = 2,
240
+ .minimum_version_id = 2,
241
.fields = (VMStateField[]) {
242
VMSTATE_UINT32(control, SysTickState),
243
- VMSTATE_UINT32(reload, SysTickState),
244
VMSTATE_INT64(tick, SysTickState),
245
- VMSTATE_TIMER_PTR(timer, SysTickState),
246
+ VMSTATE_PTIMER(ptimer, SysTickState),
247
VMSTATE_END_OF_LIST()
248
}
249
};
250
--
74
--
251
2.20.1
75
2.34.1
252
76
253
77
diff view generated by jsdifflib
1
In ptimer_reload(), we call the callback function provided by the
1
Rather than directly calling the device's implementation of its 'hold'
2
timer device that is using the ptimer. This callback might disable
2
reset phase, call device_cold_reset(). This means we don't have to
3
the ptimer. The code mostly handles this correctly, except that
3
adjust this callsite when we add another argument to the function
4
we'll still print the warning about "Timer with delta zero,
4
signature for the hold and exit reset methods.
5
disabling" if the now-disabled timer happened to be set such that it
6
would fire again immediately if it were enabled (eg because the
7
limit/reload value is zero).
8
9
Suppress the spurious warning message and the unnecessary
10
repeat-deletion of the underlying timer in this case.
11
5
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
14
Message-id: 20201015151829.14656-2-peter.maydell@linaro.org
8
Reviewed-by: Luc Michel <luc.michel@amd.com>
9
Message-id: 20240412160809.1260625-3-peter.maydell@linaro.org
15
---
10
---
16
hw/core/ptimer.c | 4 ++++
11
hw/i2c/allwinner-i2c.c | 3 +--
17
1 file changed, 4 insertions(+)
12
hw/sensor/adm1272.c | 2 +-
13
2 files changed, 2 insertions(+), 3 deletions(-)
18
14
19
diff --git a/hw/core/ptimer.c b/hw/core/ptimer.c
15
diff --git a/hw/i2c/allwinner-i2c.c b/hw/i2c/allwinner-i2c.c
20
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
21
--- a/hw/core/ptimer.c
17
--- a/hw/i2c/allwinner-i2c.c
22
+++ b/hw/core/ptimer.c
18
+++ b/hw/i2c/allwinner-i2c.c
23
@@ -XXX,XX +XXX,XX @@ static void ptimer_reload(ptimer_state *s, int delta_adjust)
19
@@ -XXX,XX +XXX,XX @@ static void allwinner_i2c_write(void *opaque, hwaddr offset,
24
}
20
break;
25
21
case TWI_SRST_REG:
26
if (delta == 0) {
22
if (((value & TWI_SRST_MASK) == 0) && (s->srst & TWI_SRST_MASK)) {
27
+ if (s->enabled == 0) {
23
- /* Perform reset */
28
+ /* trigger callback disabled the timer already */
24
- allwinner_i2c_reset_hold(OBJECT(s));
29
+ return;
25
+ device_cold_reset(DEVICE(s));
30
+ }
31
if (!qtest_enabled()) {
32
fprintf(stderr, "Timer with delta zero, disabling\n");
33
}
26
}
27
s->srst = value & TWI_SRST_MASK;
28
break;
29
diff --git a/hw/sensor/adm1272.c b/hw/sensor/adm1272.c
30
index XXXXXXX..XXXXXXX 100644
31
--- a/hw/sensor/adm1272.c
32
+++ b/hw/sensor/adm1272.c
33
@@ -XXX,XX +XXX,XX @@ static int adm1272_write_data(PMBusDevice *pmdev, const uint8_t *buf,
34
break;
35
36
case ADM1272_MFR_POWER_CYCLE:
37
- adm1272_exit_reset((Object *)s);
38
+ device_cold_reset(DEVICE(s));
39
break;
40
41
case ADM1272_HYSTERESIS_LOW:
34
--
42
--
35
2.20.1
43
2.34.1
36
37
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
We pass a ResetType argument to the Resettable class enter phase
2
method, but we don't pass it to hold and exit, even though the
3
callsites have it readily available. This means that if a device
4
cared about the ResetType it would need to record it in the enter
5
phase method to use later on. We should pass the type to all three
6
of the phase methods to avoid having to do that.
2
7
3
The note test requires gcc 10 for -mbranch-protection=standard.
8
This coccinelle script adds the ResetType argument to the hold and
4
The mmap test uses PROT_BTI and does not require special compiler support.
9
exit phases of the Resettable interface.
5
10
6
Acked-by: Alex Bennée <alex.bennee@linaro.org>
11
The first part of the script (rules holdfn_assigned, holdfn_defined,
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
exitfn_assigned, exitfn_defined) update implementations of the
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
13
interface within device models, both to change the signature of their
9
Message-id: 20201021173749.111103-13-richard.henderson@linaro.org
14
method implementations and to pass on the reset type when they invoke
15
reset on some other device.
16
17
The second part of the script is various special cases:
18
* method callsites in resettable_phase_hold(), resettable_phase_exit()
19
and device_phases_reset()
20
* updating the typedefs for the methods
21
* isl_pmbus_vr.c has some code where one device's reset method directly
22
calls the implementation of a different device's method
23
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
24
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
25
Reviewed-by: Luc Michel <luc.michel@amd.com>
26
Message-id: 20240412160809.1260625-4-peter.maydell@linaro.org
11
---
27
---
12
tests/tcg/aarch64/bti-1.c | 62 ++++++++++++++++
28
scripts/coccinelle/reset-type.cocci | 133 ++++++++++++++++++++++++++++
13
tests/tcg/aarch64/bti-2.c | 116 ++++++++++++++++++++++++++++++
29
1 file changed, 133 insertions(+)
14
tests/tcg/aarch64/bti-crt.inc.c | 51 +++++++++++++
30
create mode 100644 scripts/coccinelle/reset-type.cocci
15
tests/tcg/aarch64/Makefile.target | 10 +++
16
tests/tcg/configure.sh | 4 ++
17
5 files changed, 243 insertions(+)
18
create mode 100644 tests/tcg/aarch64/bti-1.c
19
create mode 100644 tests/tcg/aarch64/bti-2.c
20
create mode 100644 tests/tcg/aarch64/bti-crt.inc.c
21
31
22
diff --git a/tests/tcg/aarch64/bti-1.c b/tests/tcg/aarch64/bti-1.c
32
diff --git a/scripts/coccinelle/reset-type.cocci b/scripts/coccinelle/reset-type.cocci
23
new file mode 100644
33
new file mode 100644
24
index XXXXXXX..XXXXXXX
34
index XXXXXXX..XXXXXXX
25
--- /dev/null
35
--- /dev/null
26
+++ b/tests/tcg/aarch64/bti-1.c
36
+++ b/scripts/coccinelle/reset-type.cocci
27
@@ -XXX,XX +XXX,XX @@
37
@@ -XXX,XX +XXX,XX @@
28
+/*
38
+// Convert device code using three-phase reset to add a ResetType
29
+ * Branch target identification, basic notskip cases.
39
+// argument to implementations of ResettableHoldPhase and
30
+ */
40
+// ResettableEnterPhase methods.
41
+//
42
+// Copyright Linaro Ltd 2024
43
+// SPDX-License-Identifier: GPL-2.0-or-later
44
+//
45
+// for dir in include hw target; do \
46
+// spatch --macro-file scripts/cocci-macro-file.h \
47
+// --sp-file scripts/coccinelle/reset-type.cocci \
48
+// --keep-comments --smpl-spacing --in-place --include-headers \
49
+// --dir $dir; done
50
+//
51
+// This coccinelle script aims to produce a complete change that needs
52
+// no human interaction, so as well as the generic "update device
53
+// implementations of the hold and exit phase methods" it includes
54
+// the special-case transformations needed for the core code and for
55
+// one device model that does something a bit nonstandard. Those
56
+// special cases are at the end of the file.
31
+
57
+
32
+#include "bti-crt.inc.c"
58
+// Look for where we use a function as a ResettableHoldPhase method,
59
+// either by directly assigning it to phases.hold or by calling
60
+// resettable_class_set_parent_phases, and remember the function name.
61
+@ holdfn_assigned @
62
+identifier enterfn, holdfn, exitfn;
63
+identifier rc;
64
+expression e;
65
+@@
66
+ResettableClass *rc;
67
+...
68
+(
69
+ rc->phases.hold = holdfn;
70
+|
71
+ resettable_class_set_parent_phases(rc, enterfn, holdfn, exitfn, e);
72
+)
33
+
73
+
34
+static void skip2_sigill(int sig, siginfo_t *info, ucontext_t *uc)
74
+// Look for the definition of the function we found in holdfn_assigned,
75
+// and add the new argument. If the function calls a hold function
76
+// itself (probably chaining to the parent class reset) then add the
77
+// new argument there too.
78
+@ holdfn_defined @
79
+identifier holdfn_assigned.holdfn;
80
+typedef Object;
81
+identifier obj;
82
+expression parent;
83
+@@
84
+-holdfn(Object *obj)
85
++holdfn(Object *obj, ResetType type)
35
+{
86
+{
36
+ uc->uc_mcontext.pc += 8;
87
+ <...
37
+ uc->uc_mcontext.pstate = 1;
88
+- parent.hold(obj)
89
++ parent.hold(obj, type)
90
+ ...>
38
+}
91
+}
39
+
92
+
40
+#define NOP "nop"
93
+// Similarly for ResettableExitPhase.
41
+#define BTI_N "hint #32"
94
+@ exitfn_assigned @
42
+#define BTI_C "hint #34"
95
+identifier enterfn, holdfn, exitfn;
43
+#define BTI_J "hint #36"
96
+identifier rc;
44
+#define BTI_JC "hint #38"
97
+expression e;
45
+
98
+@@
46
+#define BTYPE_1(DEST) \
99
+ResettableClass *rc;
47
+ asm("mov %0,#1; adr x16, 1f; br x16; 1: " DEST "; mov %0,#0" \
100
+...
48
+ : "=r"(skipped) : : "x16")
101
+(
49
+
102
+ rc->phases.exit = exitfn;
50
+#define BTYPE_2(DEST) \
103
+|
51
+ asm("mov %0,#1; adr x16, 1f; blr x16; 1: " DEST "; mov %0,#0" \
104
+ resettable_class_set_parent_phases(rc, enterfn, holdfn, exitfn, e);
52
+ : "=r"(skipped) : : "x16", "x30")
105
+)
53
+
106
+@ exitfn_defined @
54
+#define BTYPE_3(DEST) \
107
+identifier exitfn_assigned.exitfn;
55
+ asm("mov %0,#1; adr x15, 1f; br x15; 1: " DEST "; mov %0,#0" \
108
+typedef Object;
56
+ : "=r"(skipped) : : "x15")
109
+identifier obj;
57
+
110
+expression parent;
58
+#define TEST(WHICH, DEST, EXPECT) \
111
+@@
59
+ do { WHICH(DEST); fail += skipped ^ EXPECT; } while (0)
112
+-exitfn(Object *obj)
60
+
113
++exitfn(Object *obj, ResetType type)
61
+
62
+int main()
63
+{
114
+{
64
+ int fail = 0;
115
+ <...
65
+ int skipped;
116
+- parent.exit(obj)
66
+
117
++ parent.exit(obj, type)
67
+ /* Signal-like with SA_SIGINFO. */
118
+ ...>
68
+ signal_info(SIGILL, skip2_sigill);
69
+
70
+ TEST(BTYPE_1, NOP, 1);
71
+ TEST(BTYPE_1, BTI_N, 1);
72
+ TEST(BTYPE_1, BTI_C, 0);
73
+ TEST(BTYPE_1, BTI_J, 0);
74
+ TEST(BTYPE_1, BTI_JC, 0);
75
+
76
+ TEST(BTYPE_2, NOP, 1);
77
+ TEST(BTYPE_2, BTI_N, 1);
78
+ TEST(BTYPE_2, BTI_C, 0);
79
+ TEST(BTYPE_2, BTI_J, 1);
80
+ TEST(BTYPE_2, BTI_JC, 0);
81
+
82
+ TEST(BTYPE_3, NOP, 1);
83
+ TEST(BTYPE_3, BTI_N, 1);
84
+ TEST(BTYPE_3, BTI_C, 1);
85
+ TEST(BTYPE_3, BTI_J, 0);
86
+ TEST(BTYPE_3, BTI_JC, 0);
87
+
88
+ return fail;
89
+}
90
diff --git a/tests/tcg/aarch64/bti-2.c b/tests/tcg/aarch64/bti-2.c
91
new file mode 100644
92
index XXXXXXX..XXXXXXX
93
--- /dev/null
94
+++ b/tests/tcg/aarch64/bti-2.c
95
@@ -XXX,XX +XXX,XX @@
96
+/*
97
+ * Branch target identification, basic notskip cases.
98
+ */
99
+
100
+#include <stdio.h>
101
+#include <signal.h>
102
+#include <string.h>
103
+#include <unistd.h>
104
+#include <sys/mman.h>
105
+
106
+#ifndef PROT_BTI
107
+#define PROT_BTI 0x10
108
+#endif
109
+
110
+static void skip2_sigill(int sig, siginfo_t *info, void *vuc)
111
+{
112
+ ucontext_t *uc = vuc;
113
+ uc->uc_mcontext.pc += 8;
114
+ uc->uc_mcontext.pstate = 1;
115
+}
119
+}
116
+
120
+
117
+#define NOP "nop"
121
+// SPECIAL CASES ONLY BELOW HERE
118
+#define BTI_N "hint #32"
122
+// We use a python scripted constraint on the position of the match
119
+#define BTI_C "hint #34"
123
+// to ensure that they only match in a particular function. See
120
+#define BTI_J "hint #36"
124
+// https://public-inbox.org/git/alpine.DEB.2.21.1808240652370.2344@hadrien/
121
+#define BTI_JC "hint #38"
125
+// which recommends this as the way to do "match only in this function".
122
+
126
+
123
+#define BTYPE_1(DEST) \
127
+// Special case: isl_pmbus_vr.c has some reset methods calling others directly
124
+ "mov x1, #1\n\t" \
128
+@ isl_pmbus_vr @
125
+ "adr x16, 1f\n\t" \
129
+identifier obj;
126
+ "br x16\n" \
130
+@@
127
+"1: " DEST "\n\t" \
131
+- isl_pmbus_vr_exit_reset(obj);
128
+ "mov x1, #0"
132
++ isl_pmbus_vr_exit_reset(obj, type);
129
+
133
+
130
+#define BTYPE_2(DEST) \
134
+// Special case: device_phases_reset() needs to pass RESET_TYPE_COLD
131
+ "mov x1, #1\n\t" \
135
+@ device_phases_reset_hold @
132
+ "adr x16, 1f\n\t" \
136
+expression obj;
133
+ "blr x16\n" \
137
+identifier rc;
134
+"1: " DEST "\n\t" \
138
+identifier phase;
135
+ "mov x1, #0"
139
+position p : script:python() { p[0].current_element == "device_phases_reset" };
140
+@@
141
+- rc->phases.phase(obj)@p
142
++ rc->phases.phase(obj, RESET_TYPE_COLD)
136
+
143
+
137
+#define BTYPE_3(DEST) \
144
+// Special case: in resettable_phase_hold() and resettable_phase_exit()
138
+ "mov x1, #1\n\t" \
145
+// we need to pass through the ResetType argument to the method being called
139
+ "adr x15, 1f\n\t" \
146
+@ resettable_phase_hold @
140
+ "br x15\n" \
147
+expression obj;
141
+"1: " DEST "\n\t" \
148
+identifier rc;
142
+ "mov x1, #0"
149
+position p : script:python() { p[0].current_element == "resettable_phase_hold" };
143
+
150
+@@
144
+#define TEST(WHICH, DEST, EXPECT) \
151
+- rc->phases.hold(obj)@p
145
+ WHICH(DEST) "\n" \
152
++ rc->phases.hold(obj, type)
146
+ ".if " #EXPECT "\n\t" \
153
+@ resettable_phase_exit @
147
+ "eor x1, x1," #EXPECT "\n" \
154
+expression obj;
148
+ ".endif\n\t" \
155
+identifier rc;
149
+ "add x0, x0, x1\n\t"
156
+position p : script:python() { p[0].current_element == "resettable_phase_exit" };
150
+
157
+@@
151
+asm("\n"
158
+- rc->phases.exit(obj)@p
152
+"test_begin:\n\t"
159
++ rc->phases.exit(obj, type)
153
+ BTI_C "\n\t"
160
+// Special case: the typedefs for the methods need to declare the new argument
154
+ "mov x2, x30\n\t"
161
+@ phase_typedef_hold @
155
+ "mov x0, #0\n\t"
162
+identifier obj;
156
+
163
+@@
157
+ TEST(BTYPE_1, NOP, 1)
164
+- typedef void (*ResettableHoldPhase)(Object *obj);
158
+ TEST(BTYPE_1, BTI_N, 1)
165
++ typedef void (*ResettableHoldPhase)(Object *obj, ResetType type);
159
+ TEST(BTYPE_1, BTI_C, 0)
166
+@ phase_typedef_exit @
160
+ TEST(BTYPE_1, BTI_J, 0)
167
+identifier obj;
161
+ TEST(BTYPE_1, BTI_JC, 0)
168
+@@
162
+
169
+- typedef void (*ResettableExitPhase)(Object *obj);
163
+ TEST(BTYPE_2, NOP, 1)
170
++ typedef void (*ResettableExitPhase)(Object *obj, ResetType type);
164
+ TEST(BTYPE_2, BTI_N, 1)
165
+ TEST(BTYPE_2, BTI_C, 0)
166
+ TEST(BTYPE_2, BTI_J, 1)
167
+ TEST(BTYPE_2, BTI_JC, 0)
168
+
169
+ TEST(BTYPE_3, NOP, 1)
170
+ TEST(BTYPE_3, BTI_N, 1)
171
+ TEST(BTYPE_3, BTI_C, 1)
172
+ TEST(BTYPE_3, BTI_J, 0)
173
+ TEST(BTYPE_3, BTI_JC, 0)
174
+
175
+ "ret x2\n"
176
+"test_end:"
177
+);
178
+
179
+int main()
180
+{
181
+ struct sigaction sa;
182
+ void *tb, *te;
183
+
184
+ void *p = mmap(0, getpagesize(),
185
+ PROT_EXEC | PROT_READ | PROT_WRITE | PROT_BTI,
186
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
187
+ if (p == MAP_FAILED) {
188
+ perror("mmap");
189
+ return 1;
190
+ }
191
+
192
+ memset(&sa, 0, sizeof(sa));
193
+ sa.sa_sigaction = skip2_sigill;
194
+ sa.sa_flags = SA_SIGINFO;
195
+ if (sigaction(SIGILL, &sa, NULL) < 0) {
196
+ perror("sigaction");
197
+ return 1;
198
+ }
199
+
200
+ /*
201
+ * ??? With "extern char test_begin[]", some compiler versions
202
+ * will use :got references, and some linker versions will
203
+ * resolve this reference to a static symbol incorrectly.
204
+ * Bypass this error by using a pc-relative reference directly.
205
+ */
206
+ asm("adr %0, test_begin; adr %1, test_end" : "=r"(tb), "=r"(te));
207
+
208
+ memcpy(p, tb, te - tb);
209
+
210
+ return ((int (*)(void))p)();
211
+}
212
diff --git a/tests/tcg/aarch64/bti-crt.inc.c b/tests/tcg/aarch64/bti-crt.inc.c
213
new file mode 100644
214
index XXXXXXX..XXXXXXX
215
--- /dev/null
216
+++ b/tests/tcg/aarch64/bti-crt.inc.c
217
@@ -XXX,XX +XXX,XX @@
218
+/*
219
+ * Minimal user-environment for testing BTI.
220
+ *
221
+ * Normal libc is not (yet) built with BTI support enabled,
222
+ * and so could generate a BTI TRAP before ever reaching main.
223
+ */
224
+
225
+#include <stdlib.h>
226
+#include <signal.h>
227
+#include <ucontext.h>
228
+#include <asm/unistd.h>
229
+
230
+int main(void);
231
+
232
+void _start(void)
233
+{
234
+ exit(main());
235
+}
236
+
237
+void exit(int ret)
238
+{
239
+ register int x0 __asm__("x0") = ret;
240
+ register int x8 __asm__("x8") = __NR_exit;
241
+
242
+ asm volatile("svc #0" : : "r"(x0), "r"(x8));
243
+ __builtin_unreachable();
244
+}
245
+
246
+/*
247
+ * Irritatingly, the user API struct sigaction does not match the
248
+ * kernel API struct sigaction. So for simplicity, isolate the
249
+ * kernel ABI here, and make this act like signal.
250
+ */
251
+void signal_info(int sig, void (*fn)(int, siginfo_t *, ucontext_t *))
252
+{
253
+ struct kernel_sigaction {
254
+ void (*handler)(int, siginfo_t *, ucontext_t *);
255
+ unsigned long flags;
256
+ unsigned long restorer;
257
+ unsigned long mask;
258
+ } sa = { fn, SA_SIGINFO, 0, 0 };
259
+
260
+ register int x0 __asm__("x0") = sig;
261
+ register void *x1 __asm__("x1") = &sa;
262
+ register void *x2 __asm__("x2") = 0;
263
+ register int x3 __asm__("x3") = sizeof(unsigned long);
264
+ register int x8 __asm__("x8") = __NR_rt_sigaction;
265
+
266
+ asm volatile("svc #0"
267
+ : : "r"(x0), "r"(x1), "r"(x2), "r"(x3), "r"(x8) : "memory");
268
+}
269
diff --git a/tests/tcg/aarch64/Makefile.target b/tests/tcg/aarch64/Makefile.target
270
index XXXXXXX..XXXXXXX 100644
271
--- a/tests/tcg/aarch64/Makefile.target
272
+++ b/tests/tcg/aarch64/Makefile.target
273
@@ -XXX,XX +XXX,XX @@ run-pauth-%: QEMU_OPTS += -cpu max
274
run-plugin-pauth-%: QEMU_OPTS += -cpu max
275
endif
276
277
+# BTI Tests
278
+# bti-1 tests the elf notes, so we require special compiler support.
279
+ifneq ($(DOCKER_IMAGE)$(CROSS_CC_HAS_ARMV8_BTI),)
280
+AARCH64_TESTS += bti-1
281
+bti-1: CFLAGS += -mbranch-protection=standard
282
+bti-1: LDFLAGS += -nostdlib
283
+endif
284
+# bti-2 tests PROT_BTI, so no special compiler support required.
285
+AARCH64_TESTS += bti-2
286
+
287
# Semihosting smoke test for linux-user
288
AARCH64_TESTS += semihosting
289
run-semihosting: semihosting
290
diff --git a/tests/tcg/configure.sh b/tests/tcg/configure.sh
291
index XXXXXXX..XXXXXXX 100755
292
--- a/tests/tcg/configure.sh
293
+++ b/tests/tcg/configure.sh
294
@@ -XXX,XX +XXX,XX @@ for target in $target_list; do
295
-march=armv8.3-a -o $TMPE $TMPC; then
296
echo "CROSS_CC_HAS_ARMV8_3=y" >> $config_target_mak
297
fi
298
+ if do_compiler "$target_compiler" $target_compiler_cflags \
299
+ -mbranch-protection=standard -o $TMPE $TMPC; then
300
+ echo "CROSS_CC_HAS_ARMV8_BTI=y" >> $config_target_mak
301
+ fi
302
;;
303
esac
304
305
--
171
--
306
2.20.1
172
2.34.1
307
308
diff view generated by jsdifflib
1
From: Havard Skinnemoen <hskinnemoen@google.com>
1
We pass a ResetType argument to the Resettable class enter
2
phase method, but we don't pass it to hold and exit, even though
3
the callsites have it readily available. This means that if
4
a device cared about the ResetType it would need to record it
5
in the enter phase method to use later on. Pass the type to
6
all three of the phase methods to avoid having to do that.
2
7
3
This allows us to reuse npcm7xx_timer_pause for the watchdog timer.
8
Commit created with
4
9
5
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
for dir in hw target include; do \
6
Signed-off-by: Havard Skinnemoen <hskinnemoen@google.com>
11
spatch --macro-file scripts/cocci-macro-file.h \
12
--sp-file scripts/coccinelle/reset-type.cocci \
13
--keep-comments --smpl-spacing --in-place \
14
--include-headers --dir $dir; done
15
16
and no manual edits.
17
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@amd.com>
20
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
21
Reviewed-by: Luc Michel <luc.michel@amd.com>
22
Message-id: 20240412160809.1260625-5-peter.maydell@linaro.org
8
---
23
---
9
hw/timer/npcm7xx_timer.c | 6 +++---
24
include/hw/resettable.h | 4 ++--
10
1 file changed, 3 insertions(+), 3 deletions(-)
25
hw/adc/npcm7xx_adc.c | 2 +-
26
hw/arm/pxa2xx_pic.c | 2 +-
27
hw/arm/smmu-common.c | 2 +-
28
hw/arm/smmuv3.c | 4 ++--
29
hw/arm/stellaris.c | 10 +++++-----
30
hw/audio/asc.c | 2 +-
31
hw/char/cadence_uart.c | 2 +-
32
hw/char/sifive_uart.c | 2 +-
33
hw/core/cpu-common.c | 2 +-
34
hw/core/qdev.c | 4 ++--
35
hw/core/reset.c | 2 +-
36
hw/core/resettable.c | 4 ++--
37
hw/display/virtio-vga.c | 4 ++--
38
hw/gpio/npcm7xx_gpio.c | 2 +-
39
hw/gpio/pl061.c | 2 +-
40
hw/gpio/stm32l4x5_gpio.c | 2 +-
41
hw/hyperv/vmbus.c | 2 +-
42
hw/i2c/allwinner-i2c.c | 2 +-
43
hw/i2c/npcm7xx_smbus.c | 2 +-
44
hw/input/adb.c | 2 +-
45
hw/input/ps2.c | 12 ++++++------
46
hw/intc/arm_gic_common.c | 2 +-
47
hw/intc/arm_gic_kvm.c | 4 ++--
48
hw/intc/arm_gicv3_common.c | 2 +-
49
hw/intc/arm_gicv3_its.c | 4 ++--
50
hw/intc/arm_gicv3_its_common.c | 2 +-
51
hw/intc/arm_gicv3_its_kvm.c | 4 ++--
52
hw/intc/arm_gicv3_kvm.c | 4 ++--
53
hw/intc/xics.c | 2 +-
54
hw/m68k/q800-glue.c | 2 +-
55
hw/misc/djmemc.c | 2 +-
56
hw/misc/iosb.c | 2 +-
57
hw/misc/mac_via.c | 8 ++++----
58
hw/misc/macio/cuda.c | 4 ++--
59
hw/misc/macio/pmu.c | 4 ++--
60
hw/misc/mos6522.c | 2 +-
61
hw/misc/npcm7xx_mft.c | 2 +-
62
hw/misc/npcm7xx_pwm.c | 2 +-
63
hw/misc/stm32l4x5_exti.c | 2 +-
64
hw/misc/stm32l4x5_rcc.c | 10 +++++-----
65
hw/misc/stm32l4x5_syscfg.c | 2 +-
66
hw/misc/xlnx-versal-cframe-reg.c | 2 +-
67
hw/misc/xlnx-versal-crl.c | 2 +-
68
hw/misc/xlnx-versal-pmc-iou-slcr.c | 2 +-
69
hw/misc/xlnx-versal-trng.c | 2 +-
70
hw/misc/xlnx-versal-xramc.c | 2 +-
71
hw/misc/xlnx-zynqmp-apu-ctrl.c | 2 +-
72
hw/misc/xlnx-zynqmp-crf.c | 2 +-
73
hw/misc/zynq_slcr.c | 4 ++--
74
hw/net/can/xlnx-zynqmp-can.c | 2 +-
75
hw/net/e1000.c | 2 +-
76
hw/net/e1000e.c | 2 +-
77
hw/net/igb.c | 2 +-
78
hw/net/igbvf.c | 2 +-
79
hw/nvram/xlnx-bbram.c | 2 +-
80
hw/nvram/xlnx-versal-efuse-ctrl.c | 2 +-
81
hw/nvram/xlnx-zynqmp-efuse.c | 2 +-
82
hw/pci-bridge/cxl_root_port.c | 4 ++--
83
hw/pci-bridge/pcie_root_port.c | 2 +-
84
hw/pci-host/bonito.c | 2 +-
85
hw/pci-host/pnv_phb.c | 4 ++--
86
hw/pci-host/pnv_phb3_msi.c | 4 ++--
87
hw/pci/pci.c | 4 ++--
88
hw/rtc/mc146818rtc.c | 2 +-
89
hw/s390x/css-bridge.c | 2 +-
90
hw/sensor/adm1266.c | 2 +-
91
hw/sensor/adm1272.c | 2 +-
92
hw/sensor/isl_pmbus_vr.c | 10 +++++-----
93
hw/sensor/max31785.c | 2 +-
94
hw/sensor/max34451.c | 2 +-
95
hw/ssi/npcm7xx_fiu.c | 2 +-
96
hw/timer/etraxfs_timer.c | 2 +-
97
hw/timer/npcm7xx_timer.c | 2 +-
98
hw/usb/hcd-dwc2.c | 8 ++++----
99
hw/usb/xlnx-versal-usb2-ctrl-regs.c | 2 +-
100
hw/virtio/virtio-pci.c | 2 +-
101
target/arm/cpu.c | 4 ++--
102
target/avr/cpu.c | 4 ++--
103
target/cris/cpu.c | 4 ++--
104
target/hexagon/cpu.c | 4 ++--
105
target/i386/cpu.c | 4 ++--
106
target/loongarch/cpu.c | 4 ++--
107
target/m68k/cpu.c | 4 ++--
108
target/microblaze/cpu.c | 4 ++--
109
target/mips/cpu.c | 4 ++--
110
target/openrisc/cpu.c | 4 ++--
111
target/ppc/cpu_init.c | 4 ++--
112
target/riscv/cpu.c | 4 ++--
113
target/rx/cpu.c | 4 ++--
114
target/sh4/cpu.c | 4 ++--
115
target/sparc/cpu.c | 4 ++--
116
target/tricore/cpu.c | 4 ++--
117
target/xtensa/cpu.c | 4 ++--
118
94 files changed, 150 insertions(+), 150 deletions(-)
11
119
120
diff --git a/include/hw/resettable.h b/include/hw/resettable.h
121
index XXXXXXX..XXXXXXX 100644
122
--- a/include/hw/resettable.h
123
+++ b/include/hw/resettable.h
124
@@ -XXX,XX +XXX,XX @@ typedef enum ResetType {
125
* the callback.
126
*/
127
typedef void (*ResettableEnterPhase)(Object *obj, ResetType type);
128
-typedef void (*ResettableHoldPhase)(Object *obj);
129
-typedef void (*ResettableExitPhase)(Object *obj);
130
+typedef void (*ResettableHoldPhase)(Object *obj, ResetType type);
131
+typedef void (*ResettableExitPhase)(Object *obj, ResetType type);
132
typedef ResettableState * (*ResettableGetState)(Object *obj);
133
typedef void (*ResettableTrFunction)(Object *obj);
134
typedef ResettableTrFunction (*ResettableGetTrFunction)(Object *obj);
135
diff --git a/hw/adc/npcm7xx_adc.c b/hw/adc/npcm7xx_adc.c
136
index XXXXXXX..XXXXXXX 100644
137
--- a/hw/adc/npcm7xx_adc.c
138
+++ b/hw/adc/npcm7xx_adc.c
139
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_adc_enter_reset(Object *obj, ResetType type)
140
npcm7xx_adc_reset(s);
141
}
142
143
-static void npcm7xx_adc_hold_reset(Object *obj)
144
+static void npcm7xx_adc_hold_reset(Object *obj, ResetType type)
145
{
146
NPCM7xxADCState *s = NPCM7XX_ADC(obj);
147
148
diff --git a/hw/arm/pxa2xx_pic.c b/hw/arm/pxa2xx_pic.c
149
index XXXXXXX..XXXXXXX 100644
150
--- a/hw/arm/pxa2xx_pic.c
151
+++ b/hw/arm/pxa2xx_pic.c
152
@@ -XXX,XX +XXX,XX @@ static int pxa2xx_pic_post_load(void *opaque, int version_id)
153
return 0;
154
}
155
156
-static void pxa2xx_pic_reset_hold(Object *obj)
157
+static void pxa2xx_pic_reset_hold(Object *obj, ResetType type)
158
{
159
PXA2xxPICState *s = PXA2XX_PIC(obj);
160
161
diff --git a/hw/arm/smmu-common.c b/hw/arm/smmu-common.c
162
index XXXXXXX..XXXXXXX 100644
163
--- a/hw/arm/smmu-common.c
164
+++ b/hw/arm/smmu-common.c
165
@@ -XXX,XX +XXX,XX @@ static void smmu_base_realize(DeviceState *dev, Error **errp)
166
}
167
}
168
169
-static void smmu_base_reset_hold(Object *obj)
170
+static void smmu_base_reset_hold(Object *obj, ResetType type)
171
{
172
SMMUState *s = ARM_SMMU(obj);
173
174
diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c
175
index XXXXXXX..XXXXXXX 100644
176
--- a/hw/arm/smmuv3.c
177
+++ b/hw/arm/smmuv3.c
178
@@ -XXX,XX +XXX,XX @@ static void smmu_init_irq(SMMUv3State *s, SysBusDevice *dev)
179
}
180
}
181
182
-static void smmu_reset_hold(Object *obj)
183
+static void smmu_reset_hold(Object *obj, ResetType type)
184
{
185
SMMUv3State *s = ARM_SMMUV3(obj);
186
SMMUv3Class *c = ARM_SMMUV3_GET_CLASS(s);
187
188
if (c->parent_phases.hold) {
189
- c->parent_phases.hold(obj);
190
+ c->parent_phases.hold(obj, type);
191
}
192
193
smmuv3_init_regs(s);
194
diff --git a/hw/arm/stellaris.c b/hw/arm/stellaris.c
195
index XXXXXXX..XXXXXXX 100644
196
--- a/hw/arm/stellaris.c
197
+++ b/hw/arm/stellaris.c
198
@@ -XXX,XX +XXX,XX @@ static void stellaris_sys_reset_enter(Object *obj, ResetType type)
199
s->dcgc[0] = 1;
200
}
201
202
-static void stellaris_sys_reset_hold(Object *obj)
203
+static void stellaris_sys_reset_hold(Object *obj, ResetType type)
204
{
205
ssys_state *s = STELLARIS_SYS(obj);
206
207
@@ -XXX,XX +XXX,XX @@ static void stellaris_sys_reset_hold(Object *obj)
208
ssys_calculate_system_clock(s, true);
209
}
210
211
-static void stellaris_sys_reset_exit(Object *obj)
212
+static void stellaris_sys_reset_exit(Object *obj, ResetType type)
213
{
214
}
215
216
@@ -XXX,XX +XXX,XX @@ static void stellaris_i2c_reset_enter(Object *obj, ResetType type)
217
i2c_end_transfer(s->bus);
218
}
219
220
-static void stellaris_i2c_reset_hold(Object *obj)
221
+static void stellaris_i2c_reset_hold(Object *obj, ResetType type)
222
{
223
stellaris_i2c_state *s = STELLARIS_I2C(obj);
224
225
@@ -XXX,XX +XXX,XX @@ static void stellaris_i2c_reset_hold(Object *obj)
226
s->mcr = 0;
227
}
228
229
-static void stellaris_i2c_reset_exit(Object *obj)
230
+static void stellaris_i2c_reset_exit(Object *obj, ResetType type)
231
{
232
stellaris_i2c_state *s = STELLARIS_I2C(obj);
233
234
@@ -XXX,XX +XXX,XX @@ static void stellaris_adc_trigger(void *opaque, int irq, int level)
235
}
236
}
237
238
-static void stellaris_adc_reset_hold(Object *obj)
239
+static void stellaris_adc_reset_hold(Object *obj, ResetType type)
240
{
241
StellarisADCState *s = STELLARIS_ADC(obj);
242
int n;
243
diff --git a/hw/audio/asc.c b/hw/audio/asc.c
244
index XXXXXXX..XXXXXXX 100644
245
--- a/hw/audio/asc.c
246
+++ b/hw/audio/asc.c
247
@@ -XXX,XX +XXX,XX @@ static void asc_fifo_init(ASCFIFOState *fs, int index)
248
g_free(name);
249
}
250
251
-static void asc_reset_hold(Object *obj)
252
+static void asc_reset_hold(Object *obj, ResetType type)
253
{
254
ASCState *s = ASC(obj);
255
256
diff --git a/hw/char/cadence_uart.c b/hw/char/cadence_uart.c
257
index XXXXXXX..XXXXXXX 100644
258
--- a/hw/char/cadence_uart.c
259
+++ b/hw/char/cadence_uart.c
260
@@ -XXX,XX +XXX,XX @@ static void cadence_uart_reset_init(Object *obj, ResetType type)
261
s->r[R_TTRIG] = 0x00000020;
262
}
263
264
-static void cadence_uart_reset_hold(Object *obj)
265
+static void cadence_uart_reset_hold(Object *obj, ResetType type)
266
{
267
CadenceUARTState *s = CADENCE_UART(obj);
268
269
diff --git a/hw/char/sifive_uart.c b/hw/char/sifive_uart.c
270
index XXXXXXX..XXXXXXX 100644
271
--- a/hw/char/sifive_uart.c
272
+++ b/hw/char/sifive_uart.c
273
@@ -XXX,XX +XXX,XX @@ static void sifive_uart_reset_enter(Object *obj, ResetType type)
274
s->rx_fifo_len = 0;
275
}
276
277
-static void sifive_uart_reset_hold(Object *obj)
278
+static void sifive_uart_reset_hold(Object *obj, ResetType type)
279
{
280
SiFiveUARTState *s = SIFIVE_UART(obj);
281
qemu_irq_lower(s->irq);
282
diff --git a/hw/core/cpu-common.c b/hw/core/cpu-common.c
283
index XXXXXXX..XXXXXXX 100644
284
--- a/hw/core/cpu-common.c
285
+++ b/hw/core/cpu-common.c
286
@@ -XXX,XX +XXX,XX @@ void cpu_reset(CPUState *cpu)
287
trace_cpu_reset(cpu->cpu_index);
288
}
289
290
-static void cpu_common_reset_hold(Object *obj)
291
+static void cpu_common_reset_hold(Object *obj, ResetType type)
292
{
293
CPUState *cpu = CPU(obj);
294
CPUClass *cc = CPU_GET_CLASS(cpu);
295
diff --git a/hw/core/qdev.c b/hw/core/qdev.c
296
index XXXXXXX..XXXXXXX 100644
297
--- a/hw/core/qdev.c
298
+++ b/hw/core/qdev.c
299
@@ -XXX,XX +XXX,XX @@ static void device_phases_reset(DeviceState *dev)
300
rc->phases.enter(OBJECT(dev), RESET_TYPE_COLD);
301
}
302
if (rc->phases.hold) {
303
- rc->phases.hold(OBJECT(dev));
304
+ rc->phases.hold(OBJECT(dev), RESET_TYPE_COLD);
305
}
306
if (rc->phases.exit) {
307
- rc->phases.exit(OBJECT(dev));
308
+ rc->phases.exit(OBJECT(dev), RESET_TYPE_COLD);
309
}
310
}
311
312
diff --git a/hw/core/reset.c b/hw/core/reset.c
313
index XXXXXXX..XXXXXXX 100644
314
--- a/hw/core/reset.c
315
+++ b/hw/core/reset.c
316
@@ -XXX,XX +XXX,XX @@ static ResettableState *legacy_reset_get_state(Object *obj)
317
return &lr->reset_state;
318
}
319
320
-static void legacy_reset_hold(Object *obj)
321
+static void legacy_reset_hold(Object *obj, ResetType type)
322
{
323
LegacyReset *lr = LEGACY_RESET(obj);
324
325
diff --git a/hw/core/resettable.c b/hw/core/resettable.c
326
index XXXXXXX..XXXXXXX 100644
327
--- a/hw/core/resettable.c
328
+++ b/hw/core/resettable.c
329
@@ -XXX,XX +XXX,XX @@ static void resettable_phase_hold(Object *obj, void *opaque, ResetType type)
330
trace_resettable_transitional_function(obj, obj_typename);
331
tr_func(obj);
332
} else if (rc->phases.hold) {
333
- rc->phases.hold(obj);
334
+ rc->phases.hold(obj, type);
335
}
336
}
337
trace_resettable_phase_hold_end(obj, obj_typename, s->count);
338
@@ -XXX,XX +XXX,XX @@ static void resettable_phase_exit(Object *obj, void *opaque, ResetType type)
339
if (--s->count == 0) {
340
trace_resettable_phase_exit_exec(obj, obj_typename, !!rc->phases.exit);
341
if (rc->phases.exit && !resettable_get_tr_func(rc, obj)) {
342
- rc->phases.exit(obj);
343
+ rc->phases.exit(obj, type);
344
}
345
}
346
s->exit_phase_in_progress = false;
347
diff --git a/hw/display/virtio-vga.c b/hw/display/virtio-vga.c
348
index XXXXXXX..XXXXXXX 100644
349
--- a/hw/display/virtio-vga.c
350
+++ b/hw/display/virtio-vga.c
351
@@ -XXX,XX +XXX,XX @@ static void virtio_vga_base_realize(VirtIOPCIProxy *vpci_dev, Error **errp)
352
}
353
}
354
355
-static void virtio_vga_base_reset_hold(Object *obj)
356
+static void virtio_vga_base_reset_hold(Object *obj, ResetType type)
357
{
358
VirtIOVGABaseClass *klass = VIRTIO_VGA_BASE_GET_CLASS(obj);
359
VirtIOVGABase *vvga = VIRTIO_VGA_BASE(obj);
360
361
/* reset virtio-gpu */
362
if (klass->parent_phases.hold) {
363
- klass->parent_phases.hold(obj);
364
+ klass->parent_phases.hold(obj, type);
365
}
366
367
/* reset vga */
368
diff --git a/hw/gpio/npcm7xx_gpio.c b/hw/gpio/npcm7xx_gpio.c
369
index XXXXXXX..XXXXXXX 100644
370
--- a/hw/gpio/npcm7xx_gpio.c
371
+++ b/hw/gpio/npcm7xx_gpio.c
372
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_gpio_enter_reset(Object *obj, ResetType type)
373
s->regs[NPCM7XX_GPIO_ODSC] = s->reset_odsc;
374
}
375
376
-static void npcm7xx_gpio_hold_reset(Object *obj)
377
+static void npcm7xx_gpio_hold_reset(Object *obj, ResetType type)
378
{
379
NPCM7xxGPIOState *s = NPCM7XX_GPIO(obj);
380
381
diff --git a/hw/gpio/pl061.c b/hw/gpio/pl061.c
382
index XXXXXXX..XXXXXXX 100644
383
--- a/hw/gpio/pl061.c
384
+++ b/hw/gpio/pl061.c
385
@@ -XXX,XX +XXX,XX @@ static void pl061_enter_reset(Object *obj, ResetType type)
386
s->amsel = 0;
387
}
388
389
-static void pl061_hold_reset(Object *obj)
390
+static void pl061_hold_reset(Object *obj, ResetType type)
391
{
392
PL061State *s = PL061(obj);
393
int i, level;
394
diff --git a/hw/gpio/stm32l4x5_gpio.c b/hw/gpio/stm32l4x5_gpio.c
395
index XXXXXXX..XXXXXXX 100644
396
--- a/hw/gpio/stm32l4x5_gpio.c
397
+++ b/hw/gpio/stm32l4x5_gpio.c
398
@@ -XXX,XX +XXX,XX @@ static bool is_push_pull(Stm32l4x5GpioState *s, unsigned pin)
399
return extract32(s->otyper, pin, 1) == 0;
400
}
401
402
-static void stm32l4x5_gpio_reset_hold(Object *obj)
403
+static void stm32l4x5_gpio_reset_hold(Object *obj, ResetType type)
404
{
405
Stm32l4x5GpioState *s = STM32L4X5_GPIO(obj);
406
407
diff --git a/hw/hyperv/vmbus.c b/hw/hyperv/vmbus.c
408
index XXXXXXX..XXXXXXX 100644
409
--- a/hw/hyperv/vmbus.c
410
+++ b/hw/hyperv/vmbus.c
411
@@ -XXX,XX +XXX,XX @@ static void vmbus_unrealize(BusState *bus)
412
qemu_mutex_destroy(&vmbus->rx_queue_lock);
413
}
414
415
-static void vmbus_reset_hold(Object *obj)
416
+static void vmbus_reset_hold(Object *obj, ResetType type)
417
{
418
vmbus_deinit(VMBUS(obj));
419
}
420
diff --git a/hw/i2c/allwinner-i2c.c b/hw/i2c/allwinner-i2c.c
421
index XXXXXXX..XXXXXXX 100644
422
--- a/hw/i2c/allwinner-i2c.c
423
+++ b/hw/i2c/allwinner-i2c.c
424
@@ -XXX,XX +XXX,XX @@ static inline bool allwinner_i2c_interrupt_is_enabled(AWI2CState *s)
425
return s->cntr & TWI_CNTR_INT_EN;
426
}
427
428
-static void allwinner_i2c_reset_hold(Object *obj)
429
+static void allwinner_i2c_reset_hold(Object *obj, ResetType type)
430
{
431
AWI2CState *s = AW_I2C(obj);
432
433
diff --git a/hw/i2c/npcm7xx_smbus.c b/hw/i2c/npcm7xx_smbus.c
434
index XXXXXXX..XXXXXXX 100644
435
--- a/hw/i2c/npcm7xx_smbus.c
436
+++ b/hw/i2c/npcm7xx_smbus.c
437
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_smbus_enter_reset(Object *obj, ResetType type)
438
s->rx_cur = 0;
439
}
440
441
-static void npcm7xx_smbus_hold_reset(Object *obj)
442
+static void npcm7xx_smbus_hold_reset(Object *obj, ResetType type)
443
{
444
NPCM7xxSMBusState *s = NPCM7XX_SMBUS(obj);
445
446
diff --git a/hw/input/adb.c b/hw/input/adb.c
447
index XXXXXXX..XXXXXXX 100644
448
--- a/hw/input/adb.c
449
+++ b/hw/input/adb.c
450
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_adb_bus = {
451
}
452
};
453
454
-static void adb_bus_reset_hold(Object *obj)
455
+static void adb_bus_reset_hold(Object *obj, ResetType type)
456
{
457
ADBBusState *adb_bus = ADB_BUS(obj);
458
459
diff --git a/hw/input/ps2.c b/hw/input/ps2.c
460
index XXXXXXX..XXXXXXX 100644
461
--- a/hw/input/ps2.c
462
+++ b/hw/input/ps2.c
463
@@ -XXX,XX +XXX,XX @@ void ps2_write_mouse(PS2MouseState *s, int val)
464
}
465
}
466
467
-static void ps2_reset_hold(Object *obj)
468
+static void ps2_reset_hold(Object *obj, ResetType type)
469
{
470
PS2State *s = PS2_DEVICE(obj);
471
472
@@ -XXX,XX +XXX,XX @@ static void ps2_reset_hold(Object *obj)
473
ps2_reset_queue(s);
474
}
475
476
-static void ps2_reset_exit(Object *obj)
477
+static void ps2_reset_exit(Object *obj, ResetType type)
478
{
479
PS2State *s = PS2_DEVICE(obj);
480
481
@@ -XXX,XX +XXX,XX @@ static void ps2_common_post_load(PS2State *s)
482
q->cwptr = ccount ? (q->rptr + ccount) & (PS2_BUFFER_SIZE - 1) : -1;
483
}
484
485
-static void ps2_kbd_reset_hold(Object *obj)
486
+static void ps2_kbd_reset_hold(Object *obj, ResetType type)
487
{
488
PS2DeviceClass *ps2dc = PS2_DEVICE_GET_CLASS(obj);
489
PS2KbdState *s = PS2_KBD_DEVICE(obj);
490
@@ -XXX,XX +XXX,XX @@ static void ps2_kbd_reset_hold(Object *obj)
491
trace_ps2_kbd_reset(s);
492
493
if (ps2dc->parent_phases.hold) {
494
- ps2dc->parent_phases.hold(obj);
495
+ ps2dc->parent_phases.hold(obj, type);
496
}
497
498
s->scan_enabled = 1;
499
@@ -XXX,XX +XXX,XX @@ static void ps2_kbd_reset_hold(Object *obj)
500
s->modifiers = 0;
501
}
502
503
-static void ps2_mouse_reset_hold(Object *obj)
504
+static void ps2_mouse_reset_hold(Object *obj, ResetType type)
505
{
506
PS2DeviceClass *ps2dc = PS2_DEVICE_GET_CLASS(obj);
507
PS2MouseState *s = PS2_MOUSE_DEVICE(obj);
508
@@ -XXX,XX +XXX,XX @@ static void ps2_mouse_reset_hold(Object *obj)
509
trace_ps2_mouse_reset(s);
510
511
if (ps2dc->parent_phases.hold) {
512
- ps2dc->parent_phases.hold(obj);
513
+ ps2dc->parent_phases.hold(obj, type);
514
}
515
516
s->mouse_status = 0;
517
diff --git a/hw/intc/arm_gic_common.c b/hw/intc/arm_gic_common.c
518
index XXXXXXX..XXXXXXX 100644
519
--- a/hw/intc/arm_gic_common.c
520
+++ b/hw/intc/arm_gic_common.c
521
@@ -XXX,XX +XXX,XX @@ static inline void arm_gic_common_reset_irq_state(GICState *s, int cidx,
522
}
523
}
524
525
-static void arm_gic_common_reset_hold(Object *obj)
526
+static void arm_gic_common_reset_hold(Object *obj, ResetType type)
527
{
528
GICState *s = ARM_GIC_COMMON(obj);
529
int i, j;
530
diff --git a/hw/intc/arm_gic_kvm.c b/hw/intc/arm_gic_kvm.c
531
index XXXXXXX..XXXXXXX 100644
532
--- a/hw/intc/arm_gic_kvm.c
533
+++ b/hw/intc/arm_gic_kvm.c
534
@@ -XXX,XX +XXX,XX @@ static void kvm_arm_gic_get(GICState *s)
535
}
536
}
537
538
-static void kvm_arm_gic_reset_hold(Object *obj)
539
+static void kvm_arm_gic_reset_hold(Object *obj, ResetType type)
540
{
541
GICState *s = ARM_GIC_COMMON(obj);
542
KVMARMGICClass *kgc = KVM_ARM_GIC_GET_CLASS(s);
543
544
if (kgc->parent_phases.hold) {
545
- kgc->parent_phases.hold(obj);
546
+ kgc->parent_phases.hold(obj, type);
547
}
548
549
if (kvm_arm_gic_can_save_restore(s)) {
550
diff --git a/hw/intc/arm_gicv3_common.c b/hw/intc/arm_gicv3_common.c
551
index XXXXXXX..XXXXXXX 100644
552
--- a/hw/intc/arm_gicv3_common.c
553
+++ b/hw/intc/arm_gicv3_common.c
554
@@ -XXX,XX +XXX,XX @@ static void arm_gicv3_finalize(Object *obj)
555
g_free(s->redist_region_count);
556
}
557
558
-static void arm_gicv3_common_reset_hold(Object *obj)
559
+static void arm_gicv3_common_reset_hold(Object *obj, ResetType type)
560
{
561
GICv3State *s = ARM_GICV3_COMMON(obj);
562
int i;
563
diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
564
index XXXXXXX..XXXXXXX 100644
565
--- a/hw/intc/arm_gicv3_its.c
566
+++ b/hw/intc/arm_gicv3_its.c
567
@@ -XXX,XX +XXX,XX @@ static void gicv3_arm_its_realize(DeviceState *dev, Error **errp)
568
}
569
}
570
571
-static void gicv3_its_reset_hold(Object *obj)
572
+static void gicv3_its_reset_hold(Object *obj, ResetType type)
573
{
574
GICv3ITSState *s = ARM_GICV3_ITS_COMMON(obj);
575
GICv3ITSClass *c = ARM_GICV3_ITS_GET_CLASS(s);
576
577
if (c->parent_phases.hold) {
578
- c->parent_phases.hold(obj);
579
+ c->parent_phases.hold(obj, type);
580
}
581
582
/* Quiescent bit reset to 1 */
583
diff --git a/hw/intc/arm_gicv3_its_common.c b/hw/intc/arm_gicv3_its_common.c
584
index XXXXXXX..XXXXXXX 100644
585
--- a/hw/intc/arm_gicv3_its_common.c
586
+++ b/hw/intc/arm_gicv3_its_common.c
587
@@ -XXX,XX +XXX,XX @@ void gicv3_its_init_mmio(GICv3ITSState *s, const MemoryRegionOps *ops,
588
msi_nonbroken = true;
589
}
590
591
-static void gicv3_its_common_reset_hold(Object *obj)
592
+static void gicv3_its_common_reset_hold(Object *obj, ResetType type)
593
{
594
GICv3ITSState *s = ARM_GICV3_ITS_COMMON(obj);
595
596
diff --git a/hw/intc/arm_gicv3_its_kvm.c b/hw/intc/arm_gicv3_its_kvm.c
597
index XXXXXXX..XXXXXXX 100644
598
--- a/hw/intc/arm_gicv3_its_kvm.c
599
+++ b/hw/intc/arm_gicv3_its_kvm.c
600
@@ -XXX,XX +XXX,XX @@ static void kvm_arm_its_post_load(GICv3ITSState *s)
601
GITS_CTLR, &s->ctlr, true, &error_abort);
602
}
603
604
-static void kvm_arm_its_reset_hold(Object *obj)
605
+static void kvm_arm_its_reset_hold(Object *obj, ResetType type)
606
{
607
GICv3ITSState *s = ARM_GICV3_ITS_COMMON(obj);
608
KVMARMITSClass *c = KVM_ARM_ITS_GET_CLASS(s);
609
int i;
610
611
if (c->parent_phases.hold) {
612
- c->parent_phases.hold(obj);
613
+ c->parent_phases.hold(obj, type);
614
}
615
616
if (kvm_device_check_attr(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_CTRL,
617
diff --git a/hw/intc/arm_gicv3_kvm.c b/hw/intc/arm_gicv3_kvm.c
618
index XXXXXXX..XXXXXXX 100644
619
--- a/hw/intc/arm_gicv3_kvm.c
620
+++ b/hw/intc/arm_gicv3_kvm.c
621
@@ -XXX,XX +XXX,XX @@ static void arm_gicv3_icc_reset(CPUARMState *env, const ARMCPRegInfo *ri)
622
c->icc_ctlr_el1[GICV3_S] = c->icc_ctlr_el1[GICV3_NS];
623
}
624
625
-static void kvm_arm_gicv3_reset_hold(Object *obj)
626
+static void kvm_arm_gicv3_reset_hold(Object *obj, ResetType type)
627
{
628
GICv3State *s = ARM_GICV3_COMMON(obj);
629
KVMARMGICv3Class *kgc = KVM_ARM_GICV3_GET_CLASS(s);
630
@@ -XXX,XX +XXX,XX @@ static void kvm_arm_gicv3_reset_hold(Object *obj)
631
DPRINTF("Reset\n");
632
633
if (kgc->parent_phases.hold) {
634
- kgc->parent_phases.hold(obj);
635
+ kgc->parent_phases.hold(obj, type);
636
}
637
638
if (s->migration_blocker) {
639
diff --git a/hw/intc/xics.c b/hw/intc/xics.c
640
index XXXXXXX..XXXXXXX 100644
641
--- a/hw/intc/xics.c
642
+++ b/hw/intc/xics.c
643
@@ -XXX,XX +XXX,XX @@ static void ics_reset_irq(ICSIRQState *irq)
644
irq->saved_priority = 0xff;
645
}
646
647
-static void ics_reset_hold(Object *obj)
648
+static void ics_reset_hold(Object *obj, ResetType type)
649
{
650
ICSState *ics = ICS(obj);
651
g_autofree uint8_t *flags = g_malloc(ics->nr_irqs);
652
diff --git a/hw/m68k/q800-glue.c b/hw/m68k/q800-glue.c
653
index XXXXXXX..XXXXXXX 100644
654
--- a/hw/m68k/q800-glue.c
655
+++ b/hw/m68k/q800-glue.c
656
@@ -XXX,XX +XXX,XX @@ static void glue_nmi_release(void *opaque)
657
GLUE_set_irq(s, GLUE_IRQ_IN_NMI, 0);
658
}
659
660
-static void glue_reset_hold(Object *obj)
661
+static void glue_reset_hold(Object *obj, ResetType type)
662
{
663
GLUEState *s = GLUE(obj);
664
665
diff --git a/hw/misc/djmemc.c b/hw/misc/djmemc.c
666
index XXXXXXX..XXXXXXX 100644
667
--- a/hw/misc/djmemc.c
668
+++ b/hw/misc/djmemc.c
669
@@ -XXX,XX +XXX,XX @@ static void djmemc_init(Object *obj)
670
sysbus_init_mmio(sbd, &s->mem_regs);
671
}
672
673
-static void djmemc_reset_hold(Object *obj)
674
+static void djmemc_reset_hold(Object *obj, ResetType type)
675
{
676
DJMEMCState *s = DJMEMC(obj);
677
678
diff --git a/hw/misc/iosb.c b/hw/misc/iosb.c
679
index XXXXXXX..XXXXXXX 100644
680
--- a/hw/misc/iosb.c
681
+++ b/hw/misc/iosb.c
682
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps iosb_mmio_ops = {
683
.endianness = DEVICE_BIG_ENDIAN,
684
};
685
686
-static void iosb_reset_hold(Object *obj)
687
+static void iosb_reset_hold(Object *obj, ResetType type)
688
{
689
IOSBState *s = IOSB(obj);
690
691
diff --git a/hw/misc/mac_via.c b/hw/misc/mac_via.c
692
index XXXXXXX..XXXXXXX 100644
693
--- a/hw/misc/mac_via.c
694
+++ b/hw/misc/mac_via.c
695
@@ -XXX,XX +XXX,XX @@ static int via1_post_load(void *opaque, int version_id)
696
}
697
698
/* VIA 1 */
699
-static void mos6522_q800_via1_reset_hold(Object *obj)
700
+static void mos6522_q800_via1_reset_hold(Object *obj, ResetType type)
701
{
702
MOS6522Q800VIA1State *v1s = MOS6522_Q800_VIA1(obj);
703
MOS6522State *ms = MOS6522(v1s);
704
@@ -XXX,XX +XXX,XX @@ static void mos6522_q800_via1_reset_hold(Object *obj)
705
ADBBusState *adb_bus = &v1s->adb_bus;
706
707
if (mdc->parent_phases.hold) {
708
- mdc->parent_phases.hold(obj);
709
+ mdc->parent_phases.hold(obj, type);
710
}
711
712
ms->timers[0].frequency = VIA_TIMER_FREQ;
713
@@ -XXX,XX +XXX,XX @@ static void mos6522_q800_via2_portB_write(MOS6522State *s)
714
}
715
}
716
717
-static void mos6522_q800_via2_reset_hold(Object *obj)
718
+static void mos6522_q800_via2_reset_hold(Object *obj, ResetType type)
719
{
720
MOS6522State *ms = MOS6522(obj);
721
MOS6522DeviceClass *mdc = MOS6522_GET_CLASS(ms);
722
723
if (mdc->parent_phases.hold) {
724
- mdc->parent_phases.hold(obj);
725
+ mdc->parent_phases.hold(obj, type);
726
}
727
728
ms->timers[0].frequency = VIA_TIMER_FREQ;
729
diff --git a/hw/misc/macio/cuda.c b/hw/misc/macio/cuda.c
730
index XXXXXXX..XXXXXXX 100644
731
--- a/hw/misc/macio/cuda.c
732
+++ b/hw/misc/macio/cuda.c
733
@@ -XXX,XX +XXX,XX @@ static void mos6522_cuda_portB_write(MOS6522State *s)
734
cuda_update(cs);
735
}
736
737
-static void mos6522_cuda_reset_hold(Object *obj)
738
+static void mos6522_cuda_reset_hold(Object *obj, ResetType type)
739
{
740
MOS6522State *ms = MOS6522(obj);
741
MOS6522DeviceClass *mdc = MOS6522_GET_CLASS(ms);
742
743
if (mdc->parent_phases.hold) {
744
- mdc->parent_phases.hold(obj);
745
+ mdc->parent_phases.hold(obj, type);
746
}
747
748
ms->timers[0].frequency = CUDA_TIMER_FREQ;
749
diff --git a/hw/misc/macio/pmu.c b/hw/misc/macio/pmu.c
750
index XXXXXXX..XXXXXXX 100644
751
--- a/hw/misc/macio/pmu.c
752
+++ b/hw/misc/macio/pmu.c
753
@@ -XXX,XX +XXX,XX @@ static void mos6522_pmu_portB_write(MOS6522State *s)
754
pmu_update(ps);
755
}
756
757
-static void mos6522_pmu_reset_hold(Object *obj)
758
+static void mos6522_pmu_reset_hold(Object *obj, ResetType type)
759
{
760
MOS6522State *ms = MOS6522(obj);
761
MOS6522PMUState *mps = container_of(ms, MOS6522PMUState, parent_obj);
762
@@ -XXX,XX +XXX,XX @@ static void mos6522_pmu_reset_hold(Object *obj)
763
MOS6522DeviceClass *mdc = MOS6522_GET_CLASS(ms);
764
765
if (mdc->parent_phases.hold) {
766
- mdc->parent_phases.hold(obj);
767
+ mdc->parent_phases.hold(obj, type);
768
}
769
770
ms->timers[0].frequency = VIA_TIMER_FREQ;
771
diff --git a/hw/misc/mos6522.c b/hw/misc/mos6522.c
772
index XXXXXXX..XXXXXXX 100644
773
--- a/hw/misc/mos6522.c
774
+++ b/hw/misc/mos6522.c
775
@@ -XXX,XX +XXX,XX @@ const VMStateDescription vmstate_mos6522 = {
776
}
777
};
778
779
-static void mos6522_reset_hold(Object *obj)
780
+static void mos6522_reset_hold(Object *obj, ResetType type)
781
{
782
MOS6522State *s = MOS6522(obj);
783
784
diff --git a/hw/misc/npcm7xx_mft.c b/hw/misc/npcm7xx_mft.c
785
index XXXXXXX..XXXXXXX 100644
786
--- a/hw/misc/npcm7xx_mft.c
787
+++ b/hw/misc/npcm7xx_mft.c
788
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_mft_enter_reset(Object *obj, ResetType type)
789
npcm7xx_mft_reset(s);
790
}
791
792
-static void npcm7xx_mft_hold_reset(Object *obj)
793
+static void npcm7xx_mft_hold_reset(Object *obj, ResetType type)
794
{
795
NPCM7xxMFTState *s = NPCM7XX_MFT(obj);
796
797
diff --git a/hw/misc/npcm7xx_pwm.c b/hw/misc/npcm7xx_pwm.c
798
index XXXXXXX..XXXXXXX 100644
799
--- a/hw/misc/npcm7xx_pwm.c
800
+++ b/hw/misc/npcm7xx_pwm.c
801
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_pwm_enter_reset(Object *obj, ResetType type)
802
s->piir = 0x00000000;
803
}
804
805
-static void npcm7xx_pwm_hold_reset(Object *obj)
806
+static void npcm7xx_pwm_hold_reset(Object *obj, ResetType type)
807
{
808
NPCM7xxPWMState *s = NPCM7XX_PWM(obj);
809
int i;
810
diff --git a/hw/misc/stm32l4x5_exti.c b/hw/misc/stm32l4x5_exti.c
811
index XXXXXXX..XXXXXXX 100644
812
--- a/hw/misc/stm32l4x5_exti.c
813
+++ b/hw/misc/stm32l4x5_exti.c
814
@@ -XXX,XX +XXX,XX @@ static unsigned configurable_mask(unsigned bank)
815
return valid_mask(bank) & ~exti_romask[bank];
816
}
817
818
-static void stm32l4x5_exti_reset_hold(Object *obj)
819
+static void stm32l4x5_exti_reset_hold(Object *obj, ResetType type)
820
{
821
Stm32l4x5ExtiState *s = STM32L4X5_EXTI(obj);
822
823
diff --git a/hw/misc/stm32l4x5_rcc.c b/hw/misc/stm32l4x5_rcc.c
824
index XXXXXXX..XXXXXXX 100644
825
--- a/hw/misc/stm32l4x5_rcc.c
826
+++ b/hw/misc/stm32l4x5_rcc.c
827
@@ -XXX,XX +XXX,XX @@ static void clock_mux_reset_enter(Object *obj, ResetType type)
828
set_clock_mux_init_info(s, s->id);
829
}
830
831
-static void clock_mux_reset_hold(Object *obj)
832
+static void clock_mux_reset_hold(Object *obj, ResetType type)
833
{
834
RccClockMuxState *s = RCC_CLOCK_MUX(obj);
835
clock_mux_update(s, true);
836
}
837
838
-static void clock_mux_reset_exit(Object *obj)
839
+static void clock_mux_reset_exit(Object *obj, ResetType type)
840
{
841
RccClockMuxState *s = RCC_CLOCK_MUX(obj);
842
clock_mux_update(s, false);
843
@@ -XXX,XX +XXX,XX @@ static void pll_reset_enter(Object *obj, ResetType type)
844
set_pll_init_info(s, s->id);
845
}
846
847
-static void pll_reset_hold(Object *obj)
848
+static void pll_reset_hold(Object *obj, ResetType type)
849
{
850
RccPllState *s = RCC_PLL(obj);
851
pll_update(s, true);
852
}
853
854
-static void pll_reset_exit(Object *obj)
855
+static void pll_reset_exit(Object *obj, ResetType type)
856
{
857
RccPllState *s = RCC_PLL(obj);
858
pll_update(s, false);
859
@@ -XXX,XX +XXX,XX @@ static void rcc_update_csr(Stm32l4x5RccState *s)
860
rcc_update_irq(s);
861
}
862
863
-static void stm32l4x5_rcc_reset_hold(Object *obj)
864
+static void stm32l4x5_rcc_reset_hold(Object *obj, ResetType type)
865
{
866
Stm32l4x5RccState *s = STM32L4X5_RCC(obj);
867
s->cr = 0x00000063;
868
diff --git a/hw/misc/stm32l4x5_syscfg.c b/hw/misc/stm32l4x5_syscfg.c
869
index XXXXXXX..XXXXXXX 100644
870
--- a/hw/misc/stm32l4x5_syscfg.c
871
+++ b/hw/misc/stm32l4x5_syscfg.c
872
@@ -XXX,XX +XXX,XX @@
873
874
#define NUM_LINES_PER_EXTICR_REG 4
875
876
-static void stm32l4x5_syscfg_hold_reset(Object *obj)
877
+static void stm32l4x5_syscfg_hold_reset(Object *obj, ResetType type)
878
{
879
Stm32l4x5SyscfgState *s = STM32L4X5_SYSCFG(obj);
880
881
diff --git a/hw/misc/xlnx-versal-cframe-reg.c b/hw/misc/xlnx-versal-cframe-reg.c
882
index XXXXXXX..XXXXXXX 100644
883
--- a/hw/misc/xlnx-versal-cframe-reg.c
884
+++ b/hw/misc/xlnx-versal-cframe-reg.c
885
@@ -XXX,XX +XXX,XX @@ static void cframe_reg_reset_enter(Object *obj, ResetType type)
886
}
887
}
888
889
-static void cframe_reg_reset_hold(Object *obj)
890
+static void cframe_reg_reset_hold(Object *obj, ResetType type)
891
{
892
XlnxVersalCFrameReg *s = XLNX_VERSAL_CFRAME_REG(obj);
893
894
diff --git a/hw/misc/xlnx-versal-crl.c b/hw/misc/xlnx-versal-crl.c
895
index XXXXXXX..XXXXXXX 100644
896
--- a/hw/misc/xlnx-versal-crl.c
897
+++ b/hw/misc/xlnx-versal-crl.c
898
@@ -XXX,XX +XXX,XX @@ static void crl_reset_enter(Object *obj, ResetType type)
899
}
900
}
901
902
-static void crl_reset_hold(Object *obj)
903
+static void crl_reset_hold(Object *obj, ResetType type)
904
{
905
XlnxVersalCRL *s = XLNX_VERSAL_CRL(obj);
906
907
diff --git a/hw/misc/xlnx-versal-pmc-iou-slcr.c b/hw/misc/xlnx-versal-pmc-iou-slcr.c
908
index XXXXXXX..XXXXXXX 100644
909
--- a/hw/misc/xlnx-versal-pmc-iou-slcr.c
910
+++ b/hw/misc/xlnx-versal-pmc-iou-slcr.c
911
@@ -XXX,XX +XXX,XX @@ static void xlnx_versal_pmc_iou_slcr_reset_init(Object *obj, ResetType type)
912
}
913
}
914
915
-static void xlnx_versal_pmc_iou_slcr_reset_hold(Object *obj)
916
+static void xlnx_versal_pmc_iou_slcr_reset_hold(Object *obj, ResetType type)
917
{
918
XlnxVersalPmcIouSlcr *s = XILINX_VERSAL_PMC_IOU_SLCR(obj);
919
920
diff --git a/hw/misc/xlnx-versal-trng.c b/hw/misc/xlnx-versal-trng.c
921
index XXXXXXX..XXXXXXX 100644
922
--- a/hw/misc/xlnx-versal-trng.c
923
+++ b/hw/misc/xlnx-versal-trng.c
924
@@ -XXX,XX +XXX,XX @@ static void trng_unrealize(DeviceState *dev)
925
s->prng = NULL;
926
}
927
928
-static void trng_reset_hold(Object *obj)
929
+static void trng_reset_hold(Object *obj, ResetType type)
930
{
931
trng_reset(XLNX_VERSAL_TRNG(obj));
932
}
933
diff --git a/hw/misc/xlnx-versal-xramc.c b/hw/misc/xlnx-versal-xramc.c
934
index XXXXXXX..XXXXXXX 100644
935
--- a/hw/misc/xlnx-versal-xramc.c
936
+++ b/hw/misc/xlnx-versal-xramc.c
937
@@ -XXX,XX +XXX,XX @@ static void xram_ctrl_reset_enter(Object *obj, ResetType type)
938
ARRAY_FIELD_DP32(s->regs, XRAM_IMP, SIZE, s->cfg.encoded_size);
939
}
940
941
-static void xram_ctrl_reset_hold(Object *obj)
942
+static void xram_ctrl_reset_hold(Object *obj, ResetType type)
943
{
944
XlnxXramCtrl *s = XLNX_XRAM_CTRL(obj);
945
946
diff --git a/hw/misc/xlnx-zynqmp-apu-ctrl.c b/hw/misc/xlnx-zynqmp-apu-ctrl.c
947
index XXXXXXX..XXXXXXX 100644
948
--- a/hw/misc/xlnx-zynqmp-apu-ctrl.c
949
+++ b/hw/misc/xlnx-zynqmp-apu-ctrl.c
950
@@ -XXX,XX +XXX,XX @@ static void zynqmp_apu_reset_enter(Object *obj, ResetType type)
951
s->cpu_in_wfi = 0;
952
}
953
954
-static void zynqmp_apu_reset_hold(Object *obj)
955
+static void zynqmp_apu_reset_hold(Object *obj, ResetType type)
956
{
957
XlnxZynqMPAPUCtrl *s = XLNX_ZYNQMP_APU_CTRL(obj);
958
959
diff --git a/hw/misc/xlnx-zynqmp-crf.c b/hw/misc/xlnx-zynqmp-crf.c
960
index XXXXXXX..XXXXXXX 100644
961
--- a/hw/misc/xlnx-zynqmp-crf.c
962
+++ b/hw/misc/xlnx-zynqmp-crf.c
963
@@ -XXX,XX +XXX,XX @@ static void crf_reset_enter(Object *obj, ResetType type)
964
}
965
}
966
967
-static void crf_reset_hold(Object *obj)
968
+static void crf_reset_hold(Object *obj, ResetType type)
969
{
970
XlnxZynqMPCRF *s = XLNX_ZYNQMP_CRF(obj);
971
ir_update_irq(s);
972
diff --git a/hw/misc/zynq_slcr.c b/hw/misc/zynq_slcr.c
973
index XXXXXXX..XXXXXXX 100644
974
--- a/hw/misc/zynq_slcr.c
975
+++ b/hw/misc/zynq_slcr.c
976
@@ -XXX,XX +XXX,XX @@ static void zynq_slcr_reset_init(Object *obj, ResetType type)
977
s->regs[R_DDRIOB + 12] = 0x00000021;
978
}
979
980
-static void zynq_slcr_reset_hold(Object *obj)
981
+static void zynq_slcr_reset_hold(Object *obj, ResetType type)
982
{
983
ZynqSLCRState *s = ZYNQ_SLCR(obj);
984
985
@@ -XXX,XX +XXX,XX @@ static void zynq_slcr_reset_hold(Object *obj)
986
zynq_slcr_propagate_clocks(s);
987
}
988
989
-static void zynq_slcr_reset_exit(Object *obj)
990
+static void zynq_slcr_reset_exit(Object *obj, ResetType type)
991
{
992
ZynqSLCRState *s = ZYNQ_SLCR(obj);
993
994
diff --git a/hw/net/can/xlnx-zynqmp-can.c b/hw/net/can/xlnx-zynqmp-can.c
995
index XXXXXXX..XXXXXXX 100644
996
--- a/hw/net/can/xlnx-zynqmp-can.c
997
+++ b/hw/net/can/xlnx-zynqmp-can.c
998
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_can_reset_init(Object *obj, ResetType type)
999
ptimer_transaction_commit(s->can_timer);
1000
}
1001
1002
-static void xlnx_zynqmp_can_reset_hold(Object *obj)
1003
+static void xlnx_zynqmp_can_reset_hold(Object *obj, ResetType type)
1004
{
1005
XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(obj);
1006
unsigned int i;
1007
diff --git a/hw/net/e1000.c b/hw/net/e1000.c
1008
index XXXXXXX..XXXXXXX 100644
1009
--- a/hw/net/e1000.c
1010
+++ b/hw/net/e1000.c
1011
@@ -XXX,XX +XXX,XX @@ static bool e1000_vet_init_need(void *opaque)
1012
return chkflag(VET);
1013
}
1014
1015
-static void e1000_reset_hold(Object *obj)
1016
+static void e1000_reset_hold(Object *obj, ResetType type)
1017
{
1018
E1000State *d = E1000(obj);
1019
E1000BaseClass *edc = E1000_GET_CLASS(d);
1020
diff --git a/hw/net/e1000e.c b/hw/net/e1000e.c
1021
index XXXXXXX..XXXXXXX 100644
1022
--- a/hw/net/e1000e.c
1023
+++ b/hw/net/e1000e.c
1024
@@ -XXX,XX +XXX,XX @@ static void e1000e_pci_uninit(PCIDevice *pci_dev)
1025
msi_uninit(pci_dev);
1026
}
1027
1028
-static void e1000e_qdev_reset_hold(Object *obj)
1029
+static void e1000e_qdev_reset_hold(Object *obj, ResetType type)
1030
{
1031
E1000EState *s = E1000E(obj);
1032
1033
diff --git a/hw/net/igb.c b/hw/net/igb.c
1034
index XXXXXXX..XXXXXXX 100644
1035
--- a/hw/net/igb.c
1036
+++ b/hw/net/igb.c
1037
@@ -XXX,XX +XXX,XX @@ static void igb_pci_uninit(PCIDevice *pci_dev)
1038
msi_uninit(pci_dev);
1039
}
1040
1041
-static void igb_qdev_reset_hold(Object *obj)
1042
+static void igb_qdev_reset_hold(Object *obj, ResetType type)
1043
{
1044
IGBState *s = IGB(obj);
1045
1046
diff --git a/hw/net/igbvf.c b/hw/net/igbvf.c
1047
index XXXXXXX..XXXXXXX 100644
1048
--- a/hw/net/igbvf.c
1049
+++ b/hw/net/igbvf.c
1050
@@ -XXX,XX +XXX,XX @@ static void igbvf_pci_realize(PCIDevice *dev, Error **errp)
1051
pcie_ari_init(dev, 0x150);
1052
}
1053
1054
-static void igbvf_qdev_reset_hold(Object *obj)
1055
+static void igbvf_qdev_reset_hold(Object *obj, ResetType type)
1056
{
1057
PCIDevice *vf = PCI_DEVICE(obj);
1058
1059
diff --git a/hw/nvram/xlnx-bbram.c b/hw/nvram/xlnx-bbram.c
1060
index XXXXXXX..XXXXXXX 100644
1061
--- a/hw/nvram/xlnx-bbram.c
1062
+++ b/hw/nvram/xlnx-bbram.c
1063
@@ -XXX,XX +XXX,XX @@ static RegisterAccessInfo bbram_ctrl_regs_info[] = {
1064
}
1065
};
1066
1067
-static void bbram_ctrl_reset_hold(Object *obj)
1068
+static void bbram_ctrl_reset_hold(Object *obj, ResetType type)
1069
{
1070
XlnxBBRam *s = XLNX_BBRAM(obj);
1071
unsigned int i;
1072
diff --git a/hw/nvram/xlnx-versal-efuse-ctrl.c b/hw/nvram/xlnx-versal-efuse-ctrl.c
1073
index XXXXXXX..XXXXXXX 100644
1074
--- a/hw/nvram/xlnx-versal-efuse-ctrl.c
1075
+++ b/hw/nvram/xlnx-versal-efuse-ctrl.c
1076
@@ -XXX,XX +XXX,XX @@ static void efuse_ctrl_register_reset(RegisterInfo *reg)
1077
register_reset(reg);
1078
}
1079
1080
-static void efuse_ctrl_reset_hold(Object *obj)
1081
+static void efuse_ctrl_reset_hold(Object *obj, ResetType type)
1082
{
1083
XlnxVersalEFuseCtrl *s = XLNX_VERSAL_EFUSE_CTRL(obj);
1084
unsigned int i;
1085
diff --git a/hw/nvram/xlnx-zynqmp-efuse.c b/hw/nvram/xlnx-zynqmp-efuse.c
1086
index XXXXXXX..XXXXXXX 100644
1087
--- a/hw/nvram/xlnx-zynqmp-efuse.c
1088
+++ b/hw/nvram/xlnx-zynqmp-efuse.c
1089
@@ -XXX,XX +XXX,XX @@ static void zynqmp_efuse_register_reset(RegisterInfo *reg)
1090
register_reset(reg);
1091
}
1092
1093
-static void zynqmp_efuse_reset_hold(Object *obj)
1094
+static void zynqmp_efuse_reset_hold(Object *obj, ResetType type)
1095
{
1096
XlnxZynqMPEFuse *s = XLNX_ZYNQMP_EFUSE(obj);
1097
unsigned int i;
1098
diff --git a/hw/pci-bridge/cxl_root_port.c b/hw/pci-bridge/cxl_root_port.c
1099
index XXXXXXX..XXXXXXX 100644
1100
--- a/hw/pci-bridge/cxl_root_port.c
1101
+++ b/hw/pci-bridge/cxl_root_port.c
1102
@@ -XXX,XX +XXX,XX @@ static void cxl_rp_realize(DeviceState *dev, Error **errp)
1103
component_bar);
1104
}
1105
1106
-static void cxl_rp_reset_hold(Object *obj)
1107
+static void cxl_rp_reset_hold(Object *obj, ResetType type)
1108
{
1109
PCIERootPortClass *rpc = PCIE_ROOT_PORT_GET_CLASS(obj);
1110
CXLRootPort *crp = CXL_ROOT_PORT(obj);
1111
1112
if (rpc->parent_phases.hold) {
1113
- rpc->parent_phases.hold(obj);
1114
+ rpc->parent_phases.hold(obj, type);
1115
}
1116
1117
latch_registers(crp);
1118
diff --git a/hw/pci-bridge/pcie_root_port.c b/hw/pci-bridge/pcie_root_port.c
1119
index XXXXXXX..XXXXXXX 100644
1120
--- a/hw/pci-bridge/pcie_root_port.c
1121
+++ b/hw/pci-bridge/pcie_root_port.c
1122
@@ -XXX,XX +XXX,XX @@ static void rp_write_config(PCIDevice *d, uint32_t address,
1123
pcie_aer_root_write_config(d, address, val, len, root_cmd);
1124
}
1125
1126
-static void rp_reset_hold(Object *obj)
1127
+static void rp_reset_hold(Object *obj, ResetType type)
1128
{
1129
PCIDevice *d = PCI_DEVICE(obj);
1130
DeviceState *qdev = DEVICE(obj);
1131
diff --git a/hw/pci-host/bonito.c b/hw/pci-host/bonito.c
1132
index XXXXXXX..XXXXXXX 100644
1133
--- a/hw/pci-host/bonito.c
1134
+++ b/hw/pci-host/bonito.c
1135
@@ -XXX,XX +XXX,XX @@ static int pci_bonito_map_irq(PCIDevice *pci_dev, int irq_num)
1136
}
1137
}
1138
1139
-static void bonito_reset_hold(Object *obj)
1140
+static void bonito_reset_hold(Object *obj, ResetType type)
1141
{
1142
PCIBonitoState *s = PCI_BONITO(obj);
1143
uint32_t val = 0;
1144
diff --git a/hw/pci-host/pnv_phb.c b/hw/pci-host/pnv_phb.c
1145
index XXXXXXX..XXXXXXX 100644
1146
--- a/hw/pci-host/pnv_phb.c
1147
+++ b/hw/pci-host/pnv_phb.c
1148
@@ -XXX,XX +XXX,XX @@ static void pnv_phb_class_init(ObjectClass *klass, void *data)
1149
dc->user_creatable = true;
1150
}
1151
1152
-static void pnv_phb_root_port_reset_hold(Object *obj)
1153
+static void pnv_phb_root_port_reset_hold(Object *obj, ResetType type)
1154
{
1155
PCIERootPortClass *rpc = PCIE_ROOT_PORT_GET_CLASS(obj);
1156
PnvPHBRootPort *phb_rp = PNV_PHB_ROOT_PORT(obj);
1157
@@ -XXX,XX +XXX,XX @@ static void pnv_phb_root_port_reset_hold(Object *obj)
1158
uint8_t *conf = d->config;
1159
1160
if (rpc->parent_phases.hold) {
1161
- rpc->parent_phases.hold(obj);
1162
+ rpc->parent_phases.hold(obj, type);
1163
}
1164
1165
if (phb_rp->version == 3) {
1166
diff --git a/hw/pci-host/pnv_phb3_msi.c b/hw/pci-host/pnv_phb3_msi.c
1167
index XXXXXXX..XXXXXXX 100644
1168
--- a/hw/pci-host/pnv_phb3_msi.c
1169
+++ b/hw/pci-host/pnv_phb3_msi.c
1170
@@ -XXX,XX +XXX,XX @@ static void phb3_msi_resend(ICSState *ics)
1171
}
1172
}
1173
1174
-static void phb3_msi_reset_hold(Object *obj)
1175
+static void phb3_msi_reset_hold(Object *obj, ResetType type)
1176
{
1177
Phb3MsiState *msi = PHB3_MSI(obj);
1178
ICSStateClass *icsc = ICS_GET_CLASS(obj);
1179
1180
if (icsc->parent_phases.hold) {
1181
- icsc->parent_phases.hold(obj);
1182
+ icsc->parent_phases.hold(obj, type);
1183
}
1184
1185
memset(msi->rba, 0, sizeof(msi->rba));
1186
diff --git a/hw/pci/pci.c b/hw/pci/pci.c
1187
index XXXXXXX..XXXXXXX 100644
1188
--- a/hw/pci/pci.c
1189
+++ b/hw/pci/pci.c
1190
@@ -XXX,XX +XXX,XX @@ bool pci_available = true;
1191
1192
static char *pcibus_get_dev_path(DeviceState *dev);
1193
static char *pcibus_get_fw_dev_path(DeviceState *dev);
1194
-static void pcibus_reset_hold(Object *obj);
1195
+static void pcibus_reset_hold(Object *obj, ResetType type);
1196
static bool pcie_has_upstream_port(PCIDevice *dev);
1197
1198
static Property pci_props[] = {
1199
@@ -XXX,XX +XXX,XX @@ void pci_device_reset(PCIDevice *dev)
1200
* Called via bus_cold_reset on RST# assert, after the devices
1201
* have been reset device_cold_reset-ed already.
1202
*/
1203
-static void pcibus_reset_hold(Object *obj)
1204
+static void pcibus_reset_hold(Object *obj, ResetType type)
1205
{
1206
PCIBus *bus = PCI_BUS(obj);
1207
int i;
1208
diff --git a/hw/rtc/mc146818rtc.c b/hw/rtc/mc146818rtc.c
1209
index XXXXXXX..XXXXXXX 100644
1210
--- a/hw/rtc/mc146818rtc.c
1211
+++ b/hw/rtc/mc146818rtc.c
1212
@@ -XXX,XX +XXX,XX @@ static void rtc_reset_enter(Object *obj, ResetType type)
1213
}
1214
}
1215
1216
-static void rtc_reset_hold(Object *obj)
1217
+static void rtc_reset_hold(Object *obj, ResetType type)
1218
{
1219
MC146818RtcState *s = MC146818_RTC(obj);
1220
1221
diff --git a/hw/s390x/css-bridge.c b/hw/s390x/css-bridge.c
1222
index XXXXXXX..XXXXXXX 100644
1223
--- a/hw/s390x/css-bridge.c
1224
+++ b/hw/s390x/css-bridge.c
1225
@@ -XXX,XX +XXX,XX @@ static void ccw_device_unplug(HotplugHandler *hotplug_dev,
1226
qdev_unrealize(dev);
1227
}
1228
1229
-static void virtual_css_bus_reset_hold(Object *obj)
1230
+static void virtual_css_bus_reset_hold(Object *obj, ResetType type)
1231
{
1232
/* This should actually be modelled via the generic css */
1233
css_reset();
1234
diff --git a/hw/sensor/adm1266.c b/hw/sensor/adm1266.c
1235
index XXXXXXX..XXXXXXX 100644
1236
--- a/hw/sensor/adm1266.c
1237
+++ b/hw/sensor/adm1266.c
1238
@@ -XXX,XX +XXX,XX @@ static const uint8_t adm1266_ic_device_id[] = {0x03, 0x41, 0x12, 0x66};
1239
static const uint8_t adm1266_ic_device_rev[] = {0x08, 0x01, 0x08, 0x07, 0x0,
1240
0x0, 0x07, 0x41, 0x30};
1241
1242
-static void adm1266_exit_reset(Object *obj)
1243
+static void adm1266_exit_reset(Object *obj, ResetType type)
1244
{
1245
ADM1266State *s = ADM1266(obj);
1246
PMBusDevice *pmdev = PMBUS_DEVICE(obj);
1247
diff --git a/hw/sensor/adm1272.c b/hw/sensor/adm1272.c
1248
index XXXXXXX..XXXXXXX 100644
1249
--- a/hw/sensor/adm1272.c
1250
+++ b/hw/sensor/adm1272.c
1251
@@ -XXX,XX +XXX,XX @@ static uint32_t adm1272_direct_to_watts(uint16_t value)
1252
return pmbus_direct_mode2data(c, value);
1253
}
1254
1255
-static void adm1272_exit_reset(Object *obj)
1256
+static void adm1272_exit_reset(Object *obj, ResetType type)
1257
{
1258
ADM1272State *s = ADM1272(obj);
1259
PMBusDevice *pmdev = PMBUS_DEVICE(obj);
1260
diff --git a/hw/sensor/isl_pmbus_vr.c b/hw/sensor/isl_pmbus_vr.c
1261
index XXXXXXX..XXXXXXX 100644
1262
--- a/hw/sensor/isl_pmbus_vr.c
1263
+++ b/hw/sensor/isl_pmbus_vr.c
1264
@@ -XXX,XX +XXX,XX @@ static void isl_pmbus_vr_set(Object *obj, Visitor *v, const char *name,
1265
pmbus_check_limits(pmdev);
1266
}
1267
1268
-static void isl_pmbus_vr_exit_reset(Object *obj)
1269
+static void isl_pmbus_vr_exit_reset(Object *obj, ResetType type)
1270
{
1271
PMBusDevice *pmdev = PMBUS_DEVICE(obj);
1272
1273
@@ -XXX,XX +XXX,XX @@ static void isl_pmbus_vr_exit_reset(Object *obj)
1274
}
1275
1276
/* The raa228000 uses different direct mode coefficients from most isl devices */
1277
-static void raa228000_exit_reset(Object *obj)
1278
+static void raa228000_exit_reset(Object *obj, ResetType type)
1279
{
1280
PMBusDevice *pmdev = PMBUS_DEVICE(obj);
1281
1282
- isl_pmbus_vr_exit_reset(obj);
1283
+ isl_pmbus_vr_exit_reset(obj, type);
1284
1285
pmdev->pages[0].read_iout = 0;
1286
pmdev->pages[0].read_pout = 0;
1287
@@ -XXX,XX +XXX,XX @@ static void raa228000_exit_reset(Object *obj)
1288
pmdev->pages[0].read_temperature_3 = 0;
1289
}
1290
1291
-static void isl69259_exit_reset(Object *obj)
1292
+static void isl69259_exit_reset(Object *obj, ResetType type)
1293
{
1294
ISLState *s = ISL69260(obj);
1295
static const uint8_t ic_device_id[] = {0x04, 0x00, 0x81, 0xD2, 0x49, 0x3c};
1296
g_assert(sizeof(ic_device_id) <= sizeof(s->ic_device_id));
1297
1298
- isl_pmbus_vr_exit_reset(obj);
1299
+ isl_pmbus_vr_exit_reset(obj, type);
1300
1301
s->ic_device_id_len = sizeof(ic_device_id);
1302
memcpy(s->ic_device_id, ic_device_id, sizeof(ic_device_id));
1303
diff --git a/hw/sensor/max31785.c b/hw/sensor/max31785.c
1304
index XXXXXXX..XXXXXXX 100644
1305
--- a/hw/sensor/max31785.c
1306
+++ b/hw/sensor/max31785.c
1307
@@ -XXX,XX +XXX,XX @@ static int max31785_write_data(PMBusDevice *pmdev, const uint8_t *buf,
1308
return 0;
1309
}
1310
1311
-static void max31785_exit_reset(Object *obj)
1312
+static void max31785_exit_reset(Object *obj, ResetType type)
1313
{
1314
PMBusDevice *pmdev = PMBUS_DEVICE(obj);
1315
MAX31785State *s = MAX31785(obj);
1316
diff --git a/hw/sensor/max34451.c b/hw/sensor/max34451.c
1317
index XXXXXXX..XXXXXXX 100644
1318
--- a/hw/sensor/max34451.c
1319
+++ b/hw/sensor/max34451.c
1320
@@ -XXX,XX +XXX,XX @@ static inline void *memset_word(void *s, uint16_t c, size_t n)
1321
return s;
1322
}
1323
1324
-static void max34451_exit_reset(Object *obj)
1325
+static void max34451_exit_reset(Object *obj, ResetType type)
1326
{
1327
PMBusDevice *pmdev = PMBUS_DEVICE(obj);
1328
MAX34451State *s = MAX34451(obj);
1329
diff --git a/hw/ssi/npcm7xx_fiu.c b/hw/ssi/npcm7xx_fiu.c
1330
index XXXXXXX..XXXXXXX 100644
1331
--- a/hw/ssi/npcm7xx_fiu.c
1332
+++ b/hw/ssi/npcm7xx_fiu.c
1333
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_fiu_enter_reset(Object *obj, ResetType type)
1334
s->regs[NPCM7XX_FIU_CFG] = 0x0000000b;
1335
}
1336
1337
-static void npcm7xx_fiu_hold_reset(Object *obj)
1338
+static void npcm7xx_fiu_hold_reset(Object *obj, ResetType type)
1339
{
1340
NPCM7xxFIUState *s = NPCM7XX_FIU(obj);
1341
int i;
1342
diff --git a/hw/timer/etraxfs_timer.c b/hw/timer/etraxfs_timer.c
1343
index XXXXXXX..XXXXXXX 100644
1344
--- a/hw/timer/etraxfs_timer.c
1345
+++ b/hw/timer/etraxfs_timer.c
1346
@@ -XXX,XX +XXX,XX @@ static void etraxfs_timer_reset_enter(Object *obj, ResetType type)
1347
t->rw_intr_mask = 0;
1348
}
1349
1350
-static void etraxfs_timer_reset_hold(Object *obj)
1351
+static void etraxfs_timer_reset_hold(Object *obj, ResetType type)
1352
{
1353
ETRAXTimerState *t = ETRAX_TIMER(obj);
1354
12
diff --git a/hw/timer/npcm7xx_timer.c b/hw/timer/npcm7xx_timer.c
1355
diff --git a/hw/timer/npcm7xx_timer.c b/hw/timer/npcm7xx_timer.c
13
index XXXXXXX..XXXXXXX 100644
1356
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/timer/npcm7xx_timer.c
1357
--- a/hw/timer/npcm7xx_timer.c
15
+++ b/hw/timer/npcm7xx_timer.c
1358
+++ b/hw/timer/npcm7xx_timer.c
16
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_timer_pause(NPCM7xxTimer *t)
1359
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_watchdog_timer_expired(void *opaque)
17
timer_del(&t->qtimer);
1360
}
18
now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
1361
}
19
t->remaining_ns = t->expires_ns - now;
1362
20
- if (t->remaining_ns <= 0) {
1363
-static void npcm7xx_timer_hold_reset(Object *obj)
21
- npcm7xx_timer_reached_zero(t);
1364
+static void npcm7xx_timer_hold_reset(Object *obj, ResetType type)
22
- }
1365
{
23
}
1366
NPCM7xxTimerCtrlState *s = NPCM7XX_TIMER(obj);
24
1367
int i;
25
/*
1368
diff --git a/hw/usb/hcd-dwc2.c b/hw/usb/hcd-dwc2.c
26
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_timer_write_tcsr(NPCM7xxTimer *t, uint32_t new_tcsr)
1369
index XXXXXXX..XXXXXXX 100644
27
} else {
1370
--- a/hw/usb/hcd-dwc2.c
28
t->tcsr &= ~NPCM7XX_TCSR_CACT;
1371
+++ b/hw/usb/hcd-dwc2.c
29
npcm7xx_timer_pause(t);
1372
@@ -XXX,XX +XXX,XX @@ static void dwc2_reset_enter(Object *obj, ResetType type)
30
+ if (t->remaining_ns <= 0) {
1373
}
31
+ npcm7xx_timer_reached_zero(t);
1374
}
32
+ }
1375
33
}
1376
-static void dwc2_reset_hold(Object *obj)
34
}
1377
+static void dwc2_reset_hold(Object *obj, ResetType type)
35
}
1378
{
1379
DWC2Class *c = DWC2_USB_GET_CLASS(obj);
1380
DWC2State *s = DWC2_USB(obj);
1381
@@ -XXX,XX +XXX,XX @@ static void dwc2_reset_hold(Object *obj)
1382
trace_usb_dwc2_reset_hold();
1383
1384
if (c->parent_phases.hold) {
1385
- c->parent_phases.hold(obj);
1386
+ c->parent_phases.hold(obj, type);
1387
}
1388
1389
dwc2_update_irq(s);
1390
}
1391
1392
-static void dwc2_reset_exit(Object *obj)
1393
+static void dwc2_reset_exit(Object *obj, ResetType type)
1394
{
1395
DWC2Class *c = DWC2_USB_GET_CLASS(obj);
1396
DWC2State *s = DWC2_USB(obj);
1397
@@ -XXX,XX +XXX,XX @@ static void dwc2_reset_exit(Object *obj)
1398
trace_usb_dwc2_reset_exit();
1399
1400
if (c->parent_phases.exit) {
1401
- c->parent_phases.exit(obj);
1402
+ c->parent_phases.exit(obj, type);
1403
}
1404
1405
s->hprt0 = HPRT0_PWR;
1406
diff --git a/hw/usb/xlnx-versal-usb2-ctrl-regs.c b/hw/usb/xlnx-versal-usb2-ctrl-regs.c
1407
index XXXXXXX..XXXXXXX 100644
1408
--- a/hw/usb/xlnx-versal-usb2-ctrl-regs.c
1409
+++ b/hw/usb/xlnx-versal-usb2-ctrl-regs.c
1410
@@ -XXX,XX +XXX,XX @@ static void usb2_ctrl_regs_reset_init(Object *obj, ResetType type)
1411
}
1412
}
1413
1414
-static void usb2_ctrl_regs_reset_hold(Object *obj)
1415
+static void usb2_ctrl_regs_reset_hold(Object *obj, ResetType type)
1416
{
1417
VersalUsb2CtrlRegs *s = XILINX_VERSAL_USB2_CTRL_REGS(obj);
1418
1419
diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
1420
index XXXXXXX..XXXXXXX 100644
1421
--- a/hw/virtio/virtio-pci.c
1422
+++ b/hw/virtio/virtio-pci.c
1423
@@ -XXX,XX +XXX,XX @@ static void virtio_pci_reset(DeviceState *qdev)
1424
}
1425
}
1426
1427
-static void virtio_pci_bus_reset_hold(Object *obj)
1428
+static void virtio_pci_bus_reset_hold(Object *obj, ResetType type)
1429
{
1430
PCIDevice *dev = PCI_DEVICE(obj);
1431
DeviceState *qdev = DEVICE(obj);
1432
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
1433
index XXXXXXX..XXXXXXX 100644
1434
--- a/target/arm/cpu.c
1435
+++ b/target/arm/cpu.c
1436
@@ -XXX,XX +XXX,XX @@ static void cp_reg_check_reset(gpointer key, gpointer value, gpointer opaque)
1437
assert(oldvalue == newvalue);
1438
}
1439
1440
-static void arm_cpu_reset_hold(Object *obj)
1441
+static void arm_cpu_reset_hold(Object *obj, ResetType type)
1442
{
1443
CPUState *cs = CPU(obj);
1444
ARMCPU *cpu = ARM_CPU(cs);
1445
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_reset_hold(Object *obj)
1446
CPUARMState *env = &cpu->env;
1447
1448
if (acc->parent_phases.hold) {
1449
- acc->parent_phases.hold(obj);
1450
+ acc->parent_phases.hold(obj, type);
1451
}
1452
1453
memset(env, 0, offsetof(CPUARMState, end_reset_fields));
1454
diff --git a/target/avr/cpu.c b/target/avr/cpu.c
1455
index XXXXXXX..XXXXXXX 100644
1456
--- a/target/avr/cpu.c
1457
+++ b/target/avr/cpu.c
1458
@@ -XXX,XX +XXX,XX @@ static void avr_restore_state_to_opc(CPUState *cs,
1459
cpu_env(cs)->pc_w = data[0];
1460
}
1461
1462
-static void avr_cpu_reset_hold(Object *obj)
1463
+static void avr_cpu_reset_hold(Object *obj, ResetType type)
1464
{
1465
CPUState *cs = CPU(obj);
1466
AVRCPU *cpu = AVR_CPU(cs);
1467
@@ -XXX,XX +XXX,XX @@ static void avr_cpu_reset_hold(Object *obj)
1468
CPUAVRState *env = &cpu->env;
1469
1470
if (mcc->parent_phases.hold) {
1471
- mcc->parent_phases.hold(obj);
1472
+ mcc->parent_phases.hold(obj, type);
1473
}
1474
1475
env->pc_w = 0;
1476
diff --git a/target/cris/cpu.c b/target/cris/cpu.c
1477
index XXXXXXX..XXXXXXX 100644
1478
--- a/target/cris/cpu.c
1479
+++ b/target/cris/cpu.c
1480
@@ -XXX,XX +XXX,XX @@ static int cris_cpu_mmu_index(CPUState *cs, bool ifetch)
1481
return !!(cpu_env(cs)->pregs[PR_CCS] & U_FLAG);
1482
}
1483
1484
-static void cris_cpu_reset_hold(Object *obj)
1485
+static void cris_cpu_reset_hold(Object *obj, ResetType type)
1486
{
1487
CPUState *cs = CPU(obj);
1488
CRISCPUClass *ccc = CRIS_CPU_GET_CLASS(obj);
1489
@@ -XXX,XX +XXX,XX @@ static void cris_cpu_reset_hold(Object *obj)
1490
uint32_t vr;
1491
1492
if (ccc->parent_phases.hold) {
1493
- ccc->parent_phases.hold(obj);
1494
+ ccc->parent_phases.hold(obj, type);
1495
}
1496
1497
vr = env->pregs[PR_VR];
1498
diff --git a/target/hexagon/cpu.c b/target/hexagon/cpu.c
1499
index XXXXXXX..XXXXXXX 100644
1500
--- a/target/hexagon/cpu.c
1501
+++ b/target/hexagon/cpu.c
1502
@@ -XXX,XX +XXX,XX @@ static void hexagon_restore_state_to_opc(CPUState *cs,
1503
cpu_env(cs)->gpr[HEX_REG_PC] = data[0];
1504
}
1505
1506
-static void hexagon_cpu_reset_hold(Object *obj)
1507
+static void hexagon_cpu_reset_hold(Object *obj, ResetType type)
1508
{
1509
CPUState *cs = CPU(obj);
1510
HexagonCPUClass *mcc = HEXAGON_CPU_GET_CLASS(obj);
1511
CPUHexagonState *env = cpu_env(cs);
1512
1513
if (mcc->parent_phases.hold) {
1514
- mcc->parent_phases.hold(obj);
1515
+ mcc->parent_phases.hold(obj, type);
1516
}
1517
1518
set_default_nan_mode(1, &env->fp_status);
1519
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
1520
index XXXXXXX..XXXXXXX 100644
1521
--- a/target/i386/cpu.c
1522
+++ b/target/i386/cpu.c
1523
@@ -XXX,XX +XXX,XX @@ static void x86_cpu_set_sgxlepubkeyhash(CPUX86State *env)
1524
#endif
1525
}
1526
1527
-static void x86_cpu_reset_hold(Object *obj)
1528
+static void x86_cpu_reset_hold(Object *obj, ResetType type)
1529
{
1530
CPUState *cs = CPU(obj);
1531
X86CPU *cpu = X86_CPU(cs);
1532
@@ -XXX,XX +XXX,XX @@ static void x86_cpu_reset_hold(Object *obj)
1533
int i;
1534
1535
if (xcc->parent_phases.hold) {
1536
- xcc->parent_phases.hold(obj);
1537
+ xcc->parent_phases.hold(obj, type);
1538
}
1539
1540
memset(env, 0, offsetof(CPUX86State, end_reset_fields));
1541
diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
1542
index XXXXXXX..XXXXXXX 100644
1543
--- a/target/loongarch/cpu.c
1544
+++ b/target/loongarch/cpu.c
1545
@@ -XXX,XX +XXX,XX @@ static void loongarch_max_initfn(Object *obj)
1546
loongarch_la464_initfn(obj);
1547
}
1548
1549
-static void loongarch_cpu_reset_hold(Object *obj)
1550
+static void loongarch_cpu_reset_hold(Object *obj, ResetType type)
1551
{
1552
CPUState *cs = CPU(obj);
1553
LoongArchCPUClass *lacc = LOONGARCH_CPU_GET_CLASS(obj);
1554
CPULoongArchState *env = cpu_env(cs);
1555
1556
if (lacc->parent_phases.hold) {
1557
- lacc->parent_phases.hold(obj);
1558
+ lacc->parent_phases.hold(obj, type);
1559
}
1560
1561
env->fcsr0_mask = FCSR0_M1 | FCSR0_M2 | FCSR0_M3;
1562
diff --git a/target/m68k/cpu.c b/target/m68k/cpu.c
1563
index XXXXXXX..XXXXXXX 100644
1564
--- a/target/m68k/cpu.c
1565
+++ b/target/m68k/cpu.c
1566
@@ -XXX,XX +XXX,XX @@ static void m68k_unset_feature(CPUM68KState *env, int feature)
1567
env->features &= ~BIT_ULL(feature);
1568
}
1569
1570
-static void m68k_cpu_reset_hold(Object *obj)
1571
+static void m68k_cpu_reset_hold(Object *obj, ResetType type)
1572
{
1573
CPUState *cs = CPU(obj);
1574
M68kCPUClass *mcc = M68K_CPU_GET_CLASS(obj);
1575
@@ -XXX,XX +XXX,XX @@ static void m68k_cpu_reset_hold(Object *obj)
1576
int i;
1577
1578
if (mcc->parent_phases.hold) {
1579
- mcc->parent_phases.hold(obj);
1580
+ mcc->parent_phases.hold(obj, type);
1581
}
1582
1583
memset(env, 0, offsetof(CPUM68KState, end_reset_fields));
1584
diff --git a/target/microblaze/cpu.c b/target/microblaze/cpu.c
1585
index XXXXXXX..XXXXXXX 100644
1586
--- a/target/microblaze/cpu.c
1587
+++ b/target/microblaze/cpu.c
1588
@@ -XXX,XX +XXX,XX @@ static void microblaze_cpu_set_irq(void *opaque, int irq, int level)
1589
}
1590
#endif
1591
1592
-static void mb_cpu_reset_hold(Object *obj)
1593
+static void mb_cpu_reset_hold(Object *obj, ResetType type)
1594
{
1595
CPUState *cs = CPU(obj);
1596
MicroBlazeCPU *cpu = MICROBLAZE_CPU(cs);
1597
@@ -XXX,XX +XXX,XX @@ static void mb_cpu_reset_hold(Object *obj)
1598
CPUMBState *env = &cpu->env;
1599
1600
if (mcc->parent_phases.hold) {
1601
- mcc->parent_phases.hold(obj);
1602
+ mcc->parent_phases.hold(obj, type);
1603
}
1604
1605
memset(env, 0, offsetof(CPUMBState, end_reset_fields));
1606
diff --git a/target/mips/cpu.c b/target/mips/cpu.c
1607
index XXXXXXX..XXXXXXX 100644
1608
--- a/target/mips/cpu.c
1609
+++ b/target/mips/cpu.c
1610
@@ -XXX,XX +XXX,XX @@ static int mips_cpu_mmu_index(CPUState *cs, bool ifunc)
1611
1612
#include "cpu-defs.c.inc"
1613
1614
-static void mips_cpu_reset_hold(Object *obj)
1615
+static void mips_cpu_reset_hold(Object *obj, ResetType type)
1616
{
1617
CPUState *cs = CPU(obj);
1618
MIPSCPU *cpu = MIPS_CPU(cs);
1619
@@ -XXX,XX +XXX,XX @@ static void mips_cpu_reset_hold(Object *obj)
1620
CPUMIPSState *env = &cpu->env;
1621
1622
if (mcc->parent_phases.hold) {
1623
- mcc->parent_phases.hold(obj);
1624
+ mcc->parent_phases.hold(obj, type);
1625
}
1626
1627
memset(env, 0, offsetof(CPUMIPSState, end_reset_fields));
1628
diff --git a/target/openrisc/cpu.c b/target/openrisc/cpu.c
1629
index XXXXXXX..XXXXXXX 100644
1630
--- a/target/openrisc/cpu.c
1631
+++ b/target/openrisc/cpu.c
1632
@@ -XXX,XX +XXX,XX @@ static void openrisc_disas_set_info(CPUState *cpu, disassemble_info *info)
1633
info->print_insn = print_insn_or1k;
1634
}
1635
1636
-static void openrisc_cpu_reset_hold(Object *obj)
1637
+static void openrisc_cpu_reset_hold(Object *obj, ResetType type)
1638
{
1639
CPUState *cs = CPU(obj);
1640
OpenRISCCPU *cpu = OPENRISC_CPU(cs);
1641
OpenRISCCPUClass *occ = OPENRISC_CPU_GET_CLASS(obj);
1642
1643
if (occ->parent_phases.hold) {
1644
- occ->parent_phases.hold(obj);
1645
+ occ->parent_phases.hold(obj, type);
1646
}
1647
1648
memset(&cpu->env, 0, offsetof(CPUOpenRISCState, end_reset_fields));
1649
diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
1650
index XXXXXXX..XXXXXXX 100644
1651
--- a/target/ppc/cpu_init.c
1652
+++ b/target/ppc/cpu_init.c
1653
@@ -XXX,XX +XXX,XX @@ static int ppc_cpu_mmu_index(CPUState *cs, bool ifetch)
1654
return ppc_env_mmu_index(cpu_env(cs), ifetch);
1655
}
1656
1657
-static void ppc_cpu_reset_hold(Object *obj)
1658
+static void ppc_cpu_reset_hold(Object *obj, ResetType type)
1659
{
1660
CPUState *cs = CPU(obj);
1661
PowerPCCPU *cpu = POWERPC_CPU(cs);
1662
@@ -XXX,XX +XXX,XX @@ static void ppc_cpu_reset_hold(Object *obj)
1663
int i;
1664
1665
if (pcc->parent_phases.hold) {
1666
- pcc->parent_phases.hold(obj);
1667
+ pcc->parent_phases.hold(obj, type);
1668
}
1669
1670
msr = (target_ulong)0;
1671
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
1672
index XXXXXXX..XXXXXXX 100644
1673
--- a/target/riscv/cpu.c
1674
+++ b/target/riscv/cpu.c
1675
@@ -XXX,XX +XXX,XX @@ static int riscv_cpu_mmu_index(CPUState *cs, bool ifetch)
1676
return riscv_env_mmu_index(cpu_env(cs), ifetch);
1677
}
1678
1679
-static void riscv_cpu_reset_hold(Object *obj)
1680
+static void riscv_cpu_reset_hold(Object *obj, ResetType type)
1681
{
1682
#ifndef CONFIG_USER_ONLY
1683
uint8_t iprio;
1684
@@ -XXX,XX +XXX,XX @@ static void riscv_cpu_reset_hold(Object *obj)
1685
CPURISCVState *env = &cpu->env;
1686
1687
if (mcc->parent_phases.hold) {
1688
- mcc->parent_phases.hold(obj);
1689
+ mcc->parent_phases.hold(obj, type);
1690
}
1691
#ifndef CONFIG_USER_ONLY
1692
env->misa_mxl = mcc->misa_mxl_max;
1693
diff --git a/target/rx/cpu.c b/target/rx/cpu.c
1694
index XXXXXXX..XXXXXXX 100644
1695
--- a/target/rx/cpu.c
1696
+++ b/target/rx/cpu.c
1697
@@ -XXX,XX +XXX,XX @@ static int riscv_cpu_mmu_index(CPUState *cs, bool ifunc)
1698
return 0;
1699
}
1700
1701
-static void rx_cpu_reset_hold(Object *obj)
1702
+static void rx_cpu_reset_hold(Object *obj, ResetType type)
1703
{
1704
CPUState *cs = CPU(obj);
1705
RXCPUClass *rcc = RX_CPU_GET_CLASS(obj);
1706
@@ -XXX,XX +XXX,XX @@ static void rx_cpu_reset_hold(Object *obj)
1707
uint32_t *resetvec;
1708
1709
if (rcc->parent_phases.hold) {
1710
- rcc->parent_phases.hold(obj);
1711
+ rcc->parent_phases.hold(obj, type);
1712
}
1713
1714
memset(env, 0, offsetof(CPURXState, end_reset_fields));
1715
diff --git a/target/sh4/cpu.c b/target/sh4/cpu.c
1716
index XXXXXXX..XXXXXXX 100644
1717
--- a/target/sh4/cpu.c
1718
+++ b/target/sh4/cpu.c
1719
@@ -XXX,XX +XXX,XX @@ static int sh4_cpu_mmu_index(CPUState *cs, bool ifetch)
1720
}
1721
}
1722
1723
-static void superh_cpu_reset_hold(Object *obj)
1724
+static void superh_cpu_reset_hold(Object *obj, ResetType type)
1725
{
1726
CPUState *cs = CPU(obj);
1727
SuperHCPUClass *scc = SUPERH_CPU_GET_CLASS(obj);
1728
CPUSH4State *env = cpu_env(cs);
1729
1730
if (scc->parent_phases.hold) {
1731
- scc->parent_phases.hold(obj);
1732
+ scc->parent_phases.hold(obj, type);
1733
}
1734
1735
memset(env, 0, offsetof(CPUSH4State, end_reset_fields));
1736
diff --git a/target/sparc/cpu.c b/target/sparc/cpu.c
1737
index XXXXXXX..XXXXXXX 100644
1738
--- a/target/sparc/cpu.c
1739
+++ b/target/sparc/cpu.c
1740
@@ -XXX,XX +XXX,XX @@
1741
1742
//#define DEBUG_FEATURES
1743
1744
-static void sparc_cpu_reset_hold(Object *obj)
1745
+static void sparc_cpu_reset_hold(Object *obj, ResetType type)
1746
{
1747
CPUState *cs = CPU(obj);
1748
SPARCCPUClass *scc = SPARC_CPU_GET_CLASS(obj);
1749
CPUSPARCState *env = cpu_env(cs);
1750
1751
if (scc->parent_phases.hold) {
1752
- scc->parent_phases.hold(obj);
1753
+ scc->parent_phases.hold(obj, type);
1754
}
1755
1756
memset(env, 0, offsetof(CPUSPARCState, end_reset_fields));
1757
diff --git a/target/tricore/cpu.c b/target/tricore/cpu.c
1758
index XXXXXXX..XXXXXXX 100644
1759
--- a/target/tricore/cpu.c
1760
+++ b/target/tricore/cpu.c
1761
@@ -XXX,XX +XXX,XX @@ static void tricore_restore_state_to_opc(CPUState *cs,
1762
cpu_env(cs)->PC = data[0];
1763
}
1764
1765
-static void tricore_cpu_reset_hold(Object *obj)
1766
+static void tricore_cpu_reset_hold(Object *obj, ResetType type)
1767
{
1768
CPUState *cs = CPU(obj);
1769
TriCoreCPUClass *tcc = TRICORE_CPU_GET_CLASS(obj);
1770
1771
if (tcc->parent_phases.hold) {
1772
- tcc->parent_phases.hold(obj);
1773
+ tcc->parent_phases.hold(obj, type);
1774
}
1775
1776
cpu_state_reset(cpu_env(cs));
1777
diff --git a/target/xtensa/cpu.c b/target/xtensa/cpu.c
1778
index XXXXXXX..XXXXXXX 100644
1779
--- a/target/xtensa/cpu.c
1780
+++ b/target/xtensa/cpu.c
1781
@@ -XXX,XX +XXX,XX @@ bool xtensa_abi_call0(void)
1782
}
1783
#endif
1784
1785
-static void xtensa_cpu_reset_hold(Object *obj)
1786
+static void xtensa_cpu_reset_hold(Object *obj, ResetType type)
1787
{
1788
CPUState *cs = CPU(obj);
1789
XtensaCPUClass *xcc = XTENSA_CPU_GET_CLASS(obj);
1790
@@ -XXX,XX +XXX,XX @@ static void xtensa_cpu_reset_hold(Object *obj)
1791
XTENSA_OPTION_DFP_COPROCESSOR);
1792
1793
if (xcc->parent_phases.hold) {
1794
- xcc->parent_phases.hold(obj);
1795
+ xcc->parent_phases.hold(obj, type);
1796
}
1797
1798
env->pc = env->config->exception_vector[EXC_RESET0 + env->static_vectors];
36
--
1799
--
37
2.20.1
1800
2.34.1
38
39
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
Update the reset documentation's example code to match the new API
2
for the hold and exit phase method APIs where they take a ResetType
3
argument.
2
4
3
Fix an unlikely memory leak in load_elf_image().
4
5
Fixes: bf858897b7 ("linux-user: Re-use load_elf_image for the main binary.")
6
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20201021173749.111103-5-richard.henderson@linaro.org
9
Message-Id: <20201003174944.1972444-1-f4bug@amsat.org>
10
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
8
Reviewed-by: Luc Michel <luc.michel@amd.com>
9
Message-id: 20240412160809.1260625-6-peter.maydell@linaro.org
13
---
10
---
14
linux-user/elfload.c | 8 ++++----
11
docs/devel/reset.rst | 8 ++++----
15
1 file changed, 4 insertions(+), 4 deletions(-)
12
1 file changed, 4 insertions(+), 4 deletions(-)
16
13
17
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
14
diff --git a/docs/devel/reset.rst b/docs/devel/reset.rst
18
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
19
--- a/linux-user/elfload.c
16
--- a/docs/devel/reset.rst
20
+++ b/linux-user/elfload.c
17
+++ b/docs/devel/reset.rst
21
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
18
@@ -XXX,XX +XXX,XX @@ in reset.
22
info->brk = vaddr_em;
19
mydev->var = 0;
23
}
24
} else if (eppnt->p_type == PT_INTERP && pinterp_name) {
25
- char *interp_name;
26
+ g_autofree char *interp_name = NULL;
27
28
if (*pinterp_name) {
29
errmsg = "Multiple PT_INTERP entries";
30
goto exit_errmsg;
31
}
32
- interp_name = malloc(eppnt->p_filesz);
33
+ interp_name = g_malloc(eppnt->p_filesz);
34
if (!interp_name) {
35
goto exit_perror;
36
}
37
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
38
errmsg = "Invalid PT_INTERP entry";
39
goto exit_errmsg;
40
}
41
- *pinterp_name = interp_name;
42
+ *pinterp_name = g_steal_pointer(&interp_name);
43
#ifdef TARGET_MIPS
44
} else if (eppnt->p_type == PT_MIPS_ABIFLAGS) {
45
Mips_elf_abiflags_v0 abiflags;
46
@@ -XXX,XX +XXX,XX @@ int load_elf_binary(struct linux_binprm *bprm, struct image_info *info)
47
if (elf_interpreter) {
48
info->load_bias = interp_info.load_bias;
49
info->entry = interp_info.entry;
50
- free(elf_interpreter);
51
+ g_free(elf_interpreter);
52
}
20
}
53
21
54
#ifdef USE_ELF_CORE_DUMP
22
- static void mydev_reset_hold(Object *obj)
23
+ static void mydev_reset_hold(Object *obj, ResetType type)
24
{
25
MyDevClass *myclass = MYDEV_GET_CLASS(obj);
26
MyDevState *mydev = MYDEV(obj);
27
/* call parent class hold phase */
28
if (myclass->parent_phases.hold) {
29
- myclass->parent_phases.hold(obj);
30
+ myclass->parent_phases.hold(obj, type);
31
}
32
/* set an IO */
33
qemu_set_irq(mydev->irq, 1);
34
}
35
36
- static void mydev_reset_exit(Object *obj)
37
+ static void mydev_reset_exit(Object *obj, ResetType type)
38
{
39
MyDevClass *myclass = MYDEV_GET_CLASS(obj);
40
MyDevState *mydev = MYDEV(obj);
41
/* call parent class exit phase */
42
if (myclass->parent_phases.exit) {
43
- myclass->parent_phases.exit(obj);
44
+ myclass->parent_phases.exit(obj, type);
45
}
46
/* clear an IO */
47
qemu_set_irq(mydev->irq, 0);
55
--
48
--
56
2.20.1
49
2.34.1
57
50
58
51
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
Fixing this now will clarify following patches.
4
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20201021173749.111103-6-richard.henderson@linaro.org
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
linux-user/elfload.c | 12 +++++++++---
11
1 file changed, 9 insertions(+), 3 deletions(-)
12
13
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/linux-user/elfload.c
16
+++ b/linux-user/elfload.c
17
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
18
abi_ulong vaddr, vaddr_po, vaddr_ps, vaddr_ef, vaddr_em, vaddr_len;
19
int elf_prot = 0;
20
21
- if (eppnt->p_flags & PF_R) elf_prot = PROT_READ;
22
- if (eppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;
23
- if (eppnt->p_flags & PF_X) elf_prot |= PROT_EXEC;
24
+ if (eppnt->p_flags & PF_R) {
25
+ elf_prot |= PROT_READ;
26
+ }
27
+ if (eppnt->p_flags & PF_W) {
28
+ elf_prot |= PROT_WRITE;
29
+ }
30
+ if (eppnt->p_flags & PF_X) {
31
+ elf_prot |= PROT_EXEC;
32
+ }
33
34
vaddr = load_bias + eppnt->p_vaddr;
35
vaddr_po = TARGET_ELF_PAGEOFFSET(vaddr);
36
--
37
2.20.1
38
39
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
For BTI, we need to know if the executable is static or dynamic,
4
which means looking for PT_INTERP earlier.
5
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20201021173749.111103-8-richard.henderson@linaro.org
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
linux-user/elfload.c | 60 +++++++++++++++++++++++---------------------
12
1 file changed, 31 insertions(+), 29 deletions(-)
13
14
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/linux-user/elfload.c
17
+++ b/linux-user/elfload.c
18
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
19
20
mmap_lock();
21
22
- /* Find the maximum size of the image and allocate an appropriate
23
- amount of memory to handle that. */
24
+ /*
25
+ * Find the maximum size of the image and allocate an appropriate
26
+ * amount of memory to handle that. Locate the interpreter, if any.
27
+ */
28
loaddr = -1, hiaddr = 0;
29
info->alignment = 0;
30
for (i = 0; i < ehdr->e_phnum; ++i) {
31
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
32
}
33
++info->nsegs;
34
info->alignment |= eppnt->p_align;
35
+ } else if (eppnt->p_type == PT_INTERP && pinterp_name) {
36
+ g_autofree char *interp_name = NULL;
37
+
38
+ if (*pinterp_name) {
39
+ errmsg = "Multiple PT_INTERP entries";
40
+ goto exit_errmsg;
41
+ }
42
+ interp_name = g_malloc(eppnt->p_filesz);
43
+ if (!interp_name) {
44
+ goto exit_perror;
45
+ }
46
+
47
+ if (eppnt->p_offset + eppnt->p_filesz <= BPRM_BUF_SIZE) {
48
+ memcpy(interp_name, bprm_buf + eppnt->p_offset,
49
+ eppnt->p_filesz);
50
+ } else {
51
+ retval = pread(image_fd, interp_name, eppnt->p_filesz,
52
+ eppnt->p_offset);
53
+ if (retval != eppnt->p_filesz) {
54
+ goto exit_perror;
55
+ }
56
+ }
57
+ if (interp_name[eppnt->p_filesz - 1] != 0) {
58
+ errmsg = "Invalid PT_INTERP entry";
59
+ goto exit_errmsg;
60
+ }
61
+ *pinterp_name = g_steal_pointer(&interp_name);
62
}
63
}
64
65
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
66
if (vaddr_em > info->brk) {
67
info->brk = vaddr_em;
68
}
69
- } else if (eppnt->p_type == PT_INTERP && pinterp_name) {
70
- g_autofree char *interp_name = NULL;
71
-
72
- if (*pinterp_name) {
73
- errmsg = "Multiple PT_INTERP entries";
74
- goto exit_errmsg;
75
- }
76
- interp_name = g_malloc(eppnt->p_filesz);
77
- if (!interp_name) {
78
- goto exit_perror;
79
- }
80
-
81
- if (eppnt->p_offset + eppnt->p_filesz <= BPRM_BUF_SIZE) {
82
- memcpy(interp_name, bprm_buf + eppnt->p_offset,
83
- eppnt->p_filesz);
84
- } else {
85
- retval = pread(image_fd, interp_name, eppnt->p_filesz,
86
- eppnt->p_offset);
87
- if (retval != eppnt->p_filesz) {
88
- goto exit_perror;
89
- }
90
- }
91
- if (interp_name[eppnt->p_filesz - 1] != 0) {
92
- errmsg = "Invalid PT_INTERP entry";
93
- goto exit_errmsg;
94
- }
95
- *pinterp_name = g_steal_pointer(&interp_name);
96
#ifdef TARGET_MIPS
97
} else if (eppnt->p_type == PT_MIPS_ABIFLAGS) {
98
Mips_elf_abiflags_v0 abiflags;
99
--
100
2.20.1
101
102
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
Use the new generic support for NT_GNU_PROPERTY_TYPE_0.
4
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20201021173749.111103-12-richard.henderson@linaro.org
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
linux-user/elfload.c | 48 ++++++++++++++++++++++++++++++++++++++++++--
11
1 file changed, 46 insertions(+), 2 deletions(-)
12
13
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/linux-user/elfload.c
16
+++ b/linux-user/elfload.c
17
@@ -XXX,XX +XXX,XX @@ static void elf_core_copy_regs(target_elf_gregset_t *regs,
18
19
#include "elf.h"
20
21
+/* We must delay the following stanzas until after "elf.h". */
22
+#if defined(TARGET_AARCH64)
23
+
24
+static bool arch_parse_elf_property(uint32_t pr_type, uint32_t pr_datasz,
25
+ const uint32_t *data,
26
+ struct image_info *info,
27
+ Error **errp)
28
+{
29
+ if (pr_type == GNU_PROPERTY_AARCH64_FEATURE_1_AND) {
30
+ if (pr_datasz != sizeof(uint32_t)) {
31
+ error_setg(errp, "Ill-formed GNU_PROPERTY_AARCH64_FEATURE_1_AND");
32
+ return false;
33
+ }
34
+ /* We will extract GNU_PROPERTY_AARCH64_FEATURE_1_BTI later. */
35
+ info->note_flags = *data;
36
+ }
37
+ return true;
38
+}
39
+#define ARCH_USE_GNU_PROPERTY 1
40
+
41
+#else
42
+
43
static bool arch_parse_elf_property(uint32_t pr_type, uint32_t pr_datasz,
44
const uint32_t *data,
45
struct image_info *info,
46
@@ -XXX,XX +XXX,XX @@ static bool arch_parse_elf_property(uint32_t pr_type, uint32_t pr_datasz,
47
}
48
#define ARCH_USE_GNU_PROPERTY 0
49
50
+#endif
51
+
52
struct exec
53
{
54
unsigned int a_info; /* Use macros N_MAGIC, etc for access */
55
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
56
struct elfhdr *ehdr = (struct elfhdr *)bprm_buf;
57
struct elf_phdr *phdr;
58
abi_ulong load_addr, load_bias, loaddr, hiaddr, error;
59
- int i, retval;
60
+ int i, retval, prot_exec;
61
Error *err = NULL;
62
63
/* First of all, some simple consistency checks */
64
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
65
info->brk = 0;
66
info->elf_flags = ehdr->e_flags;
67
68
+ prot_exec = PROT_EXEC;
69
+#ifdef TARGET_AARCH64
70
+ /*
71
+ * If the BTI feature is present, this indicates that the executable
72
+ * pages of the startup binary should be mapped with PROT_BTI, so that
73
+ * branch targets are enforced.
74
+ *
75
+ * The startup binary is either the interpreter or the static executable.
76
+ * The interpreter is responsible for all pages of a dynamic executable.
77
+ *
78
+ * Elf notes are backward compatible to older cpus.
79
+ * Do not enable BTI unless it is supported.
80
+ */
81
+ if ((info->note_flags & GNU_PROPERTY_AARCH64_FEATURE_1_BTI)
82
+ && (pinterp_name == NULL || *pinterp_name == 0)
83
+ && cpu_isar_feature(aa64_bti, ARM_CPU(thread_cpu))) {
84
+ prot_exec |= TARGET_PROT_BTI;
85
+ }
86
+#endif
87
+
88
for (i = 0; i < ehdr->e_phnum; i++) {
89
struct elf_phdr *eppnt = phdr + i;
90
if (eppnt->p_type == PT_LOAD) {
91
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
92
elf_prot |= PROT_WRITE;
93
}
94
if (eppnt->p_flags & PF_X) {
95
- elf_prot |= PROT_EXEC;
96
+ elf_prot |= prot_exec;
97
}
98
99
vaddr = load_bias + eppnt->p_vaddr;
100
--
101
2.20.1
102
103
diff view generated by jsdifflib
Deleted patch
1
From: Pavel Dovgalyuk <pavel.dovgalyuk@ispras.ru>
2
1
3
This patch sets min_cpus field for xlnx-versal-virt platform,
4
because it always creates XLNX_VERSAL_NR_ACPUS cpus even with
5
-smp 1 command line option.
6
7
Signed-off-by: Pavel Dovgalyuk <pavel.dovgalyuk@ispras.ru>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
10
Message-id: 160343854912.8460.17915238517799132371.stgit@pasha-ThinkPad-X280
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
13
hw/arm/xlnx-versal-virt.c | 1 +
14
1 file changed, 1 insertion(+)
15
16
diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/arm/xlnx-versal-virt.c
19
+++ b/hw/arm/xlnx-versal-virt.c
20
@@ -XXX,XX +XXX,XX @@ static void versal_virt_machine_class_init(ObjectClass *oc, void *data)
21
22
mc->desc = "Xilinx Versal Virtual development board";
23
mc->init = versal_virt_init;
24
+ mc->min_cpus = XLNX_VERSAL_NR_ACPUS;
25
mc->max_cpus = XLNX_VERSAL_NR_ACPUS;
26
mc->default_cpus = XLNX_VERSAL_NR_ACPUS;
27
mc->no_cdrom = true;
28
--
29
2.20.1
30
31
diff view generated by jsdifflib
1
From: Luc Michel <luc@lmichel.fr>
1
Some devices and machines need to handle the reset before a vmsave
2
snapshot is loaded differently -- the main user is the handling of
3
RNG seed information, which does not want to put a new RNG seed into
4
a ROM blob when we are doing a snapshot load.
2
5
3
Those reset values have been extracted from a Raspberry Pi 3 model B
6
Currently this kind of reset handling is supported only for:
4
v1.2, using the 2020-08-20 version of raspios. The dump was done using
7
* TYPE_MACHINE reset methods, which take a ShutdownCause argument
5
the debugfs interface of the CPRMAN driver in Linux (under
8
* reset functions registered with qemu_register_reset_nosnapshotload
6
'/sys/kernel/debug/clk'). Each exposed clock tree stage (PLLs, channels
7
and muxes) can be observed by reading the 'regdump' file (e.g.
8
'plla/regdump').
9
9
10
Those values are set by the Raspberry Pi firmware at boot time (Linux
10
To allow a three-phase-reset device to also distinguish "snapshot
11
expects them to be set when it boots up).
11
load" reset from the normal kind, add a new ResetType
12
RESET_TYPE_SNAPSHOT_LOAD. All our existing reset methods ignore
13
the reset type, so we don't need to update any device code.
12
14
13
Some stages are not exposed by the Linux driver (e.g. the PLL B). For
15
Add the enum type, and make qemu_devices_reset() use the
14
those, the reset values are unknown and left to 0 which implies a
16
right reset type for the ShutdownCause it is passed. This
15
disabled output.
17
allows us to get rid of the device_reset_reason global we
18
were using to implement qemu_register_reset_nosnapshotload().
16
19
17
Once booted in QEMU, the final clock tree is very similar to the one
20
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
visible on real hardware. The differences come from some unimplemented
21
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
19
devices for which the driver simply disable the corresponding clock.
22
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
23
Reviewed-by: Luc Michel <luc.michel@amd.com>
24
Message-id: 20240412160809.1260625-7-peter.maydell@linaro.org
25
---
26
docs/devel/reset.rst | 17 ++++++++++++++---
27
include/hw/resettable.h | 1 +
28
hw/core/reset.c | 15 ++++-----------
29
hw/core/resettable.c | 4 ----
30
4 files changed, 19 insertions(+), 18 deletions(-)
20
31
21
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
32
diff --git a/docs/devel/reset.rst b/docs/devel/reset.rst
22
Signed-off-by: Luc Michel <luc@lmichel.fr>
23
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
24
Tested-by: Guenter Roeck <linux@roeck-us.net>
25
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
26
---
27
include/hw/misc/bcm2835_cprman_internals.h | 269 +++++++++++++++++++++
28
hw/misc/bcm2835_cprman.c | 31 +++
29
2 files changed, 300 insertions(+)
30
31
diff --git a/include/hw/misc/bcm2835_cprman_internals.h b/include/hw/misc/bcm2835_cprman_internals.h
32
index XXXXXXX..XXXXXXX 100644
33
index XXXXXXX..XXXXXXX 100644
33
--- a/include/hw/misc/bcm2835_cprman_internals.h
34
--- a/docs/devel/reset.rst
34
+++ b/include/hw/misc/bcm2835_cprman_internals.h
35
+++ b/docs/devel/reset.rst
35
@@ -XXX,XX +XXX,XX @@ static inline void set_clock_mux_init_info(BCM2835CprmanState *s,
36
@@ -XXX,XX +XXX,XX @@ instantly reset an object, without keeping it in reset state, just call
36
mux->frac_bits = CLOCK_MUX_INIT_INFO[id].frac_bits;
37
``resettable_reset()``. These functions take two parameters: a pointer to the
38
object to reset and a reset type.
39
40
-Several types of reset will be supported. For now only cold reset is defined;
41
-others may be added later. The Resettable interface handles reset types with an
42
-enum:
43
+The Resettable interface handles reset types with an enum ``ResetType``:
44
45
``RESET_TYPE_COLD``
46
Cold reset is supported by every resettable object. In QEMU, it means we reset
47
@@ -XXX,XX +XXX,XX @@ enum:
48
from what is a real hardware cold reset. It differs from other resets (like
49
warm or bus resets) which may keep certain parts untouched.
50
51
+``RESET_TYPE_SNAPSHOT_LOAD``
52
+ This is called for a reset which is being done to put the system into a
53
+ clean state prior to loading a snapshot. (This corresponds to a reset
54
+ with ``SHUTDOWN_CAUSE_SNAPSHOT_LOAD``.) Almost all devices should treat
55
+ this the same as ``RESET_TYPE_COLD``. The main exception is devices which
56
+ have some non-deterministic state they want to reinitialize to a different
57
+ value on each cold reset, such as RNG seed information, and which they
58
+ must not reinitialize on a snapshot-load reset.
59
+
60
+Devices which implement reset methods must treat any unknown ``ResetType``
61
+as equivalent to ``RESET_TYPE_COLD``; this will reduce the amount of
62
+existing code we need to change if we add more types in future.
63
+
64
Calling ``resettable_reset()`` is equivalent to calling
65
``resettable_assert_reset()`` then ``resettable_release_reset()``. It is
66
possible to interleave multiple calls to these three functions. There may
67
diff --git a/include/hw/resettable.h b/include/hw/resettable.h
68
index XXXXXXX..XXXXXXX 100644
69
--- a/include/hw/resettable.h
70
+++ b/include/hw/resettable.h
71
@@ -XXX,XX +XXX,XX @@ typedef struct ResettableState ResettableState;
72
*/
73
typedef enum ResetType {
74
RESET_TYPE_COLD,
75
+ RESET_TYPE_SNAPSHOT_LOAD,
76
} ResetType;
77
78
/*
79
diff --git a/hw/core/reset.c b/hw/core/reset.c
80
index XXXXXXX..XXXXXXX 100644
81
--- a/hw/core/reset.c
82
+++ b/hw/core/reset.c
83
@@ -XXX,XX +XXX,XX @@ static ResettableContainer *get_root_reset_container(void)
84
return root_reset_container;
37
}
85
}
38
86
39
+
87
-/*
40
+/*
88
- * Reason why the currently in-progress qemu_devices_reset() was called.
41
+ * Object reset info
89
- * If we made at least SHUTDOWN_CAUSE_SNAPSHOT_LOAD have a corresponding
42
+ * Those values have been dumped from a Raspberry Pi 3 Model B v1.2 using the
90
- * ResetType we could perhaps avoid the need for this global.
43
+ * clk debugfs interface in Linux.
91
- */
44
+ */
92
-static ShutdownCause device_reset_reason;
45
+typedef struct PLLResetInfo {
93
-
46
+ uint32_t cm;
94
/*
47
+ uint32_t a2w_ctrl;
95
* This is an Object which implements Resettable simply to call the
48
+ uint32_t a2w_ana[4];
96
* callback function in the hold phase.
49
+ uint32_t a2w_frac;
97
@@ -XXX,XX +XXX,XX @@ static void legacy_reset_hold(Object *obj, ResetType type)
50
+} PLLResetInfo;
98
{
51
+
99
LegacyReset *lr = LEGACY_RESET(obj);
52
+static const PLLResetInfo PLL_RESET_INFO[] = {
100
53
+ [CPRMAN_PLLA] = {
101
- if (device_reset_reason == SHUTDOWN_CAUSE_SNAPSHOT_LOAD &&
54
+ .cm = 0x0000008a,
102
- lr->skip_on_snapshot_load) {
55
+ .a2w_ctrl = 0x0002103a,
103
+ if (type == RESET_TYPE_SNAPSHOT_LOAD && lr->skip_on_snapshot_load) {
56
+ .a2w_frac = 0x00098000,
104
return;
57
+ .a2w_ana = { 0x00000000, 0x00144000, 0x00000000, 0x00000100 }
105
}
58
+ },
106
lr->func(lr->opaque);
59
+
107
@@ -XXX,XX +XXX,XX @@ void qemu_unregister_resettable(Object *obj)
60
+ [CPRMAN_PLLC] = {
108
61
+ .cm = 0x00000228,
109
void qemu_devices_reset(ShutdownCause reason)
62
+ .a2w_ctrl = 0x0002103e,
110
{
63
+ .a2w_frac = 0x00080000,
111
- device_reset_reason = reason;
64
+ .a2w_ana = { 0x00000000, 0x00144000, 0x00000000, 0x00000100 }
112
+ ResetType type = (reason == SHUTDOWN_CAUSE_SNAPSHOT_LOAD) ?
65
+ },
113
+ RESET_TYPE_SNAPSHOT_LOAD : RESET_TYPE_COLD;
66
+
114
67
+ [CPRMAN_PLLD] = {
115
/* Reset the simulation */
68
+ .cm = 0x0000020a,
116
- resettable_reset(OBJECT(get_root_reset_container()), RESET_TYPE_COLD);
69
+ .a2w_ctrl = 0x00021034,
117
+ resettable_reset(OBJECT(get_root_reset_container()), type);
70
+ .a2w_frac = 0x00015556,
118
}
71
+ .a2w_ana = { 0x00000000, 0x00144000, 0x00000000, 0x00000100 }
119
diff --git a/hw/core/resettable.c b/hw/core/resettable.c
72
+ },
73
+
74
+ [CPRMAN_PLLH] = {
75
+ .cm = 0x00000000,
76
+ .a2w_ctrl = 0x0002102d,
77
+ .a2w_frac = 0x00000000,
78
+ .a2w_ana = { 0x00900000, 0x0000000c, 0x00000000, 0x00000000 }
79
+ },
80
+
81
+ [CPRMAN_PLLB] = {
82
+ /* unknown */
83
+ .cm = 0x00000000,
84
+ .a2w_ctrl = 0x00000000,
85
+ .a2w_frac = 0x00000000,
86
+ .a2w_ana = { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }
87
+ }
88
+};
89
+
90
+typedef struct PLLChannelResetInfo {
91
+ /*
92
+ * Even though a PLL channel has a CM register, it shares it with its
93
+ * parent PLL. The parent already takes care of the reset value.
94
+ */
95
+ uint32_t a2w_ctrl;
96
+} PLLChannelResetInfo;
97
+
98
+static const PLLChannelResetInfo PLL_CHANNEL_RESET_INFO[] = {
99
+ [CPRMAN_PLLA_CHANNEL_DSI0] = { .a2w_ctrl = 0x00000100 },
100
+ [CPRMAN_PLLA_CHANNEL_CORE] = { .a2w_ctrl = 0x00000003 },
101
+ [CPRMAN_PLLA_CHANNEL_PER] = { .a2w_ctrl = 0x00000000 }, /* unknown */
102
+ [CPRMAN_PLLA_CHANNEL_CCP2] = { .a2w_ctrl = 0x00000100 },
103
+
104
+ [CPRMAN_PLLC_CHANNEL_CORE2] = { .a2w_ctrl = 0x00000100 },
105
+ [CPRMAN_PLLC_CHANNEL_CORE1] = { .a2w_ctrl = 0x00000100 },
106
+ [CPRMAN_PLLC_CHANNEL_PER] = { .a2w_ctrl = 0x00000002 },
107
+ [CPRMAN_PLLC_CHANNEL_CORE0] = { .a2w_ctrl = 0x00000002 },
108
+
109
+ [CPRMAN_PLLD_CHANNEL_DSI0] = { .a2w_ctrl = 0x00000100 },
110
+ [CPRMAN_PLLD_CHANNEL_CORE] = { .a2w_ctrl = 0x00000004 },
111
+ [CPRMAN_PLLD_CHANNEL_PER] = { .a2w_ctrl = 0x00000004 },
112
+ [CPRMAN_PLLD_CHANNEL_DSI1] = { .a2w_ctrl = 0x00000100 },
113
+
114
+ [CPRMAN_PLLH_CHANNEL_AUX] = { .a2w_ctrl = 0x00000004 },
115
+ [CPRMAN_PLLH_CHANNEL_RCAL] = { .a2w_ctrl = 0x00000000 },
116
+ [CPRMAN_PLLH_CHANNEL_PIX] = { .a2w_ctrl = 0x00000000 },
117
+
118
+ [CPRMAN_PLLB_CHANNEL_ARM] = { .a2w_ctrl = 0x00000000 }, /* unknown */
119
+};
120
+
121
+typedef struct ClockMuxResetInfo {
122
+ uint32_t cm_ctl;
123
+ uint32_t cm_div;
124
+} ClockMuxResetInfo;
125
+
126
+static const ClockMuxResetInfo CLOCK_MUX_RESET_INFO[] = {
127
+ [CPRMAN_CLOCK_GNRIC] = {
128
+ .cm_ctl = 0, /* unknown */
129
+ .cm_div = 0
130
+ },
131
+
132
+ [CPRMAN_CLOCK_VPU] = {
133
+ .cm_ctl = 0x00000245,
134
+ .cm_div = 0x00003000,
135
+ },
136
+
137
+ [CPRMAN_CLOCK_SYS] = {
138
+ .cm_ctl = 0, /* unknown */
139
+ .cm_div = 0
140
+ },
141
+
142
+ [CPRMAN_CLOCK_PERIA] = {
143
+ .cm_ctl = 0, /* unknown */
144
+ .cm_div = 0
145
+ },
146
+
147
+ [CPRMAN_CLOCK_PERII] = {
148
+ .cm_ctl = 0, /* unknown */
149
+ .cm_div = 0
150
+ },
151
+
152
+ [CPRMAN_CLOCK_H264] = {
153
+ .cm_ctl = 0x00000244,
154
+ .cm_div = 0x00003000,
155
+ },
156
+
157
+ [CPRMAN_CLOCK_ISP] = {
158
+ .cm_ctl = 0x00000244,
159
+ .cm_div = 0x00003000,
160
+ },
161
+
162
+ [CPRMAN_CLOCK_V3D] = {
163
+ .cm_ctl = 0, /* unknown */
164
+ .cm_div = 0
165
+ },
166
+
167
+ [CPRMAN_CLOCK_CAM0] = {
168
+ .cm_ctl = 0x00000000,
169
+ .cm_div = 0x00000000,
170
+ },
171
+
172
+ [CPRMAN_CLOCK_CAM1] = {
173
+ .cm_ctl = 0x00000000,
174
+ .cm_div = 0x00000000,
175
+ },
176
+
177
+ [CPRMAN_CLOCK_CCP2] = {
178
+ .cm_ctl = 0, /* unknown */
179
+ .cm_div = 0
180
+ },
181
+
182
+ [CPRMAN_CLOCK_DSI0E] = {
183
+ .cm_ctl = 0x00000000,
184
+ .cm_div = 0x00000000,
185
+ },
186
+
187
+ [CPRMAN_CLOCK_DSI0P] = {
188
+ .cm_ctl = 0x00000000,
189
+ .cm_div = 0x00000000,
190
+ },
191
+
192
+ [CPRMAN_CLOCK_DPI] = {
193
+ .cm_ctl = 0x00000000,
194
+ .cm_div = 0x00000000,
195
+ },
196
+
197
+ [CPRMAN_CLOCK_GP0] = {
198
+ .cm_ctl = 0x00000200,
199
+ .cm_div = 0x00000000,
200
+ },
201
+
202
+ [CPRMAN_CLOCK_GP1] = {
203
+ .cm_ctl = 0x00000096,
204
+ .cm_div = 0x00014000,
205
+ },
206
+
207
+ [CPRMAN_CLOCK_GP2] = {
208
+ .cm_ctl = 0x00000291,
209
+ .cm_div = 0x00249f00,
210
+ },
211
+
212
+ [CPRMAN_CLOCK_HSM] = {
213
+ .cm_ctl = 0x00000000,
214
+ .cm_div = 0x00000000,
215
+ },
216
+
217
+ [CPRMAN_CLOCK_OTP] = {
218
+ .cm_ctl = 0x00000091,
219
+ .cm_div = 0x00004000,
220
+ },
221
+
222
+ [CPRMAN_CLOCK_PCM] = {
223
+ .cm_ctl = 0x00000200,
224
+ .cm_div = 0x00000000,
225
+ },
226
+
227
+ [CPRMAN_CLOCK_PWM] = {
228
+ .cm_ctl = 0x00000200,
229
+ .cm_div = 0x00000000,
230
+ },
231
+
232
+ [CPRMAN_CLOCK_SLIM] = {
233
+ .cm_ctl = 0x00000200,
234
+ .cm_div = 0x00000000,
235
+ },
236
+
237
+ [CPRMAN_CLOCK_SMI] = {
238
+ .cm_ctl = 0x00000000,
239
+ .cm_div = 0x00000000,
240
+ },
241
+
242
+ [CPRMAN_CLOCK_TEC] = {
243
+ .cm_ctl = 0x00000000,
244
+ .cm_div = 0x00000000,
245
+ },
246
+
247
+ [CPRMAN_CLOCK_TD0] = {
248
+ .cm_ctl = 0, /* unknown */
249
+ .cm_div = 0
250
+ },
251
+
252
+ [CPRMAN_CLOCK_TD1] = {
253
+ .cm_ctl = 0, /* unknown */
254
+ .cm_div = 0
255
+ },
256
+
257
+ [CPRMAN_CLOCK_TSENS] = {
258
+ .cm_ctl = 0x00000091,
259
+ .cm_div = 0x0000a000,
260
+ },
261
+
262
+ [CPRMAN_CLOCK_TIMER] = {
263
+ .cm_ctl = 0x00000291,
264
+ .cm_div = 0x00013333,
265
+ },
266
+
267
+ [CPRMAN_CLOCK_UART] = {
268
+ .cm_ctl = 0x00000296,
269
+ .cm_div = 0x0000a6ab,
270
+ },
271
+
272
+ [CPRMAN_CLOCK_VEC] = {
273
+ .cm_ctl = 0x00000097,
274
+ .cm_div = 0x00002000,
275
+ },
276
+
277
+ [CPRMAN_CLOCK_PULSE] = {
278
+ .cm_ctl = 0, /* unknown */
279
+ .cm_div = 0
280
+ },
281
+
282
+ [CPRMAN_CLOCK_SDC] = {
283
+ .cm_ctl = 0x00004006,
284
+ .cm_div = 0x00003000,
285
+ },
286
+
287
+ [CPRMAN_CLOCK_ARM] = {
288
+ .cm_ctl = 0, /* unknown */
289
+ .cm_div = 0
290
+ },
291
+
292
+ [CPRMAN_CLOCK_AVEO] = {
293
+ .cm_ctl = 0x00000000,
294
+ .cm_div = 0x00000000,
295
+ },
296
+
297
+ [CPRMAN_CLOCK_EMMC] = {
298
+ .cm_ctl = 0x00000295,
299
+ .cm_div = 0x00006000,
300
+ },
301
+
302
+ [CPRMAN_CLOCK_EMMC2] = {
303
+ .cm_ctl = 0, /* unknown */
304
+ .cm_div = 0
305
+ },
306
+};
307
+
308
#endif
309
diff --git a/hw/misc/bcm2835_cprman.c b/hw/misc/bcm2835_cprman.c
310
index XXXXXXX..XXXXXXX 100644
120
index XXXXXXX..XXXXXXX 100644
311
--- a/hw/misc/bcm2835_cprman.c
121
--- a/hw/core/resettable.c
312
+++ b/hw/misc/bcm2835_cprman.c
122
+++ b/hw/core/resettable.c
313
@@ -XXX,XX +XXX,XX @@
123
@@ -XXX,XX +XXX,XX @@ void resettable_reset(Object *obj, ResetType type)
314
124
315
/* PLL */
125
void resettable_assert_reset(Object *obj, ResetType type)
316
317
+static void pll_reset(DeviceState *dev)
318
+{
319
+ CprmanPllState *s = CPRMAN_PLL(dev);
320
+ const PLLResetInfo *info = &PLL_RESET_INFO[s->id];
321
+
322
+ *s->reg_cm = info->cm;
323
+ *s->reg_a2w_ctrl = info->a2w_ctrl;
324
+ memcpy(s->reg_a2w_ana, info->a2w_ana, sizeof(info->a2w_ana));
325
+ *s->reg_a2w_frac = info->a2w_frac;
326
+}
327
+
328
static bool pll_is_locked(const CprmanPllState *pll)
329
{
126
{
330
return !FIELD_EX32(*pll->reg_a2w_ctrl, A2W_PLLx_CTRL, PWRDN)
127
- /* TODO: change this assert when adding support for other reset types */
331
@@ -XXX,XX +XXX,XX @@ static void pll_class_init(ObjectClass *klass, void *data)
128
- assert(type == RESET_TYPE_COLD);
129
trace_resettable_reset_assert_begin(obj, type);
130
assert(!enter_phase_in_progress);
131
132
@@ -XXX,XX +XXX,XX @@ void resettable_assert_reset(Object *obj, ResetType type)
133
134
void resettable_release_reset(Object *obj, ResetType type)
332
{
135
{
333
DeviceClass *dc = DEVICE_CLASS(klass);
136
- /* TODO: change this assert when adding support for other reset types */
334
137
- assert(type == RESET_TYPE_COLD);
335
+ dc->reset = pll_reset;
138
trace_resettable_reset_release_begin(obj, type);
336
dc->vmsd = &pll_vmstate;
139
assert(!enter_phase_in_progress);
337
}
338
339
@@ -XXX,XX +XXX,XX @@ static const TypeInfo cprman_pll_info = {
340
341
/* PLL channel */
342
343
+static void pll_channel_reset(DeviceState *dev)
344
+{
345
+ CprmanPllChannelState *s = CPRMAN_PLL_CHANNEL(dev);
346
+ const PLLChannelResetInfo *info = &PLL_CHANNEL_RESET_INFO[s->id];
347
+
348
+ *s->reg_a2w_ctrl = info->a2w_ctrl;
349
+}
350
+
351
static bool pll_channel_is_enabled(CprmanPllChannelState *channel)
352
{
353
/*
354
@@ -XXX,XX +XXX,XX @@ static void pll_channel_class_init(ObjectClass *klass, void *data)
355
{
356
DeviceClass *dc = DEVICE_CLASS(klass);
357
358
+ dc->reset = pll_channel_reset;
359
dc->vmsd = &pll_channel_vmstate;
360
}
361
362
@@ -XXX,XX +XXX,XX @@ static void clock_mux_src_update(void *opaque)
363
clock_mux_update(s);
364
}
365
366
+static void clock_mux_reset(DeviceState *dev)
367
+{
368
+ CprmanClockMuxState *clock = CPRMAN_CLOCK_MUX(dev);
369
+ const ClockMuxResetInfo *info = &CLOCK_MUX_RESET_INFO[clock->id];
370
+
371
+ *clock->reg_ctl = info->cm_ctl;
372
+ *clock->reg_div = info->cm_div;
373
+}
374
+
375
static void clock_mux_init(Object *obj)
376
{
377
CprmanClockMuxState *s = CPRMAN_CLOCK_MUX(obj);
378
@@ -XXX,XX +XXX,XX @@ static void clock_mux_class_init(ObjectClass *klass, void *data)
379
{
380
DeviceClass *dc = DEVICE_CLASS(klass);
381
382
+ dc->reset = clock_mux_reset;
383
dc->vmsd = &clock_mux_vmstate;
384
}
385
140
386
--
141
--
387
2.20.1
142
2.34.1
388
143
389
144
diff view generated by jsdifflib
1
From: Luc Michel <luc@lmichel.fr>
1
From: Arnaud Minier <arnaud.minier@telecom-paris.fr>
2
2
3
The BCM2835 CPRMAN is the clock manager of the SoC. It is composed of a
3
Add the basic infrastructure (register read/write, type...)
4
main oscillator, and several sub-components (PLLs, multiplexers, ...) to
4
to implement the STM32L4x5 USART.
5
generate the BCM2835 clock tree.
6
5
7
This commit adds a skeleton of the CPRMAN, with a dummy register
6
Also create different types for the USART, UART and LPUART
8
read/write implementation. It embeds the main oscillator (xosc) from
7
of the STM32L4x5 to deduplicate code and enable the
9
which all the clocks will be derived.
8
implementation of different behaviors depending on the type.
10
9
11
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
Signed-off-by: Arnaud Minier <arnaud.minier@telecom-paris.fr>
12
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
11
Signed-off-by: Inès Varhol <ines.varhol@telecom-paris.fr>
13
Signed-off-by: Luc Michel <luc@lmichel.fr>
12
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
Tested-by: Guenter Roeck <linux@roeck-us.net>
13
Message-id: 20240329174402.60382-2-arnaud.minier@telecom-paris.fr
14
[PMM: update to new reset hold method signature;
15
fixed a few checkpatch nits]
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
---
17
---
17
include/hw/arm/bcm2835_peripherals.h | 3 +-
18
MAINTAINERS | 1 +
18
include/hw/misc/bcm2835_cprman.h | 37 +++++
19
include/hw/char/stm32l4x5_usart.h | 66 +++++
19
include/hw/misc/bcm2835_cprman_internals.h | 24 +++
20
hw/char/stm32l4x5_usart.c | 396 ++++++++++++++++++++++++++++++
20
hw/arm/bcm2835_peripherals.c | 11 +-
21
hw/char/Kconfig | 3 +
21
hw/misc/bcm2835_cprman.c | 163 +++++++++++++++++++++
22
hw/char/meson.build | 1 +
22
hw/misc/meson.build | 1 +
23
hw/char/trace-events | 4 +
23
hw/misc/trace-events | 5 +
24
6 files changed, 471 insertions(+)
24
7 files changed, 242 insertions(+), 2 deletions(-)
25
create mode 100644 include/hw/char/stm32l4x5_usart.h
25
create mode 100644 include/hw/misc/bcm2835_cprman.h
26
create mode 100644 hw/char/stm32l4x5_usart.c
26
create mode 100644 include/hw/misc/bcm2835_cprman_internals.h
27
create mode 100644 hw/misc/bcm2835_cprman.c
28
27
29
diff --git a/include/hw/arm/bcm2835_peripherals.h b/include/hw/arm/bcm2835_peripherals.h
28
diff --git a/MAINTAINERS b/MAINTAINERS
30
index XXXXXXX..XXXXXXX 100644
29
index XXXXXXX..XXXXXXX 100644
31
--- a/include/hw/arm/bcm2835_peripherals.h
30
--- a/MAINTAINERS
32
+++ b/include/hw/arm/bcm2835_peripherals.h
31
+++ b/MAINTAINERS
33
@@ -XXX,XX +XXX,XX @@
32
@@ -XXX,XX +XXX,XX @@ M: Inès Varhol <ines.varhol@telecom-paris.fr>
34
#include "hw/misc/bcm2835_mbox.h"
33
L: qemu-arm@nongnu.org
35
#include "hw/misc/bcm2835_mphi.h"
34
S: Maintained
36
#include "hw/misc/bcm2835_thermal.h"
35
F: hw/arm/stm32l4x5_soc.c
37
+#include "hw/misc/bcm2835_cprman.h"
36
+F: hw/char/stm32l4x5_usart.c
38
#include "hw/sd/sdhci.h"
37
F: hw/misc/stm32l4x5_exti.c
39
#include "hw/sd/bcm2835_sdhost.h"
38
F: hw/misc/stm32l4x5_syscfg.c
40
#include "hw/gpio/bcm2835_gpio.h"
39
F: hw/misc/stm32l4x5_rcc.c
41
@@ -XXX,XX +XXX,XX @@ struct BCM2835PeripheralState {
40
diff --git a/include/hw/char/stm32l4x5_usart.h b/include/hw/char/stm32l4x5_usart.h
42
UnimplementedDeviceState txp;
43
UnimplementedDeviceState armtmr;
44
UnimplementedDeviceState powermgt;
45
- UnimplementedDeviceState cprman;
46
+ BCM2835CprmanState cprman;
47
PL011State uart0;
48
BCM2835AuxState aux;
49
BCM2835FBState fb;
50
diff --git a/include/hw/misc/bcm2835_cprman.h b/include/hw/misc/bcm2835_cprman.h
51
new file mode 100644
41
new file mode 100644
52
index XXXXXXX..XXXXXXX
42
index XXXXXXX..XXXXXXX
53
--- /dev/null
43
--- /dev/null
54
+++ b/include/hw/misc/bcm2835_cprman.h
44
+++ b/include/hw/char/stm32l4x5_usart.h
55
@@ -XXX,XX +XXX,XX @@
45
@@ -XXX,XX +XXX,XX @@
56
+/*
46
+/*
57
+ * BCM2835 CPRMAN clock manager
47
+ * STM32L4X5 USART (Universal Synchronous Asynchronous Receiver Transmitter)
58
+ *
48
+ *
59
+ * Copyright (c) 2020 Luc Michel <luc@lmichel.fr>
49
+ * Copyright (c) 2023 Arnaud Minier <arnaud.minier@telecom-paris.fr>
50
+ * Copyright (c) 2023 Inès Varhol <ines.varhol@telecom-paris.fr>
60
+ *
51
+ *
61
+ * SPDX-License-Identifier: GPL-2.0-or-later
52
+ * SPDX-License-Identifier: GPL-2.0-or-later
53
+ *
54
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
55
+ * See the COPYING file in the top-level directory.
56
+ *
57
+ * The STM32L4X5 USART is heavily inspired by the stm32f2xx_usart
58
+ * by Alistair Francis.
59
+ * The reference used is the STMicroElectronics RM0351 Reference manual
60
+ * for STM32L4x5 and STM32L4x6 advanced Arm ® -based 32-bit MCUs.
62
+ */
61
+ */
63
+
62
+
64
+#ifndef HW_MISC_CPRMAN_H
63
+#ifndef HW_STM32L4X5_USART_H
65
+#define HW_MISC_CPRMAN_H
64
+#define HW_STM32L4X5_USART_H
66
+
65
+
67
+#include "hw/sysbus.h"
66
+#include "hw/sysbus.h"
68
+#include "hw/qdev-clock.h"
67
+#include "chardev/char-fe.h"
69
+
68
+#include "qom/object.h"
70
+#define TYPE_BCM2835_CPRMAN "bcm2835-cprman"
69
+
71
+
70
+#define TYPE_STM32L4X5_USART_BASE "stm32l4x5-usart-base"
72
+typedef struct BCM2835CprmanState BCM2835CprmanState;
71
+#define TYPE_STM32L4X5_USART "stm32l4x5-usart"
73
+
72
+#define TYPE_STM32L4X5_UART "stm32l4x5-uart"
74
+DECLARE_INSTANCE_CHECKER(BCM2835CprmanState, CPRMAN,
73
+#define TYPE_STM32L4X5_LPUART "stm32l4x5-lpuart"
75
+ TYPE_BCM2835_CPRMAN)
74
+OBJECT_DECLARE_TYPE(Stm32l4x5UsartBaseState, Stm32l4x5UsartBaseClass,
76
+
75
+ STM32L4X5_USART_BASE)
77
+#define CPRMAN_NUM_REGS (0x2000 / sizeof(uint32_t))
76
+
78
+
77
+typedef enum {
79
+struct BCM2835CprmanState {
78
+ STM32L4x5_USART,
80
+ /*< private >*/
79
+ STM32L4x5_UART,
80
+ STM32L4x5_LPUART,
81
+} Stm32l4x5UsartType;
82
+
83
+struct Stm32l4x5UsartBaseState {
81
+ SysBusDevice parent_obj;
84
+ SysBusDevice parent_obj;
82
+
85
+
83
+ /*< public >*/
86
+ MemoryRegion mmio;
84
+ MemoryRegion iomem;
87
+
85
+
88
+ uint32_t cr1;
86
+ uint32_t regs[CPRMAN_NUM_REGS];
89
+ uint32_t cr2;
87
+ uint32_t xosc_freq;
90
+ uint32_t cr3;
88
+
91
+ uint32_t brr;
89
+ Clock *xosc;
92
+ uint32_t gtpr;
93
+ uint32_t rtor;
94
+ /* rqr is write-only */
95
+ uint32_t isr;
96
+ /* icr is a clear register */
97
+ uint32_t rdr;
98
+ uint32_t tdr;
99
+
100
+ Clock *clk;
101
+ CharBackend chr;
102
+ qemu_irq irq;
90
+};
103
+};
91
+
104
+
92
+#endif
105
+struct Stm32l4x5UsartBaseClass {
93
diff --git a/include/hw/misc/bcm2835_cprman_internals.h b/include/hw/misc/bcm2835_cprman_internals.h
106
+ SysBusDeviceClass parent_class;
107
+
108
+ Stm32l4x5UsartType type;
109
+};
110
+
111
+#endif /* HW_STM32L4X5_USART_H */
112
diff --git a/hw/char/stm32l4x5_usart.c b/hw/char/stm32l4x5_usart.c
94
new file mode 100644
113
new file mode 100644
95
index XXXXXXX..XXXXXXX
114
index XXXXXXX..XXXXXXX
96
--- /dev/null
115
--- /dev/null
97
+++ b/include/hw/misc/bcm2835_cprman_internals.h
116
+++ b/hw/char/stm32l4x5_usart.c
98
@@ -XXX,XX +XXX,XX @@
117
@@ -XXX,XX +XXX,XX @@
99
+/*
118
+/*
100
+ * BCM2835 CPRMAN clock manager
119
+ * STM32L4X5 USART (Universal Synchronous Asynchronous Receiver Transmitter)
101
+ *
120
+ *
102
+ * Copyright (c) 2020 Luc Michel <luc@lmichel.fr>
121
+ * Copyright (c) 2023 Arnaud Minier <arnaud.minier@telecom-paris.fr>
122
+ * Copyright (c) 2023 Inès Varhol <ines.varhol@telecom-paris.fr>
103
+ *
123
+ *
104
+ * SPDX-License-Identifier: GPL-2.0-or-later
124
+ * SPDX-License-Identifier: GPL-2.0-or-later
105
+ */
125
+ *
106
+
126
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
107
+#ifndef HW_MISC_CPRMAN_INTERNALS_H
127
+ * See the COPYING file in the top-level directory.
108
+#define HW_MISC_CPRMAN_INTERNALS_H
128
+ *
109
+
129
+ * The STM32L4X5 USART is heavily inspired by the stm32f2xx_usart
110
+#include "hw/registerfields.h"
130
+ * by Alistair Francis.
111
+#include "hw/misc/bcm2835_cprman.h"
131
+ * The reference used is the STMicroElectronics RM0351 Reference manual
112
+
132
+ * for STM32L4x5 and STM32L4x6 advanced Arm ® -based 32-bit MCUs.
113
+/* Register map */
114
+
115
+/*
116
+ * This field is common to all registers. Each register write value must match
117
+ * the CPRMAN_PASSWORD magic value in its 8 MSB.
118
+ */
119
+FIELD(CPRMAN, PASSWORD, 24, 8)
120
+#define CPRMAN_PASSWORD 0x5a
121
+
122
+#endif
123
diff --git a/hw/arm/bcm2835_peripherals.c b/hw/arm/bcm2835_peripherals.c
124
index XXXXXXX..XXXXXXX 100644
125
--- a/hw/arm/bcm2835_peripherals.c
126
+++ b/hw/arm/bcm2835_peripherals.c
127
@@ -XXX,XX +XXX,XX @@ static void bcm2835_peripherals_init(Object *obj)
128
/* DWC2 */
129
object_initialize_child(obj, "dwc2", &s->dwc2, TYPE_DWC2_USB);
130
131
+ /* CPRMAN clock manager */
132
+ object_initialize_child(obj, "cprman", &s->cprman, TYPE_BCM2835_CPRMAN);
133
+
134
object_property_add_const_link(OBJECT(&s->dwc2), "dma-mr",
135
OBJECT(&s->gpu_bus_mr));
136
}
137
@@ -XXX,XX +XXX,XX @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
138
return;
139
}
140
141
+ /* CPRMAN clock manager */
142
+ if (!sysbus_realize(SYS_BUS_DEVICE(&s->cprman), errp)) {
143
+ return;
144
+ }
145
+ memory_region_add_subregion(&s->peri_mr, CPRMAN_OFFSET,
146
+ sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->cprman), 0));
147
+
148
memory_region_add_subregion(&s->peri_mr, ARMCTRL_IC_OFFSET,
149
sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->ic), 0));
150
sysbus_pass_irq(SYS_BUS_DEVICE(s), SYS_BUS_DEVICE(&s->ic));
151
@@ -XXX,XX +XXX,XX @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
152
create_unimp(s, &s->txp, "bcm2835-txp", TXP_OFFSET, 0x1000);
153
create_unimp(s, &s->armtmr, "bcm2835-sp804", ARMCTRL_TIMER0_1_OFFSET, 0x40);
154
create_unimp(s, &s->powermgt, "bcm2835-powermgt", PM_OFFSET, 0x114);
155
- create_unimp(s, &s->cprman, "bcm2835-cprman", CPRMAN_OFFSET, 0x2000);
156
create_unimp(s, &s->i2s, "bcm2835-i2s", I2S_OFFSET, 0x100);
157
create_unimp(s, &s->smi, "bcm2835-smi", SMI_OFFSET, 0x100);
158
create_unimp(s, &s->spi[0], "bcm2835-spi0", SPI0_OFFSET, 0x20);
159
diff --git a/hw/misc/bcm2835_cprman.c b/hw/misc/bcm2835_cprman.c
160
new file mode 100644
161
index XXXXXXX..XXXXXXX
162
--- /dev/null
163
+++ b/hw/misc/bcm2835_cprman.c
164
@@ -XXX,XX +XXX,XX @@
165
+/*
166
+ * BCM2835 CPRMAN clock manager
167
+ *
168
+ * Copyright (c) 2020 Luc Michel <luc@lmichel.fr>
169
+ *
170
+ * SPDX-License-Identifier: GPL-2.0-or-later
171
+ */
172
+
173
+/*
174
+ * This peripheral is roughly divided into 3 main parts:
175
+ * - the PLLs
176
+ * - the PLL channels
177
+ * - the clock muxes
178
+ *
179
+ * A main oscillator (xosc) feeds all the PLLs. Each PLLs has one or more
180
+ * channels. Those channel are then connected to the clock muxes. Each mux has
181
+ * multiples sources (usually the xosc, some of the PLL channels and some "test
182
+ * debug" clocks). A mux is configured to select a given source through its
183
+ * control register. Each mux has one output clock that also goes out of the
184
+ * CPRMAN. This output clock usually connects to another peripheral in the SoC
185
+ * (so a given mux is dedicated to a peripheral).
186
+ *
187
+ * At each level (PLL, channel and mux), the clock can be altered through
188
+ * dividers (and multipliers in case of the PLLs), and can be disabled (in this
189
+ * case, the next levels see no clock).
190
+ *
191
+ * This can be sum-up as follows (this is an example and not the actual BCM2835
192
+ * clock tree):
193
+ *
194
+ * /-->[PLL]-|->[PLL channel]--... [mux]--> to peripherals
195
+ * | |->[PLL channel] muxes takes [mux]
196
+ * | \->[PLL channel] inputs from [mux]
197
+ * | some channels [mux]
198
+ * [xosc]---|-->[PLL]-|->[PLL channel] and other srcs [mux]
199
+ * | \->[PLL channel] ...-->[mux]
200
+ * | [mux]
201
+ * \-->[PLL]--->[PLL channel] [mux]
202
+ *
203
+ * The page at https://elinux.org/The_Undocumented_Pi gives the actual clock
204
+ * tree configuration.
205
+ */
133
+ */
206
+
134
+
207
+#include "qemu/osdep.h"
135
+#include "qemu/osdep.h"
208
+#include "qemu/log.h"
136
+#include "qemu/log.h"
137
+#include "qemu/module.h"
138
+#include "qapi/error.h"
139
+#include "chardev/char-fe.h"
140
+#include "chardev/char-serial.h"
209
+#include "migration/vmstate.h"
141
+#include "migration/vmstate.h"
142
+#include "hw/char/stm32l4x5_usart.h"
143
+#include "hw/clock.h"
144
+#include "hw/irq.h"
145
+#include "hw/qdev-clock.h"
210
+#include "hw/qdev-properties.h"
146
+#include "hw/qdev-properties.h"
211
+#include "hw/misc/bcm2835_cprman.h"
147
+#include "hw/qdev-properties-system.h"
212
+#include "hw/misc/bcm2835_cprman_internals.h"
148
+#include "hw/registerfields.h"
213
+#include "trace.h"
149
+#include "trace.h"
214
+
150
+
215
+/* CPRMAN "top level" model */
151
+
216
+
152
+REG32(CR1, 0x00)
217
+static uint64_t cprman_read(void *opaque, hwaddr offset,
153
+ FIELD(CR1, M1, 28, 1) /* Word length (part 2, see M0) */
218
+ unsigned size)
154
+ FIELD(CR1, EOBIE, 27, 1) /* End of Block interrupt enable */
219
+{
155
+ FIELD(CR1, RTOIE, 26, 1) /* Receiver timeout interrupt enable */
220
+ BCM2835CprmanState *s = CPRMAN(opaque);
156
+ FIELD(CR1, DEAT, 21, 5) /* Driver Enable assertion time */
221
+ uint64_t r = 0;
157
+ FIELD(CR1, DEDT, 16, 5) /* Driver Enable de-assertion time */
222
+ size_t idx = offset / sizeof(uint32_t);
158
+ FIELD(CR1, OVER8, 15, 1) /* Oversampling mode */
223
+
159
+ FIELD(CR1, CMIE, 14, 1) /* Character match interrupt enable */
224
+ switch (idx) {
160
+ FIELD(CR1, MME, 13, 1) /* Mute mode enable */
161
+ FIELD(CR1, M0, 12, 1) /* Word length (part 1, see M1) */
162
+ FIELD(CR1, WAKE, 11, 1) /* Receiver wakeup method */
163
+ FIELD(CR1, PCE, 10, 1) /* Parity control enable */
164
+ FIELD(CR1, PS, 9, 1) /* Parity selection */
165
+ FIELD(CR1, PEIE, 8, 1) /* PE interrupt enable */
166
+ FIELD(CR1, TXEIE, 7, 1) /* TXE interrupt enable */
167
+ FIELD(CR1, TCIE, 6, 1) /* Transmission complete interrupt enable */
168
+ FIELD(CR1, RXNEIE, 5, 1) /* RXNE interrupt enable */
169
+ FIELD(CR1, IDLEIE, 4, 1) /* IDLE interrupt enable */
170
+ FIELD(CR1, TE, 3, 1) /* Transmitter enable */
171
+ FIELD(CR1, RE, 2, 1) /* Receiver enable */
172
+ FIELD(CR1, UESM, 1, 1) /* USART enable in Stop mode */
173
+ FIELD(CR1, UE, 0, 1) /* USART enable */
174
+REG32(CR2, 0x04)
175
+ FIELD(CR2, ADD_1, 28, 4) /* ADD[7:4] */
176
+ FIELD(CR2, ADD_0, 24, 1) /* ADD[3:0] */
177
+ FIELD(CR2, RTOEN, 23, 1) /* Receiver timeout enable */
178
+ FIELD(CR2, ABRMOD, 21, 2) /* Auto baud rate mode */
179
+ FIELD(CR2, ABREN, 20, 1) /* Auto baud rate enable */
180
+ FIELD(CR2, MSBFIRST, 19, 1) /* Most significant bit first */
181
+ FIELD(CR2, DATAINV, 18, 1) /* Binary data inversion */
182
+ FIELD(CR2, TXINV, 17, 1) /* TX pin active level inversion */
183
+ FIELD(CR2, RXINV, 16, 1) /* RX pin active level inversion */
184
+ FIELD(CR2, SWAP, 15, 1) /* Swap RX/TX pins */
185
+ FIELD(CR2, LINEN, 14, 1) /* LIN mode enable */
186
+ FIELD(CR2, STOP, 12, 2) /* STOP bits */
187
+ FIELD(CR2, CLKEN, 11, 1) /* Clock enable */
188
+ FIELD(CR2, CPOL, 10, 1) /* Clock polarity */
189
+ FIELD(CR2, CPHA, 9, 1) /* Clock phase */
190
+ FIELD(CR2, LBCL, 8, 1) /* Last bit clock pulse */
191
+ FIELD(CR2, LBDIE, 6, 1) /* LIN break detection interrupt enable */
192
+ FIELD(CR2, LBDL, 5, 1) /* LIN break detection length */
193
+ FIELD(CR2, ADDM7, 4, 1) /* 7-bit / 4-bit Address Detection */
194
+
195
+REG32(CR3, 0x08)
196
+ /* TCBGTIE only on STM32L496xx/4A6xx devices */
197
+ FIELD(CR3, UCESM, 23, 1) /* USART Clock Enable in Stop Mode */
198
+ FIELD(CR3, WUFIE, 22, 1) /* Wakeup from Stop mode interrupt enable */
199
+ FIELD(CR3, WUS, 20, 2) /* Wakeup from Stop mode interrupt flag selection */
200
+ FIELD(CR3, SCARCNT, 17, 3) /* Smartcard auto-retry count */
201
+ FIELD(CR3, DEP, 15, 1) /* Driver enable polarity selection */
202
+ FIELD(CR3, DEM, 14, 1) /* Driver enable mode */
203
+ FIELD(CR3, DDRE, 13, 1) /* DMA Disable on Reception Error */
204
+ FIELD(CR3, OVRDIS, 12, 1) /* Overrun Disable */
205
+ FIELD(CR3, ONEBIT, 11, 1) /* One sample bit method enable */
206
+ FIELD(CR3, CTSIE, 10, 1) /* CTS interrupt enable */
207
+ FIELD(CR3, CTSE, 9, 1) /* CTS enable */
208
+ FIELD(CR3, RTSE, 8, 1) /* RTS enable */
209
+ FIELD(CR3, DMAT, 7, 1) /* DMA enable transmitter */
210
+ FIELD(CR3, DMAR, 6, 1) /* DMA enable receiver */
211
+ FIELD(CR3, SCEN, 5, 1) /* Smartcard mode enable */
212
+ FIELD(CR3, NACK, 4, 1) /* Smartcard NACK enable */
213
+ FIELD(CR3, HDSEL, 3, 1) /* Half-duplex selection */
214
+ FIELD(CR3, IRLP, 2, 1) /* IrDA low-power */
215
+ FIELD(CR3, IREN, 1, 1) /* IrDA mode enable */
216
+ FIELD(CR3, EIE, 0, 1) /* Error interrupt enable */
217
+REG32(BRR, 0x0C)
218
+ FIELD(BRR, BRR, 0, 16)
219
+REG32(GTPR, 0x10)
220
+ FIELD(GTPR, GT, 8, 8) /* Guard time value */
221
+ FIELD(GTPR, PSC, 0, 8) /* Prescaler value */
222
+REG32(RTOR, 0x14)
223
+ FIELD(RTOR, BLEN, 24, 8) /* Block Length */
224
+ FIELD(RTOR, RTO, 0, 24) /* Receiver timeout value */
225
+REG32(RQR, 0x18)
226
+ FIELD(RQR, TXFRQ, 4, 1) /* Transmit data flush request */
227
+ FIELD(RQR, RXFRQ, 3, 1) /* Receive data flush request */
228
+ FIELD(RQR, MMRQ, 2, 1) /* Mute mode request */
229
+ FIELD(RQR, SBKRQ, 1, 1) /* Send break request */
230
+ FIELD(RQR, ABBRRQ, 0, 1) /* Auto baud rate request */
231
+REG32(ISR, 0x1C)
232
+ /* TCBGT only for STM32L475xx/476xx/486xx devices */
233
+ FIELD(ISR, REACK, 22, 1) /* Receive enable acknowledge flag */
234
+ FIELD(ISR, TEACK, 21, 1) /* Transmit enable acknowledge flag */
235
+ FIELD(ISR, WUF, 20, 1) /* Wakeup from Stop mode flag */
236
+ FIELD(ISR, RWU, 19, 1) /* Receiver wakeup from Mute mode */
237
+ FIELD(ISR, SBKF, 18, 1) /* Send break flag */
238
+ FIELD(ISR, CMF, 17, 1) /* Character match flag */
239
+ FIELD(ISR, BUSY, 16, 1) /* Busy flag */
240
+ FIELD(ISR, ABRF, 15, 1) /* Auto Baud rate flag */
241
+ FIELD(ISR, ABRE, 14, 1) /* Auto Baud rate error */
242
+ FIELD(ISR, EOBF, 12, 1) /* End of block flag */
243
+ FIELD(ISR, RTOF, 11, 1) /* Receiver timeout */
244
+ FIELD(ISR, CTS, 10, 1) /* CTS flag */
245
+ FIELD(ISR, CTSIF, 9, 1) /* CTS interrupt flag */
246
+ FIELD(ISR, LBDF, 8, 1) /* LIN break detection flag */
247
+ FIELD(ISR, TXE, 7, 1) /* Transmit data register empty */
248
+ FIELD(ISR, TC, 6, 1) /* Transmission complete */
249
+ FIELD(ISR, RXNE, 5, 1) /* Read data register not empty */
250
+ FIELD(ISR, IDLE, 4, 1) /* Idle line detected */
251
+ FIELD(ISR, ORE, 3, 1) /* Overrun error */
252
+ FIELD(ISR, NF, 2, 1) /* START bit Noise detection flag */
253
+ FIELD(ISR, FE, 1, 1) /* Framing Error */
254
+ FIELD(ISR, PE, 0, 1) /* Parity Error */
255
+REG32(ICR, 0x20)
256
+ FIELD(ICR, WUCF, 20, 1) /* Wakeup from Stop mode clear flag */
257
+ FIELD(ICR, CMCF, 17, 1) /* Character match clear flag */
258
+ FIELD(ICR, EOBCF, 12, 1) /* End of block clear flag */
259
+ FIELD(ICR, RTOCF, 11, 1) /* Receiver timeout clear flag */
260
+ FIELD(ICR, CTSCF, 9, 1) /* CTS clear flag */
261
+ FIELD(ICR, LBDCF, 8, 1) /* LIN break detection clear flag */
262
+ /* TCBGTCF only on STM32L496xx/4A6xx devices */
263
+ FIELD(ICR, TCCF, 6, 1) /* Transmission complete clear flag */
264
+ FIELD(ICR, IDLECF, 4, 1) /* Idle line detected clear flag */
265
+ FIELD(ICR, ORECF, 3, 1) /* Overrun error clear flag */
266
+ FIELD(ICR, NCF, 2, 1) /* Noise detected clear flag */
267
+ FIELD(ICR, FECF, 1, 1) /* Framing error clear flag */
268
+ FIELD(ICR, PECF, 0, 1) /* Parity error clear flag */
269
+REG32(RDR, 0x24)
270
+ FIELD(RDR, RDR, 0, 9)
271
+REG32(TDR, 0x28)
272
+ FIELD(TDR, TDR, 0, 9)
273
+
274
+static void stm32l4x5_usart_base_reset_hold(Object *obj, ResetType type)
275
+{
276
+ Stm32l4x5UsartBaseState *s = STM32L4X5_USART_BASE(obj);
277
+
278
+ s->cr1 = 0x00000000;
279
+ s->cr2 = 0x00000000;
280
+ s->cr3 = 0x00000000;
281
+ s->brr = 0x00000000;
282
+ s->gtpr = 0x00000000;
283
+ s->rtor = 0x00000000;
284
+ s->isr = 0x020000C0;
285
+ s->rdr = 0x00000000;
286
+ s->tdr = 0x00000000;
287
+}
288
+
289
+static uint64_t stm32l4x5_usart_base_read(void *opaque, hwaddr addr,
290
+ unsigned int size)
291
+{
292
+ Stm32l4x5UsartBaseState *s = opaque;
293
+ uint64_t retvalue = 0;
294
+
295
+ switch (addr) {
296
+ case A_CR1:
297
+ retvalue = s->cr1;
298
+ break;
299
+ case A_CR2:
300
+ retvalue = s->cr2;
301
+ break;
302
+ case A_CR3:
303
+ retvalue = s->cr3;
304
+ break;
305
+ case A_BRR:
306
+ retvalue = FIELD_EX32(s->brr, BRR, BRR);
307
+ break;
308
+ case A_GTPR:
309
+ retvalue = s->gtpr;
310
+ break;
311
+ case A_RTOR:
312
+ retvalue = s->rtor;
313
+ break;
314
+ case A_RQR:
315
+ /* RQR is a write only register */
316
+ retvalue = 0x00000000;
317
+ break;
318
+ case A_ISR:
319
+ retvalue = s->isr;
320
+ break;
321
+ case A_ICR:
322
+ /* ICR is a clear register */
323
+ retvalue = 0x00000000;
324
+ break;
325
+ case A_RDR:
326
+ retvalue = FIELD_EX32(s->rdr, RDR, RDR);
327
+ /* Reset RXNE flag */
328
+ s->isr &= ~R_ISR_RXNE_MASK;
329
+ break;
330
+ case A_TDR:
331
+ retvalue = FIELD_EX32(s->tdr, TDR, TDR);
332
+ break;
225
+ default:
333
+ default:
226
+ r = s->regs[idx];
334
+ qemu_log_mask(LOG_GUEST_ERROR,
335
+ "%s: Bad offset 0x%"HWADDR_PRIx"\n", __func__, addr);
336
+ break;
227
+ }
337
+ }
228
+
338
+
229
+ trace_bcm2835_cprman_read(offset, r);
339
+ trace_stm32l4x5_usart_read(addr, retvalue);
230
+ return r;
340
+
231
+}
341
+ return retvalue;
232
+
342
+}
233
+static void cprman_write(void *opaque, hwaddr offset,
343
+
234
+ uint64_t value, unsigned size)
344
+static void stm32l4x5_usart_base_write(void *opaque, hwaddr addr,
235
+{
345
+ uint64_t val64, unsigned int size)
236
+ BCM2835CprmanState *s = CPRMAN(opaque);
346
+{
237
+ size_t idx = offset / sizeof(uint32_t);
347
+ Stm32l4x5UsartBaseState *s = opaque;
238
+
348
+ const uint32_t value = val64;
239
+ if (FIELD_EX32(value, CPRMAN, PASSWORD) != CPRMAN_PASSWORD) {
349
+
240
+ trace_bcm2835_cprman_write_invalid_magic(offset, value);
350
+ trace_stm32l4x5_usart_write(addr, value);
241
+ return;
351
+
352
+ switch (addr) {
353
+ case A_CR1:
354
+ s->cr1 = value;
355
+ return;
356
+ case A_CR2:
357
+ s->cr2 = value;
358
+ return;
359
+ case A_CR3:
360
+ s->cr3 = value;
361
+ return;
362
+ case A_BRR:
363
+ s->brr = value;
364
+ return;
365
+ case A_GTPR:
366
+ s->gtpr = value;
367
+ return;
368
+ case A_RTOR:
369
+ s->rtor = value;
370
+ return;
371
+ case A_RQR:
372
+ return;
373
+ case A_ISR:
374
+ qemu_log_mask(LOG_GUEST_ERROR,
375
+ "%s: ISR is read only !\n", __func__);
376
+ return;
377
+ case A_ICR:
378
+ /* Clear the status flags */
379
+ s->isr &= ~value;
380
+ return;
381
+ case A_RDR:
382
+ qemu_log_mask(LOG_GUEST_ERROR,
383
+ "%s: RDR is read only !\n", __func__);
384
+ return;
385
+ case A_TDR:
386
+ s->tdr = value;
387
+ return;
388
+ default:
389
+ qemu_log_mask(LOG_GUEST_ERROR,
390
+ "%s: Bad offset 0x%"HWADDR_PRIx"\n", __func__, addr);
242
+ }
391
+ }
243
+
392
+}
244
+ value &= ~R_CPRMAN_PASSWORD_MASK;
393
+
245
+
394
+static const MemoryRegionOps stm32l4x5_usart_base_ops = {
246
+ trace_bcm2835_cprman_write(offset, value);
395
+ .read = stm32l4x5_usart_base_read,
247
+ s->regs[idx] = value;
396
+ .write = stm32l4x5_usart_base_write,
248
+
397
+ .endianness = DEVICE_NATIVE_ENDIAN,
249
+}
250
+
251
+static const MemoryRegionOps cprman_ops = {
252
+ .read = cprman_read,
253
+ .write = cprman_write,
254
+ .endianness = DEVICE_LITTLE_ENDIAN,
255
+ .valid = {
398
+ .valid = {
256
+ /*
399
+ .max_access_size = 4,
257
+ * Although this hasn't been checked against real hardware, nor the
400
+ .min_access_size = 4,
258
+ * information can be found in a datasheet, it seems reasonable because
401
+ .unaligned = false
259
+ * of the "PASSWORD" magic value found in every registers.
260
+ */
261
+ .min_access_size = 4,
262
+ .max_access_size = 4,
263
+ .unaligned = false,
264
+ },
402
+ },
265
+ .impl = {
403
+ .impl = {
266
+ .max_access_size = 4,
404
+ .max_access_size = 4,
405
+ .min_access_size = 4,
406
+ .unaligned = false
267
+ },
407
+ },
268
+};
408
+};
269
+
409
+
270
+static void cprman_reset(DeviceState *dev)
410
+static Property stm32l4x5_usart_base_properties[] = {
271
+{
411
+ DEFINE_PROP_CHR("chardev", Stm32l4x5UsartBaseState, chr),
272
+ BCM2835CprmanState *s = CPRMAN(dev);
412
+ DEFINE_PROP_END_OF_LIST(),
273
+
413
+};
274
+ memset(s->regs, 0, sizeof(s->regs));
414
+
275
+
415
+static void stm32l4x5_usart_base_init(Object *obj)
276
+ clock_update_hz(s->xosc, s->xosc_freq);
416
+{
277
+}
417
+ Stm32l4x5UsartBaseState *s = STM32L4X5_USART_BASE(obj);
278
+
418
+
279
+static void cprman_init(Object *obj)
419
+ sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->irq);
280
+{
420
+
281
+ BCM2835CprmanState *s = CPRMAN(obj);
421
+ memory_region_init_io(&s->mmio, obj, &stm32l4x5_usart_base_ops, s,
282
+
422
+ TYPE_STM32L4X5_USART_BASE, 0x400);
283
+ s->xosc = clock_new(obj, "xosc");
423
+ sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio);
284
+
424
+
285
+ memory_region_init_io(&s->iomem, obj, &cprman_ops,
425
+ s->clk = qdev_init_clock_in(DEVICE(s), "clk", NULL, s, 0);
286
+ s, "bcm2835-cprman", 0x2000);
426
+}
287
+ sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->iomem);
427
+
288
+}
428
+static const VMStateDescription vmstate_stm32l4x5_usart_base = {
289
+
429
+ .name = TYPE_STM32L4X5_USART_BASE,
290
+static const VMStateDescription cprman_vmstate = {
291
+ .name = TYPE_BCM2835_CPRMAN,
292
+ .version_id = 1,
430
+ .version_id = 1,
293
+ .minimum_version_id = 1,
431
+ .minimum_version_id = 1,
294
+ .fields = (VMStateField[]) {
432
+ .fields = (VMStateField[]) {
295
+ VMSTATE_UINT32_ARRAY(regs, BCM2835CprmanState, CPRMAN_NUM_REGS),
433
+ VMSTATE_UINT32(cr1, Stm32l4x5UsartBaseState),
434
+ VMSTATE_UINT32(cr2, Stm32l4x5UsartBaseState),
435
+ VMSTATE_UINT32(cr3, Stm32l4x5UsartBaseState),
436
+ VMSTATE_UINT32(brr, Stm32l4x5UsartBaseState),
437
+ VMSTATE_UINT32(gtpr, Stm32l4x5UsartBaseState),
438
+ VMSTATE_UINT32(rtor, Stm32l4x5UsartBaseState),
439
+ VMSTATE_UINT32(isr, Stm32l4x5UsartBaseState),
440
+ VMSTATE_UINT32(rdr, Stm32l4x5UsartBaseState),
441
+ VMSTATE_UINT32(tdr, Stm32l4x5UsartBaseState),
442
+ VMSTATE_CLOCK(clk, Stm32l4x5UsartBaseState),
296
+ VMSTATE_END_OF_LIST()
443
+ VMSTATE_END_OF_LIST()
297
+ }
444
+ }
298
+};
445
+};
299
+
446
+
300
+static Property cprman_properties[] = {
447
+
301
+ DEFINE_PROP_UINT32("xosc-freq-hz", BCM2835CprmanState, xosc_freq, 19200000),
448
+static void stm32l4x5_usart_base_realize(DeviceState *dev, Error **errp)
302
+ DEFINE_PROP_END_OF_LIST()
449
+{
450
+ ERRP_GUARD();
451
+ Stm32l4x5UsartBaseState *s = STM32L4X5_USART_BASE(dev);
452
+ if (!clock_has_source(s->clk)) {
453
+ error_setg(errp, "USART clock must be wired up by SoC code");
454
+ return;
455
+ }
456
+}
457
+
458
+static void stm32l4x5_usart_base_class_init(ObjectClass *klass, void *data)
459
+{
460
+ DeviceClass *dc = DEVICE_CLASS(klass);
461
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
462
+
463
+ rc->phases.hold = stm32l4x5_usart_base_reset_hold;
464
+ device_class_set_props(dc, stm32l4x5_usart_base_properties);
465
+ dc->realize = stm32l4x5_usart_base_realize;
466
+ dc->vmsd = &vmstate_stm32l4x5_usart_base;
467
+}
468
+
469
+static void stm32l4x5_usart_class_init(ObjectClass *oc, void *data)
470
+{
471
+ Stm32l4x5UsartBaseClass *subc = STM32L4X5_USART_BASE_CLASS(oc);
472
+
473
+ subc->type = STM32L4x5_USART;
474
+}
475
+
476
+static void stm32l4x5_uart_class_init(ObjectClass *oc, void *data)
477
+{
478
+ Stm32l4x5UsartBaseClass *subc = STM32L4X5_USART_BASE_CLASS(oc);
479
+
480
+ subc->type = STM32L4x5_UART;
481
+}
482
+
483
+static void stm32l4x5_lpuart_class_init(ObjectClass *oc, void *data)
484
+{
485
+ Stm32l4x5UsartBaseClass *subc = STM32L4X5_USART_BASE_CLASS(oc);
486
+
487
+ subc->type = STM32L4x5_LPUART;
488
+}
489
+
490
+static const TypeInfo stm32l4x5_usart_types[] = {
491
+ {
492
+ .name = TYPE_STM32L4X5_USART_BASE,
493
+ .parent = TYPE_SYS_BUS_DEVICE,
494
+ .instance_size = sizeof(Stm32l4x5UsartBaseState),
495
+ .instance_init = stm32l4x5_usart_base_init,
496
+ .class_init = stm32l4x5_usart_base_class_init,
497
+ .abstract = true,
498
+ }, {
499
+ .name = TYPE_STM32L4X5_USART,
500
+ .parent = TYPE_STM32L4X5_USART_BASE,
501
+ .class_init = stm32l4x5_usart_class_init,
502
+ }, {
503
+ .name = TYPE_STM32L4X5_UART,
504
+ .parent = TYPE_STM32L4X5_USART_BASE,
505
+ .class_init = stm32l4x5_uart_class_init,
506
+ }, {
507
+ .name = TYPE_STM32L4X5_LPUART,
508
+ .parent = TYPE_STM32L4X5_USART_BASE,
509
+ .class_init = stm32l4x5_lpuart_class_init,
510
+ }
303
+};
511
+};
304
+
512
+
305
+static void cprman_class_init(ObjectClass *klass, void *data)
513
+DEFINE_TYPES(stm32l4x5_usart_types)
306
+{
514
diff --git a/hw/char/Kconfig b/hw/char/Kconfig
307
+ DeviceClass *dc = DEVICE_CLASS(klass);
308
+
309
+ dc->reset = cprman_reset;
310
+ dc->vmsd = &cprman_vmstate;
311
+ device_class_set_props(dc, cprman_properties);
312
+}
313
+
314
+static const TypeInfo cprman_info = {
315
+ .name = TYPE_BCM2835_CPRMAN,
316
+ .parent = TYPE_SYS_BUS_DEVICE,
317
+ .instance_size = sizeof(BCM2835CprmanState),
318
+ .class_init = cprman_class_init,
319
+ .instance_init = cprman_init,
320
+};
321
+
322
+static void cprman_register_types(void)
323
+{
324
+ type_register_static(&cprman_info);
325
+}
326
+
327
+type_init(cprman_register_types);
328
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
329
index XXXXXXX..XXXXXXX 100644
515
index XXXXXXX..XXXXXXX 100644
330
--- a/hw/misc/meson.build
516
--- a/hw/char/Kconfig
331
+++ b/hw/misc/meson.build
517
+++ b/hw/char/Kconfig
332
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_RASPI', if_true: files(
518
@@ -XXX,XX +XXX,XX @@ config VIRTIO_SERIAL
333
'bcm2835_property.c',
519
config STM32F2XX_USART
334
'bcm2835_rng.c',
520
bool
335
'bcm2835_thermal.c',
521
336
+ 'bcm2835_cprman.c',
522
+config STM32L4X5_USART
337
))
523
+ bool
338
softmmu_ss.add(when: 'CONFIG_SLAVIO', if_true: files('slavio_misc.c'))
524
+
339
softmmu_ss.add(when: 'CONFIG_ZYNQ', if_true: files('zynq_slcr.c', 'zynq-xadc.c'))
525
config CMSDK_APB_UART
340
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
526
bool
527
528
diff --git a/hw/char/meson.build b/hw/char/meson.build
341
index XXXXXXX..XXXXXXX 100644
529
index XXXXXXX..XXXXXXX 100644
342
--- a/hw/misc/trace-events
530
--- a/hw/char/meson.build
343
+++ b/hw/misc/trace-events
531
+++ b/hw/char/meson.build
344
@@ -XXX,XX +XXX,XX @@ grlib_apb_pnp_read(uint64_t addr, uint32_t value) "APB PnP read addr:0x%03"PRIx6
532
@@ -XXX,XX +XXX,XX @@ system_ss.add(when: 'CONFIG_RENESAS_SCI', if_true: files('renesas_sci.c'))
345
# pca9552.c
533
system_ss.add(when: 'CONFIG_SIFIVE_UART', if_true: files('sifive_uart.c'))
346
pca955x_gpio_status(const char *description, const char *buf) "%s GPIOs 0-15 [%s]"
534
system_ss.add(when: 'CONFIG_SH_SCI', if_true: files('sh_serial.c'))
347
pca955x_gpio_change(const char *description, unsigned id, unsigned prev_state, unsigned current_state) "%s GPIO id:%u status: %u -> %u"
535
system_ss.add(when: 'CONFIG_STM32F2XX_USART', if_true: files('stm32f2xx_usart.c'))
348
+
536
+system_ss.add(when: 'CONFIG_STM32L4X5_USART', if_true: files('stm32l4x5_usart.c'))
349
+# bcm2835_cprman.c
537
system_ss.add(when: 'CONFIG_MCHP_PFSOC_MMUART', if_true: files('mchp_pfsoc_mmuart.c'))
350
+bcm2835_cprman_read(uint64_t offset, uint64_t value) "offset:0x%" PRIx64 " value:0x%" PRIx64
538
system_ss.add(when: 'CONFIG_HTIF', if_true: files('riscv_htif.c'))
351
+bcm2835_cprman_write(uint64_t offset, uint64_t value) "offset:0x%" PRIx64 " value:0x%" PRIx64
539
system_ss.add(when: 'CONFIG_GOLDFISH_TTY', if_true: files('goldfish_tty.c'))
352
+bcm2835_cprman_write_invalid_magic(uint64_t offset, uint64_t value) "offset:0x%" PRIx64 " value:0x%" PRIx64
540
diff --git a/hw/char/trace-events b/hw/char/trace-events
541
index XXXXXXX..XXXXXXX 100644
542
--- a/hw/char/trace-events
543
+++ b/hw/char/trace-events
544
@@ -XXX,XX +XXX,XX @@ cadence_uart_baudrate(unsigned baudrate) "baudrate %u"
545
sh_serial_read(char *id, unsigned size, uint64_t offs, uint64_t val) " %s size %d offs 0x%02" PRIx64 " -> 0x%02" PRIx64
546
sh_serial_write(char *id, unsigned size, uint64_t offs, uint64_t val) "%s size %d offs 0x%02" PRIx64 " <- 0x%02" PRIx64
547
548
+# stm32l4x5_usart.c
549
+stm32l4x5_usart_read(uint64_t addr, uint32_t data) "USART: Read <0x%" PRIx64 "> -> 0x%" PRIx32 ""
550
+stm32l4x5_usart_write(uint64_t addr, uint32_t data) "USART: Write <0x%" PRIx64 "> <- 0x%" PRIx32 ""
551
+
552
# xen_console.c
553
xen_console_connect(unsigned int idx, unsigned int ring_ref, unsigned int port, unsigned int limit) "idx %u ring_ref %u port %u limit %u"
554
xen_console_disconnect(unsigned int idx) "idx %u"
353
--
555
--
354
2.20.1
556
2.34.1
355
557
356
558
diff view generated by jsdifflib
1
From: Luc Michel <luc@lmichel.fr>
1
From: Arnaud Minier <arnaud.minier@telecom-paris.fr>
2
2
3
Add a clock input to the PL011 UART so we can compute the current baud
3
Implement the ability to read and write characters to the
4
rate and trace it. This is intended for developers who wish to use QEMU
4
usart using the serial port.
5
to e.g. debug their firmware or to figure out the baud rate configured
5
6
by an unknown/closed source binary.
6
The character transmission is based on the
7
7
cmsdk-apb-uart implementation.
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
9
Signed-off-by: Luc Michel <luc@lmichel.fr>
9
Signed-off-by: Arnaud Minier <arnaud.minier@telecom-paris.fr>
10
Tested-by: Guenter Roeck <linux@roeck-us.net>
10
Signed-off-by: Inès Varhol <ines.varhol@telecom-paris.fr>
11
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
Message-id: 20240329174402.60382-3-arnaud.minier@telecom-paris.fr
13
[PMM: fixed a few checkpatch nits]
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
15
---
14
include/hw/char/pl011.h | 1 +
16
include/hw/char/stm32l4x5_usart.h | 1 +
15
hw/char/pl011.c | 45 +++++++++++++++++++++++++++++++++++++++++
17
hw/char/stm32l4x5_usart.c | 143 ++++++++++++++++++++++++++++++
16
hw/char/trace-events | 1 +
18
hw/char/trace-events | 7 ++
17
3 files changed, 47 insertions(+)
19
3 files changed, 151 insertions(+)
18
20
19
diff --git a/include/hw/char/pl011.h b/include/hw/char/pl011.h
21
diff --git a/include/hw/char/stm32l4x5_usart.h b/include/hw/char/stm32l4x5_usart.h
20
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
21
--- a/include/hw/char/pl011.h
23
--- a/include/hw/char/stm32l4x5_usart.h
22
+++ b/include/hw/char/pl011.h
24
+++ b/include/hw/char/stm32l4x5_usart.h
23
@@ -XXX,XX +XXX,XX @@ struct PL011State {
25
@@ -XXX,XX +XXX,XX @@ struct Stm32l4x5UsartBaseState {
24
int read_trigger;
26
Clock *clk;
25
CharBackend chr;
27
CharBackend chr;
26
qemu_irq irq[6];
28
qemu_irq irq;
27
+ Clock *clk;
29
+ guint watch_tag;
28
const unsigned char *id;
29
};
30
};
30
31
31
diff --git a/hw/char/pl011.c b/hw/char/pl011.c
32
struct Stm32l4x5UsartBaseClass {
33
diff --git a/hw/char/stm32l4x5_usart.c b/hw/char/stm32l4x5_usart.c
32
index XXXXXXX..XXXXXXX 100644
34
index XXXXXXX..XXXXXXX 100644
33
--- a/hw/char/pl011.c
35
--- a/hw/char/stm32l4x5_usart.c
34
+++ b/hw/char/pl011.c
36
+++ b/hw/char/stm32l4x5_usart.c
35
@@ -XXX,XX +XXX,XX @@
37
@@ -XXX,XX +XXX,XX @@ REG32(RDR, 0x24)
36
#include "hw/char/pl011.h"
38
REG32(TDR, 0x28)
37
#include "hw/irq.h"
39
FIELD(TDR, TDR, 0, 9)
38
#include "hw/sysbus.h"
40
39
+#include "hw/qdev-clock.h"
41
+static void stm32l4x5_update_irq(Stm32l4x5UsartBaseState *s)
40
#include "migration/vmstate.h"
42
+{
41
#include "chardev/char-fe.h"
43
+ if (((s->isr & R_ISR_WUF_MASK) && (s->cr3 & R_CR3_WUFIE_MASK)) ||
42
#include "qemu/log.h"
44
+ ((s->isr & R_ISR_CMF_MASK) && (s->cr1 & R_CR1_CMIE_MASK)) ||
43
@@ -XXX,XX +XXX,XX @@ static void pl011_set_read_trigger(PL011State *s)
45
+ ((s->isr & R_ISR_ABRF_MASK) && (s->cr1 & R_CR1_RXNEIE_MASK)) ||
44
s->read_trigger = 1;
46
+ ((s->isr & R_ISR_EOBF_MASK) && (s->cr1 & R_CR1_EOBIE_MASK)) ||
47
+ ((s->isr & R_ISR_RTOF_MASK) && (s->cr1 & R_CR1_RTOIE_MASK)) ||
48
+ ((s->isr & R_ISR_CTSIF_MASK) && (s->cr3 & R_CR3_CTSIE_MASK)) ||
49
+ ((s->isr & R_ISR_LBDF_MASK) && (s->cr2 & R_CR2_LBDIE_MASK)) ||
50
+ ((s->isr & R_ISR_TXE_MASK) && (s->cr1 & R_CR1_TXEIE_MASK)) ||
51
+ ((s->isr & R_ISR_TC_MASK) && (s->cr1 & R_CR1_TCIE_MASK)) ||
52
+ ((s->isr & R_ISR_RXNE_MASK) && (s->cr1 & R_CR1_RXNEIE_MASK)) ||
53
+ ((s->isr & R_ISR_IDLE_MASK) && (s->cr1 & R_CR1_IDLEIE_MASK)) ||
54
+ ((s->isr & R_ISR_ORE_MASK) &&
55
+ ((s->cr1 & R_CR1_RXNEIE_MASK) || (s->cr3 & R_CR3_EIE_MASK))) ||
56
+ /* TODO: Handle NF ? */
57
+ ((s->isr & R_ISR_FE_MASK) && (s->cr3 & R_CR3_EIE_MASK)) ||
58
+ ((s->isr & R_ISR_PE_MASK) && (s->cr1 & R_CR1_PEIE_MASK))) {
59
+ qemu_irq_raise(s->irq);
60
+ trace_stm32l4x5_usart_irq_raised(s->isr);
61
+ } else {
62
+ qemu_irq_lower(s->irq);
63
+ trace_stm32l4x5_usart_irq_lowered();
64
+ }
65
+}
66
+
67
+static int stm32l4x5_usart_base_can_receive(void *opaque)
68
+{
69
+ Stm32l4x5UsartBaseState *s = opaque;
70
+
71
+ if (!(s->isr & R_ISR_RXNE_MASK)) {
72
+ return 1;
73
+ }
74
+
75
+ return 0;
76
+}
77
+
78
+static void stm32l4x5_usart_base_receive(void *opaque, const uint8_t *buf,
79
+ int size)
80
+{
81
+ Stm32l4x5UsartBaseState *s = opaque;
82
+
83
+ if (!((s->cr1 & R_CR1_UE_MASK) && (s->cr1 & R_CR1_RE_MASK))) {
84
+ trace_stm32l4x5_usart_receiver_not_enabled(
85
+ FIELD_EX32(s->cr1, CR1, UE), FIELD_EX32(s->cr1, CR1, RE));
86
+ return;
87
+ }
88
+
89
+ /* Check if overrun detection is enabled and if there is an overrun */
90
+ if (!(s->cr3 & R_CR3_OVRDIS_MASK) && (s->isr & R_ISR_RXNE_MASK)) {
91
+ /*
92
+ * A character has been received while
93
+ * the previous has not been read = Overrun.
94
+ */
95
+ s->isr |= R_ISR_ORE_MASK;
96
+ trace_stm32l4x5_usart_overrun_detected(s->rdr, *buf);
97
+ } else {
98
+ /* No overrun */
99
+ s->rdr = *buf;
100
+ s->isr |= R_ISR_RXNE_MASK;
101
+ trace_stm32l4x5_usart_rx(s->rdr);
102
+ }
103
+
104
+ stm32l4x5_update_irq(s);
105
+}
106
+
107
+/*
108
+ * Try to send tx data, and arrange to be called back later if
109
+ * we can't (ie the char backend is busy/blocking).
110
+ */
111
+static gboolean usart_transmit(void *do_not_use, GIOCondition cond,
112
+ void *opaque)
113
+{
114
+ Stm32l4x5UsartBaseState *s = STM32L4X5_USART_BASE(opaque);
115
+ int ret;
116
+ /* TODO: Handle 9 bits transmission */
117
+ uint8_t ch = s->tdr;
118
+
119
+ s->watch_tag = 0;
120
+
121
+ if (!(s->cr1 & R_CR1_TE_MASK) || (s->isr & R_ISR_TXE_MASK)) {
122
+ return G_SOURCE_REMOVE;
123
+ }
124
+
125
+ ret = qemu_chr_fe_write(&s->chr, &ch, 1);
126
+ if (ret <= 0) {
127
+ s->watch_tag = qemu_chr_fe_add_watch(&s->chr, G_IO_OUT | G_IO_HUP,
128
+ usart_transmit, s);
129
+ if (!s->watch_tag) {
130
+ /*
131
+ * Most common reason to be here is "no chardev backend":
132
+ * just insta-drain the buffer, so the serial output
133
+ * goes into a void, rather than blocking the guest.
134
+ */
135
+ goto buffer_drained;
136
+ }
137
+ /* Transmit pending */
138
+ trace_stm32l4x5_usart_tx_pending();
139
+ return G_SOURCE_REMOVE;
140
+ }
141
+
142
+buffer_drained:
143
+ /* Character successfully sent */
144
+ trace_stm32l4x5_usart_tx(ch);
145
+ s->isr |= R_ISR_TC_MASK | R_ISR_TXE_MASK;
146
+ stm32l4x5_update_irq(s);
147
+ return G_SOURCE_REMOVE;
148
+}
149
+
150
+static void usart_cancel_transmit(Stm32l4x5UsartBaseState *s)
151
+{
152
+ if (s->watch_tag) {
153
+ g_source_remove(s->watch_tag);
154
+ s->watch_tag = 0;
155
+ }
156
+}
157
+
158
static void stm32l4x5_usart_base_reset_hold(Object *obj, ResetType type)
159
{
160
Stm32l4x5UsartBaseState *s = STM32L4X5_USART_BASE(obj);
161
@@ -XXX,XX +XXX,XX @@ static void stm32l4x5_usart_base_reset_hold(Object *obj, ResetType type)
162
s->isr = 0x020000C0;
163
s->rdr = 0x00000000;
164
s->tdr = 0x00000000;
165
+
166
+ usart_cancel_transmit(s);
167
+ stm32l4x5_update_irq(s);
168
+}
169
+
170
+static void usart_update_rqr(Stm32l4x5UsartBaseState *s, uint32_t value)
171
+{
172
+ /* TXFRQ */
173
+ /* Reset RXNE flag */
174
+ if (value & R_RQR_RXFRQ_MASK) {
175
+ s->isr &= ~R_ISR_RXNE_MASK;
176
+ }
177
+ /* MMRQ */
178
+ /* SBKRQ */
179
+ /* ABRRQ */
180
+ stm32l4x5_update_irq(s);
45
}
181
}
46
182
47
+static unsigned int pl011_get_baudrate(const PL011State *s)
183
static uint64_t stm32l4x5_usart_base_read(void *opaque, hwaddr addr,
48
+{
184
@@ -XXX,XX +XXX,XX @@ static uint64_t stm32l4x5_usart_base_read(void *opaque, hwaddr addr,
49
+ uint64_t clk;
185
retvalue = FIELD_EX32(s->rdr, RDR, RDR);
50
+
186
/* Reset RXNE flag */
51
+ if (s->fbrd == 0) {
187
s->isr &= ~R_ISR_RXNE_MASK;
52
+ return 0;
188
+ stm32l4x5_update_irq(s);
53
+ }
54
+
55
+ clk = clock_get_hz(s->clk);
56
+ return (clk / ((s->ibrd << 6) + s->fbrd)) << 2;
57
+}
58
+
59
+static void pl011_trace_baudrate_change(const PL011State *s)
60
+{
61
+ trace_pl011_baudrate_change(pl011_get_baudrate(s),
62
+ clock_get_hz(s->clk),
63
+ s->ibrd, s->fbrd);
64
+}
65
+
66
static void pl011_write(void *opaque, hwaddr offset,
67
uint64_t value, unsigned size)
68
{
69
@@ -XXX,XX +XXX,XX @@ static void pl011_write(void *opaque, hwaddr offset,
70
break;
189
break;
71
case 9: /* UARTIBRD */
190
case A_TDR:
72
s->ibrd = value;
191
retvalue = FIELD_EX32(s->tdr, TDR, TDR);
73
+ pl011_trace_baudrate_change(s);
192
@@ -XXX,XX +XXX,XX @@ static void stm32l4x5_usart_base_write(void *opaque, hwaddr addr,
74
break;
193
switch (addr) {
75
case 10: /* UARTFBRD */
194
case A_CR1:
76
s->fbrd = value;
195
s->cr1 = value;
77
+ pl011_trace_baudrate_change(s);
196
+ stm32l4x5_update_irq(s);
78
break;
197
return;
79
case 11: /* UARTLCR_H */
198
case A_CR2:
80
/* Reset the FIFO state on FIFO enable or disable */
199
s->cr2 = value;
81
@@ -XXX,XX +XXX,XX @@ static void pl011_event(void *opaque, QEMUChrEvent event)
200
@@ -XXX,XX +XXX,XX @@ static void stm32l4x5_usart_base_write(void *opaque, hwaddr addr,
82
pl011_put_fifo(opaque, 0x400);
201
s->rtor = value;
202
return;
203
case A_RQR:
204
+ usart_update_rqr(s, value);
205
return;
206
case A_ISR:
207
qemu_log_mask(LOG_GUEST_ERROR,
208
@@ -XXX,XX +XXX,XX @@ static void stm32l4x5_usart_base_write(void *opaque, hwaddr addr,
209
case A_ICR:
210
/* Clear the status flags */
211
s->isr &= ~value;
212
+ stm32l4x5_update_irq(s);
213
return;
214
case A_RDR:
215
qemu_log_mask(LOG_GUEST_ERROR,
216
@@ -XXX,XX +XXX,XX @@ static void stm32l4x5_usart_base_write(void *opaque, hwaddr addr,
217
return;
218
case A_TDR:
219
s->tdr = value;
220
+ s->isr &= ~R_ISR_TXE_MASK;
221
+ usart_transmit(NULL, G_IO_OUT, s);
222
return;
223
default:
224
qemu_log_mask(LOG_GUEST_ERROR,
225
@@ -XXX,XX +XXX,XX @@ static void stm32l4x5_usart_base_realize(DeviceState *dev, Error **errp)
226
error_setg(errp, "USART clock must be wired up by SoC code");
227
return;
228
}
229
+
230
+ qemu_chr_fe_set_handlers(&s->chr, stm32l4x5_usart_base_can_receive,
231
+ stm32l4x5_usart_base_receive, NULL, NULL,
232
+ s, NULL, true);
83
}
233
}
84
234
85
+static void pl011_clock_update(void *opaque)
235
static void stm32l4x5_usart_base_class_init(ObjectClass *klass, void *data)
86
+{
87
+ PL011State *s = PL011(opaque);
88
+
89
+ pl011_trace_baudrate_change(s);
90
+}
91
+
92
static const MemoryRegionOps pl011_ops = {
93
.read = pl011_read,
94
.write = pl011_write,
95
.endianness = DEVICE_NATIVE_ENDIAN,
96
};
97
98
+static const VMStateDescription vmstate_pl011_clock = {
99
+ .name = "pl011/clock",
100
+ .version_id = 1,
101
+ .minimum_version_id = 1,
102
+ .fields = (VMStateField[]) {
103
+ VMSTATE_CLOCK(clk, PL011State),
104
+ VMSTATE_END_OF_LIST()
105
+ }
106
+};
107
+
108
static const VMStateDescription vmstate_pl011 = {
109
.name = "pl011",
110
.version_id = 2,
111
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_pl011 = {
112
VMSTATE_INT32(read_count, PL011State),
113
VMSTATE_INT32(read_trigger, PL011State),
114
VMSTATE_END_OF_LIST()
115
+ },
116
+ .subsections = (const VMStateDescription * []) {
117
+ &vmstate_pl011_clock,
118
+ NULL
119
}
120
};
121
122
@@ -XXX,XX +XXX,XX @@ static void pl011_init(Object *obj)
123
sysbus_init_irq(sbd, &s->irq[i]);
124
}
125
126
+ s->clk = qdev_init_clock_in(DEVICE(obj), "clk", pl011_clock_update, s);
127
+
128
s->read_trigger = 1;
129
s->ifl = 0x12;
130
s->cr = 0x300;
131
diff --git a/hw/char/trace-events b/hw/char/trace-events
236
diff --git a/hw/char/trace-events b/hw/char/trace-events
132
index XXXXXXX..XXXXXXX 100644
237
index XXXXXXX..XXXXXXX 100644
133
--- a/hw/char/trace-events
238
--- a/hw/char/trace-events
134
+++ b/hw/char/trace-events
239
+++ b/hw/char/trace-events
135
@@ -XXX,XX +XXX,XX @@ pl011_write(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x"
240
@@ -XXX,XX +XXX,XX @@ sh_serial_write(char *id, unsigned size, uint64_t offs, uint64_t val) "%s size %
136
pl011_can_receive(uint32_t lcr, int read_count, int r) "LCR 0x%08x read_count %d returning %d"
241
# stm32l4x5_usart.c
137
pl011_put_fifo(uint32_t c, int read_count) "new char 0x%x read_count now %d"
242
stm32l4x5_usart_read(uint64_t addr, uint32_t data) "USART: Read <0x%" PRIx64 "> -> 0x%" PRIx32 ""
138
pl011_put_fifo_full(void) "FIFO now full, RXFF set"
243
stm32l4x5_usart_write(uint64_t addr, uint32_t data) "USART: Write <0x%" PRIx64 "> <- 0x%" PRIx32 ""
139
+pl011_baudrate_change(unsigned int baudrate, uint64_t clock, uint32_t ibrd, uint32_t fbrd) "new baudrate %u (clk: %" PRIu64 "hz, ibrd: %" PRIu32 ", fbrd: %" PRIu32 ")"
244
+stm32l4x5_usart_rx(uint8_t c) "USART: got character 0x%x from backend"
140
245
+stm32l4x5_usart_tx(uint8_t c) "USART: character 0x%x sent to backend"
141
# cmsdk-apb-uart.c
246
+stm32l4x5_usart_tx_pending(void) "USART: character send to backend pending"
142
cmsdk_apb_uart_read(uint64_t offset, uint64_t data, unsigned size) "CMSDK APB UART read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
247
+stm32l4x5_usart_irq_raised(uint32_t reg) "USART: IRQ raised: 0x%08"PRIx32
248
+stm32l4x5_usart_irq_lowered(void) "USART: IRQ lowered"
249
+stm32l4x5_usart_overrun_detected(uint8_t current, uint8_t received) "USART: Overrun detected, RDR='0x%x', received 0x%x"
250
+stm32l4x5_usart_receiver_not_enabled(uint8_t ue_bit, uint8_t re_bit) "USART: Receiver not enabled, UE=0x%x, RE=0x%x"
251
252
# xen_console.c
253
xen_console_connect(unsigned int idx, unsigned int ring_ref, unsigned int port, unsigned int limit) "idx %u ring_ref %u port %u limit %u"
143
--
254
--
144
2.20.1
255
2.34.1
145
256
146
257
diff view generated by jsdifflib
1
From: Luc Michel <luc@lmichel.fr>
1
From: Arnaud Minier <arnaud.minier@telecom-paris.fr>
2
2
3
The CPRMAN PLLs generate a clock based on a prescaler, a multiplier and
3
Add a function to change the settings of the
4
a divider. The prescaler doubles the parent (xosc) frequency, then the
4
serial connection.
5
multiplier/divider are applied. The multiplier has an integer and a
6
fractional part.
7
5
8
This commit also implements the CPRMAN CM_LOCK register. This register
6
Signed-off-by: Arnaud Minier <arnaud.minier@telecom-paris.fr>
9
reports which PLL is currently locked. We consider a PLL has being
7
Signed-off-by: Inès Varhol <ines.varhol@telecom-paris.fr>
10
locked as soon as it is enabled (on real hardware, there is a delay
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
after turning a PLL on, for it to stabilize).
9
Message-id: 20240329174402.60382-4-arnaud.minier@telecom-paris.fr
12
13
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
14
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
15
Signed-off-by: Luc Michel <luc@lmichel.fr>
16
Tested-by: Guenter Roeck <linux@roeck-us.net>
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
---
11
---
19
include/hw/misc/bcm2835_cprman_internals.h | 8 +++
12
hw/char/stm32l4x5_usart.c | 98 +++++++++++++++++++++++++++++++++++++++
20
hw/misc/bcm2835_cprman.c | 64 +++++++++++++++++++++-
13
hw/char/trace-events | 1 +
21
2 files changed, 71 insertions(+), 1 deletion(-)
14
2 files changed, 99 insertions(+)
22
15
23
diff --git a/include/hw/misc/bcm2835_cprman_internals.h b/include/hw/misc/bcm2835_cprman_internals.h
16
diff --git a/hw/char/stm32l4x5_usart.c b/hw/char/stm32l4x5_usart.c
24
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
25
--- a/include/hw/misc/bcm2835_cprman_internals.h
18
--- a/hw/char/stm32l4x5_usart.c
26
+++ b/include/hw/misc/bcm2835_cprman_internals.h
19
+++ b/hw/char/stm32l4x5_usart.c
27
@@ -XXX,XX +XXX,XX @@ REG32(A2W_PLLD_FRAC, 0x1240)
20
@@ -XXX,XX +XXX,XX @@ static void usart_cancel_transmit(Stm32l4x5UsartBaseState *s)
28
REG32(A2W_PLLH_FRAC, 0x1260)
21
}
29
REG32(A2W_PLLB_FRAC, 0x12e0)
22
}
30
23
31
+/* misc registers */
24
+static void stm32l4x5_update_params(Stm32l4x5UsartBaseState *s)
32
+REG32(CM_LOCK, 0x114)
25
+{
33
+ FIELD(CM_LOCK, FLOCKH, 12, 1)
26
+ int speed, parity, data_bits, stop_bits;
34
+ FIELD(CM_LOCK, FLOCKD, 11, 1)
27
+ uint32_t value, usart_div;
35
+ FIELD(CM_LOCK, FLOCKC, 10, 1)
28
+ QEMUSerialSetParams ssp;
36
+ FIELD(CM_LOCK, FLOCKB, 9, 1)
37
+ FIELD(CM_LOCK, FLOCKA, 8, 1)
38
+
29
+
39
/*
30
+ /* Select the parity type */
40
* This field is common to all registers. Each register write value must match
31
+ if (s->cr1 & R_CR1_PCE_MASK) {
41
* the CPRMAN_PASSWORD magic value in its 8 MSB.
32
+ if (s->cr1 & R_CR1_PS_MASK) {
42
diff --git a/hw/misc/bcm2835_cprman.c b/hw/misc/bcm2835_cprman.c
33
+ parity = 'O';
43
index XXXXXXX..XXXXXXX 100644
34
+ } else {
44
--- a/hw/misc/bcm2835_cprman.c
35
+ parity = 'E';
45
+++ b/hw/misc/bcm2835_cprman.c
36
+ }
46
@@ -XXX,XX +XXX,XX @@
37
+ } else {
47
38
+ parity = 'N';
48
/* PLL */
39
+ }
49
50
+static bool pll_is_locked(const CprmanPllState *pll)
51
+{
52
+ return !FIELD_EX32(*pll->reg_a2w_ctrl, A2W_PLLx_CTRL, PWRDN)
53
+ && !FIELD_EX32(*pll->reg_cm, CM_PLLx, ANARST);
54
+}
55
+
40
+
56
static void pll_update(CprmanPllState *pll)
41
+ /* Select the number of stop bits */
57
{
42
+ switch (FIELD_EX32(s->cr2, CR2, STOP)) {
58
- clock_update(pll->out, 0);
43
+ case 0:
59
+ uint64_t freq, ndiv, fdiv, pdiv;
44
+ stop_bits = 1;
60
+
45
+ break;
61
+ if (!pll_is_locked(pll)) {
46
+ case 2:
62
+ clock_update(pll->out, 0);
47
+ stop_bits = 2;
48
+ break;
49
+ default:
50
+ qemu_log_mask(LOG_UNIMP,
51
+ "UNIMPLEMENTED: fractionnal stop bits; CR2[13:12] = %u",
52
+ FIELD_EX32(s->cr2, CR2, STOP));
63
+ return;
53
+ return;
64
+ }
54
+ }
65
+
55
+
66
+ pdiv = FIELD_EX32(*pll->reg_a2w_ctrl, A2W_PLLx_CTRL, PDIV);
56
+ /* Select the length of the word */
67
+
57
+ switch ((FIELD_EX32(s->cr1, CR1, M1) << 1) | FIELD_EX32(s->cr1, CR1, M0)) {
68
+ if (!pdiv) {
58
+ case 0:
69
+ clock_update(pll->out, 0);
59
+ data_bits = 8;
60
+ break;
61
+ case 1:
62
+ data_bits = 9;
63
+ break;
64
+ case 2:
65
+ data_bits = 7;
66
+ break;
67
+ default:
68
+ qemu_log_mask(LOG_GUEST_ERROR,
69
+ "UNDEFINED: invalid word length, CR1.M = 0b11");
70
+ return;
70
+ return;
71
+ }
71
+ }
72
+
72
+
73
+ ndiv = FIELD_EX32(*pll->reg_a2w_ctrl, A2W_PLLx_CTRL, NDIV);
73
+ /* Select the baud rate */
74
+ fdiv = FIELD_EX32(*pll->reg_a2w_frac, A2W_PLLx_FRAC, FRAC);
74
+ value = FIELD_EX32(s->brr, BRR, BRR);
75
+
75
+ if (value < 16) {
76
+ if (pll->reg_a2w_ana[1] & pll->prediv_mask) {
76
+ qemu_log_mask(LOG_GUEST_ERROR,
77
+ /* The prescaler doubles the parent frequency */
77
+ "UNDEFINED: BRR less than 16: %u", value);
78
+ ndiv *= 2;
78
+ return;
79
+ fdiv *= 2;
80
+ }
79
+ }
81
+
80
+
82
+ /*
81
+ if (FIELD_EX32(s->cr1, CR1, OVER8) == 0) {
83
+ * We have a multiplier with an integer part (ndiv) and a fractional part
82
+ /*
84
+ * (fdiv), and a divider (pdiv).
83
+ * Oversampling by 16
85
+ */
84
+ * BRR = USARTDIV
86
+ freq = clock_get_hz(pll->xosc_in) *
85
+ */
87
+ ((ndiv << R_A2W_PLLx_FRAC_FRAC_LENGTH) + fdiv);
86
+ usart_div = value;
88
+ freq /= pdiv;
87
+ } else {
89
+ freq >>= R_A2W_PLLx_FRAC_FRAC_LENGTH;
88
+ /*
90
+
89
+ * Oversampling by 8
91
+ clock_update_hz(pll->out, freq);
90
+ * - BRR[2:0] = USARTDIV[3:0] shifted 1 bit to the right.
92
}
91
+ * - BRR[3] must be kept cleared.
93
92
+ * - BRR[15:4] = USARTDIV[15:4]
94
static void pll_xosc_update(void *opaque)
93
+ * - The frequency is multiplied by 2
95
@@ -XXX,XX +XXX,XX @@ static const TypeInfo cprman_pll_info = {
94
+ */
96
95
+ usart_div = ((value & 0xFFF0) | ((value & 0x0007) << 1)) / 2;
97
/* CPRMAN "top level" model */
98
99
+static uint32_t get_cm_lock(const BCM2835CprmanState *s)
100
+{
101
+ static const int CM_LOCK_MAPPING[CPRMAN_NUM_PLL] = {
102
+ [CPRMAN_PLLA] = R_CM_LOCK_FLOCKA_SHIFT,
103
+ [CPRMAN_PLLC] = R_CM_LOCK_FLOCKC_SHIFT,
104
+ [CPRMAN_PLLD] = R_CM_LOCK_FLOCKD_SHIFT,
105
+ [CPRMAN_PLLH] = R_CM_LOCK_FLOCKH_SHIFT,
106
+ [CPRMAN_PLLB] = R_CM_LOCK_FLOCKB_SHIFT,
107
+ };
108
+
109
+ uint32_t r = 0;
110
+ size_t i;
111
+
112
+ for (i = 0; i < CPRMAN_NUM_PLL; i++) {
113
+ r |= pll_is_locked(&s->plls[i]) << CM_LOCK_MAPPING[i];
114
+ }
96
+ }
115
+
97
+
116
+ return r;
98
+ speed = clock_get_hz(s->clk) / usart_div;
99
+
100
+ ssp.speed = speed;
101
+ ssp.parity = parity;
102
+ ssp.data_bits = data_bits;
103
+ ssp.stop_bits = stop_bits;
104
+
105
+ qemu_chr_fe_ioctl(&s->chr, CHR_IOCTL_SERIAL_SET_PARAMS, &ssp);
106
+
107
+ trace_stm32l4x5_usart_update_params(speed, parity, data_bits, stop_bits);
117
+}
108
+}
118
+
109
+
119
static uint64_t cprman_read(void *opaque, hwaddr offset,
110
static void stm32l4x5_usart_base_reset_hold(Object *obj, ResetType type)
120
unsigned size)
121
{
111
{
122
@@ -XXX,XX +XXX,XX @@ static uint64_t cprman_read(void *opaque, hwaddr offset,
112
Stm32l4x5UsartBaseState *s = STM32L4X5_USART_BASE(obj);
123
size_t idx = offset / sizeof(uint32_t);
113
@@ -XXX,XX +XXX,XX @@ static void stm32l4x5_usart_base_write(void *opaque, hwaddr addr,
124
114
switch (addr) {
125
switch (idx) {
115
case A_CR1:
126
+ case R_CM_LOCK:
116
s->cr1 = value;
127
+ r = get_cm_lock(s);
117
+ stm32l4x5_update_params(s);
128
+ break;
118
stm32l4x5_update_irq(s);
119
return;
120
case A_CR2:
121
s->cr2 = value;
122
+ stm32l4x5_update_params(s);
123
return;
124
case A_CR3:
125
s->cr3 = value;
126
return;
127
case A_BRR:
128
s->brr = value;
129
+ stm32l4x5_update_params(s);
130
return;
131
case A_GTPR:
132
s->gtpr = value;
133
@@ -XXX,XX +XXX,XX @@ static void stm32l4x5_usart_base_init(Object *obj)
134
s->clk = qdev_init_clock_in(DEVICE(s), "clk", NULL, s, 0);
135
}
136
137
+static int stm32l4x5_usart_base_post_load(void *opaque, int version_id)
138
+{
139
+ Stm32l4x5UsartBaseState *s = (Stm32l4x5UsartBaseState *)opaque;
129
+
140
+
130
default:
141
+ stm32l4x5_update_params(s);
131
r = s->regs[idx];
142
+ return 0;
132
}
143
+}
144
+
145
static const VMStateDescription vmstate_stm32l4x5_usart_base = {
146
.name = TYPE_STM32L4X5_USART_BASE,
147
.version_id = 1,
148
.minimum_version_id = 1,
149
+ .post_load = stm32l4x5_usart_base_post_load,
150
.fields = (VMStateField[]) {
151
VMSTATE_UINT32(cr1, Stm32l4x5UsartBaseState),
152
VMSTATE_UINT32(cr2, Stm32l4x5UsartBaseState),
153
diff --git a/hw/char/trace-events b/hw/char/trace-events
154
index XXXXXXX..XXXXXXX 100644
155
--- a/hw/char/trace-events
156
+++ b/hw/char/trace-events
157
@@ -XXX,XX +XXX,XX @@ stm32l4x5_usart_irq_raised(uint32_t reg) "USART: IRQ raised: 0x%08"PRIx32
158
stm32l4x5_usart_irq_lowered(void) "USART: IRQ lowered"
159
stm32l4x5_usart_overrun_detected(uint8_t current, uint8_t received) "USART: Overrun detected, RDR='0x%x', received 0x%x"
160
stm32l4x5_usart_receiver_not_enabled(uint8_t ue_bit, uint8_t re_bit) "USART: Receiver not enabled, UE=0x%x, RE=0x%x"
161
+stm32l4x5_usart_update_params(int speed, uint8_t parity, int data, int stop) "USART: speed: %d, parity: %c, data bits: %d, stop bits: %d"
162
163
# xen_console.c
164
xen_console_connect(unsigned int idx, unsigned int ring_ref, unsigned int port, unsigned int limit) "idx %u ring_ref %u port %u limit %u"
133
--
165
--
134
2.20.1
166
2.34.1
135
167
136
168
diff view generated by jsdifflib
1
From: Shashi Mallela <shashi.mallela@linaro.org>
1
From: Arnaud Minier <arnaud.minier@telecom-paris.fr>
2
2
3
Generic watchdog device model implementation as per ARM SBSA v6.0
3
Add the USART to the SoC and connect it to the other implemented devices.
4
4
5
Signed-off-by: Shashi Mallela <shashi.mallela@linaro.org>
5
Signed-off-by: Arnaud Minier <arnaud.minier@telecom-paris.fr>
6
Message-id: 20201027015927.29495-2-shashi.mallela@linaro.org
6
Signed-off-by: Inès Varhol <ines.varhol@telecom-paris.fr>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Message-id: 20240329174402.60382-5-arnaud.minier@telecom-paris.fr
9
[PMM: fixed a few checkpatch nits]
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
11
---
10
include/hw/watchdog/sbsa_gwdt.h | 79 +++++++++
12
docs/system/arm/b-l475e-iot01a.rst | 2 +-
11
hw/watchdog/sbsa_gwdt.c | 293 ++++++++++++++++++++++++++++++++
13
include/hw/arm/stm32l4x5_soc.h | 7 +++
12
hw/arm/Kconfig | 1 +
14
hw/arm/stm32l4x5_soc.c | 83 +++++++++++++++++++++++++++---
13
hw/watchdog/Kconfig | 3 +
15
hw/arm/Kconfig | 1 +
14
hw/watchdog/meson.build | 1 +
16
4 files changed, 86 insertions(+), 7 deletions(-)
15
5 files changed, 377 insertions(+)
17
16
create mode 100644 include/hw/watchdog/sbsa_gwdt.h
18
diff --git a/docs/system/arm/b-l475e-iot01a.rst b/docs/system/arm/b-l475e-iot01a.rst
17
create mode 100644 hw/watchdog/sbsa_gwdt.c
19
index XXXXXXX..XXXXXXX 100644
18
20
--- a/docs/system/arm/b-l475e-iot01a.rst
19
diff --git a/include/hw/watchdog/sbsa_gwdt.h b/include/hw/watchdog/sbsa_gwdt.h
21
+++ b/docs/system/arm/b-l475e-iot01a.rst
20
new file mode 100644
22
@@ -XXX,XX +XXX,XX @@ Currently B-L475E-IOT01A machine's only supports the following devices:
21
index XXXXXXX..XXXXXXX
23
- STM32L4x5 SYSCFG (System configuration controller)
22
--- /dev/null
24
- STM32L4x5 RCC (Reset and clock control)
23
+++ b/include/hw/watchdog/sbsa_gwdt.h
25
- STM32L4x5 GPIOs (General-purpose I/Os)
26
+- STM32L4x5 USARTs, UARTs and LPUART (Serial ports)
27
28
Missing devices
29
"""""""""""""""
30
31
The B-L475E-IOT01A does *not* support the following devices:
32
33
-- Serial ports (UART)
34
- Analog to Digital Converter (ADC)
35
- SPI controller
36
- Timer controller (TIMER)
37
diff --git a/include/hw/arm/stm32l4x5_soc.h b/include/hw/arm/stm32l4x5_soc.h
38
index XXXXXXX..XXXXXXX 100644
39
--- a/include/hw/arm/stm32l4x5_soc.h
40
+++ b/include/hw/arm/stm32l4x5_soc.h
24
@@ -XXX,XX +XXX,XX @@
41
@@ -XXX,XX +XXX,XX @@
25
+/*
42
#include "hw/misc/stm32l4x5_exti.h"
26
+ * Copyright (c) 2020 Linaro Limited
43
#include "hw/misc/stm32l4x5_rcc.h"
27
+ *
44
#include "hw/gpio/stm32l4x5_gpio.h"
28
+ * Authors:
45
+#include "hw/char/stm32l4x5_usart.h"
29
+ * Shashi Mallela <shashi.mallela@linaro.org>
46
#include "qom/object.h"
30
+ *
47
31
+ * This work is licensed under the terms of the GNU GPL, version 2 or (at your
48
#define TYPE_STM32L4X5_SOC "stm32l4x5-soc"
32
+ * option) any later version. See the COPYING file in the top-level directory.
49
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_TYPE(Stm32l4x5SocState, Stm32l4x5SocClass, STM32L4X5_SOC)
33
+ *
50
34
+ */
51
#define NUM_EXTI_OR_GATES 4
35
+
52
36
+#ifndef WDT_SBSA_GWDT_H
53
+#define STM_NUM_USARTS 3
37
+#define WDT_SBSA_GWDT_H
54
+#define STM_NUM_UARTS 2
38
+
55
+
39
+#include "qemu/bitops.h"
56
struct Stm32l4x5SocState {
40
+#include "hw/sysbus.h"
57
SysBusDevice parent_obj;
41
+#include "hw/irq.h"
58
42
+
59
@@ -XXX,XX +XXX,XX @@ struct Stm32l4x5SocState {
43
+#define TYPE_WDT_SBSA "sbsa_gwdt"
60
Stm32l4x5SyscfgState syscfg;
44
+#define SBSA_GWDT(obj) \
61
Stm32l4x5RccState rcc;
45
+ OBJECT_CHECK(SBSA_GWDTState, (obj), TYPE_WDT_SBSA)
62
Stm32l4x5GpioState gpio[NUM_GPIOS];
46
+#define SBSA_GWDT_CLASS(klass) \
63
+ Stm32l4x5UsartBaseState usart[STM_NUM_USARTS];
47
+ OBJECT_CLASS_CHECK(SBSA_GWDTClass, (klass), TYPE_WDT_SBSA)
64
+ Stm32l4x5UsartBaseState uart[STM_NUM_UARTS];
48
+#define SBSA_GWDT_GET_CLASS(obj) \
65
+ Stm32l4x5UsartBaseState lpuart;
49
+ OBJECT_GET_CLASS(SBSA_GWDTClass, (obj), TYPE_WDT_SBSA)
66
50
+
67
MemoryRegion sram1;
51
+/* SBSA Generic Watchdog register definitions */
68
MemoryRegion sram2;
52
+/* refresh frame */
69
diff --git a/hw/arm/stm32l4x5_soc.c b/hw/arm/stm32l4x5_soc.c
53
+#define SBSA_GWDT_WRR 0x000
70
index XXXXXXX..XXXXXXX 100644
54
+
71
--- a/hw/arm/stm32l4x5_soc.c
55
+/* control frame */
72
+++ b/hw/arm/stm32l4x5_soc.c
56
+#define SBSA_GWDT_WCS 0x000
57
+#define SBSA_GWDT_WOR 0x008
58
+#define SBSA_GWDT_WORU 0x00C
59
+#define SBSA_GWDT_WCV 0x010
60
+#define SBSA_GWDT_WCVU 0x014
61
+
62
+/* Watchdog Interface Identification Register */
63
+#define SBSA_GWDT_W_IIDR 0xFCC
64
+
65
+/* Watchdog Control and Status Register Bits */
66
+#define SBSA_GWDT_WCS_EN BIT(0)
67
+#define SBSA_GWDT_WCS_WS0 BIT(1)
68
+#define SBSA_GWDT_WCS_WS1 BIT(2)
69
+
70
+#define SBSA_GWDT_WOR_MASK 0x0000FFFF
71
+
72
+/*
73
+ * Watchdog Interface Identification Register definition
74
+ * considering JEP106 code for ARM in Bits [11:0]
75
+ */
76
+#define SBSA_GWDT_ID 0x1043B
77
+
78
+/* 2 Separate memory regions for each of refresh & control register frames */
79
+#define SBSA_GWDT_RMMIO_SIZE 0x1000
80
+#define SBSA_GWDT_CMMIO_SIZE 0x1000
81
+
82
+#define SBSA_TIMER_FREQ 62500000 /* Hz */
83
+
84
+typedef struct SBSA_GWDTState {
85
+ /* <private> */
86
+ SysBusDevice parent_obj;
87
+
88
+ /*< public >*/
89
+ MemoryRegion rmmio;
90
+ MemoryRegion cmmio;
91
+ qemu_irq irq;
92
+
93
+ QEMUTimer *timer;
94
+
95
+ uint32_t id;
96
+ uint32_t wcs;
97
+ uint32_t worl;
98
+ uint32_t woru;
99
+ uint32_t wcvl;
100
+ uint32_t wcvu;
101
+} SBSA_GWDTState;
102
+
103
+#endif /* WDT_SBSA_GWDT_H */
104
diff --git a/hw/watchdog/sbsa_gwdt.c b/hw/watchdog/sbsa_gwdt.c
105
new file mode 100644
106
index XXXXXXX..XXXXXXX
107
--- /dev/null
108
+++ b/hw/watchdog/sbsa_gwdt.c
109
@@ -XXX,XX +XXX,XX @@
73
@@ -XXX,XX +XXX,XX @@
110
+/*
74
#include "sysemu/sysemu.h"
111
+ * Generic watchdog device model for SBSA
75
#include "hw/or-irq.h"
112
+ *
76
#include "hw/arm/stm32l4x5_soc.h"
113
+ * The watchdog device has been implemented as revision 1 variant of
77
+#include "hw/char/stm32l4x5_usart.h"
114
+ * the ARM SBSA specification v6.0
78
#include "hw/gpio/stm32l4x5_gpio.h"
115
+ * (https://developer.arm.com/documentation/den0029/d?lang=en)
79
#include "hw/qdev-clock.h"
116
+ *
80
#include "hw/misc/unimp.h"
117
+ * Copyright Linaro.org 2020
81
@@ -XXX,XX +XXX,XX @@ static const struct {
118
+ *
82
{ 0x48001C00, 0x0000000F, 0x00000000, 0x00000000 },
119
+ * Authors:
83
};
120
+ * Shashi Mallela <shashi.mallela@linaro.org>
84
121
+ *
85
+static const hwaddr usart_addr[] = {
122
+ * This work is licensed under the terms of the GNU GPL, version 2 or (at your
86
+ 0x40013800, /* "USART1", 0x400 */
123
+ * option) any later version. See the COPYING file in the top-level directory.
87
+ 0x40004400, /* "USART2", 0x400 */
124
+ *
88
+ 0x40004800, /* "USART3", 0x400 */
125
+ */
126
+
127
+#include "qemu/osdep.h"
128
+#include "sysemu/reset.h"
129
+#include "sysemu/watchdog.h"
130
+#include "hw/watchdog/sbsa_gwdt.h"
131
+#include "qemu/timer.h"
132
+#include "migration/vmstate.h"
133
+#include "qemu/log.h"
134
+#include "qemu/module.h"
135
+
136
+static WatchdogTimerModel model = {
137
+ .wdt_name = TYPE_WDT_SBSA,
138
+ .wdt_description = "SBSA-compliant generic watchdog device",
139
+};
89
+};
140
+
90
+static const hwaddr uart_addr[] = {
141
+static const VMStateDescription vmstate_sbsa_gwdt = {
91
+ 0x40004C00, /* "UART4" , 0x400 */
142
+ .name = "sbsa-gwdt",
92
+ 0x40005000 /* "UART5" , 0x400 */
143
+ .version_id = 1,
144
+ .minimum_version_id = 1,
145
+ .fields = (VMStateField[]) {
146
+ VMSTATE_TIMER_PTR(timer, SBSA_GWDTState),
147
+ VMSTATE_UINT32(wcs, SBSA_GWDTState),
148
+ VMSTATE_UINT32(worl, SBSA_GWDTState),
149
+ VMSTATE_UINT32(woru, SBSA_GWDTState),
150
+ VMSTATE_UINT32(wcvl, SBSA_GWDTState),
151
+ VMSTATE_UINT32(wcvu, SBSA_GWDTState),
152
+ VMSTATE_END_OF_LIST()
153
+ }
154
+};
93
+};
155
+
94
+
156
+typedef enum WdtRefreshType {
95
+#define LPUART_BASE_ADDRESS 0x40008000
157
+ EXPLICIT_REFRESH = 0,
96
+
158
+ TIMEOUT_REFRESH = 1,
97
+static const int usart_irq[] = { 37, 38, 39 };
159
+} WdtRefreshType;
98
+static const int uart_irq[] = { 52, 53 };
160
+
99
+#define LPUART_IRQ 70
161
+static uint64_t sbsa_gwdt_rread(void *opaque, hwaddr addr, unsigned int size)
100
+
162
+{
101
static void stm32l4x5_soc_initfn(Object *obj)
163
+ SBSA_GWDTState *s = SBSA_GWDT(opaque);
102
{
164
+ uint32_t ret = 0;
103
Stm32l4x5SocState *s = STM32L4X5_SOC(obj);
165
+
104
@@ -XXX,XX +XXX,XX @@ static void stm32l4x5_soc_initfn(Object *obj)
166
+ switch (addr) {
105
g_autofree char *name = g_strdup_printf("gpio%c", 'a' + i);
167
+ case SBSA_GWDT_WRR:
106
object_initialize_child(obj, name, &s->gpio[i], TYPE_STM32L4X5_GPIO);
168
+ /* watch refresh read has no effect and returns 0 */
107
}
169
+ ret = 0;
108
+
170
+ break;
109
+ for (int i = 0; i < STM_NUM_USARTS; i++) {
171
+ case SBSA_GWDT_W_IIDR:
110
+ object_initialize_child(obj, "usart[*]", &s->usart[i],
172
+ ret = s->id;
111
+ TYPE_STM32L4X5_USART);
173
+ break;
112
+ }
174
+ default:
113
+
175
+ qemu_log_mask(LOG_GUEST_ERROR, "bad address in refresh frame read :"
114
+ for (int i = 0; i < STM_NUM_UARTS; i++) {
176
+ " 0x%x\n", (int)addr);
115
+ object_initialize_child(obj, "uart[*]", &s->uart[i],
177
+ }
116
+ TYPE_STM32L4X5_UART);
178
+ return ret;
117
+ }
179
+}
118
+ object_initialize_child(obj, "lpuart1", &s->lpuart,
180
+
119
+ TYPE_STM32L4X5_LPUART);
181
+static uint64_t sbsa_gwdt_read(void *opaque, hwaddr addr, unsigned int size)
120
}
182
+{
121
183
+ SBSA_GWDTState *s = SBSA_GWDT(opaque);
122
static void stm32l4x5_soc_realize(DeviceState *dev_soc, Error **errp)
184
+ uint32_t ret = 0;
123
@@ -XXX,XX +XXX,XX @@ static void stm32l4x5_soc_realize(DeviceState *dev_soc, Error **errp)
185
+
124
sysbus_mmio_map(busdev, 0, RCC_BASE_ADDRESS);
186
+ switch (addr) {
125
sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(armv7m, RCC_IRQ));
187
+ case SBSA_GWDT_WCS:
126
188
+ ret = s->wcs;
127
+ /* USART devices */
189
+ break;
128
+ for (int i = 0; i < STM_NUM_USARTS; i++) {
190
+ case SBSA_GWDT_WOR:
129
+ g_autofree char *name = g_strdup_printf("usart%d-out", i + 1);
191
+ ret = s->worl;
130
+ dev = DEVICE(&(s->usart[i]));
192
+ break;
131
+ qdev_prop_set_chr(dev, "chardev", serial_hd(i));
193
+ case SBSA_GWDT_WORU:
132
+ qdev_connect_clock_in(dev, "clk",
194
+ ret = s->woru;
133
+ qdev_get_clock_out(DEVICE(&(s->rcc)), name));
195
+ break;
134
+ busdev = SYS_BUS_DEVICE(dev);
196
+ case SBSA_GWDT_WCV:
135
+ if (!sysbus_realize(busdev, errp)) {
197
+ ret = s->wcvl;
136
+ return;
198
+ break;
199
+ case SBSA_GWDT_WCVU:
200
+ ret = s->wcvu;
201
+ break;
202
+ case SBSA_GWDT_W_IIDR:
203
+ ret = s->id;
204
+ break;
205
+ default:
206
+ qemu_log_mask(LOG_GUEST_ERROR, "bad address in control frame read :"
207
+ " 0x%x\n", (int)addr);
208
+ }
209
+ return ret;
210
+}
211
+
212
+static void sbsa_gwdt_update_timer(SBSA_GWDTState *s, WdtRefreshType rtype)
213
+{
214
+ uint64_t timeout = 0;
215
+
216
+ timer_del(s->timer);
217
+
218
+ if (s->wcs & SBSA_GWDT_WCS_EN) {
219
+ /*
220
+ * Extract the upper 16 bits from woru & 32 bits from worl
221
+ * registers to construct the 48 bit offset value
222
+ */
223
+ timeout = s->woru;
224
+ timeout <<= 32;
225
+ timeout |= s->worl;
226
+ timeout = muldiv64(timeout, NANOSECONDS_PER_SECOND, SBSA_TIMER_FREQ);
227
+ timeout += qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
228
+
229
+ if ((rtype == EXPLICIT_REFRESH) || ((rtype == TIMEOUT_REFRESH) &&
230
+ (!(s->wcs & SBSA_GWDT_WCS_WS0)))) {
231
+ /* store the current timeout value into compare registers */
232
+ s->wcvu = timeout >> 32;
233
+ s->wcvl = timeout;
234
+ }
137
+ }
235
+ timer_mod(s->timer, timeout);
138
+ sysbus_mmio_map(busdev, 0, usart_addr[i]);
236
+ }
139
+ sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(armv7m, usart_irq[i]));
237
+}
140
+ }
238
+
141
+
239
+static void sbsa_gwdt_rwrite(void *opaque, hwaddr offset, uint64_t data,
142
+ /*
240
+ unsigned size) {
143
+ * TODO: Connect the USARTs, UARTs and LPUART to the EXTI once the EXTI
241
+ SBSA_GWDTState *s = SBSA_GWDT(opaque);
144
+ * can handle other gpio-in than the gpios. (e.g. Direct Lines for the
242
+
145
+ * usarts)
243
+ if (offset == SBSA_GWDT_WRR) {
146
+ */
244
+ s->wcs &= ~(SBSA_GWDT_WCS_WS0 | SBSA_GWDT_WCS_WS1);
147
+
245
+
148
+ /* UART devices */
246
+ sbsa_gwdt_update_timer(s, EXPLICIT_REFRESH);
149
+ for (int i = 0; i < STM_NUM_UARTS; i++) {
247
+ } else {
150
+ g_autofree char *name = g_strdup_printf("uart%d-out", STM_NUM_USARTS + i + 1);
248
+ qemu_log_mask(LOG_GUEST_ERROR, "bad address in refresh frame write :"
151
+ dev = DEVICE(&(s->uart[i]));
249
+ " 0x%x\n", (int)offset);
152
+ qdev_prop_set_chr(dev, "chardev", serial_hd(STM_NUM_USARTS + i));
250
+ }
153
+ qdev_connect_clock_in(dev, "clk",
251
+}
154
+ qdev_get_clock_out(DEVICE(&(s->rcc)), name));
252
+
155
+ busdev = SYS_BUS_DEVICE(dev);
253
+static void sbsa_gwdt_write(void *opaque, hwaddr offset, uint64_t data,
156
+ if (!sysbus_realize(busdev, errp)) {
254
+ unsigned size) {
157
+ return;
255
+ SBSA_GWDTState *s = SBSA_GWDT(opaque);
256
+
257
+ switch (offset) {
258
+ case SBSA_GWDT_WCS:
259
+ s->wcs = data & SBSA_GWDT_WCS_EN;
260
+ qemu_set_irq(s->irq, 0);
261
+ sbsa_gwdt_update_timer(s, EXPLICIT_REFRESH);
262
+ break;
263
+
264
+ case SBSA_GWDT_WOR:
265
+ s->worl = data;
266
+ s->wcs &= ~(SBSA_GWDT_WCS_WS0 | SBSA_GWDT_WCS_WS1);
267
+ qemu_set_irq(s->irq, 0);
268
+ sbsa_gwdt_update_timer(s, EXPLICIT_REFRESH);
269
+ break;
270
+
271
+ case SBSA_GWDT_WORU:
272
+ s->woru = data & SBSA_GWDT_WOR_MASK;
273
+ s->wcs &= ~(SBSA_GWDT_WCS_WS0 | SBSA_GWDT_WCS_WS1);
274
+ qemu_set_irq(s->irq, 0);
275
+ sbsa_gwdt_update_timer(s, EXPLICIT_REFRESH);
276
+ break;
277
+
278
+ case SBSA_GWDT_WCV:
279
+ s->wcvl = data;
280
+ break;
281
+
282
+ case SBSA_GWDT_WCVU:
283
+ s->wcvu = data;
284
+ break;
285
+
286
+ default:
287
+ qemu_log_mask(LOG_GUEST_ERROR, "bad address in control frame write :"
288
+ " 0x%x\n", (int)offset);
289
+ }
290
+ return;
291
+}
292
+
293
+static void wdt_sbsa_gwdt_reset(DeviceState *dev)
294
+{
295
+ SBSA_GWDTState *s = SBSA_GWDT(dev);
296
+
297
+ timer_del(s->timer);
298
+
299
+ s->wcs = 0;
300
+ s->wcvl = 0;
301
+ s->wcvu = 0;
302
+ s->worl = 0;
303
+ s->woru = 0;
304
+ s->id = SBSA_GWDT_ID;
305
+}
306
+
307
+static void sbsa_gwdt_timer_sysinterrupt(void *opaque)
308
+{
309
+ SBSA_GWDTState *s = SBSA_GWDT(opaque);
310
+
311
+ if (!(s->wcs & SBSA_GWDT_WCS_WS0)) {
312
+ s->wcs |= SBSA_GWDT_WCS_WS0;
313
+ sbsa_gwdt_update_timer(s, TIMEOUT_REFRESH);
314
+ qemu_set_irq(s->irq, 1);
315
+ } else {
316
+ s->wcs |= SBSA_GWDT_WCS_WS1;
317
+ qemu_log_mask(CPU_LOG_RESET, "Watchdog timer expired.\n");
318
+ /*
319
+ * Reset the watchdog only if the guest gets notified about
320
+ * expiry. watchdog_perform_action() may temporarily relinquish
321
+ * the BQL; reset before triggering the action to avoid races with
322
+ * sbsa_gwdt instructions.
323
+ */
324
+ switch (get_watchdog_action()) {
325
+ case WATCHDOG_ACTION_DEBUG:
326
+ case WATCHDOG_ACTION_NONE:
327
+ case WATCHDOG_ACTION_PAUSE:
328
+ break;
329
+ default:
330
+ wdt_sbsa_gwdt_reset(DEVICE(s));
331
+ }
158
+ }
332
+ watchdog_perform_action();
159
+ sysbus_mmio_map(busdev, 0, uart_addr[i]);
333
+ }
160
+ sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(armv7m, uart_irq[i]));
334
+}
161
+ }
335
+
162
+
336
+static const MemoryRegionOps sbsa_gwdt_rops = {
163
+ /* LPUART device*/
337
+ .read = sbsa_gwdt_rread,
164
+ dev = DEVICE(&(s->lpuart));
338
+ .write = sbsa_gwdt_rwrite,
165
+ qdev_prop_set_chr(dev, "chardev", serial_hd(STM_NUM_USARTS + STM_NUM_UARTS));
339
+ .endianness = DEVICE_LITTLE_ENDIAN,
166
+ qdev_connect_clock_in(dev, "clk",
340
+ .valid.min_access_size = 4,
167
+ qdev_get_clock_out(DEVICE(&(s->rcc)), "lpuart1-out"));
341
+ .valid.max_access_size = 4,
168
+ busdev = SYS_BUS_DEVICE(dev);
342
+ .valid.unaligned = false,
169
+ if (!sysbus_realize(busdev, errp)) {
343
+};
170
+ return;
344
+
171
+ }
345
+static const MemoryRegionOps sbsa_gwdt_ops = {
172
+ sysbus_mmio_map(busdev, 0, LPUART_BASE_ADDRESS);
346
+ .read = sbsa_gwdt_read,
173
+ sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(armv7m, LPUART_IRQ));
347
+ .write = sbsa_gwdt_write,
174
+
348
+ .endianness = DEVICE_LITTLE_ENDIAN,
175
/* APB1 BUS */
349
+ .valid.min_access_size = 4,
176
create_unimplemented_device("TIM2", 0x40000000, 0x400);
350
+ .valid.max_access_size = 4,
177
create_unimplemented_device("TIM3", 0x40000400, 0x400);
351
+ .valid.unaligned = false,
178
@@ -XXX,XX +XXX,XX @@ static void stm32l4x5_soc_realize(DeviceState *dev_soc, Error **errp)
352
+};
179
create_unimplemented_device("SPI2", 0x40003800, 0x400);
353
+
180
create_unimplemented_device("SPI3", 0x40003C00, 0x400);
354
+static void wdt_sbsa_gwdt_realize(DeviceState *dev, Error **errp)
181
/* RESERVED: 0x40004000, 0x400 */
355
+{
182
- create_unimplemented_device("USART2", 0x40004400, 0x400);
356
+ SBSA_GWDTState *s = SBSA_GWDT(dev);
183
- create_unimplemented_device("USART3", 0x40004800, 0x400);
357
+ SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
184
- create_unimplemented_device("UART4", 0x40004C00, 0x400);
358
+
185
- create_unimplemented_device("UART5", 0x40005000, 0x400);
359
+ memory_region_init_io(&s->rmmio, OBJECT(dev),
186
create_unimplemented_device("I2C1", 0x40005400, 0x400);
360
+ &sbsa_gwdt_rops, s,
187
create_unimplemented_device("I2C2", 0x40005800, 0x400);
361
+ "sbsa_gwdt.refresh",
188
create_unimplemented_device("I2C3", 0x40005C00, 0x400);
362
+ SBSA_GWDT_RMMIO_SIZE);
189
@@ -XXX,XX +XXX,XX @@ static void stm32l4x5_soc_realize(DeviceState *dev_soc, Error **errp)
363
+
190
create_unimplemented_device("DAC1", 0x40007400, 0x400);
364
+ memory_region_init_io(&s->cmmio, OBJECT(dev),
191
create_unimplemented_device("OPAMP", 0x40007800, 0x400);
365
+ &sbsa_gwdt_ops, s,
192
create_unimplemented_device("LPTIM1", 0x40007C00, 0x400);
366
+ "sbsa_gwdt.control",
193
- create_unimplemented_device("LPUART1", 0x40008000, 0x400);
367
+ SBSA_GWDT_CMMIO_SIZE);
194
/* RESERVED: 0x40008400, 0x400 */
368
+
195
create_unimplemented_device("SWPMI1", 0x40008800, 0x400);
369
+ sysbus_init_mmio(sbd, &s->rmmio);
196
/* RESERVED: 0x40008C00, 0x800 */
370
+ sysbus_init_mmio(sbd, &s->cmmio);
197
@@ -XXX,XX +XXX,XX @@ static void stm32l4x5_soc_realize(DeviceState *dev_soc, Error **errp)
371
+
198
create_unimplemented_device("TIM1", 0x40012C00, 0x400);
372
+ sysbus_init_irq(sbd, &s->irq);
199
create_unimplemented_device("SPI1", 0x40013000, 0x400);
373
+
200
create_unimplemented_device("TIM8", 0x40013400, 0x400);
374
+ s->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, sbsa_gwdt_timer_sysinterrupt,
201
- create_unimplemented_device("USART1", 0x40013800, 0x400);
375
+ dev);
202
/* RESERVED: 0x40013C00, 0x400 */
376
+}
203
create_unimplemented_device("TIM15", 0x40014000, 0x400);
377
+
204
create_unimplemented_device("TIM16", 0x40014400, 0x400);
378
+static void wdt_sbsa_gwdt_class_init(ObjectClass *klass, void *data)
379
+{
380
+ DeviceClass *dc = DEVICE_CLASS(klass);
381
+
382
+ dc->realize = wdt_sbsa_gwdt_realize;
383
+ dc->reset = wdt_sbsa_gwdt_reset;
384
+ dc->hotpluggable = false;
385
+ set_bit(DEVICE_CATEGORY_MISC, dc->categories);
386
+ dc->vmsd = &vmstate_sbsa_gwdt;
387
+}
388
+
389
+static const TypeInfo wdt_sbsa_gwdt_info = {
390
+ .class_init = wdt_sbsa_gwdt_class_init,
391
+ .parent = TYPE_SYS_BUS_DEVICE,
392
+ .name = TYPE_WDT_SBSA,
393
+ .instance_size = sizeof(SBSA_GWDTState),
394
+};
395
+
396
+static void wdt_sbsa_gwdt_register_types(void)
397
+{
398
+ watchdog_add_model(&model);
399
+ type_register_static(&wdt_sbsa_gwdt_info);
400
+}
401
+
402
+type_init(wdt_sbsa_gwdt_register_types)
403
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
205
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
404
index XXXXXXX..XXXXXXX 100644
206
index XXXXXXX..XXXXXXX 100644
405
--- a/hw/arm/Kconfig
207
--- a/hw/arm/Kconfig
406
+++ b/hw/arm/Kconfig
208
+++ b/hw/arm/Kconfig
407
@@ -XXX,XX +XXX,XX @@ config SBSA_REF
209
@@ -XXX,XX +XXX,XX @@ config STM32L4X5_SOC
408
select PL031 # RTC
210
select STM32L4X5_SYSCFG
409
select PL061 # GPIO
211
select STM32L4X5_RCC
410
select USB_EHCI_SYSBUS
212
select STM32L4X5_GPIO
411
+ select WDT_SBSA
213
+ select STM32L4X5_USART
412
214
413
config SABRELITE
215
config XLNX_ZYNQMP_ARM
414
bool
216
bool
415
diff --git a/hw/watchdog/Kconfig b/hw/watchdog/Kconfig
416
index XXXXXXX..XXXXXXX 100644
417
--- a/hw/watchdog/Kconfig
418
+++ b/hw/watchdog/Kconfig
419
@@ -XXX,XX +XXX,XX @@ config WDT_DIAG288
420
421
config WDT_IMX2
422
bool
423
+
424
+config WDT_SBSA
425
+ bool
426
diff --git a/hw/watchdog/meson.build b/hw/watchdog/meson.build
427
index XXXXXXX..XXXXXXX 100644
428
--- a/hw/watchdog/meson.build
429
+++ b/hw/watchdog/meson.build
430
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_WDT_IB700', if_true: files('wdt_ib700.c'))
431
softmmu_ss.add(when: 'CONFIG_WDT_DIAG288', if_true: files('wdt_diag288.c'))
432
softmmu_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files('wdt_aspeed.c'))
433
softmmu_ss.add(when: 'CONFIG_WDT_IMX2', if_true: files('wdt_imx2.c'))
434
+softmmu_ss.add(when: 'CONFIG_WDT_SBSA', if_true: files('sbsa_gwdt.c'))
435
--
217
--
436
2.20.1
218
2.34.1
437
219
438
220
diff view generated by jsdifflib
1
From: Havard Skinnemoen <hskinnemoen@google.com>
1
From: Arnaud Minier <arnaud.minier@telecom-paris.fr>
2
2
3
The RNG module returns a byte of randomness when the Data Valid bit is
3
Test:
4
set.
4
- read/write from/to the usart registers
5
5
- send/receive a character/string over the serial port
6
This implementation ignores the prescaler setting, and loads a new value
6
7
into RNGD every time RNGCS is read while the RNG is enabled and random
7
Signed-off-by: Arnaud Minier <arnaud.minier@telecom-paris.fr>
8
data is available.
8
Signed-off-by: Inès Varhol <ines.varhol@telecom-paris.fr>
9
10
A qtest featuring some simple randomness tests is included.
11
12
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
13
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Havard Skinnemoen <hskinnemoen@google.com>
10
Message-id: 20240329174402.60382-6-arnaud.minier@telecom-paris.fr
11
[PMM: fix checkpatch nits, remove commented out code]
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
---
13
---
17
docs/system/arm/nuvoton.rst | 2 +-
14
tests/qtest/stm32l4x5_usart-test.c | 315 +++++++++++++++++++++++++++++
18
include/hw/arm/npcm7xx.h | 2 +
15
tests/qtest/meson.build | 4 +-
19
include/hw/misc/npcm7xx_rng.h | 34 ++++
16
2 files changed, 318 insertions(+), 1 deletion(-)
20
hw/arm/npcm7xx.c | 7 +-
17
create mode 100644 tests/qtest/stm32l4x5_usart-test.c
21
hw/misc/npcm7xx_rng.c | 180 +++++++++++++++++++++
18
22
tests/qtest/npcm7xx_rng-test.c | 278 +++++++++++++++++++++++++++++++++
19
diff --git a/tests/qtest/stm32l4x5_usart-test.c b/tests/qtest/stm32l4x5_usart-test.c
23
hw/misc/meson.build | 1 +
24
hw/misc/trace-events | 4 +
25
tests/qtest/meson.build | 5 +-
26
9 files changed, 510 insertions(+), 3 deletions(-)
27
create mode 100644 include/hw/misc/npcm7xx_rng.h
28
create mode 100644 hw/misc/npcm7xx_rng.c
29
create mode 100644 tests/qtest/npcm7xx_rng-test.c
30
31
diff --git a/docs/system/arm/nuvoton.rst b/docs/system/arm/nuvoton.rst
32
index XXXXXXX..XXXXXXX 100644
33
--- a/docs/system/arm/nuvoton.rst
34
+++ b/docs/system/arm/nuvoton.rst
35
@@ -XXX,XX +XXX,XX @@ Supported devices
36
* DDR4 memory controller (dummy interface indicating memory training is done)
37
* OTP controllers (no protection features)
38
* Flash Interface Unit (FIU; no protection features)
39
+ * Random Number Generator (RNG)
40
41
Missing devices
42
---------------
43
@@ -XXX,XX +XXX,XX @@ Missing devices
44
* Peripheral SPI controller (PSPI)
45
* Analog to Digital Converter (ADC)
46
* SD/MMC host
47
- * Random Number Generator (RNG)
48
* PECI interface
49
* Pulse Width Modulation (PWM)
50
* Tachometer
51
diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h
52
index XXXXXXX..XXXXXXX 100644
53
--- a/include/hw/arm/npcm7xx.h
54
+++ b/include/hw/arm/npcm7xx.h
55
@@ -XXX,XX +XXX,XX @@
56
#include "hw/mem/npcm7xx_mc.h"
57
#include "hw/misc/npcm7xx_clk.h"
58
#include "hw/misc/npcm7xx_gcr.h"
59
+#include "hw/misc/npcm7xx_rng.h"
60
#include "hw/nvram/npcm7xx_otp.h"
61
#include "hw/timer/npcm7xx_timer.h"
62
#include "hw/ssi/npcm7xx_fiu.h"
63
@@ -XXX,XX +XXX,XX @@ typedef struct NPCM7xxState {
64
NPCM7xxOTPState key_storage;
65
NPCM7xxOTPState fuse_array;
66
NPCM7xxMCState mc;
67
+ NPCM7xxRNGState rng;
68
NPCM7xxFIUState fiu[2];
69
} NPCM7xxState;
70
71
diff --git a/include/hw/misc/npcm7xx_rng.h b/include/hw/misc/npcm7xx_rng.h
72
new file mode 100644
20
new file mode 100644
73
index XXXXXXX..XXXXXXX
21
index XXXXXXX..XXXXXXX
74
--- /dev/null
22
--- /dev/null
75
+++ b/include/hw/misc/npcm7xx_rng.h
23
+++ b/tests/qtest/stm32l4x5_usart-test.c
76
@@ -XXX,XX +XXX,XX @@
24
@@ -XXX,XX +XXX,XX @@
77
+/*
25
+/*
78
+ * Nuvoton NPCM7xx Random Number Generator.
26
+ * QTest testcase for STML4X5_USART
79
+ *
27
+ *
80
+ * Copyright 2020 Google LLC
28
+ * Copyright (c) 2023 Arnaud Minier <arnaud.minier@telecom-paris.fr>
29
+ * Copyright (c) 2023 Inès Varhol <ines.varhol@telecom-paris.fr>
81
+ *
30
+ *
82
+ * This program is free software; you can redistribute it and/or modify it
31
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
83
+ * under the terms of the GNU General Public License as published by the
32
+ * See the COPYING file in the top-level directory.
84
+ * Free Software Foundation; either version 2 of the License, or
85
+ * (at your option) any later version.
86
+ *
87
+ * This program is distributed in the hope that it will be useful, but WITHOUT
88
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
89
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
90
+ * for more details.
91
+ */
33
+ */
92
+#ifndef NPCM7XX_RNG_H
34
+
93
+#define NPCM7XX_RNG_H
35
+#include "qemu/osdep.h"
94
+
36
+#include "libqtest.h"
95
+#include "hw/sysbus.h"
37
+#include "hw/misc/stm32l4x5_rcc_internals.h"
96
+
38
+#include "hw/registerfields.h"
97
+typedef struct NPCM7xxRNGState {
39
+
98
+ SysBusDevice parent;
40
+#define RCC_BASE_ADDR 0x40021000
99
+
41
+/* Use USART 1 ADDR, assume the others work the same */
100
+ MemoryRegion iomem;
42
+#define USART1_BASE_ADDR 0x40013800
101
+
43
+
102
+ uint8_t rngcs;
44
+/* See stm32l4x5_usart for definitions */
103
+ uint8_t rngd;
45
+REG32(CR1, 0x00)
104
+ uint8_t rngmode;
46
+ FIELD(CR1, M1, 28, 1)
105
+} NPCM7xxRNGState;
47
+ FIELD(CR1, OVER8, 15, 1)
106
+
48
+ FIELD(CR1, M0, 12, 1)
107
+#define TYPE_NPCM7XX_RNG "npcm7xx-rng"
49
+ FIELD(CR1, PCE, 10, 1)
108
+#define NPCM7XX_RNG(obj) OBJECT_CHECK(NPCM7xxRNGState, (obj), TYPE_NPCM7XX_RNG)
50
+ FIELD(CR1, TXEIE, 7, 1)
109
+
51
+ FIELD(CR1, RXNEIE, 5, 1)
110
+#endif /* NPCM7XX_RNG_H */
52
+ FIELD(CR1, TE, 3, 1)
111
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
53
+ FIELD(CR1, RE, 2, 1)
112
index XXXXXXX..XXXXXXX 100644
54
+ FIELD(CR1, UE, 0, 1)
113
--- a/hw/arm/npcm7xx.c
55
+REG32(CR2, 0x04)
114
+++ b/hw/arm/npcm7xx.c
56
+REG32(CR3, 0x08)
115
@@ -XXX,XX +XXX,XX @@
57
+ FIELD(CR3, OVRDIS, 12, 1)
116
#define NPCM7XX_GCR_BA (0xf0800000)
58
+REG32(BRR, 0x0C)
117
#define NPCM7XX_CLK_BA (0xf0801000)
59
+REG32(GTPR, 0x10)
118
#define NPCM7XX_MC_BA (0xf0824000)
60
+REG32(RTOR, 0x14)
119
+#define NPCM7XX_RNG_BA (0xf000b000)
61
+REG32(RQR, 0x18)
120
62
+REG32(ISR, 0x1C)
121
/* Internal AHB SRAM */
63
+ FIELD(ISR, TXE, 7, 1)
122
#define NPCM7XX_RAM3_BA (0xc0008000)
64
+ FIELD(ISR, RXNE, 5, 1)
123
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_init(Object *obj)
65
+ FIELD(ISR, ORE, 3, 1)
124
object_initialize_child(obj, "otp2", &s->fuse_array,
66
+REG32(ICR, 0x20)
125
TYPE_NPCM7XX_FUSE_ARRAY);
67
+REG32(RDR, 0x24)
126
object_initialize_child(obj, "mc", &s->mc, TYPE_NPCM7XX_MC);
68
+REG32(TDR, 0x28)
127
+ object_initialize_child(obj, "rng", &s->rng, TYPE_NPCM7XX_RNG);
69
+
128
70
+#define NVIC_ISPR1 0XE000E204
129
for (i = 0; i < ARRAY_SIZE(s->tim); i++) {
71
+#define NVIC_ICPR1 0xE000E284
130
object_initialize_child(obj, "tim[*]", &s->tim[i], TYPE_NPCM7XX_TIMER);
72
+#define USART1_IRQ 37
131
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
73
+
132
serial_hd(i), DEVICE_LITTLE_ENDIAN);
74
+static bool check_nvic_pending(QTestState *qts, unsigned int n)
133
}
75
+{
134
76
+ /* No USART interrupts are less than 32 */
135
+ /* Random Number Generator. Cannot fail. */
77
+ assert(n > 32);
136
+ sysbus_realize(SYS_BUS_DEVICE(&s->rng), &error_abort);
78
+ n -= 32;
137
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->rng), 0, NPCM7XX_RNG_BA);
79
+ return qtest_readl(qts, NVIC_ISPR1) & (1 << n);
138
+
80
+}
139
/*
81
+
140
* Flash Interface Unit (FIU). Can fail if incorrect number of chip selects
82
+static bool clear_nvic_pending(QTestState *qts, unsigned int n)
141
* specified, but this is a programming error.
83
+{
142
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
84
+ /* No USART interrupts are less than 32 */
143
create_unimplemented_device("npcm7xx.vdmx", 0xe0800000, 4 * KiB);
85
+ assert(n > 32);
144
create_unimplemented_device("npcm7xx.pcierc", 0xe1000000, 64 * KiB);
86
+ n -= 32;
145
create_unimplemented_device("npcm7xx.kcs", 0xf0007000, 4 * KiB);
87
+ qtest_writel(qts, NVIC_ICPR1, (1 << n));
146
- create_unimplemented_device("npcm7xx.rng", 0xf000b000, 4 * KiB);
88
+ return true;
147
create_unimplemented_device("npcm7xx.adc", 0xf000c000, 4 * KiB);
89
+}
148
create_unimplemented_device("npcm7xx.gfxi", 0xf000e000, 4 * KiB);
90
+
149
create_unimplemented_device("npcm7xx.gpio[0]", 0xf0010000, 4 * KiB);
150
diff --git a/hw/misc/npcm7xx_rng.c b/hw/misc/npcm7xx_rng.c
151
new file mode 100644
152
index XXXXXXX..XXXXXXX
153
--- /dev/null
154
+++ b/hw/misc/npcm7xx_rng.c
155
@@ -XXX,XX +XXX,XX @@
156
+/*
91
+/*
157
+ * Nuvoton NPCM7xx Random Number Generator.
92
+ * Wait indefinitely for the flag to be updated.
158
+ *
93
+ * If this is run on a slow CI runner,
159
+ * Copyright 2020 Google LLC
94
+ * the meson harness will timeout after 10 minutes for us.
160
+ *
161
+ * This program is free software; you can redistribute it and/or modify it
162
+ * under the terms of the GNU General Public License as published by the
163
+ * Free Software Foundation; either version 2 of the License, or
164
+ * (at your option) any later version.
165
+ *
166
+ * This program is distributed in the hope that it will be useful, but WITHOUT
167
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
168
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
169
+ * for more details.
170
+ */
95
+ */
171
+
96
+static bool usart_wait_for_flag(QTestState *qts, uint32_t event_addr,
172
+#include "qemu/osdep.h"
97
+ uint32_t flag)
173
+
98
+{
174
+#include "hw/misc/npcm7xx_rng.h"
99
+ while (true) {
175
+#include "migration/vmstate.h"
100
+ if ((qtest_readl(qts, event_addr) & flag)) {
176
+#include "qemu/bitops.h"
177
+#include "qemu/guest-random.h"
178
+#include "qemu/log.h"
179
+#include "qemu/module.h"
180
+#include "qemu/units.h"
181
+
182
+#include "trace.h"
183
+
184
+#define NPCM7XX_RNG_REGS_SIZE (4 * KiB)
185
+
186
+#define NPCM7XX_RNGCS (0x00)
187
+#define NPCM7XX_RNGCS_CLKP(rv) extract32(rv, 2, 4)
188
+#define NPCM7XX_RNGCS_DVALID BIT(1)
189
+#define NPCM7XX_RNGCS_RNGE BIT(0)
190
+
191
+#define NPCM7XX_RNGD (0x04)
192
+#define NPCM7XX_RNGMODE (0x08)
193
+#define NPCM7XX_RNGMODE_NORMAL (0x02)
194
+
195
+static bool npcm7xx_rng_is_enabled(NPCM7xxRNGState *s)
196
+{
197
+ return (s->rngcs & NPCM7XX_RNGCS_RNGE) &&
198
+ (s->rngmode == NPCM7XX_RNGMODE_NORMAL);
199
+}
200
+
201
+static uint64_t npcm7xx_rng_read(void *opaque, hwaddr offset, unsigned size)
202
+{
203
+ NPCM7xxRNGState *s = opaque;
204
+ uint64_t value = 0;
205
+
206
+ switch (offset) {
207
+ case NPCM7XX_RNGCS:
208
+ /*
209
+ * If the RNG is enabled, but we don't have any valid random data, try
210
+ * obtaining some and update the DVALID bit accordingly.
211
+ */
212
+ if (!npcm7xx_rng_is_enabled(s)) {
213
+ s->rngcs &= ~NPCM7XX_RNGCS_DVALID;
214
+ } else if (!(s->rngcs & NPCM7XX_RNGCS_DVALID)) {
215
+ uint8_t byte = 0;
216
+
217
+ if (qemu_guest_getrandom(&byte, sizeof(byte), NULL) == 0) {
218
+ s->rngd = byte;
219
+ s->rngcs |= NPCM7XX_RNGCS_DVALID;
220
+ }
221
+ }
222
+ value = s->rngcs;
223
+ break;
224
+ case NPCM7XX_RNGD:
225
+ if (npcm7xx_rng_is_enabled(s) && s->rngcs & NPCM7XX_RNGCS_DVALID) {
226
+ s->rngcs &= ~NPCM7XX_RNGCS_DVALID;
227
+ value = s->rngd;
228
+ s->rngd = 0;
229
+ }
230
+ break;
231
+ case NPCM7XX_RNGMODE:
232
+ value = s->rngmode;
233
+ break;
234
+
235
+ default:
236
+ qemu_log_mask(LOG_GUEST_ERROR,
237
+ "%s: read from invalid offset 0x%" HWADDR_PRIx "\n",
238
+ DEVICE(s)->canonical_path, offset);
239
+ break;
240
+ }
241
+
242
+ trace_npcm7xx_rng_read(offset, value, size);
243
+
244
+ return value;
245
+}
246
+
247
+static void npcm7xx_rng_write(void *opaque, hwaddr offset, uint64_t value,
248
+ unsigned size)
249
+{
250
+ NPCM7xxRNGState *s = opaque;
251
+
252
+ trace_npcm7xx_rng_write(offset, value, size);
253
+
254
+ switch (offset) {
255
+ case NPCM7XX_RNGCS:
256
+ s->rngcs &= NPCM7XX_RNGCS_DVALID;
257
+ s->rngcs |= value & ~NPCM7XX_RNGCS_DVALID;
258
+ break;
259
+ case NPCM7XX_RNGD:
260
+ qemu_log_mask(LOG_GUEST_ERROR,
261
+ "%s: write to read-only register @ 0x%" HWADDR_PRIx "\n",
262
+ DEVICE(s)->canonical_path, offset);
263
+ break;
264
+ case NPCM7XX_RNGMODE:
265
+ s->rngmode = value;
266
+ break;
267
+ default:
268
+ qemu_log_mask(LOG_GUEST_ERROR,
269
+ "%s: write to invalid offset 0x%" HWADDR_PRIx "\n",
270
+ DEVICE(s)->canonical_path, offset);
271
+ break;
272
+ }
273
+}
274
+
275
+static const MemoryRegionOps npcm7xx_rng_ops = {
276
+ .read = npcm7xx_rng_read,
277
+ .write = npcm7xx_rng_write,
278
+ .endianness = DEVICE_LITTLE_ENDIAN,
279
+ .valid = {
280
+ .min_access_size = 1,
281
+ .max_access_size = 4,
282
+ .unaligned = false,
283
+ },
284
+};
285
+
286
+static void npcm7xx_rng_enter_reset(Object *obj, ResetType type)
287
+{
288
+ NPCM7xxRNGState *s = NPCM7XX_RNG(obj);
289
+
290
+ s->rngcs = 0;
291
+ s->rngd = 0;
292
+ s->rngmode = 0;
293
+}
294
+
295
+static void npcm7xx_rng_init(Object *obj)
296
+{
297
+ NPCM7xxRNGState *s = NPCM7XX_RNG(obj);
298
+
299
+ memory_region_init_io(&s->iomem, obj, &npcm7xx_rng_ops, s, "regs",
300
+ NPCM7XX_RNG_REGS_SIZE);
301
+ sysbus_init_mmio(&s->parent, &s->iomem);
302
+}
303
+
304
+static const VMStateDescription vmstate_npcm7xx_rng = {
305
+ .name = "npcm7xx-rng",
306
+ .version_id = 0,
307
+ .minimum_version_id = 0,
308
+ .fields = (VMStateField[]) {
309
+ VMSTATE_UINT8(rngcs, NPCM7xxRNGState),
310
+ VMSTATE_UINT8(rngd, NPCM7xxRNGState),
311
+ VMSTATE_UINT8(rngmode, NPCM7xxRNGState),
312
+ VMSTATE_END_OF_LIST(),
313
+ },
314
+};
315
+
316
+static void npcm7xx_rng_class_init(ObjectClass *klass, void *data)
317
+{
318
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
319
+ DeviceClass *dc = DEVICE_CLASS(klass);
320
+
321
+ dc->desc = "NPCM7xx Random Number Generator";
322
+ dc->vmsd = &vmstate_npcm7xx_rng;
323
+ rc->phases.enter = npcm7xx_rng_enter_reset;
324
+}
325
+
326
+static const TypeInfo npcm7xx_rng_types[] = {
327
+ {
328
+ .name = TYPE_NPCM7XX_RNG,
329
+ .parent = TYPE_SYS_BUS_DEVICE,
330
+ .instance_size = sizeof(NPCM7xxRNGState),
331
+ .class_init = npcm7xx_rng_class_init,
332
+ .instance_init = npcm7xx_rng_init,
333
+ },
334
+};
335
+DEFINE_TYPES(npcm7xx_rng_types);
336
diff --git a/tests/qtest/npcm7xx_rng-test.c b/tests/qtest/npcm7xx_rng-test.c
337
new file mode 100644
338
index XXXXXXX..XXXXXXX
339
--- /dev/null
340
+++ b/tests/qtest/npcm7xx_rng-test.c
341
@@ -XXX,XX +XXX,XX @@
342
+/*
343
+ * QTest testcase for the Nuvoton NPCM7xx Random Number Generator
344
+ *
345
+ * Copyright 2020 Google LLC
346
+ *
347
+ * This program is free software; you can redistribute it and/or modify it
348
+ * under the terms of the GNU General Public License as published by the
349
+ * Free Software Foundation; either version 2 of the License, or
350
+ * (at your option) any later version.
351
+ *
352
+ * This program is distributed in the hope that it will be useful, but WITHOUT
353
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
354
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
355
+ * for more details.
356
+ */
357
+
358
+#include "qemu/osdep.h"
359
+
360
+#include <math.h>
361
+
362
+#include "libqtest-single.h"
363
+#include "qemu/bitops.h"
364
+
365
+#define RNG_BASE_ADDR 0xf000b000
366
+
367
+/* Control and Status Register */
368
+#define RNGCS 0x00
369
+# define DVALID BIT(1) /* Data Valid */
370
+# define RNGE BIT(0) /* RNG Enable */
371
+/* Data Register */
372
+#define RNGD 0x04
373
+/* Mode Register */
374
+#define RNGMODE 0x08
375
+# define ROSEL_NORMAL (2) /* RNG only works in this mode */
376
+
377
+/* Number of bits to collect for randomness tests. */
378
+#define TEST_INPUT_BITS (128)
379
+
380
+static void rng_writeb(unsigned int offset, uint8_t value)
381
+{
382
+ writeb(RNG_BASE_ADDR + offset, value);
383
+}
384
+
385
+static uint8_t rng_readb(unsigned int offset)
386
+{
387
+ return readb(RNG_BASE_ADDR + offset);
388
+}
389
+
390
+/* Disable RNG and set normal ring oscillator mode. */
391
+static void rng_reset(void)
392
+{
393
+ rng_writeb(RNGCS, 0);
394
+ rng_writeb(RNGMODE, ROSEL_NORMAL);
395
+}
396
+
397
+/* Reset RNG and then enable it. */
398
+static void rng_reset_enable(void)
399
+{
400
+ rng_reset();
401
+ rng_writeb(RNGCS, RNGE);
402
+}
403
+
404
+/* Wait until Data Valid bit is set. */
405
+static bool rng_wait_ready(void)
406
+{
407
+ /* qemu_guest_getrandom may fail. Assume it won't fail 10 times in a row. */
408
+ int retries = 10;
409
+
410
+ while (retries-- > 0) {
411
+ if (rng_readb(RNGCS) & DVALID) {
412
+ return true;
101
+ return true;
413
+ }
102
+ }
103
+ g_usleep(1000);
414
+ }
104
+ }
415
+
105
+
416
+ return false;
106
+ return false;
417
+}
107
+}
418
+
108
+
419
+/*
109
+static void usart_receive_string(QTestState *qts, int sock_fd, const char *in,
420
+ * Perform a frequency (monobit) test, as defined by NIST SP 800-22, on the
110
+ char *out)
421
+ * sequence in buf and return the P-value. This represents the probability of a
111
+{
422
+ * truly random sequence having the same proportion of zeros and ones as the
112
+ int i, in_len = strlen(in);
423
+ * sequence in buf.
113
+
424
+ *
114
+ g_assert_true(send(sock_fd, in, in_len, 0) == in_len);
425
+ * An RNG which always returns 0x00 or 0xff, or has some bits stuck at 0 or 1,
115
+ for (i = 0; i < in_len; i++) {
426
+ * will fail this test. However, an RNG which always returns 0x55, 0xf0 or some
116
+ g_assert_true(usart_wait_for_flag(qts,
427
+ * other value with an equal number of zeroes and ones will pass.
117
+ USART1_BASE_ADDR + A_ISR, R_ISR_RXNE_MASK));
428
+ */
118
+ out[i] = qtest_readl(qts, USART1_BASE_ADDR + A_RDR);
429
+static double calc_monobit_p(const uint8_t *buf, unsigned int len)
430
+{
431
+ unsigned int i;
432
+ double s_obs;
433
+ int sn = 0;
434
+
435
+ for (i = 0; i < len; i++) {
436
+ /*
437
+ * Each 1 counts as 1, each 0 counts as -1.
438
+ * s = cp - (8 - cp) = 2 * cp - 8
439
+ */
440
+ sn += 2 * ctpop8(buf[i]) - 8;
441
+ }
119
+ }
442
+
120
+ out[i] = '\0';
443
+ s_obs = abs(sn) / sqrt(len * BITS_PER_BYTE);
121
+}
444
+
122
+
445
+ return erfc(s_obs / sqrt(2));
123
+static void usart_send_string(QTestState *qts, const char *in)
446
+}
124
+{
447
+
125
+ int i, in_len = strlen(in);
448
+/*
126
+
449
+ * Perform a runs test, as defined by NIST SP 800-22, and return the P-value.
127
+ for (i = 0; i < in_len; i++) {
450
+ * This represents the probability of a truly random sequence having the same
128
+ qtest_writel(qts, USART1_BASE_ADDR + A_TDR, in[i]);
451
+ * number of runs (i.e. uninterrupted sequences of identical bits) as the
129
+ g_assert_true(usart_wait_for_flag(qts,
452
+ * sequence in buf.
130
+ USART1_BASE_ADDR + A_ISR, R_ISR_TXE_MASK));
453
+ */
454
+static double calc_runs_p(const unsigned long *buf, unsigned int nr_bits)
455
+{
456
+ unsigned int j;
457
+ unsigned int k;
458
+ int nr_ones = 0;
459
+ int vn_obs = 0;
460
+ double pi;
461
+
462
+ g_assert(nr_bits % BITS_PER_LONG == 0);
463
+
464
+ for (j = 0; j < nr_bits / BITS_PER_LONG; j++) {
465
+ nr_ones += __builtin_popcountl(buf[j]);
466
+ }
131
+ }
467
+ pi = (double)nr_ones / nr_bits;
132
+}
468
+
133
+
469
+ for (k = 0; k < nr_bits - 1; k++) {
134
+/* Init the RCC clocks to run at 80 MHz */
470
+ vn_obs += !(test_bit(k, buf) ^ test_bit(k + 1, buf));
135
+static void init_clocks(QTestState *qts)
471
+ }
136
+{
472
+ vn_obs += 1;
137
+ uint32_t value;
473
+
138
+
474
+ return erfc(fabs(vn_obs - 2 * nr_bits * pi * (1.0 - pi))
139
+ /* MSIRANGE can be set only when MSI is OFF or READY */
475
+ / (2 * sqrt(2 * nr_bits) * pi * (1.0 - pi)));
140
+ qtest_writel(qts, (RCC_BASE_ADDR + A_CR), R_CR_MSION_MASK);
476
+}
141
+
477
+
142
+ /* Clocking from MSI, in case MSI was not the default source */
478
+/*
143
+ qtest_writel(qts, (RCC_BASE_ADDR + A_CFGR), 0);
479
+ * Verifies that DVALID is clear, and RNGD reads zero, when RNGE is cleared,
144
+
480
+ * and DVALID eventually becomes set when RNGE is set.
145
+ /*
481
+ */
146
+ * Update PLL and set MSI as the source clock.
482
+static void test_enable_disable(void)
147
+ * PLLM = 1 --> 000
483
+{
148
+ * PLLN = 40 --> 40
484
+ /* Disable: DVALID should not be set, and RNGD should read zero */
149
+ * PPLLR = 2 --> 00
485
+ rng_reset();
150
+ * PLLDIV = unused, PLLP = unused (SAI3), PLLQ = unused (48M1)
486
+ g_assert_cmphex(rng_readb(RNGCS), ==, 0);
151
+ * SRC = MSI --> 01
487
+ g_assert_cmphex(rng_readb(RNGD), ==, 0);
152
+ */
488
+
153
+ qtest_writel(qts, (RCC_BASE_ADDR + A_PLLCFGR), R_PLLCFGR_PLLREN_MASK |
489
+ /* Enable: DVALID should be set, but we can't make assumptions about RNGD */
154
+ (40 << R_PLLCFGR_PLLN_SHIFT) |
490
+ rng_writeb(RNGCS, RNGE);
155
+ (0b01 << R_PLLCFGR_PLLSRC_SHIFT));
491
+ g_assert_true(rng_wait_ready());
156
+
492
+ g_assert_cmphex(rng_readb(RNGCS), ==, DVALID | RNGE);
157
+ /* PLL activation */
493
+
158
+
494
+ /* Disable: DVALID should not be set, and RNGD should read zero */
159
+ value = qtest_readl(qts, (RCC_BASE_ADDR + A_CR));
495
+ rng_writeb(RNGCS, 0);
160
+ qtest_writel(qts, (RCC_BASE_ADDR + A_CR), value | R_CR_PLLON_MASK);
496
+ g_assert_cmphex(rng_readb(RNGCS), ==, 0);
161
+
497
+ g_assert_cmphex(rng_readb(RNGD), ==, 0);
162
+ /* RCC_CFGR is OK by defaut */
498
+}
163
+ qtest_writel(qts, (RCC_BASE_ADDR + A_CFGR), 0);
499
+
164
+
500
+/*
165
+ /* CCIPR : no periph clock by default */
501
+ * Verifies that the RNG only produces data when RNGMODE is set to 'normal'
166
+ qtest_writel(qts, (RCC_BASE_ADDR + A_CCIPR), 0);
502
+ * ring oscillator mode.
167
+
503
+ */
168
+ /* Switches on the PLL clock source */
504
+static void test_rosel(void)
169
+ value = qtest_readl(qts, (RCC_BASE_ADDR + A_CFGR));
505
+{
170
+ qtest_writel(qts, (RCC_BASE_ADDR + A_CFGR), (value & ~R_CFGR_SW_MASK) |
506
+ rng_reset_enable();
171
+ (0b11 << R_CFGR_SW_SHIFT));
507
+ g_assert_true(rng_wait_ready());
172
+
508
+ rng_writeb(RNGMODE, 0);
173
+ /* Enable SYSCFG clock enabled */
509
+ g_assert_false(rng_wait_ready());
174
+ qtest_writel(qts, (RCC_BASE_ADDR + A_APB2ENR), R_APB2ENR_SYSCFGEN_MASK);
510
+ rng_writeb(RNGMODE, ROSEL_NORMAL);
175
+
511
+ g_assert_true(rng_wait_ready());
176
+ /* Enable the IO port B clock (See p.252) */
512
+ rng_writeb(RNGMODE, 0);
177
+ qtest_writel(qts, (RCC_BASE_ADDR + A_AHB2ENR), R_AHB2ENR_GPIOBEN_MASK);
513
+ g_assert_false(rng_wait_ready());
178
+
514
+}
179
+ /* Enable the clock for USART1 (cf p.259) */
515
+
180
+ /* We rewrite SYSCFGEN to not disable it */
516
+/*
181
+ qtest_writel(qts, (RCC_BASE_ADDR + A_APB2ENR),
517
+ * Verifies that a continuous sequence of bits collected after enabling the RNG
182
+ R_APB2ENR_SYSCFGEN_MASK | R_APB2ENR_USART1EN_MASK);
518
+ * satisfies a monobit test.
183
+
519
+ */
184
+ /* TODO: Enable usart via gpio */
520
+static void test_continuous_monobit(void)
185
+
521
+{
186
+ /* Set PCLK as the clock for USART1(cf p.272) i.e. reset both bits */
522
+ uint8_t buf[TEST_INPUT_BITS / BITS_PER_BYTE];
187
+ qtest_writel(qts, (RCC_BASE_ADDR + A_CCIPR), 0);
523
+ unsigned int i;
188
+
524
+
189
+ /* Reset USART1 (see p.249) */
525
+ rng_reset_enable();
190
+ qtest_writel(qts, (RCC_BASE_ADDR + A_APB2RSTR), 1 << 14);
526
+ for (i = 0; i < sizeof(buf); i++) {
191
+ qtest_writel(qts, (RCC_BASE_ADDR + A_APB2RSTR), 0);
527
+ g_assert_true(rng_wait_ready());
192
+}
528
+ buf[i] = rng_readb(RNGD);
193
+
529
+ }
194
+static void init_uart(QTestState *qts)
530
+
195
+{
531
+ g_assert_cmpfloat(calc_monobit_p(buf, sizeof(buf)), >, 0.01);
196
+ uint32_t cr1;
532
+}
197
+
533
+
198
+ init_clocks(qts);
534
+/*
199
+
535
+ * Verifies that a continuous sequence of bits collected after enabling the RNG
200
+ /*
536
+ * satisfies a runs test.
201
+ * For 115200 bauds, see p.1349.
537
+ */
202
+ * The clock has a frequency of 80Mhz,
538
+static void test_continuous_runs(void)
203
+ * for 115200, we have to put a divider of 695 = 0x2B7.
539
+{
204
+ */
540
+ union {
205
+ qtest_writel(qts, (USART1_BASE_ADDR + A_BRR), 0x2B7);
541
+ unsigned long l[TEST_INPUT_BITS / BITS_PER_LONG];
206
+
542
+ uint8_t c[TEST_INPUT_BITS / BITS_PER_BYTE];
207
+ /*
543
+ } buf;
208
+ * Set the oversampling by 16,
544
+ unsigned int i;
209
+ * disable the parity control and
545
+
210
+ * set the word length to 8. (cf p.1377)
546
+ rng_reset_enable();
211
+ */
547
+ for (i = 0; i < sizeof(buf); i++) {
212
+ cr1 = qtest_readl(qts, (USART1_BASE_ADDR + A_CR1));
548
+ g_assert_true(rng_wait_ready());
213
+ cr1 &= ~(R_CR1_M1_MASK | R_CR1_M0_MASK | R_CR1_OVER8_MASK | R_CR1_PCE_MASK);
549
+ buf.c[i] = rng_readb(RNGD);
214
+ qtest_writel(qts, (USART1_BASE_ADDR + A_CR1), cr1);
550
+ }
215
+
551
+
216
+ /* Enable the transmitter, the receiver and the USART. */
552
+ g_assert_cmpfloat(calc_runs_p(buf.l, sizeof(buf) * BITS_PER_BYTE), >, 0.01);
217
+ qtest_writel(qts, (USART1_BASE_ADDR + A_CR1),
553
+}
218
+ R_CR1_UE_MASK | R_CR1_RE_MASK | R_CR1_TE_MASK);
554
+
219
+}
555
+/*
220
+
556
+ * Verifies that the first data byte collected after enabling the RNG satisfies
221
+static void test_write_read(void)
557
+ * a monobit test.
222
+{
558
+ */
223
+ QTestState *qts = qtest_init("-M b-l475e-iot01a");
559
+static void test_first_byte_monobit(void)
224
+
560
+{
225
+ /* Test that we can write and retrieve a value from the device */
561
+ /* Enable, collect one byte, disable. Repeat until we have 100 bits. */
226
+ qtest_writel(qts, USART1_BASE_ADDR + A_TDR, 0xFFFFFFFF);
562
+ uint8_t buf[TEST_INPUT_BITS / BITS_PER_BYTE];
227
+ const uint32_t tdr = qtest_readl(qts, USART1_BASE_ADDR + A_TDR);
563
+ unsigned int i;
228
+ g_assert_cmpuint(tdr, ==, 0x000001FF);
564
+
229
+}
565
+ rng_reset();
230
+
566
+ for (i = 0; i < sizeof(buf); i++) {
231
+static void test_receive_char(void)
567
+ rng_writeb(RNGCS, RNGE);
232
+{
568
+ g_assert_true(rng_wait_ready());
233
+ int sock_fd;
569
+ buf[i] = rng_readb(RNGD);
234
+ uint32_t cr1;
570
+ rng_writeb(RNGCS, 0);
235
+ QTestState *qts = qtest_init_with_serial("-M b-l475e-iot01a", &sock_fd);
571
+ }
236
+
572
+
237
+ init_uart(qts);
573
+ g_assert_cmpfloat(calc_monobit_p(buf, sizeof(buf)), >, 0.01);
238
+
574
+}
239
+ /* Try without initializing IRQ */
575
+
240
+ g_assert_true(send(sock_fd, "a", 1, 0) == 1);
576
+/*
241
+ usart_wait_for_flag(qts, USART1_BASE_ADDR + A_ISR, R_ISR_RXNE_MASK);
577
+ * Verifies that the first data byte collected after enabling the RNG satisfies
242
+ g_assert_cmphex(qtest_readl(qts, USART1_BASE_ADDR + A_RDR), ==, 'a');
578
+ * a runs test.
243
+ g_assert_false(check_nvic_pending(qts, USART1_IRQ));
579
+ */
244
+
580
+static void test_first_byte_runs(void)
245
+ /* Now with the IRQ */
581
+{
246
+ cr1 = qtest_readl(qts, (USART1_BASE_ADDR + A_CR1));
582
+ /* Enable, collect one byte, disable. Repeat until we have 100 bits. */
247
+ cr1 |= R_CR1_RXNEIE_MASK;
583
+ union {
248
+ qtest_writel(qts, USART1_BASE_ADDR + A_CR1, cr1);
584
+ unsigned long l[TEST_INPUT_BITS / BITS_PER_LONG];
249
+ g_assert_true(send(sock_fd, "b", 1, 0) == 1);
585
+ uint8_t c[TEST_INPUT_BITS / BITS_PER_BYTE];
250
+ usart_wait_for_flag(qts, USART1_BASE_ADDR + A_ISR, R_ISR_RXNE_MASK);
586
+ } buf;
251
+ g_assert_cmphex(qtest_readl(qts, USART1_BASE_ADDR + A_RDR), ==, 'b');
587
+ unsigned int i;
252
+ g_assert_true(check_nvic_pending(qts, USART1_IRQ));
588
+
253
+ clear_nvic_pending(qts, USART1_IRQ);
589
+ rng_reset();
254
+
590
+ for (i = 0; i < sizeof(buf); i++) {
255
+ close(sock_fd);
591
+ rng_writeb(RNGCS, RNGE);
256
+
592
+ g_assert_true(rng_wait_ready());
257
+ qtest_quit(qts);
593
+ buf.c[i] = rng_readb(RNGD);
258
+}
594
+ rng_writeb(RNGCS, 0);
259
+
595
+ }
260
+static void test_send_char(void)
596
+
261
+{
597
+ g_assert_cmpfloat(calc_runs_p(buf.l, sizeof(buf) * BITS_PER_BYTE), >, 0.01);
262
+ int sock_fd;
263
+ char s[1];
264
+ uint32_t cr1;
265
+ QTestState *qts = qtest_init_with_serial("-M b-l475e-iot01a", &sock_fd);
266
+
267
+ init_uart(qts);
268
+
269
+ /* Try without initializing IRQ */
270
+ qtest_writel(qts, USART1_BASE_ADDR + A_TDR, 'c');
271
+ g_assert_true(recv(sock_fd, s, 1, 0) == 1);
272
+ g_assert_cmphex(s[0], ==, 'c');
273
+ g_assert_false(check_nvic_pending(qts, USART1_IRQ));
274
+
275
+ /* Now with the IRQ */
276
+ cr1 = qtest_readl(qts, (USART1_BASE_ADDR + A_CR1));
277
+ cr1 |= R_CR1_TXEIE_MASK;
278
+ qtest_writel(qts, USART1_BASE_ADDR + A_CR1, cr1);
279
+ qtest_writel(qts, USART1_BASE_ADDR + A_TDR, 'd');
280
+ g_assert_true(recv(sock_fd, s, 1, 0) == 1);
281
+ g_assert_cmphex(s[0], ==, 'd');
282
+ g_assert_true(check_nvic_pending(qts, USART1_IRQ));
283
+ clear_nvic_pending(qts, USART1_IRQ);
284
+
285
+ close(sock_fd);
286
+
287
+ qtest_quit(qts);
288
+}
289
+
290
+static void test_receive_str(void)
291
+{
292
+ int sock_fd;
293
+ char s[10];
294
+ QTestState *qts = qtest_init_with_serial("-M b-l475e-iot01a", &sock_fd);
295
+
296
+ init_uart(qts);
297
+
298
+ usart_receive_string(qts, sock_fd, "hello", s);
299
+ g_assert_true(memcmp(s, "hello", 5) == 0);
300
+
301
+ close(sock_fd);
302
+
303
+ qtest_quit(qts);
304
+}
305
+
306
+static void test_send_str(void)
307
+{
308
+ int sock_fd;
309
+ char s[10];
310
+ QTestState *qts = qtest_init_with_serial("-M b-l475e-iot01a", &sock_fd);
311
+
312
+ init_uart(qts);
313
+
314
+ usart_send_string(qts, "world");
315
+ g_assert_true(recv(sock_fd, s, 10, 0) == 5);
316
+ g_assert_true(memcmp(s, "world", 5) == 0);
317
+
318
+ close(sock_fd);
319
+
320
+ qtest_quit(qts);
598
+}
321
+}
599
+
322
+
600
+int main(int argc, char **argv)
323
+int main(int argc, char **argv)
601
+{
324
+{
602
+ int ret;
325
+ int ret;
603
+
326
+
604
+ g_test_init(&argc, &argv, NULL);
327
+ g_test_init(&argc, &argv, NULL);
605
+ g_test_set_nonfatal_assertions();
328
+ g_test_set_nonfatal_assertions();
606
+
329
+
607
+ qtest_add_func("npcm7xx_rng/enable_disable", test_enable_disable);
330
+ qtest_add_func("stm32l4x5/usart/write_read", test_write_read);
608
+ qtest_add_func("npcm7xx_rng/rosel", test_rosel);
331
+ qtest_add_func("stm32l4x5/usart/receive_char", test_receive_char);
609
+ qtest_add_func("npcm7xx_rng/continuous/monobit", test_continuous_monobit);
332
+ qtest_add_func("stm32l4x5/usart/send_char", test_send_char);
610
+ qtest_add_func("npcm7xx_rng/continuous/runs", test_continuous_runs);
333
+ qtest_add_func("stm32l4x5/usart/receive_str", test_receive_str);
611
+ qtest_add_func("npcm7xx_rng/first_byte/monobit", test_first_byte_monobit);
334
+ qtest_add_func("stm32l4x5/usart/send_str", test_send_str);
612
+ qtest_add_func("npcm7xx_rng/first_byte/runs", test_first_byte_runs);
613
+
614
+ qtest_start("-machine npcm750-evb");
615
+ ret = g_test_run();
335
+ ret = g_test_run();
616
+ qtest_end();
617
+
336
+
618
+ return ret;
337
+ return ret;
619
+}
338
+}
620
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
339
+
621
index XXXXXXX..XXXXXXX 100644
622
--- a/hw/misc/meson.build
623
+++ b/hw/misc/meson.build
624
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_MAINSTONE', if_true: files('mst_fpga.c'))
625
softmmu_ss.add(when: 'CONFIG_NPCM7XX', if_true: files(
626
'npcm7xx_clk.c',
627
'npcm7xx_gcr.c',
628
+ 'npcm7xx_rng.c',
629
))
630
softmmu_ss.add(when: 'CONFIG_OMAP', if_true: files(
631
'omap_clk.c',
632
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
633
index XXXXXXX..XXXXXXX 100644
634
--- a/hw/misc/trace-events
635
+++ b/hw/misc/trace-events
636
@@ -XXX,XX +XXX,XX @@ npcm7xx_clk_write(uint64_t offset, uint32_t value) "offset: 0x%04" PRIx64 " valu
637
npcm7xx_gcr_read(uint64_t offset, uint32_t value) " offset: 0x%04" PRIx64 " value: 0x%08" PRIx32
638
npcm7xx_gcr_write(uint64_t offset, uint32_t value) "offset: 0x%04" PRIx64 " value: 0x%08" PRIx32
639
640
+# npcm7xx_rng.c
641
+npcm7xx_rng_read(uint64_t offset, uint64_t value, unsigned size) "offset: 0x%04" PRIx64 " value: 0x%02" PRIx64 " size: %u"
642
+npcm7xx_rng_write(uint64_t offset, uint64_t value, unsigned size) "offset: 0x%04" PRIx64 " value: 0x%02" PRIx64 " size: %u"
643
+
644
# stm32f4xx_syscfg.c
645
stm32f4xx_syscfg_set_irq(int gpio, int line, int level) "Interupt: GPIO: %d, Line: %d; Level: %d"
646
stm32f4xx_pulse_exti(int irq) "Pulse EXTI: %d"
647
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
340
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
648
index XXXXXXX..XXXXXXX 100644
341
index XXXXXXX..XXXXXXX 100644
649
--- a/tests/qtest/meson.build
342
--- a/tests/qtest/meson.build
650
+++ b/tests/qtest/meson.build
343
+++ b/tests/qtest/meson.build
651
@@ -XXX,XX +XXX,XX @@ qtests_sparc64 = \
344
@@ -XXX,XX +XXX,XX @@ slow_qtests = {
652
(config_all_devices.has_key('CONFIG_ISA_TESTDEV') ? ['endianness-test'] : []) + \
345
'npcm7xx_pwm-test': 300,
653
['prom-env-test', 'boot-serial-test']
346
'npcm7xx_watchdog_timer-test': 120,
654
347
'qom-test' : 900,
655
-qtests_npcm7xx = ['npcm7xx_timer-test', 'npcm7xx_watchdog_timer-test']
348
+ 'stm32l4x5_usart-test' : 600,
656
+qtests_npcm7xx = \
349
'test-hmp' : 240,
657
+ ['npcm7xx_rng-test',
350
'pxe-test': 610,
658
+ 'npcm7xx_timer-test',
351
'prom-env-test': 360,
659
+ 'npcm7xx_watchdog_timer-test']
352
@@ -XXX,XX +XXX,XX @@ qtests_stm32l4x5 = \
353
['stm32l4x5_exti-test',
354
'stm32l4x5_syscfg-test',
355
'stm32l4x5_rcc-test',
356
- 'stm32l4x5_gpio-test']
357
+ 'stm32l4x5_gpio-test',
358
+ 'stm32l4x5_usart-test']
359
660
qtests_arm = \
360
qtests_arm = \
661
(config_all_devices.has_key('CONFIG_PFLASH_CFI02') ? ['pflash-cfi02-test'] : []) + \
361
(config_all_devices.has_key('CONFIG_MPS2') ? ['sse-timer-test'] : []) + \
662
(config_all_devices.has_key('CONFIG_NPCM7XX') ? qtests_npcm7xx : []) + \
663
--
362
--
664
2.20.1
363
2.34.1
665
364
666
365
diff view generated by jsdifflib
Deleted patch
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
1
3
No code out of bcm2836.c uses (or requires) the BCM283XInfo
4
declarations. Move it locally to the C source file.
5
6
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
7
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Message-id: 20201024170127.3592182-2-f4bug@amsat.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
include/hw/arm/bcm2836.h | 8 --------
12
hw/arm/bcm2836.c | 14 ++++++++++++++
13
2 files changed, 14 insertions(+), 8 deletions(-)
14
15
diff --git a/include/hw/arm/bcm2836.h b/include/hw/arm/bcm2836.h
16
index XXXXXXX..XXXXXXX 100644
17
--- a/include/hw/arm/bcm2836.h
18
+++ b/include/hw/arm/bcm2836.h
19
@@ -XXX,XX +XXX,XX @@ struct BCM283XState {
20
BCM2835PeripheralState peripherals;
21
};
22
23
-typedef struct BCM283XInfo BCM283XInfo;
24
-
25
-struct BCM283XClass {
26
- DeviceClass parent_class;
27
- const BCM283XInfo *info;
28
-};
29
-
30
-
31
#endif /* BCM2836_H */
32
diff --git a/hw/arm/bcm2836.c b/hw/arm/bcm2836.c
33
index XXXXXXX..XXXXXXX 100644
34
--- a/hw/arm/bcm2836.c
35
+++ b/hw/arm/bcm2836.c
36
@@ -XXX,XX +XXX,XX @@
37
#include "hw/arm/raspi_platform.h"
38
#include "hw/sysbus.h"
39
40
+typedef struct BCM283XInfo BCM283XInfo;
41
+
42
+typedef struct BCM283XClass {
43
+ /*< private >*/
44
+ DeviceClass parent_class;
45
+ /*< public >*/
46
+ const BCM283XInfo *info;
47
+} BCM283XClass;
48
+
49
struct BCM283XInfo {
50
const char *name;
51
const char *cpu_type;
52
@@ -XXX,XX +XXX,XX @@ struct BCM283XInfo {
53
int clusterid;
54
};
55
56
+#define BCM283X_CLASS(klass) \
57
+ OBJECT_CLASS_CHECK(BCM283XClass, (klass), TYPE_BCM283X)
58
+#define BCM283X_GET_CLASS(obj) \
59
+ OBJECT_GET_CLASS(BCM283XClass, (obj), TYPE_BCM283X)
60
+
61
static const BCM283XInfo bcm283x_socs[] = {
62
{
63
.name = TYPE_BCM2836,
64
--
65
2.20.1
66
67
diff view generated by jsdifflib
Deleted patch
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
1
3
The BCM2835 has only one core. Introduce the core_count field to
4
be able to use values different than BCM283X_NCPUS (4).
5
6
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
7
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Message-id: 20201024170127.3592182-4-f4bug@amsat.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
hw/arm/bcm2836.c | 5 ++++-
12
1 file changed, 4 insertions(+), 1 deletion(-)
13
14
diff --git a/hw/arm/bcm2836.c b/hw/arm/bcm2836.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/arm/bcm2836.c
17
+++ b/hw/arm/bcm2836.c
18
@@ -XXX,XX +XXX,XX @@ typedef struct BCM283XClass {
19
/*< public >*/
20
const char *name;
21
const char *cpu_type;
22
+ unsigned core_count;
23
hwaddr peri_base; /* Peripheral base address seen by the CPU */
24
hwaddr ctrl_base; /* Interrupt controller and mailboxes etc. */
25
int clusterid;
26
@@ -XXX,XX +XXX,XX @@ static void bcm2836_init(Object *obj)
27
BCM283XClass *bc = BCM283X_GET_CLASS(obj);
28
int n;
29
30
- for (n = 0; n < BCM283X_NCPUS; n++) {
31
+ for (n = 0; n < bc->core_count; n++) {
32
object_initialize_child(obj, "cpu[*]", &s->cpu[n].core,
33
bc->cpu_type);
34
}
35
@@ -XXX,XX +XXX,XX @@ static void bcm2836_class_init(ObjectClass *oc, void *data)
36
BCM283XClass *bc = BCM283X_CLASS(oc);
37
38
bc->cpu_type = ARM_CPU_TYPE_NAME("cortex-a7");
39
+ bc->core_count = BCM283X_NCPUS;
40
bc->peri_base = 0x3f000000;
41
bc->ctrl_base = 0x40000000;
42
bc->clusterid = 0xf;
43
@@ -XXX,XX +XXX,XX @@ static void bcm2837_class_init(ObjectClass *oc, void *data)
44
BCM283XClass *bc = BCM283X_CLASS(oc);
45
46
bc->cpu_type = ARM_CPU_TYPE_NAME("cortex-a53");
47
+ bc->core_count = BCM283X_NCPUS;
48
bc->peri_base = 0x3f000000;
49
bc->ctrl_base = 0x40000000;
50
bc->clusterid = 0x0;
51
--
52
2.20.1
53
54
diff view generated by jsdifflib
Deleted patch
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
1
3
The Pi A is almost the first machine released.
4
It uses a BCM2835 SoC which includes a ARMv6Z core.
5
6
Example booting the machine using content from [*]
7
(we use the device tree from the B model):
8
9
$ qemu-system-arm -M raspi1ap -serial stdio \
10
-kernel raspberrypi/firmware/boot/kernel.img \
11
-dtb raspberrypi/firmware/boot/bcm2708-rpi-b-plus.dtb \
12
-append 'earlycon=pl011,0x20201000 console=ttyAMA0'
13
[ 0.000000] Booting Linux on physical CPU 0x0
14
[ 0.000000] Linux version 4.19.118+ (dom@buildbot) (gcc version 4.9.3 (crosstool-NG crosstool-ng-1.22.0-88-g8460611)) #1311 Mon Apr 27 14:16:15 BST 2020
15
[ 0.000000] CPU: ARMv6-compatible processor [410fb767] revision 7 (ARMv7), cr=00c5387d
16
[ 0.000000] CPU: VIPT aliasing data cache, unknown instruction cache
17
[ 0.000000] OF: fdt: Machine model: Raspberry Pi Model B+
18
...
19
20
[*] http://archive.raspberrypi.org/debian/pool/main/r/raspberrypi-firmware/raspberrypi-kernel_1.20200512-2_armhf.deb
21
22
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
23
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
24
Message-id: 20201024170127.3592182-8-f4bug@amsat.org
25
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
26
---
27
hw/arm/raspi.c | 13 +++++++++++++
28
1 file changed, 13 insertions(+)
29
30
diff --git a/hw/arm/raspi.c b/hw/arm/raspi.c
31
index XXXXXXX..XXXXXXX 100644
32
--- a/hw/arm/raspi.c
33
+++ b/hw/arm/raspi.c
34
@@ -XXX,XX +XXX,XX @@ static void raspi_machine_class_common_init(MachineClass *mc,
35
mc->default_ram_id = "ram";
36
};
37
38
+static void raspi1ap_machine_class_init(ObjectClass *oc, void *data)
39
+{
40
+ MachineClass *mc = MACHINE_CLASS(oc);
41
+ RaspiMachineClass *rmc = RASPI_MACHINE_CLASS(oc);
42
+
43
+ rmc->board_rev = 0x900021; /* Revision 1.1 */
44
+ raspi_machine_class_common_init(mc, rmc->board_rev);
45
+};
46
+
47
static void raspi2b_machine_class_init(ObjectClass *oc, void *data)
48
{
49
MachineClass *mc = MACHINE_CLASS(oc);
50
@@ -XXX,XX +XXX,XX @@ static void raspi3b_machine_class_init(ObjectClass *oc, void *data)
51
52
static const TypeInfo raspi_machine_types[] = {
53
{
54
+ .name = MACHINE_TYPE_NAME("raspi1ap"),
55
+ .parent = TYPE_RASPI_MACHINE,
56
+ .class_init = raspi1ap_machine_class_init,
57
+ }, {
58
.name = MACHINE_TYPE_NAME("raspi2b"),
59
.parent = TYPE_RASPI_MACHINE,
60
.class_init = raspi2b_machine_class_init,
61
--
62
2.20.1
63
64
diff view generated by jsdifflib
Deleted patch
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
1
3
Similarly to the Pi A, the Pi Zero uses a BCM2835 SoC (ARMv6Z core).
4
5
The only difference between the revision 1.2 and 1.3 is the latter
6
exposes a CSI camera connector. As we do not implement the Unicam
7
peripheral, there is no point in exposing a camera connector :)
8
Therefore we choose to model the 1.2 revision.
9
10
Example booting the machine using content from [*]:
11
12
$ qemu-system-arm -M raspi0 -serial stdio \
13
-kernel raspberrypi/firmware/boot/kernel.img \
14
-dtb raspberrypi/firmware/boot/bcm2708-rpi-zero.dtb \
15
-append 'printk.time=0 earlycon=pl011,0x20201000 console=ttyAMA0'
16
[ 0.000000] Booting Linux on physical CPU 0x0
17
[ 0.000000] Linux version 4.19.118+ (dom@buildbot) (gcc version 4.9.3 (crosstool-NG crosstool-ng-1.22.0-88-g8460611)) #1311 Mon Apr 27 14:16:15 BST 2020
18
[ 0.000000] CPU: ARMv6-compatible processor [410fb767] revision 7 (ARMv7), cr=00c5387d
19
[ 0.000000] CPU: VIPT aliasing data cache, unknown instruction cache
20
[ 0.000000] OF: fdt: Machine model: Raspberry Pi Zero
21
...
22
23
[*] http://archive.raspberrypi.org/debian/pool/main/r/raspberrypi-firmware/raspberrypi-kernel_1.20200512-2_armhf.deb
24
25
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
26
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
27
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
28
Message-id: 20201024170127.3592182-9-f4bug@amsat.org
29
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
30
---
31
hw/arm/raspi.c | 13 +++++++++++++
32
1 file changed, 13 insertions(+)
33
34
diff --git a/hw/arm/raspi.c b/hw/arm/raspi.c
35
index XXXXXXX..XXXXXXX 100644
36
--- a/hw/arm/raspi.c
37
+++ b/hw/arm/raspi.c
38
@@ -XXX,XX +XXX,XX @@ static void raspi_machine_class_common_init(MachineClass *mc,
39
mc->default_ram_id = "ram";
40
};
41
42
+static void raspi0_machine_class_init(ObjectClass *oc, void *data)
43
+{
44
+ MachineClass *mc = MACHINE_CLASS(oc);
45
+ RaspiMachineClass *rmc = RASPI_MACHINE_CLASS(oc);
46
+
47
+ rmc->board_rev = 0x920092; /* Revision 1.2 */
48
+ raspi_machine_class_common_init(mc, rmc->board_rev);
49
+};
50
+
51
static void raspi1ap_machine_class_init(ObjectClass *oc, void *data)
52
{
53
MachineClass *mc = MACHINE_CLASS(oc);
54
@@ -XXX,XX +XXX,XX @@ static void raspi3b_machine_class_init(ObjectClass *oc, void *data)
55
56
static const TypeInfo raspi_machine_types[] = {
57
{
58
+ .name = MACHINE_TYPE_NAME("raspi0"),
59
+ .parent = TYPE_RASPI_MACHINE,
60
+ .class_init = raspi0_machine_class_init,
61
+ }, {
62
.name = MACHINE_TYPE_NAME("raspi1ap"),
63
.parent = TYPE_RASPI_MACHINE,
64
.class_init = raspi1ap_machine_class_init,
65
--
66
2.20.1
67
68
diff view generated by jsdifflib
Deleted patch
1
From: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
2
1
3
Use of 0x%d - make up our mind as 0x%x
4
5
Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Acked-by: Eric Auger <eric.auger@redhat.com>
8
Message-id: 20201014193355.53074-1-dgilbert@redhat.com
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
hw/arm/trace-events | 2 +-
12
1 file changed, 1 insertion(+), 1 deletion(-)
13
14
diff --git a/hw/arm/trace-events b/hw/arm/trace-events
15
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/arm/trace-events
17
+++ b/hw/arm/trace-events
18
@@ -XXX,XX +XXX,XX @@ smmuv3_get_cd(uint64_t addr) "CD addr: 0x%"PRIx64
19
smmuv3_decode_cd(uint32_t oas) "oas=%d"
20
smmuv3_decode_cd_tt(int i, uint32_t tsz, uint64_t ttb, uint32_t granule_sz, bool had) "TT[%d]:tsz:%d ttb:0x%"PRIx64" granule_sz:%d had:%d"
21
smmuv3_cmdq_cfgi_ste(int streamid) "streamid =%d"
22
-smmuv3_cmdq_cfgi_ste_range(int start, int end) "start=0x%d - end=0x%d"
23
+smmuv3_cmdq_cfgi_ste_range(int start, int end) "start=0x%x - end=0x%x"
24
smmuv3_cmdq_cfgi_cd(uint32_t sid) "streamid = %d"
25
smmuv3_config_cache_hit(uint32_t sid, uint32_t hits, uint32_t misses, uint32_t perc) "Config cache HIT for sid %d (hits=%d, misses=%d, hit rate=%d)"
26
smmuv3_config_cache_miss(uint32_t sid, uint32_t hits, uint32_t misses, uint32_t perc) "Config cache MISS for sid %d (hits=%d, misses=%d, hit rate=%d)"
27
--
28
2.20.1
29
30
diff view generated by jsdifflib