1
This is almost all the mps3-an547 series, but there are a few
1
Some arm patches before softfreeze. These are all bug fixes.
2
other bits in there too.
3
2
4
thanks
5
-- PMM
3
-- PMM
6
4
5
The following changes since commit 0ebf76aae58324b8f7bf6af798696687f5f4c2a9:
7
6
8
The following changes since commit 0436c55edf6b357ff56e2a5bf688df8636f83456:
7
Merge tag 'nvme-next-pull-request' of git://git.infradead.org/qemu-nvme into staging (2022-07-15 15:38:13 +0100)
9
10
Merge remote-tracking branch 'remotes/bonzini-gitlab/tags/for-upstream' into staging (2021-03-08 13:51:41 +0000)
11
8
12
are available in the Git repository at:
9
are available in the Git repository at:
13
10
14
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20210308-1
11
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20220718
15
12
16
for you to fetch changes up to da2140183ac3a04b1ccb861aeac1f2c048c71b66:
13
for you to fetch changes up to 004c8a8bc569c8b18fca6fc90ffe3223daaf17b7:
17
14
18
hw/timer/renesas_tmr: Fix use of uninitialized data in read_tcnt() (2021-03-08 17:20:04 +0000)
15
Align Raspberry Pi DMA interrupts with Linux DTS (2022-07-18 13:25:13 +0100)
19
16
20
----------------------------------------------------------------
17
----------------------------------------------------------------
21
* Add new mps3-an547 board
18
target-arm queue:
22
* target/arm: Restrict v7A TCG cpus to TCG accel
19
* hw/intc/armv7m_nvic: ICPRn must not unpend an IRQ that is being held high
23
* Implement a Xilinx CSU DMA model
20
* target/arm: Fill in VL for tbflags when SME enabled and SVE disabled
24
* hw/timer/renesas_tmr: Fix use of uninitialized data in read_tcnt()
21
* target/arm: Fix aarch64_sve_change_el for SME
22
* linux-user/aarch64: Do not clear PROT_MTE on mprotect
23
* target/arm: Honour VTCR_EL2 bits in Secure EL2
24
* hw/adc: Fix CONV bit in NPCM7XX ADC CON register
25
* hw/adc: Make adci[*] R/W in NPCM7XX ADC
26
* target/arm: Don't set syndrome ISS for loads and stores with writeback
27
* Align Raspberry Pi DMA interrupts with Linux DTS
25
28
26
----------------------------------------------------------------
29
----------------------------------------------------------------
27
Peter Maydell (48):
30
Andrey Makarov (1):
28
clock: Add ClockEvent parameter to callbacks
31
Align Raspberry Pi DMA interrupts with Linux DTS
29
clock: Add ClockPreUpdate callback event type
30
clock: Add clock_ns_to_ticks() function
31
hw/timer/npcm7xx_timer: Use new clock_ns_to_ticks()
32
hw/arm/armsse: Introduce SSE subsystem version property
33
hw/misc/iotkit-sysctl: Remove is_sse200 flag
34
hw/misc/iotkit-secctl.c: Implement SSE-300 PID register values
35
hw/misc/iotkit-sysinfo.c: Implement SSE-300 PID register values
36
hw/arm/armsse.c: Use correct SYS_CONFIG0 register value for SSE-300
37
hw/misc/iotkit-sysinfo.c: Implement SYS_CONFIG1 and IIDR
38
hw/timer/sse-counter: Model the SSE Subsystem System Counter
39
hw/timer/sse-timer: Model the SSE Subsystem System Timer
40
hw/misc/iotkit-sysctl: Add SSE-300 cases which match SSE-200 behaviour
41
hw/misc/iotkit-sysctl: Handle CPU_WAIT, NMI_ENABLE for SSE-300
42
hw/misc/iotkit-sysctl: Handle INITSVTOR* for SSE-300
43
hw/misc/iotkit-sysctl: Implement dummy version of SSE-300 PWRCTRL register
44
hw/misc/iotkit-sysctl: Handle SSE-300 changes to PDCM_PD_*_SENSE registers
45
hw/misc/iotkit-sysctl: Implement SSE-200 and SSE-300 PID register values
46
hw/arm/Kconfig: Move ARMSSE_CPUID and ARMSSE_MHU stanzas to hw/misc
47
hw/misc/sse-cpu-pwrctrl: Implement SSE-300 CPU<N>_PWRCTRL register block
48
hw/arm/armsse: Use an array for apb_ppc fields in the state structure
49
hw/arm/armsse: Add a define for number of IRQs used by the SSE itself
50
hw/arm/armsse: Add framework for data-driven device placement
51
hw/arm/armsse: Move dual-timer device into data-driven framework
52
hw/arm/armsse: Move watchdogs into data-driven framework
53
hw/arm/armsse: Move s32ktimer into data-driven framework
54
hw/arm/armsse: Move sysinfo register block into data-driven framework
55
hw/arm/armsse: Move sysctl register block into data-driven framework
56
hw/arm/armsse: Move PPUs into data-driven framework
57
hw/arm/armsse: Add missing SSE-200 SYS_PPU
58
hw/arm/armsse: Indirect irq_is_common[] through ARMSSEInfo
59
hw/arm/armsse: Add support for SSE variants with a system counter
60
hw/arm/armsse: Add support for TYPE_SSE_TIMER in ARMSSEDeviceInfo
61
hw/arm/armsse: Support variants with ARMSSE_CPU_PWRCTRL block
62
hw/arm/armsse: Add SSE-300 support
63
hw/arm/mps2-tz: Make UART overflow IRQ board-specific
64
hw/misc/mps2-fpgaio: Fold counters subsection into main vmstate
65
hw/misc/mps2-fpgaio: Support AN547 DBGCTRL register
66
hw/misc/mps2-scc: Implement changes for AN547
67
hw/arm/mps2-tz: Support running APB peripherals on different clock
68
hw/arm/mps2-tz: Make initsvtor0 setting board-specific
69
hw/arm/mps2-tz: Add new mps3-an547 board
70
docs/system/arm/mps2.rst: Document the new mps3-an547 board
71
tests/qtest/sse-timer-test: Add simple test of the SSE counter
72
tests/qtest/sse-timer-test: Test the system timer
73
tests/qtest/sse-timer-test: Test counter scaling changes
74
hw/timer/renesas_tmr: Prefix constants for CSS values with CSS_
75
hw/timer/renesas_tmr: Fix use of uninitialized data in read_tcnt()
76
32
77
Philippe Mathieu-Daudé (1):
33
Hao Wu (2):
78
target/arm: Restrict v7A TCG cpus to TCG accel
34
hw/adc: Fix CONV bit in NPCM7XX ADC CON register
35
hw/adc: Make adci[*] R/W in NPCM7XX ADC
79
36
80
Xuzhou Cheng (5):
37
Peter Maydell (9):
81
hw/dma: Implement a Xilinx CSU DMA model
38
hw/intc/armv7m_nvic: ICPRn must not unpend an IRQ that is being held high
82
hw/arm: xlnx-zynqmp: Clean up coding convention issues
39
target/arm: Define and use new regime_tcr_value() function
83
hw/arm: xlnx-zynqmp: Connect a Xilinx CSU DMA module for QSPI
40
target/arm: Calculate mask/base_mask in get_level1_table_address()
84
hw/ssi: xilinx_spips: Clean up coding convention issues
41
target/arm: Fold regime_tcr() and regime_tcr_value() together
85
hw/ssi: xilinx_spips: Remove DMA related dead codes from zynqmp_spips
42
target/arm: Fix big-endian host handling of VTCR
43
target/arm: Store VTCR_EL2, VSTCR_EL2 registers as uint64_t
44
target/arm: Store TCR_EL* registers as uint64_t
45
target/arm: Honour VTCR_EL2 bits in Secure EL2
46
target/arm: Don't set syndrome ISS for loads and stores with writeback
86
47
87
docs/devel/clocks.rst | 71 ++-
48
Richard Henderson (3):
88
docs/system/arm/mps2.rst | 6 +-
49
target/arm: Fill in VL for tbflags when SME enabled and SVE disabled
89
include/hw/arm/armsse-version.h | 42 ++
50
target/arm: Fix aarch64_sve_change_el for SME
90
include/hw/arm/armsse.h | 40 +-
51
linux-user/aarch64: Do not clear PROT_MTE on mprotect
91
include/hw/arm/xlnx-zynqmp.h | 5 +-
92
include/hw/clock.h | 63 ++-
93
include/hw/dma/xlnx_csu_dma.h | 52 ++
94
include/hw/misc/armsse-cpu-pwrctrl.h | 40 ++
95
include/hw/misc/iotkit-secctl.h | 2 +
96
include/hw/misc/iotkit-sysctl.h | 13 +-
97
include/hw/misc/iotkit-sysinfo.h | 2 +
98
include/hw/misc/mps2-fpgaio.h | 2 +
99
include/hw/qdev-clock.h | 17 +-
100
include/hw/ssi/xilinx_spips.h | 2 +-
101
include/hw/timer/sse-counter.h | 105 ++++
102
include/hw/timer/sse-timer.h | 53 ++
103
hw/adc/npcm7xx_adc.c | 2 +-
104
hw/arm/armsse.c | 1008 +++++++++++++++++++++++++---------
105
hw/arm/mps2-tz.c | 168 +++++-
106
hw/arm/xlnx-zynqmp.c | 21 +-
107
hw/char/cadence_uart.c | 4 +-
108
hw/char/ibex_uart.c | 4 +-
109
hw/char/pl011.c | 5 +-
110
hw/core/clock.c | 24 +-
111
hw/core/qdev-clock.c | 8 +-
112
hw/dma/xlnx_csu_dma.c | 745 +++++++++++++++++++++++++
113
hw/mips/cps.c | 2 +-
114
hw/misc/armsse-cpu-pwrctrl.c | 149 +++++
115
hw/misc/bcm2835_cprman.c | 23 +-
116
hw/misc/iotkit-secctl.c | 50 +-
117
hw/misc/iotkit-sysctl.c | 522 +++++++++++++++---
118
hw/misc/iotkit-sysinfo.c | 51 +-
119
hw/misc/mps2-fpgaio.c | 52 +-
120
hw/misc/mps2-scc.c | 15 +-
121
hw/misc/npcm7xx_clk.c | 26 +-
122
hw/misc/npcm7xx_pwm.c | 2 +-
123
hw/misc/zynq_slcr.c | 5 +-
124
hw/ssi/xilinx_spips.c | 33 +-
125
hw/timer/cmsdk-apb-dualtimer.c | 5 +-
126
hw/timer/cmsdk-apb-timer.c | 4 +-
127
hw/timer/npcm7xx_timer.c | 6 +-
128
hw/timer/renesas_tmr.c | 33 +-
129
hw/timer/sse-counter.c | 474 ++++++++++++++++
130
hw/timer/sse-timer.c | 470 ++++++++++++++++
131
hw/watchdog/cmsdk-apb-watchdog.c | 5 +-
132
target/arm/cpu.c | 335 -----------
133
target/arm/cpu_tcg.c | 318 +++++++++++
134
target/mips/cpu.c | 2 +-
135
tests/qtest/sse-timer-test.c | 240 ++++++++
136
MAINTAINERS | 7 +
137
hw/arm/Kconfig | 10 +-
138
hw/dma/Kconfig | 4 +
139
hw/dma/meson.build | 1 +
140
hw/misc/Kconfig | 9 +
141
hw/misc/meson.build | 1 +
142
hw/misc/trace-events | 4 +
143
hw/timer/Kconfig | 6 +
144
hw/timer/meson.build | 2 +
145
hw/timer/trace-events | 12 +
146
tests/qtest/meson.build | 1 +
147
60 files changed, 4537 insertions(+), 846 deletions(-)
148
create mode 100644 include/hw/arm/armsse-version.h
149
create mode 100644 include/hw/dma/xlnx_csu_dma.h
150
create mode 100644 include/hw/misc/armsse-cpu-pwrctrl.h
151
create mode 100644 include/hw/timer/sse-counter.h
152
create mode 100644 include/hw/timer/sse-timer.h
153
create mode 100644 hw/dma/xlnx_csu_dma.c
154
create mode 100644 hw/misc/armsse-cpu-pwrctrl.c
155
create mode 100644 hw/timer/sse-counter.c
156
create mode 100644 hw/timer/sse-timer.c
157
create mode 100644 tests/qtest/sse-timer-test.c
158
52
53
include/hw/arm/bcm2835_peripherals.h | 2 +
54
target/arm/cpu.h | 38 ++++++++---
55
target/arm/internals.h | 34 +++++++---
56
accel/tcg/translate-all.c | 13 +++-
57
hw/adc/npcm7xx_adc.c | 4 +-
58
hw/arm/bcm2835_peripherals.c | 26 ++++++-
59
hw/intc/armv7m_nvic.c | 9 ++-
60
target/arm/cpu.c | 2 +-
61
target/arm/debug_helper.c | 2 +-
62
target/arm/helper.c | 128 ++++++++++++++++-------------------
63
target/arm/ptw.c | 38 ++++++-----
64
target/arm/tlb_helper.c | 2 +-
65
target/arm/translate-a64.c | 4 +-
66
tests/qtest/bcm2835-dma-test.c | 118 ++++++++++++++++++++++++++++++++
67
tests/qtest/npcm7xx_adc-test.c | 2 +-
68
tests/qtest/meson.build | 3 +-
69
16 files changed, 306 insertions(+), 119 deletions(-)
70
create mode 100644 tests/qtest/bcm2835-dma-test.c
diff view generated by jsdifflib
1
The read_tcnt() function calculates the TCNT register values for the
1
In the M-profile Arm ARM, rule R_CVJS defines when an interrupt should
2
two channels of the timer module; it sets these up in the local
2
be set to the Pending state:
3
tcnt[] array, and eventually returns either one or both of them,
3
A) when the input line is high and the interrupt is not Active
4
depending on whether the access is 8 or 16 bits. However, not all of
4
B) when the input line transitions from low to high and the interrupt
5
the code paths through this function set both elements of this array:
5
is Active
6
if the guest has programmed the TCCR.CSS register fields to values
6
(Note that the first of these is an ongoing condition, and the
7
which are either documented as not to be used or which QEMU does not
7
second is a point-in-time event.)
8
implement, then the function will return uninitialized data. (This
9
was spotted by Coverity.)
10
8
11
Add the missing CSS cases to this code, so that we return a
9
This can be rephrased as:
12
consistent value instead of uninitialized data, and so the code
10
1 when the line goes from low to high, set Pending
13
structure indicates what's happening.
11
2 when Active goes from 1 to 0, if line is high then set Pending
12
3 ignore attempts to clear Pending when the line is high
13
and Active is 0
14
14
15
Fixes: CID 1429976
15
where 1 covers both B and one of the "transition into condition A"
16
cases, 2 deals with the other "transition into condition A"
17
possibility, and 3 is "don't drop Pending if we're already in
18
condition A". Transitions out of condition A don't affect Pending
19
state.
20
21
We handle case 1 in set_irq_level(). For an interrupt (as opposed
22
to other kinds of exception) the only place where we clear Active
23
is in armv7m_nvic_complete_irq(), where we handle case 2 by
24
checking for whether we need to re-pend the exception. For case 3,
25
the only places where we clear Pending state on an interrupt are in
26
armv7m_nvic_acknowledge_irq() (where we are setting Active so it
27
doesn't count) and for writes to NVIC_ICPRn.
28
29
It is the "write to NVIC_ICPRn" case that we missed: we must ignore
30
this if the input line is high and the interrupt is not Active.
31
(This required behaviour is differently and perhaps more clearly
32
stated in the v7M Arm ARM, which has pseudocode in section B3.4.1
33
that implies it.)
34
35
Reported-by: Igor Kotrasiński <i.kotrasinsk@samsung.com>
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
36
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
37
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
18
Message-id: 20210219223241.16344-3-peter.maydell@linaro.org
38
Message-id: 20220628154724.3297442-1-peter.maydell@linaro.org
19
---
39
---
20
hw/timer/renesas_tmr.c | 19 +++++++++++++++----
40
hw/intc/armv7m_nvic.c | 9 ++++++++-
21
1 file changed, 15 insertions(+), 4 deletions(-)
41
1 file changed, 8 insertions(+), 1 deletion(-)
22
42
23
diff --git a/hw/timer/renesas_tmr.c b/hw/timer/renesas_tmr.c
43
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
24
index XXXXXXX..XXXXXXX 100644
44
index XXXXXXX..XXXXXXX 100644
25
--- a/hw/timer/renesas_tmr.c
45
--- a/hw/intc/armv7m_nvic.c
26
+++ b/hw/timer/renesas_tmr.c
46
+++ b/hw/intc/armv7m_nvic.c
27
@@ -XXX,XX +XXX,XX @@ REG8(TCCR, 10)
47
@@ -XXX,XX +XXX,XX @@ static MemTxResult nvic_sysreg_write(void *opaque, hwaddr addr,
28
FIELD(TCCR, CSS, 3, 2)
48
startvec = 8 * (offset - 0x280) + NVIC_FIRST_IRQ; /* vector # */
29
FIELD(TCCR, TMRIS, 7, 1)
49
30
50
for (i = 0, end = size * 8; i < end && startvec + i < s->num_irq; i++) {
31
+#define CSS_EXTERNAL 0x00
51
+ /*
32
#define CSS_INTERNAL 0x01
52
+ * Note that if the input line is still held high and the interrupt
33
+#define CSS_INVALID 0x02
53
+ * is not active then rule R_CVJS requires that the Pending state
34
#define CSS_CASCADING 0x03
54
+ * remains set; in that case we mustn't let it be cleared.
35
#define CCLR_A 0x01
55
+ */
36
#define CCLR_B 0x02
56
if (value & (1 << i) &&
37
@@ -XXX,XX +XXX,XX @@ static uint16_t read_tcnt(RTMRState *tmr, unsigned size, int ch)
57
- (attrs.secure || s->itns[startvec + i])) {
38
if (delta > 0) {
58
+ (attrs.secure || s->itns[startvec + i]) &&
39
tmr->tick = now;
59
+ !(setval == 0 && s->vectors[startvec + i].level &&
40
60
+ !s->vectors[startvec + i].active)) {
41
- if (FIELD_EX8(tmr->tccr[1], TCCR, CSS) == CSS_INTERNAL) {
61
s->vectors[startvec + i].pending = setval;
42
+ switch (FIELD_EX8(tmr->tccr[1], TCCR, CSS)) {
43
+ case CSS_INTERNAL:
44
/* timer1 count update */
45
elapsed = elapsed_time(tmr, 1, delta);
46
if (elapsed >= 0x100) {
47
ovf = elapsed >> 8;
48
}
62
}
49
tcnt[1] = tmr->tcnt[1] + (elapsed & 0xff);
50
+ break;
51
+ case CSS_INVALID: /* guest error to have set this */
52
+ case CSS_EXTERNAL: /* QEMU doesn't implement these */
53
+ case CSS_CASCADING:
54
+ tcnt[1] = tmr->tcnt[1];
55
+ break;
56
}
63
}
57
switch (FIELD_EX8(tmr->tccr[0], TCCR, CSS)) {
58
case CSS_INTERNAL:
59
@@ -XXX,XX +XXX,XX @@ static uint16_t read_tcnt(RTMRState *tmr, unsigned size, int ch)
60
tcnt[0] = tmr->tcnt[0] + elapsed;
61
break;
62
case CSS_CASCADING:
63
- if (ovf > 0) {
64
- tcnt[0] = tmr->tcnt[0] + ovf;
65
- }
66
+ tcnt[0] = tmr->tcnt[0] + ovf;
67
+ break;
68
+ case CSS_INVALID: /* guest error to have set this */
69
+ case CSS_EXTERNAL: /* QEMU doesn't implement this */
70
+ tcnt[0] = tmr->tcnt[0];
71
break;
72
}
73
} else {
74
--
64
--
75
2.20.1
65
2.25.1
76
66
77
67
diff view generated by jsdifflib
1
From: Xuzhou Cheng <xuzhou.cheng@windriver.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Now that the Xilinx CSU DMA model is implemented, the existing
3
When PSTATE.SM, VL = SVL even if SVE is disabled.
4
DMA related dead codes in the ZynqMP QSPI are useless and should
4
This is visible in kselftest ssve-test.
5
be removed. The maximum register number is also updated to only
6
include the QSPI registers.
7
5
8
Signed-off-by: Xuzhou Cheng <xuzhou.cheng@windriver.com>
6
Reported-by: Mark Brown <broonie@kernel.org>
9
Signed-off-by: Bin Meng <bin.meng@windriver.com>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
8
Message-id: 20220713045848.217364-2-richard.henderson@linaro.org
11
Message-id: 20210303135254.3970-6-bmeng.cn@gmail.com
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
11
---
14
include/hw/ssi/xilinx_spips.h | 2 +-
12
target/arm/helper.c | 10 ++++++++--
15
hw/ssi/xilinx_spips.c | 10 ----------
13
1 file changed, 8 insertions(+), 2 deletions(-)
16
2 files changed, 1 insertion(+), 11 deletions(-)
17
14
18
diff --git a/include/hw/ssi/xilinx_spips.h b/include/hw/ssi/xilinx_spips.h
15
diff --git a/target/arm/helper.c b/target/arm/helper.c
19
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
20
--- a/include/hw/ssi/xilinx_spips.h
17
--- a/target/arm/helper.c
21
+++ b/include/hw/ssi/xilinx_spips.h
18
+++ b/target/arm/helper.c
22
@@ -XXX,XX +XXX,XX @@
19
@@ -XXX,XX +XXX,XX @@ static CPUARMTBFlags rebuild_hflags_a64(CPUARMState *env, int el, int fp_el,
23
typedef struct XilinxSPIPS XilinxSPIPS;
20
}
24
21
if (cpu_isar_feature(aa64_sme, env_archcpu(env))) {
25
#define XLNX_SPIPS_R_MAX (0x100 / 4)
22
int sme_el = sme_exception_el(env, el);
26
-#define XLNX_ZYNQMP_SPIPS_R_MAX (0x830 / 4)
23
+ bool sm = FIELD_EX64(env->svcr, SVCR, SM);
27
+#define XLNX_ZYNQMP_SPIPS_R_MAX (0x200 / 4)
24
28
25
DP_TBFLAG_A64(flags, SMEEXC_EL, sme_el);
29
/* Bite off 4k chunks at a time */
26
if (sme_el == 0) {
30
#define LQSPI_CACHE_SIZE 1024
27
/* Similarly, do not compute SVL if SME is disabled. */
31
diff --git a/hw/ssi/xilinx_spips.c b/hw/ssi/xilinx_spips.c
28
- DP_TBFLAG_A64(flags, SVL, sve_vqm1_for_el_sm(env, el, true));
32
index XXXXXXX..XXXXXXX 100644
29
+ int svl = sve_vqm1_for_el_sm(env, el, true);
33
--- a/hw/ssi/xilinx_spips.c
30
+ DP_TBFLAG_A64(flags, SVL, svl);
34
+++ b/hw/ssi/xilinx_spips.c
31
+ if (sm) {
35
@@ -XXX,XX +XXX,XX @@
32
+ /* If SVE is disabled, we will not have set VL above. */
36
#define R_GQSPI_MOD_ID (0x1fc / 4)
33
+ DP_TBFLAG_A64(flags, VL, svl);
37
#define R_GQSPI_MOD_ID_RESET (0x10a0000)
34
+ }
38
35
}
39
-#define R_QSPIDMA_DST_CTRL (0x80c / 4)
36
- if (FIELD_EX64(env->svcr, SVCR, SM)) {
40
-#define R_QSPIDMA_DST_CTRL_RESET (0x803ffa00)
37
+ if (sm) {
41
-#define R_QSPIDMA_DST_I_MASK (0x820 / 4)
38
DP_TBFLAG_A64(flags, PSTATE_SM, 1);
42
-#define R_QSPIDMA_DST_I_MASK_RESET (0xfe)
39
DP_TBFLAG_A64(flags, SME_TRAP_NONSTREAMING, !sme_fa64(env, el));
43
-#define R_QSPIDMA_DST_CTRL2 (0x824 / 4)
40
}
44
-#define R_QSPIDMA_DST_CTRL2_RESET (0x081bfff8)
45
-
46
/* size of TXRX FIFOs */
47
#define RXFF_A (128)
48
#define TXFF_A (128)
49
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_qspips_reset(DeviceState *d)
50
s->regs[R_GQSPI_GPIO] = 1;
51
s->regs[R_GQSPI_LPBK_DLY_ADJ] = R_GQSPI_LPBK_DLY_ADJ_RESET;
52
s->regs[R_GQSPI_MOD_ID] = R_GQSPI_MOD_ID_RESET;
53
- s->regs[R_QSPIDMA_DST_CTRL] = R_QSPIDMA_DST_CTRL_RESET;
54
- s->regs[R_QSPIDMA_DST_I_MASK] = R_QSPIDMA_DST_I_MASK_RESET;
55
- s->regs[R_QSPIDMA_DST_CTRL2] = R_QSPIDMA_DST_CTRL2_RESET;
56
s->man_start_com_g = false;
57
s->gqspi_irqline = 0;
58
xlnx_zynqmp_qspips_update_ixr(s);
59
--
41
--
60
2.20.1
42
2.25.1
61
62
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
KVM requires the target cpu to be at least ARMv8 architecture
3
We were only checking for SVE disabled and not taking into
4
(support on ARMv7 has been dropped in commit 82bf7ae84ce:
4
account PSTATE.SM to check SME disabled, which resulted in
5
"target/arm: Remove KVM support for 32-bit Arm hosts").
5
vectors being incorrectly truncated.
6
6
7
A KVM-only build won't be able to run TCG cpus, move the
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
v7A CPU definitions to cpu_tcg.c.
8
Message-id: 20220713045848.217364-3-richard.henderson@linaro.org
9
10
Reported-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
13
Message-id: 20210306151801.2388182-1-f4bug@amsat.org
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
---
11
---
16
target/arm/cpu.c | 335 -------------------------------------------
12
target/arm/helper.c | 31 +++++++++++++++++++++++++------
17
target/arm/cpu_tcg.c | 318 ++++++++++++++++++++++++++++++++++++++++
13
1 file changed, 25 insertions(+), 6 deletions(-)
18
2 files changed, 318 insertions(+), 335 deletions(-)
19
14
20
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
15
diff --git a/target/arm/helper.c b/target/arm/helper.c
21
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
22
--- a/target/arm/cpu.c
17
--- a/target/arm/helper.c
23
+++ b/target/arm/cpu.c
18
+++ b/target/arm/helper.c
24
@@ -XXX,XX +XXX,XX @@ static ObjectClass *arm_cpu_class_by_name(const char *cpu_model)
19
@@ -XXX,XX +XXX,XX @@ void aarch64_sve_narrow_vq(CPUARMState *env, unsigned vq)
25
return oc;
20
}
26
}
21
}
27
22
28
-/* CPU models. These are not needed for the AArch64 linux-user build. */
23
+static uint32_t sve_vqm1_for_el_sm_ena(CPUARMState *env, int el, bool sm)
29
-#if !defined(CONFIG_USER_ONLY) || !defined(TARGET_AARCH64)
24
+{
30
-
25
+ int exc_el;
31
-static const ARMCPRegInfo cortexa8_cp_reginfo[] = {
32
- { .name = "L2LOCKDOWN", .cp = 15, .crn = 9, .crm = 0, .opc1 = 1, .opc2 = 0,
33
- .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
34
- { .name = "L2AUXCR", .cp = 15, .crn = 9, .crm = 0, .opc1 = 1, .opc2 = 2,
35
- .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
36
- REGINFO_SENTINEL
37
-};
38
-
39
-static void cortex_a8_initfn(Object *obj)
40
-{
41
- ARMCPU *cpu = ARM_CPU(obj);
42
-
43
- cpu->dtb_compatible = "arm,cortex-a8";
44
- set_feature(&cpu->env, ARM_FEATURE_V7);
45
- set_feature(&cpu->env, ARM_FEATURE_NEON);
46
- set_feature(&cpu->env, ARM_FEATURE_THUMB2EE);
47
- set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS);
48
- set_feature(&cpu->env, ARM_FEATURE_EL3);
49
- cpu->midr = 0x410fc080;
50
- cpu->reset_fpsid = 0x410330c0;
51
- cpu->isar.mvfr0 = 0x11110222;
52
- cpu->isar.mvfr1 = 0x00011111;
53
- cpu->ctr = 0x82048004;
54
- cpu->reset_sctlr = 0x00c50078;
55
- cpu->isar.id_pfr0 = 0x1031;
56
- cpu->isar.id_pfr1 = 0x11;
57
- cpu->isar.id_dfr0 = 0x400;
58
- cpu->id_afr0 = 0;
59
- cpu->isar.id_mmfr0 = 0x31100003;
60
- cpu->isar.id_mmfr1 = 0x20000000;
61
- cpu->isar.id_mmfr2 = 0x01202000;
62
- cpu->isar.id_mmfr3 = 0x11;
63
- cpu->isar.id_isar0 = 0x00101111;
64
- cpu->isar.id_isar1 = 0x12112111;
65
- cpu->isar.id_isar2 = 0x21232031;
66
- cpu->isar.id_isar3 = 0x11112131;
67
- cpu->isar.id_isar4 = 0x00111142;
68
- cpu->isar.dbgdidr = 0x15141000;
69
- cpu->clidr = (1 << 27) | (2 << 24) | 3;
70
- cpu->ccsidr[0] = 0xe007e01a; /* 16k L1 dcache. */
71
- cpu->ccsidr[1] = 0x2007e01a; /* 16k L1 icache. */
72
- cpu->ccsidr[2] = 0xf0000000; /* No L2 icache. */
73
- cpu->reset_auxcr = 2;
74
- define_arm_cp_regs(cpu, cortexa8_cp_reginfo);
75
-}
76
-
77
-static const ARMCPRegInfo cortexa9_cp_reginfo[] = {
78
- /*
79
- * power_control should be set to maximum latency. Again,
80
- * default to 0 and set by private hook
81
- */
82
- { .name = "A9_PWRCTL", .cp = 15, .crn = 15, .crm = 0, .opc1 = 0, .opc2 = 0,
83
- .access = PL1_RW, .resetvalue = 0,
84
- .fieldoffset = offsetof(CPUARMState, cp15.c15_power_control) },
85
- { .name = "A9_DIAG", .cp = 15, .crn = 15, .crm = 0, .opc1 = 0, .opc2 = 1,
86
- .access = PL1_RW, .resetvalue = 0,
87
- .fieldoffset = offsetof(CPUARMState, cp15.c15_diagnostic) },
88
- { .name = "A9_PWRDIAG", .cp = 15, .crn = 15, .crm = 0, .opc1 = 0, .opc2 = 2,
89
- .access = PL1_RW, .resetvalue = 0,
90
- .fieldoffset = offsetof(CPUARMState, cp15.c15_power_diagnostic) },
91
- { .name = "NEONBUSY", .cp = 15, .crn = 15, .crm = 1, .opc1 = 0, .opc2 = 0,
92
- .access = PL1_RW, .resetvalue = 0, .type = ARM_CP_CONST },
93
- /* TLB lockdown control */
94
- { .name = "TLB_LOCKR", .cp = 15, .crn = 15, .crm = 4, .opc1 = 5, .opc2 = 2,
95
- .access = PL1_W, .resetvalue = 0, .type = ARM_CP_NOP },
96
- { .name = "TLB_LOCKW", .cp = 15, .crn = 15, .crm = 4, .opc1 = 5, .opc2 = 4,
97
- .access = PL1_W, .resetvalue = 0, .type = ARM_CP_NOP },
98
- { .name = "TLB_VA", .cp = 15, .crn = 15, .crm = 5, .opc1 = 5, .opc2 = 2,
99
- .access = PL1_RW, .resetvalue = 0, .type = ARM_CP_CONST },
100
- { .name = "TLB_PA", .cp = 15, .crn = 15, .crm = 6, .opc1 = 5, .opc2 = 2,
101
- .access = PL1_RW, .resetvalue = 0, .type = ARM_CP_CONST },
102
- { .name = "TLB_ATTR", .cp = 15, .crn = 15, .crm = 7, .opc1 = 5, .opc2 = 2,
103
- .access = PL1_RW, .resetvalue = 0, .type = ARM_CP_CONST },
104
- REGINFO_SENTINEL
105
-};
106
-
107
-static void cortex_a9_initfn(Object *obj)
108
-{
109
- ARMCPU *cpu = ARM_CPU(obj);
110
-
111
- cpu->dtb_compatible = "arm,cortex-a9";
112
- set_feature(&cpu->env, ARM_FEATURE_V7);
113
- set_feature(&cpu->env, ARM_FEATURE_NEON);
114
- set_feature(&cpu->env, ARM_FEATURE_THUMB2EE);
115
- set_feature(&cpu->env, ARM_FEATURE_EL3);
116
- /*
117
- * Note that A9 supports the MP extensions even for
118
- * A9UP and single-core A9MP (which are both different
119
- * and valid configurations; we don't model A9UP).
120
- */
121
- set_feature(&cpu->env, ARM_FEATURE_V7MP);
122
- set_feature(&cpu->env, ARM_FEATURE_CBAR);
123
- cpu->midr = 0x410fc090;
124
- cpu->reset_fpsid = 0x41033090;
125
- cpu->isar.mvfr0 = 0x11110222;
126
- cpu->isar.mvfr1 = 0x01111111;
127
- cpu->ctr = 0x80038003;
128
- cpu->reset_sctlr = 0x00c50078;
129
- cpu->isar.id_pfr0 = 0x1031;
130
- cpu->isar.id_pfr1 = 0x11;
131
- cpu->isar.id_dfr0 = 0x000;
132
- cpu->id_afr0 = 0;
133
- cpu->isar.id_mmfr0 = 0x00100103;
134
- cpu->isar.id_mmfr1 = 0x20000000;
135
- cpu->isar.id_mmfr2 = 0x01230000;
136
- cpu->isar.id_mmfr3 = 0x00002111;
137
- cpu->isar.id_isar0 = 0x00101111;
138
- cpu->isar.id_isar1 = 0x13112111;
139
- cpu->isar.id_isar2 = 0x21232041;
140
- cpu->isar.id_isar3 = 0x11112131;
141
- cpu->isar.id_isar4 = 0x00111142;
142
- cpu->isar.dbgdidr = 0x35141000;
143
- cpu->clidr = (1 << 27) | (1 << 24) | 3;
144
- cpu->ccsidr[0] = 0xe00fe019; /* 16k L1 dcache. */
145
- cpu->ccsidr[1] = 0x200fe019; /* 16k L1 icache. */
146
- define_arm_cp_regs(cpu, cortexa9_cp_reginfo);
147
-}
148
-
149
-#ifndef CONFIG_USER_ONLY
150
-static uint64_t a15_l2ctlr_read(CPUARMState *env, const ARMCPRegInfo *ri)
151
-{
152
- MachineState *ms = MACHINE(qdev_get_machine());
153
-
154
- /*
155
- * Linux wants the number of processors from here.
156
- * Might as well set the interrupt-controller bit too.
157
- */
158
- return ((ms->smp.cpus - 1) << 24) | (1 << 23);
159
-}
160
-#endif
161
-
162
-static const ARMCPRegInfo cortexa15_cp_reginfo[] = {
163
-#ifndef CONFIG_USER_ONLY
164
- { .name = "L2CTLR", .cp = 15, .crn = 9, .crm = 0, .opc1 = 1, .opc2 = 2,
165
- .access = PL1_RW, .resetvalue = 0, .readfn = a15_l2ctlr_read,
166
- .writefn = arm_cp_write_ignore, },
167
-#endif
168
- { .name = "L2ECTLR", .cp = 15, .crn = 9, .crm = 0, .opc1 = 1, .opc2 = 3,
169
- .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
170
- REGINFO_SENTINEL
171
-};
172
-
173
-static void cortex_a7_initfn(Object *obj)
174
-{
175
- ARMCPU *cpu = ARM_CPU(obj);
176
-
177
- cpu->dtb_compatible = "arm,cortex-a7";
178
- set_feature(&cpu->env, ARM_FEATURE_V7VE);
179
- set_feature(&cpu->env, ARM_FEATURE_NEON);
180
- set_feature(&cpu->env, ARM_FEATURE_THUMB2EE);
181
- set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
182
- set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS);
183
- set_feature(&cpu->env, ARM_FEATURE_CBAR_RO);
184
- set_feature(&cpu->env, ARM_FEATURE_EL2);
185
- set_feature(&cpu->env, ARM_FEATURE_EL3);
186
- set_feature(&cpu->env, ARM_FEATURE_PMU);
187
- cpu->kvm_target = QEMU_KVM_ARM_TARGET_CORTEX_A7;
188
- cpu->midr = 0x410fc075;
189
- cpu->reset_fpsid = 0x41023075;
190
- cpu->isar.mvfr0 = 0x10110222;
191
- cpu->isar.mvfr1 = 0x11111111;
192
- cpu->ctr = 0x84448003;
193
- cpu->reset_sctlr = 0x00c50078;
194
- cpu->isar.id_pfr0 = 0x00001131;
195
- cpu->isar.id_pfr1 = 0x00011011;
196
- cpu->isar.id_dfr0 = 0x02010555;
197
- cpu->id_afr0 = 0x00000000;
198
- cpu->isar.id_mmfr0 = 0x10101105;
199
- cpu->isar.id_mmfr1 = 0x40000000;
200
- cpu->isar.id_mmfr2 = 0x01240000;
201
- cpu->isar.id_mmfr3 = 0x02102211;
202
- /*
203
- * a7_mpcore_r0p5_trm, page 4-4 gives 0x01101110; but
204
- * table 4-41 gives 0x02101110, which includes the arm div insns.
205
- */
206
- cpu->isar.id_isar0 = 0x02101110;
207
- cpu->isar.id_isar1 = 0x13112111;
208
- cpu->isar.id_isar2 = 0x21232041;
209
- cpu->isar.id_isar3 = 0x11112131;
210
- cpu->isar.id_isar4 = 0x10011142;
211
- cpu->isar.dbgdidr = 0x3515f005;
212
- cpu->clidr = 0x0a200023;
213
- cpu->ccsidr[0] = 0x701fe00a; /* 32K L1 dcache */
214
- cpu->ccsidr[1] = 0x201fe00a; /* 32K L1 icache */
215
- cpu->ccsidr[2] = 0x711fe07a; /* 4096K L2 unified cache */
216
- define_arm_cp_regs(cpu, cortexa15_cp_reginfo); /* Same as A15 */
217
-}
218
-
219
-static void cortex_a15_initfn(Object *obj)
220
-{
221
- ARMCPU *cpu = ARM_CPU(obj);
222
-
223
- cpu->dtb_compatible = "arm,cortex-a15";
224
- set_feature(&cpu->env, ARM_FEATURE_V7VE);
225
- set_feature(&cpu->env, ARM_FEATURE_NEON);
226
- set_feature(&cpu->env, ARM_FEATURE_THUMB2EE);
227
- set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
228
- set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS);
229
- set_feature(&cpu->env, ARM_FEATURE_CBAR_RO);
230
- set_feature(&cpu->env, ARM_FEATURE_EL2);
231
- set_feature(&cpu->env, ARM_FEATURE_EL3);
232
- set_feature(&cpu->env, ARM_FEATURE_PMU);
233
- cpu->kvm_target = QEMU_KVM_ARM_TARGET_CORTEX_A15;
234
- cpu->midr = 0x412fc0f1;
235
- cpu->reset_fpsid = 0x410430f0;
236
- cpu->isar.mvfr0 = 0x10110222;
237
- cpu->isar.mvfr1 = 0x11111111;
238
- cpu->ctr = 0x8444c004;
239
- cpu->reset_sctlr = 0x00c50078;
240
- cpu->isar.id_pfr0 = 0x00001131;
241
- cpu->isar.id_pfr1 = 0x00011011;
242
- cpu->isar.id_dfr0 = 0x02010555;
243
- cpu->id_afr0 = 0x00000000;
244
- cpu->isar.id_mmfr0 = 0x10201105;
245
- cpu->isar.id_mmfr1 = 0x20000000;
246
- cpu->isar.id_mmfr2 = 0x01240000;
247
- cpu->isar.id_mmfr3 = 0x02102211;
248
- cpu->isar.id_isar0 = 0x02101110;
249
- cpu->isar.id_isar1 = 0x13112111;
250
- cpu->isar.id_isar2 = 0x21232041;
251
- cpu->isar.id_isar3 = 0x11112131;
252
- cpu->isar.id_isar4 = 0x10011142;
253
- cpu->isar.dbgdidr = 0x3515f021;
254
- cpu->clidr = 0x0a200023;
255
- cpu->ccsidr[0] = 0x701fe00a; /* 32K L1 dcache */
256
- cpu->ccsidr[1] = 0x201fe00a; /* 32K L1 icache */
257
- cpu->ccsidr[2] = 0x711fe07a; /* 4096K L2 unified cache */
258
- define_arm_cp_regs(cpu, cortexa15_cp_reginfo);
259
-}
260
-
261
-#ifndef TARGET_AARCH64
262
-/*
263
- * -cpu max: a CPU with as many features enabled as our emulation supports.
264
- * The version of '-cpu max' for qemu-system-aarch64 is defined in cpu64.c;
265
- * this only needs to handle 32 bits, and need not care about KVM.
266
- */
267
-static void arm_max_initfn(Object *obj)
268
-{
269
- ARMCPU *cpu = ARM_CPU(obj);
270
-
271
- cortex_a15_initfn(obj);
272
-
273
- /* old-style VFP short-vector support */
274
- cpu->isar.mvfr0 = FIELD_DP32(cpu->isar.mvfr0, MVFR0, FPSHVEC, 1);
275
-
276
-#ifdef CONFIG_USER_ONLY
277
- /*
278
- * We don't set these in system emulation mode for the moment,
279
- * since we don't correctly set (all of) the ID registers to
280
- * advertise them.
281
- */
282
- set_feature(&cpu->env, ARM_FEATURE_V8);
283
- {
284
- uint32_t t;
285
-
286
- t = cpu->isar.id_isar5;
287
- t = FIELD_DP32(t, ID_ISAR5, AES, 2);
288
- t = FIELD_DP32(t, ID_ISAR5, SHA1, 1);
289
- t = FIELD_DP32(t, ID_ISAR5, SHA2, 1);
290
- t = FIELD_DP32(t, ID_ISAR5, CRC32, 1);
291
- t = FIELD_DP32(t, ID_ISAR5, RDM, 1);
292
- t = FIELD_DP32(t, ID_ISAR5, VCMA, 1);
293
- cpu->isar.id_isar5 = t;
294
-
295
- t = cpu->isar.id_isar6;
296
- t = FIELD_DP32(t, ID_ISAR6, JSCVT, 1);
297
- t = FIELD_DP32(t, ID_ISAR6, DP, 1);
298
- t = FIELD_DP32(t, ID_ISAR6, FHM, 1);
299
- t = FIELD_DP32(t, ID_ISAR6, SB, 1);
300
- t = FIELD_DP32(t, ID_ISAR6, SPECRES, 1);
301
- cpu->isar.id_isar6 = t;
302
-
303
- t = cpu->isar.mvfr1;
304
- t = FIELD_DP32(t, MVFR1, FPHP, 3); /* v8.2-FP16 */
305
- t = FIELD_DP32(t, MVFR1, SIMDHP, 2); /* v8.2-FP16 */
306
- cpu->isar.mvfr1 = t;
307
-
308
- t = cpu->isar.mvfr2;
309
- t = FIELD_DP32(t, MVFR2, SIMDMISC, 3); /* SIMD MaxNum */
310
- t = FIELD_DP32(t, MVFR2, FPMISC, 4); /* FP MaxNum */
311
- cpu->isar.mvfr2 = t;
312
-
313
- t = cpu->isar.id_mmfr3;
314
- t = FIELD_DP32(t, ID_MMFR3, PAN, 2); /* ATS1E1 */
315
- cpu->isar.id_mmfr3 = t;
316
-
317
- t = cpu->isar.id_mmfr4;
318
- t = FIELD_DP32(t, ID_MMFR4, HPDS, 1); /* AA32HPD */
319
- t = FIELD_DP32(t, ID_MMFR4, AC2, 1); /* ACTLR2, HACTLR2 */
320
- t = FIELD_DP32(t, ID_MMFR4, CNP, 1); /* TTCNP */
321
- t = FIELD_DP32(t, ID_MMFR4, XNX, 1); /* TTS2UXN */
322
- cpu->isar.id_mmfr4 = t;
323
-
324
- t = cpu->isar.id_pfr0;
325
- t = FIELD_DP32(t, ID_PFR0, DIT, 1);
326
- cpu->isar.id_pfr0 = t;
327
-
328
- t = cpu->isar.id_pfr2;
329
- t = FIELD_DP32(t, ID_PFR2, SSBS, 1);
330
- cpu->isar.id_pfr2 = t;
331
- }
332
-#endif
333
-}
334
-#endif
335
-
336
-#endif /* !defined(CONFIG_USER_ONLY) || !defined(TARGET_AARCH64) */
337
-
338
-static const ARMCPUInfo arm_cpus[] = {
339
-#if !defined(CONFIG_USER_ONLY) || !defined(TARGET_AARCH64)
340
- { .name = "cortex-a7", .initfn = cortex_a7_initfn },
341
- { .name = "cortex-a8", .initfn = cortex_a8_initfn },
342
- { .name = "cortex-a9", .initfn = cortex_a9_initfn },
343
- { .name = "cortex-a15", .initfn = cortex_a15_initfn },
344
-#ifndef TARGET_AARCH64
345
- { .name = "max", .initfn = arm_max_initfn },
346
-#endif
347
-#ifdef CONFIG_USER_ONLY
348
- { .name = "any", .initfn = arm_max_initfn },
349
-#endif
350
-#endif
351
-};
352
-
353
static Property arm_cpu_properties[] = {
354
DEFINE_PROP_UINT32("psci-conduit", ARMCPU, psci_conduit, 0),
355
DEFINE_PROP_UINT64("midr", ARMCPU, midr, 0),
356
@@ -XXX,XX +XXX,XX @@ static const TypeInfo arm_cpu_type_info = {
357
358
static void arm_cpu_register_types(void)
359
{
360
- const size_t cpu_count = ARRAY_SIZE(arm_cpus);
361
-
362
type_register_static(&arm_cpu_type_info);
363
364
#ifdef CONFIG_KVM
365
type_register_static(&host_arm_cpu_type_info);
366
#endif
367
-
368
- if (cpu_count) {
369
- size_t i;
370
-
371
- for (i = 0; i < cpu_count; ++i) {
372
- arm_cpu_register(&arm_cpus[i]);
373
- }
374
- }
375
}
376
377
type_init(arm_cpu_register_types)
378
diff --git a/target/arm/cpu_tcg.c b/target/arm/cpu_tcg.c
379
index XXXXXXX..XXXXXXX 100644
380
--- a/target/arm/cpu_tcg.c
381
+++ b/target/arm/cpu_tcg.c
382
@@ -XXX,XX +XXX,XX @@
383
#endif /* CONFIG_TCG */
384
#include "internals.h"
385
#include "target/arm/idau.h"
386
+#if !defined(CONFIG_USER_ONLY)
387
+#include "hw/boards.h"
388
+#endif
389
390
/* CPU models. These are not needed for the AArch64 linux-user build. */
391
#if !defined(CONFIG_USER_ONLY) || !defined(TARGET_AARCH64)
392
@@ -XXX,XX +XXX,XX @@ static void arm11mpcore_initfn(Object *obj)
393
cpu->reset_auxcr = 1;
394
}
395
396
+static const ARMCPRegInfo cortexa8_cp_reginfo[] = {
397
+ { .name = "L2LOCKDOWN", .cp = 15, .crn = 9, .crm = 0, .opc1 = 1, .opc2 = 0,
398
+ .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
399
+ { .name = "L2AUXCR", .cp = 15, .crn = 9, .crm = 0, .opc1 = 1, .opc2 = 2,
400
+ .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
401
+ REGINFO_SENTINEL
402
+};
403
+
26
+
404
+static void cortex_a8_initfn(Object *obj)
27
+ if (sm) {
405
+{
28
+ exc_el = sme_exception_el(env, el);
406
+ ARMCPU *cpu = ARM_CPU(obj);
29
+ } else {
407
+
30
+ exc_el = sve_exception_el(env, el);
408
+ cpu->dtb_compatible = "arm,cortex-a8";
31
+ }
409
+ set_feature(&cpu->env, ARM_FEATURE_V7);
32
+ if (exc_el) {
410
+ set_feature(&cpu->env, ARM_FEATURE_NEON);
33
+ return 0; /* disabled */
411
+ set_feature(&cpu->env, ARM_FEATURE_THUMB2EE);
34
+ }
412
+ set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS);
35
+ return sve_vqm1_for_el_sm(env, el, sm);
413
+ set_feature(&cpu->env, ARM_FEATURE_EL3);
414
+ cpu->midr = 0x410fc080;
415
+ cpu->reset_fpsid = 0x410330c0;
416
+ cpu->isar.mvfr0 = 0x11110222;
417
+ cpu->isar.mvfr1 = 0x00011111;
418
+ cpu->ctr = 0x82048004;
419
+ cpu->reset_sctlr = 0x00c50078;
420
+ cpu->isar.id_pfr0 = 0x1031;
421
+ cpu->isar.id_pfr1 = 0x11;
422
+ cpu->isar.id_dfr0 = 0x400;
423
+ cpu->id_afr0 = 0;
424
+ cpu->isar.id_mmfr0 = 0x31100003;
425
+ cpu->isar.id_mmfr1 = 0x20000000;
426
+ cpu->isar.id_mmfr2 = 0x01202000;
427
+ cpu->isar.id_mmfr3 = 0x11;
428
+ cpu->isar.id_isar0 = 0x00101111;
429
+ cpu->isar.id_isar1 = 0x12112111;
430
+ cpu->isar.id_isar2 = 0x21232031;
431
+ cpu->isar.id_isar3 = 0x11112131;
432
+ cpu->isar.id_isar4 = 0x00111142;
433
+ cpu->isar.dbgdidr = 0x15141000;
434
+ cpu->clidr = (1 << 27) | (2 << 24) | 3;
435
+ cpu->ccsidr[0] = 0xe007e01a; /* 16k L1 dcache. */
436
+ cpu->ccsidr[1] = 0x2007e01a; /* 16k L1 icache. */
437
+ cpu->ccsidr[2] = 0xf0000000; /* No L2 icache. */
438
+ cpu->reset_auxcr = 2;
439
+ define_arm_cp_regs(cpu, cortexa8_cp_reginfo);
440
+}
36
+}
441
+
37
+
442
+static const ARMCPRegInfo cortexa9_cp_reginfo[] = {
38
/*
443
+ /*
39
* Notice a change in SVE vector size when changing EL.
444
+ * power_control should be set to maximum latency. Again,
40
*/
445
+ * default to 0 and set by private hook
41
@@ -XXX,XX +XXX,XX @@ void aarch64_sve_change_el(CPUARMState *env, int old_el,
446
+ */
447
+ { .name = "A9_PWRCTL", .cp = 15, .crn = 15, .crm = 0, .opc1 = 0, .opc2 = 0,
448
+ .access = PL1_RW, .resetvalue = 0,
449
+ .fieldoffset = offsetof(CPUARMState, cp15.c15_power_control) },
450
+ { .name = "A9_DIAG", .cp = 15, .crn = 15, .crm = 0, .opc1 = 0, .opc2 = 1,
451
+ .access = PL1_RW, .resetvalue = 0,
452
+ .fieldoffset = offsetof(CPUARMState, cp15.c15_diagnostic) },
453
+ { .name = "A9_PWRDIAG", .cp = 15, .crn = 15, .crm = 0, .opc1 = 0, .opc2 = 2,
454
+ .access = PL1_RW, .resetvalue = 0,
455
+ .fieldoffset = offsetof(CPUARMState, cp15.c15_power_diagnostic) },
456
+ { .name = "NEONBUSY", .cp = 15, .crn = 15, .crm = 1, .opc1 = 0, .opc2 = 0,
457
+ .access = PL1_RW, .resetvalue = 0, .type = ARM_CP_CONST },
458
+ /* TLB lockdown control */
459
+ { .name = "TLB_LOCKR", .cp = 15, .crn = 15, .crm = 4, .opc1 = 5, .opc2 = 2,
460
+ .access = PL1_W, .resetvalue = 0, .type = ARM_CP_NOP },
461
+ { .name = "TLB_LOCKW", .cp = 15, .crn = 15, .crm = 4, .opc1 = 5, .opc2 = 4,
462
+ .access = PL1_W, .resetvalue = 0, .type = ARM_CP_NOP },
463
+ { .name = "TLB_VA", .cp = 15, .crn = 15, .crm = 5, .opc1 = 5, .opc2 = 2,
464
+ .access = PL1_RW, .resetvalue = 0, .type = ARM_CP_CONST },
465
+ { .name = "TLB_PA", .cp = 15, .crn = 15, .crm = 6, .opc1 = 5, .opc2 = 2,
466
+ .access = PL1_RW, .resetvalue = 0, .type = ARM_CP_CONST },
467
+ { .name = "TLB_ATTR", .cp = 15, .crn = 15, .crm = 7, .opc1 = 5, .opc2 = 2,
468
+ .access = PL1_RW, .resetvalue = 0, .type = ARM_CP_CONST },
469
+ REGINFO_SENTINEL
470
+};
471
+
472
+static void cortex_a9_initfn(Object *obj)
473
+{
474
+ ARMCPU *cpu = ARM_CPU(obj);
475
+
476
+ cpu->dtb_compatible = "arm,cortex-a9";
477
+ set_feature(&cpu->env, ARM_FEATURE_V7);
478
+ set_feature(&cpu->env, ARM_FEATURE_NEON);
479
+ set_feature(&cpu->env, ARM_FEATURE_THUMB2EE);
480
+ set_feature(&cpu->env, ARM_FEATURE_EL3);
481
+ /*
482
+ * Note that A9 supports the MP extensions even for
483
+ * A9UP and single-core A9MP (which are both different
484
+ * and valid configurations; we don't model A9UP).
485
+ */
486
+ set_feature(&cpu->env, ARM_FEATURE_V7MP);
487
+ set_feature(&cpu->env, ARM_FEATURE_CBAR);
488
+ cpu->midr = 0x410fc090;
489
+ cpu->reset_fpsid = 0x41033090;
490
+ cpu->isar.mvfr0 = 0x11110222;
491
+ cpu->isar.mvfr1 = 0x01111111;
492
+ cpu->ctr = 0x80038003;
493
+ cpu->reset_sctlr = 0x00c50078;
494
+ cpu->isar.id_pfr0 = 0x1031;
495
+ cpu->isar.id_pfr1 = 0x11;
496
+ cpu->isar.id_dfr0 = 0x000;
497
+ cpu->id_afr0 = 0;
498
+ cpu->isar.id_mmfr0 = 0x00100103;
499
+ cpu->isar.id_mmfr1 = 0x20000000;
500
+ cpu->isar.id_mmfr2 = 0x01230000;
501
+ cpu->isar.id_mmfr3 = 0x00002111;
502
+ cpu->isar.id_isar0 = 0x00101111;
503
+ cpu->isar.id_isar1 = 0x13112111;
504
+ cpu->isar.id_isar2 = 0x21232041;
505
+ cpu->isar.id_isar3 = 0x11112131;
506
+ cpu->isar.id_isar4 = 0x00111142;
507
+ cpu->isar.dbgdidr = 0x35141000;
508
+ cpu->clidr = (1 << 27) | (1 << 24) | 3;
509
+ cpu->ccsidr[0] = 0xe00fe019; /* 16k L1 dcache. */
510
+ cpu->ccsidr[1] = 0x200fe019; /* 16k L1 icache. */
511
+ define_arm_cp_regs(cpu, cortexa9_cp_reginfo);
512
+}
513
+
514
+#ifndef CONFIG_USER_ONLY
515
+static uint64_t a15_l2ctlr_read(CPUARMState *env, const ARMCPRegInfo *ri)
516
+{
517
+ MachineState *ms = MACHINE(qdev_get_machine());
518
+
519
+ /*
520
+ * Linux wants the number of processors from here.
521
+ * Might as well set the interrupt-controller bit too.
522
+ */
523
+ return ((ms->smp.cpus - 1) << 24) | (1 << 23);
524
+}
525
+#endif
526
+
527
+static const ARMCPRegInfo cortexa15_cp_reginfo[] = {
528
+#ifndef CONFIG_USER_ONLY
529
+ { .name = "L2CTLR", .cp = 15, .crn = 9, .crm = 0, .opc1 = 1, .opc2 = 2,
530
+ .access = PL1_RW, .resetvalue = 0, .readfn = a15_l2ctlr_read,
531
+ .writefn = arm_cp_write_ignore, },
532
+#endif
533
+ { .name = "L2ECTLR", .cp = 15, .crn = 9, .crm = 0, .opc1 = 1, .opc2 = 3,
534
+ .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
535
+ REGINFO_SENTINEL
536
+};
537
+
538
+static void cortex_a7_initfn(Object *obj)
539
+{
540
+ ARMCPU *cpu = ARM_CPU(obj);
541
+
542
+ cpu->dtb_compatible = "arm,cortex-a7";
543
+ set_feature(&cpu->env, ARM_FEATURE_V7VE);
544
+ set_feature(&cpu->env, ARM_FEATURE_NEON);
545
+ set_feature(&cpu->env, ARM_FEATURE_THUMB2EE);
546
+ set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
547
+ set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS);
548
+ set_feature(&cpu->env, ARM_FEATURE_CBAR_RO);
549
+ set_feature(&cpu->env, ARM_FEATURE_EL2);
550
+ set_feature(&cpu->env, ARM_FEATURE_EL3);
551
+ set_feature(&cpu->env, ARM_FEATURE_PMU);
552
+ cpu->kvm_target = QEMU_KVM_ARM_TARGET_CORTEX_A7;
553
+ cpu->midr = 0x410fc075;
554
+ cpu->reset_fpsid = 0x41023075;
555
+ cpu->isar.mvfr0 = 0x10110222;
556
+ cpu->isar.mvfr1 = 0x11111111;
557
+ cpu->ctr = 0x84448003;
558
+ cpu->reset_sctlr = 0x00c50078;
559
+ cpu->isar.id_pfr0 = 0x00001131;
560
+ cpu->isar.id_pfr1 = 0x00011011;
561
+ cpu->isar.id_dfr0 = 0x02010555;
562
+ cpu->id_afr0 = 0x00000000;
563
+ cpu->isar.id_mmfr0 = 0x10101105;
564
+ cpu->isar.id_mmfr1 = 0x40000000;
565
+ cpu->isar.id_mmfr2 = 0x01240000;
566
+ cpu->isar.id_mmfr3 = 0x02102211;
567
+ /*
568
+ * a7_mpcore_r0p5_trm, page 4-4 gives 0x01101110; but
569
+ * table 4-41 gives 0x02101110, which includes the arm div insns.
570
+ */
571
+ cpu->isar.id_isar0 = 0x02101110;
572
+ cpu->isar.id_isar1 = 0x13112111;
573
+ cpu->isar.id_isar2 = 0x21232041;
574
+ cpu->isar.id_isar3 = 0x11112131;
575
+ cpu->isar.id_isar4 = 0x10011142;
576
+ cpu->isar.dbgdidr = 0x3515f005;
577
+ cpu->clidr = 0x0a200023;
578
+ cpu->ccsidr[0] = 0x701fe00a; /* 32K L1 dcache */
579
+ cpu->ccsidr[1] = 0x201fe00a; /* 32K L1 icache */
580
+ cpu->ccsidr[2] = 0x711fe07a; /* 4096K L2 unified cache */
581
+ define_arm_cp_regs(cpu, cortexa15_cp_reginfo); /* Same as A15 */
582
+}
583
+
584
+static void cortex_a15_initfn(Object *obj)
585
+{
586
+ ARMCPU *cpu = ARM_CPU(obj);
587
+
588
+ cpu->dtb_compatible = "arm,cortex-a15";
589
+ set_feature(&cpu->env, ARM_FEATURE_V7VE);
590
+ set_feature(&cpu->env, ARM_FEATURE_NEON);
591
+ set_feature(&cpu->env, ARM_FEATURE_THUMB2EE);
592
+ set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
593
+ set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS);
594
+ set_feature(&cpu->env, ARM_FEATURE_CBAR_RO);
595
+ set_feature(&cpu->env, ARM_FEATURE_EL2);
596
+ set_feature(&cpu->env, ARM_FEATURE_EL3);
597
+ set_feature(&cpu->env, ARM_FEATURE_PMU);
598
+ cpu->kvm_target = QEMU_KVM_ARM_TARGET_CORTEX_A15;
599
+ cpu->midr = 0x412fc0f1;
600
+ cpu->reset_fpsid = 0x410430f0;
601
+ cpu->isar.mvfr0 = 0x10110222;
602
+ cpu->isar.mvfr1 = 0x11111111;
603
+ cpu->ctr = 0x8444c004;
604
+ cpu->reset_sctlr = 0x00c50078;
605
+ cpu->isar.id_pfr0 = 0x00001131;
606
+ cpu->isar.id_pfr1 = 0x00011011;
607
+ cpu->isar.id_dfr0 = 0x02010555;
608
+ cpu->id_afr0 = 0x00000000;
609
+ cpu->isar.id_mmfr0 = 0x10201105;
610
+ cpu->isar.id_mmfr1 = 0x20000000;
611
+ cpu->isar.id_mmfr2 = 0x01240000;
612
+ cpu->isar.id_mmfr3 = 0x02102211;
613
+ cpu->isar.id_isar0 = 0x02101110;
614
+ cpu->isar.id_isar1 = 0x13112111;
615
+ cpu->isar.id_isar2 = 0x21232041;
616
+ cpu->isar.id_isar3 = 0x11112131;
617
+ cpu->isar.id_isar4 = 0x10011142;
618
+ cpu->isar.dbgdidr = 0x3515f021;
619
+ cpu->clidr = 0x0a200023;
620
+ cpu->ccsidr[0] = 0x701fe00a; /* 32K L1 dcache */
621
+ cpu->ccsidr[1] = 0x201fe00a; /* 32K L1 icache */
622
+ cpu->ccsidr[2] = 0x711fe07a; /* 4096K L2 unified cache */
623
+ define_arm_cp_regs(cpu, cortexa15_cp_reginfo);
624
+}
625
+
626
static void cortex_m0_initfn(Object *obj)
627
{
42
{
628
ARMCPU *cpu = ARM_CPU(obj);
43
ARMCPU *cpu = env_archcpu(env);
629
@@ -XXX,XX +XXX,XX @@ static void arm_v7m_class_init(ObjectClass *oc, void *data)
44
int old_len, new_len;
630
cc->gdb_core_xml_file = "arm-m-profile.xml";
45
- bool old_a64, new_a64;
631
}
46
+ bool old_a64, new_a64, sm;
632
47
633
+#ifndef TARGET_AARCH64
48
/* Nothing to do if no SVE. */
634
+/*
49
if (!cpu_isar_feature(aa64_sve, cpu)) {
635
+ * -cpu max: a CPU with as many features enabled as our emulation supports.
50
@@ -XXX,XX +XXX,XX @@ void aarch64_sve_change_el(CPUARMState *env, int old_el,
636
+ * The version of '-cpu max' for qemu-system-aarch64 is defined in cpu64.c;
51
* invoke ResetSVEState when taking an exception from, or
637
+ * this only needs to handle 32 bits, and need not care about KVM.
52
* returning to, AArch32 state when PSTATE.SM is enabled.
638
+ */
53
*/
639
+static void arm_max_initfn(Object *obj)
54
- if (old_a64 != new_a64 && FIELD_EX64(env->svcr, SVCR, SM)) {
640
+{
55
+ sm = FIELD_EX64(env->svcr, SVCR, SM);
641
+ ARMCPU *cpu = ARM_CPU(obj);
56
+ if (old_a64 != new_a64 && sm) {
642
+
57
arm_reset_sve_state(env);
643
+ cortex_a15_initfn(obj);
58
return;
644
+
59
}
645
+ /* old-style VFP short-vector support */
60
@@ -XXX,XX +XXX,XX @@ void aarch64_sve_change_el(CPUARMState *env, int old_el,
646
+ cpu->isar.mvfr0 = FIELD_DP32(cpu->isar.mvfr0, MVFR0, FPSHVEC, 1);
61
* we already have the correct register contents when encountering the
647
+
62
* vq0->vq0 transition between EL0->EL1.
648
+#ifdef CONFIG_USER_ONLY
63
*/
649
+ /*
64
- old_len = (old_a64 && !sve_exception_el(env, old_el)
650
+ * We don't set these in system emulation mode for the moment,
65
- ? sve_vqm1_for_el(env, old_el) : 0);
651
+ * since we don't correctly set (all of) the ID registers to
66
- new_len = (new_a64 && !sve_exception_el(env, new_el)
652
+ * advertise them.
67
- ? sve_vqm1_for_el(env, new_el) : 0);
653
+ */
68
+ old_len = new_len = 0;
654
+ set_feature(&cpu->env, ARM_FEATURE_V8);
69
+ if (old_a64) {
655
+ {
70
+ old_len = sve_vqm1_for_el_sm_ena(env, old_el, sm);
656
+ uint32_t t;
657
+
658
+ t = cpu->isar.id_isar5;
659
+ t = FIELD_DP32(t, ID_ISAR5, AES, 2);
660
+ t = FIELD_DP32(t, ID_ISAR5, SHA1, 1);
661
+ t = FIELD_DP32(t, ID_ISAR5, SHA2, 1);
662
+ t = FIELD_DP32(t, ID_ISAR5, CRC32, 1);
663
+ t = FIELD_DP32(t, ID_ISAR5, RDM, 1);
664
+ t = FIELD_DP32(t, ID_ISAR5, VCMA, 1);
665
+ cpu->isar.id_isar5 = t;
666
+
667
+ t = cpu->isar.id_isar6;
668
+ t = FIELD_DP32(t, ID_ISAR6, JSCVT, 1);
669
+ t = FIELD_DP32(t, ID_ISAR6, DP, 1);
670
+ t = FIELD_DP32(t, ID_ISAR6, FHM, 1);
671
+ t = FIELD_DP32(t, ID_ISAR6, SB, 1);
672
+ t = FIELD_DP32(t, ID_ISAR6, SPECRES, 1);
673
+ cpu->isar.id_isar6 = t;
674
+
675
+ t = cpu->isar.mvfr1;
676
+ t = FIELD_DP32(t, MVFR1, FPHP, 3); /* v8.2-FP16 */
677
+ t = FIELD_DP32(t, MVFR1, SIMDHP, 2); /* v8.2-FP16 */
678
+ cpu->isar.mvfr1 = t;
679
+
680
+ t = cpu->isar.mvfr2;
681
+ t = FIELD_DP32(t, MVFR2, SIMDMISC, 3); /* SIMD MaxNum */
682
+ t = FIELD_DP32(t, MVFR2, FPMISC, 4); /* FP MaxNum */
683
+ cpu->isar.mvfr2 = t;
684
+
685
+ t = cpu->isar.id_mmfr3;
686
+ t = FIELD_DP32(t, ID_MMFR3, PAN, 2); /* ATS1E1 */
687
+ cpu->isar.id_mmfr3 = t;
688
+
689
+ t = cpu->isar.id_mmfr4;
690
+ t = FIELD_DP32(t, ID_MMFR4, HPDS, 1); /* AA32HPD */
691
+ t = FIELD_DP32(t, ID_MMFR4, AC2, 1); /* ACTLR2, HACTLR2 */
692
+ t = FIELD_DP32(t, ID_MMFR4, CNP, 1); /* TTCNP */
693
+ t = FIELD_DP32(t, ID_MMFR4, XNX, 1); /* TTS2UXN */
694
+ cpu->isar.id_mmfr4 = t;
695
+
696
+ t = cpu->isar.id_pfr0;
697
+ t = FIELD_DP32(t, ID_PFR0, DIT, 1);
698
+ cpu->isar.id_pfr0 = t;
699
+
700
+ t = cpu->isar.id_pfr2;
701
+ t = FIELD_DP32(t, ID_PFR2, SSBS, 1);
702
+ cpu->isar.id_pfr2 = t;
703
+ }
71
+ }
704
+#endif /* CONFIG_USER_ONLY */
72
+ if (new_a64) {
705
+}
73
+ new_len = sve_vqm1_for_el_sm_ena(env, new_el, sm);
706
+#endif /* !TARGET_AARCH64 */
74
+ }
707
+
75
708
static const ARMCPUInfo arm_tcg_cpus[] = {
76
/* When changing vector length, clear inaccessible state. */
709
{ .name = "arm926", .initfn = arm926_initfn },
77
if (new_len < old_len) {
710
{ .name = "arm946", .initfn = arm946_initfn },
711
@@ -XXX,XX +XXX,XX @@ static const ARMCPUInfo arm_tcg_cpus[] = {
712
{ .name = "arm1136", .initfn = arm1136_initfn },
713
{ .name = "arm1176", .initfn = arm1176_initfn },
714
{ .name = "arm11mpcore", .initfn = arm11mpcore_initfn },
715
+ { .name = "cortex-a7", .initfn = cortex_a7_initfn },
716
+ { .name = "cortex-a8", .initfn = cortex_a8_initfn },
717
+ { .name = "cortex-a9", .initfn = cortex_a9_initfn },
718
+ { .name = "cortex-a15", .initfn = cortex_a15_initfn },
719
{ .name = "cortex-m0", .initfn = cortex_m0_initfn,
720
.class_init = arm_v7m_class_init },
721
{ .name = "cortex-m3", .initfn = cortex_m3_initfn,
722
@@ -XXX,XX +XXX,XX @@ static const ARMCPUInfo arm_tcg_cpus[] = {
723
{ .name = "pxa270-b1", .initfn = pxa270b1_initfn },
724
{ .name = "pxa270-c0", .initfn = pxa270c0_initfn },
725
{ .name = "pxa270-c5", .initfn = pxa270c5_initfn },
726
+#ifndef TARGET_AARCH64
727
+ { .name = "max", .initfn = arm_max_initfn },
728
+#endif
729
+#ifdef CONFIG_USER_ONLY
730
+ { .name = "any", .initfn = arm_max_initfn },
731
+#endif
732
};
733
734
static const TypeInfo idau_interface_type_info = {
735
--
78
--
736
2.20.1
79
2.25.1
737
738
diff view generated by jsdifflib
1
The SSE-300 is mostly the same as the SSE-200, but it has moved some
1
From: Richard Henderson <richard.henderson@linaro.org>
2
of the devices in the memory map and uses different device types in
3
some cases. To accommodate this, add a framework where the placement
4
and wiring of some devices can be specified in a data table.
5
2
6
This commit adds the framework for this data-driven device placement,
3
The documentation for PROT_MTE says that it cannot be cleared
7
and makes the CMSDK APB timer devices use it. Subsequent commits
4
by mprotect. Further, the implementation of the VM_ARCH_CLEAR bit,
8
will convert the other devices which differ between SSE-200 and
5
contains PROT_BTI confiming that bit should be cleared.
9
SSE-300.
10
6
7
Introduce PAGE_TARGET_STICKY to allow target/arch/cpu.h to control
8
which bits may be reset during page_set_flags. This is sort of the
9
opposite of VM_ARCH_CLEAR, but works better with qemu's PAGE_* bits
10
that are separate from PROT_* bits.
11
12
Reported-by: Vitaly Buka <vitalybuka@google.com>
13
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
14
Message-id: 20220711031420.17820-1-richard.henderson@linaro.org
15
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
13
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
14
Message-id: 20210219144617.4782-24-peter.maydell@linaro.org
15
---
17
---
16
include/hw/arm/armsse.h | 3 +-
18
target/arm/cpu.h | 7 +++++--
17
hw/arm/armsse.c | 147 +++++++++++++++++++++++++++++++++-------
19
accel/tcg/translate-all.c | 13 +++++++++++--
18
2 files changed, 125 insertions(+), 25 deletions(-)
20
2 files changed, 16 insertions(+), 4 deletions(-)
19
21
20
diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
22
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
21
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
22
--- a/include/hw/arm/armsse.h
24
--- a/target/arm/cpu.h
23
+++ b/include/hw/arm/armsse.h
25
+++ b/target/arm/cpu.h
24
@@ -XXX,XX +XXX,XX @@ struct ARMSSE {
26
@@ -XXX,XX +XXX,XX @@ static inline MemTxAttrs *typecheck_memtxattrs(MemTxAttrs *x)
25
IoTKitSecCtl secctl;
27
26
TZPPC apb_ppc[NUM_INTERNAL_PPCS];
28
/*
27
TZMPC mpc[IOTS_NUM_MPC];
29
* AArch64 usage of the PAGE_TARGET_* bits for linux-user.
28
- CMSDKAPBTimer timer0;
30
+ * Note that with the Linux kernel, PROT_MTE may not be cleared by mprotect
29
- CMSDKAPBTimer timer1;
31
+ * mprotect but PROT_BTI may be cleared. C.f. the kernel's VM_ARCH_CLEAR.
30
+ CMSDKAPBTimer timer[2];
32
*/
31
CMSDKAPBTimer s32ktimer;
33
-#define PAGE_BTI PAGE_TARGET_1
32
qemu_or_irq ppc_irq_orgate;
34
-#define PAGE_MTE PAGE_TARGET_2
33
SplitIRQ sec_resp_splitter;
35
+#define PAGE_BTI PAGE_TARGET_1
34
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
36
+#define PAGE_MTE PAGE_TARGET_2
37
+#define PAGE_TARGET_STICKY PAGE_MTE
38
39
#ifdef TARGET_TAGGED_ADDRESSES
40
/**
41
diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
35
index XXXXXXX..XXXXXXX 100644
42
index XXXXXXX..XXXXXXX 100644
36
--- a/hw/arm/armsse.c
43
--- a/accel/tcg/translate-all.c
37
+++ b/hw/arm/armsse.c
44
+++ b/accel/tcg/translate-all.c
38
@@ -XXX,XX +XXX,XX @@
45
@@ -XXX,XX +XXX,XX @@ int page_get_flags(target_ulong address)
39
#include "hw/irq.h"
46
return p->flags;
40
#include "hw/qdev-clock.h"
47
}
41
48
42
+/*
49
+/*
43
+ * The SSE-300 puts some devices in different places to the
50
+ * Allow the target to decide if PAGE_TARGET_[12] may be reset.
44
+ * SSE-200 (and original IoTKit). We use an array of these structs
51
+ * By default, they are not kept.
45
+ * to define how each variant lays out these devices. (Parts of the
46
+ * SoC that are the same for all variants aren't handled via these
47
+ * data structures.)
48
+ */
52
+ */
53
+#ifndef PAGE_TARGET_STICKY
54
+#define PAGE_TARGET_STICKY 0
55
+#endif
56
+#define PAGE_STICKY (PAGE_ANON | PAGE_TARGET_STICKY)
49
+
57
+
50
+#define NO_IRQ -1
58
/* Modify the flags of a page and invalidate the code if necessary.
51
+#define NO_PPC -1
59
The flag PAGE_WRITE_ORG is positioned automatically depending
52
+
60
on PAGE_WRITE. The mmap_lock should already be held. */
53
+typedef struct ARMSSEDeviceInfo {
61
@@ -XXX,XX +XXX,XX @@ void page_set_flags(target_ulong start, target_ulong end, int flags)
54
+ const char *name; /* name to use for the QOM object; NULL terminates list */
62
p->target_data = NULL;
55
+ const char *type; /* QOM type name */
63
p->flags = flags;
56
+ unsigned int index; /* Which of the N devices of this type is this ? */
64
} else {
57
+ hwaddr addr;
65
- /* Using mprotect on a page does not change MAP_ANON. */
58
+ int ppc; /* Index of APB PPC this device is wired up to, or NO_PPC */
66
- p->flags = (p->flags & PAGE_ANON) | flags;
59
+ int ppc_port; /* Port number of this device on the PPC */
67
+ /* Using mprotect on a page does not change sticky bits. */
60
+ int irq; /* NO_IRQ, or 0..NUM_SSE_IRQS-1 */
68
+ p->flags = (p->flags & PAGE_STICKY) | flags;
61
+} ARMSSEDeviceInfo;
62
+
63
struct ARMSSEInfo {
64
const char *name;
65
uint32_t sse_version;
66
@@ -XXX,XX +XXX,XX @@ struct ARMSSEInfo {
67
bool has_cpusecctrl;
68
bool has_cpuid;
69
Property *props;
70
+ const ARMSSEDeviceInfo *devinfo;
71
};
72
73
static Property iotkit_properties[] = {
74
@@ -XXX,XX +XXX,XX @@ static Property armsse_properties[] = {
75
DEFINE_PROP_END_OF_LIST()
76
};
77
78
+static const ARMSSEDeviceInfo sse200_devices[] = {
79
+ {
80
+ .name = "timer0",
81
+ .type = TYPE_CMSDK_APB_TIMER,
82
+ .index = 0,
83
+ .addr = 0x40000000,
84
+ .ppc = 0,
85
+ .ppc_port = 0,
86
+ .irq = 3,
87
+ },
88
+ {
89
+ .name = "timer1",
90
+ .type = TYPE_CMSDK_APB_TIMER,
91
+ .index = 1,
92
+ .addr = 0x40001000,
93
+ .ppc = 0,
94
+ .ppc_port = 1,
95
+ .irq = 4,
96
+ },
97
+ {
98
+ .name = NULL,
99
+ }
100
+};
101
+
102
static const ARMSSEInfo armsse_variants[] = {
103
{
104
.name = TYPE_IOTKIT,
105
@@ -XXX,XX +XXX,XX @@ static const ARMSSEInfo armsse_variants[] = {
106
.has_cpusecctrl = false,
107
.has_cpuid = false,
108
.props = iotkit_properties,
109
+ .devinfo = sse200_devices,
110
},
111
{
112
.name = TYPE_SSE200,
113
@@ -XXX,XX +XXX,XX @@ static const ARMSSEInfo armsse_variants[] = {
114
.has_cpusecctrl = true,
115
.has_cpuid = true,
116
.props = armsse_properties,
117
+ .devinfo = sse200_devices,
118
},
119
};
120
121
@@ -XXX,XX +XXX,XX @@ static void armsse_init(Object *obj)
122
ARMSSE *s = ARM_SSE(obj);
123
ARMSSEClass *asc = ARM_SSE_GET_CLASS(obj);
124
const ARMSSEInfo *info = asc->info;
125
+ const ARMSSEDeviceInfo *devinfo;
126
int i;
127
128
assert(info->sram_banks <= MAX_SRAM_BANKS);
129
@@ -XXX,XX +XXX,XX @@ static void armsse_init(Object *obj)
130
}
69
}
131
}
70
}
132
71
}
133
+ for (devinfo = info->devinfo; devinfo->name; devinfo++) {
134
+ assert(devinfo->ppc == NO_PPC || devinfo->ppc < ARRAY_SIZE(s->apb_ppc));
135
+ if (!strcmp(devinfo->type, TYPE_CMSDK_APB_TIMER)) {
136
+ assert(devinfo->index < ARRAY_SIZE(s->timer));
137
+ object_initialize_child(obj, devinfo->name,
138
+ &s->timer[devinfo->index],
139
+ TYPE_CMSDK_APB_TIMER);
140
+ } else {
141
+ g_assert_not_reached();
142
+ }
143
+ }
144
+
145
object_initialize_child(obj, "secctl", &s->secctl, TYPE_IOTKIT_SECCTL);
146
147
for (i = 0; i < ARRAY_SIZE(s->apb_ppc); i++) {
148
@@ -XXX,XX +XXX,XX @@ static void armsse_init(Object *obj)
149
object_initialize_child(obj, name, splitter, TYPE_SPLIT_IRQ);
150
g_free(name);
151
}
152
- object_initialize_child(obj, "timer0", &s->timer0, TYPE_CMSDK_APB_TIMER);
153
- object_initialize_child(obj, "timer1", &s->timer1, TYPE_CMSDK_APB_TIMER);
154
object_initialize_child(obj, "s32ktimer", &s->s32ktimer,
155
TYPE_CMSDK_APB_TIMER);
156
object_initialize_child(obj, "dualtimer", &s->dualtimer,
157
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
158
ARMSSE *s = ARM_SSE(dev);
159
ARMSSEClass *asc = ARM_SSE_GET_CLASS(dev);
160
const ARMSSEInfo *info = asc->info;
161
+ const ARMSSEDeviceInfo *devinfo;
162
int i;
163
MemoryRegion *mr;
164
Error *err = NULL;
165
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
166
* it to the appropriate PPC port; then we can realize the PPC and
167
* map its upstream ends to the right place in the container.
168
*/
169
- qdev_connect_clock_in(DEVICE(&s->timer0), "pclk", s->mainclk);
170
- if (!sysbus_realize(SYS_BUS_DEVICE(&s->timer0), errp)) {
171
- return;
172
- }
173
- sysbus_connect_irq(SYS_BUS_DEVICE(&s->timer0), 0,
174
- armsse_get_common_irq_in(s, 3));
175
- mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->timer0), 0);
176
- object_property_set_link(OBJECT(&s->apb_ppc[0]), "port[0]", OBJECT(mr),
177
- &error_abort);
178
+ for (devinfo = info->devinfo; devinfo->name; devinfo++) {
179
+ SysBusDevice *sbd;
180
+ qemu_irq irq;
181
182
- qdev_connect_clock_in(DEVICE(&s->timer1), "pclk", s->mainclk);
183
- if (!sysbus_realize(SYS_BUS_DEVICE(&s->timer1), errp)) {
184
- return;
185
+ if (!strcmp(devinfo->type, TYPE_CMSDK_APB_TIMER)) {
186
+ sbd = SYS_BUS_DEVICE(&s->timer[devinfo->index]);
187
+
188
+ qdev_connect_clock_in(DEVICE(sbd), "pclk", s->mainclk);
189
+ if (!sysbus_realize(sbd, errp)) {
190
+ return;
191
+ }
192
+ mr = sysbus_mmio_get_region(sbd, 0);
193
+ } else {
194
+ g_assert_not_reached();
195
+ }
196
+
197
+ switch (devinfo->irq) {
198
+ case NO_IRQ:
199
+ irq = NULL;
200
+ break;
201
+ case 0 ... NUM_SSE_IRQS - 1:
202
+ irq = armsse_get_common_irq_in(s, devinfo->irq);
203
+ break;
204
+ default:
205
+ g_assert_not_reached();
206
+ }
207
+
208
+ if (irq) {
209
+ sysbus_connect_irq(sbd, 0, irq);
210
+ }
211
+
212
+ /*
213
+ * Devices connected to a PPC are connected to the port here;
214
+ * we will map the upstream end of that port to the right address
215
+ * in the container later after the PPC has been realized.
216
+ * Devices not connected to a PPC can be mapped immediately.
217
+ */
218
+ if (devinfo->ppc != NO_PPC) {
219
+ TZPPC *ppc = &s->apb_ppc[devinfo->ppc];
220
+ g_autofree char *portname = g_strdup_printf("port[%d]",
221
+ devinfo->ppc_port);
222
+ object_property_set_link(OBJECT(ppc), portname, OBJECT(mr),
223
+ &error_abort);
224
+ } else {
225
+ memory_region_add_subregion(&s->container, devinfo->addr, mr);
226
+ }
227
}
228
- sysbus_connect_irq(SYS_BUS_DEVICE(&s->timer1), 0,
229
- armsse_get_common_irq_in(s, 4));
230
- mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->timer1), 0);
231
- object_property_set_link(OBJECT(&s->apb_ppc[0]), "port[1]", OBJECT(mr),
232
- &error_abort);
233
234
qdev_connect_clock_in(DEVICE(&s->dualtimer), "TIMCLK", s->mainclk);
235
if (!sysbus_realize(SYS_BUS_DEVICE(&s->dualtimer), errp)) {
236
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
237
sbd_apb_ppc0 = SYS_BUS_DEVICE(&s->apb_ppc[0]);
238
dev_apb_ppc0 = DEVICE(&s->apb_ppc[0]);
239
240
- mr = sysbus_mmio_get_region(sbd_apb_ppc0, 0);
241
- memory_region_add_subregion(&s->container, 0x40000000, mr);
242
- mr = sysbus_mmio_get_region(sbd_apb_ppc0, 1);
243
- memory_region_add_subregion(&s->container, 0x40001000, mr);
244
mr = sysbus_mmio_get_region(sbd_apb_ppc0, 2);
245
memory_region_add_subregion(&s->container, 0x40002000, mr);
246
if (info->has_mhus) {
247
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
248
qdev_get_gpio_in_named(dev_apb_ppc1,
249
"cfg_sec_resp", 0));
250
251
+ /*
252
+ * Now both PPCs are realized we can map the upstream ends of
253
+ * ports which correspond to entries in the devinfo array.
254
+ * The ports which are connected to non-devinfo devices have
255
+ * already been mapped.
256
+ */
257
+ for (devinfo = info->devinfo; devinfo->name; devinfo++) {
258
+ SysBusDevice *ppc_sbd;
259
+
260
+ if (devinfo->ppc == NO_PPC) {
261
+ continue;
262
+ }
263
+ ppc_sbd = SYS_BUS_DEVICE(&s->apb_ppc[devinfo->ppc]);
264
+ mr = sysbus_mmio_get_region(ppc_sbd, devinfo->ppc_port);
265
+ memory_region_add_subregion(&s->container, devinfo->addr, mr);
266
+ }
267
+
268
if (!object_property_set_int(OBJECT(&s->sysinfo), "SYS_VERSION",
269
info->sys_version, errp)) {
270
return;
271
--
72
--
272
2.20.1
73
2.25.1
273
274
diff view generated by jsdifflib
1
Add a clock_ns_to_ticks() function which does the opposite of
1
The regime_tcr() function returns a pointer to a struct TCR
2
clock_ticks_to_ns(): given a duration in nanoseconds, it returns the
2
corresponding to the TCR controlling a translation regime. The
3
number of clock ticks that would happen in that time. This is useful
3
struct TCR has the raw value of the register, plus two fields mask
4
for devices that have a free running counter register whose value can
4
and base_mask which are used as a small optimization in the case of
5
be calculated when it is read.
5
32-bit short-descriptor lookups. Almost all callers of regime_tcr()
6
only want the raw register value. Define and use a new
7
regime_tcr_value() function which returns only the raw 64-bit
8
register value.
9
10
This is a preliminary to removing the 32-bit short descriptor
11
optimization -- it only saves a handful of bit operations, which is
12
tiny compared to the overhead of doing a page table walk at all, and
13
the TCR struct is awkward and makes fixing
14
https://gitlab.com/qemu-project/qemu/-/issues/1103 unnecessarily
15
difficult.
6
16
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Luc Michel <luc@lmichel.fr>
18
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Reviewed-by: Hao Wu <wuhaotsh@google.com>
19
Message-id: 20220714132303.1287193-2-peter.maydell@linaro.org
10
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
11
Message-id: 20210219144617.4782-4-peter.maydell@linaro.org
12
---
20
---
13
docs/devel/clocks.rst | 12 ++++++++++++
21
target/arm/internals.h | 6 ++++++
14
include/hw/clock.h | 41 +++++++++++++++++++++++++++++++++++++++++
22
target/arm/helper.c | 6 +++---
15
2 files changed, 53 insertions(+)
23
target/arm/ptw.c | 8 ++++----
24
target/arm/tlb_helper.c | 2 +-
25
4 files changed, 14 insertions(+), 8 deletions(-)
16
26
17
diff --git a/docs/devel/clocks.rst b/docs/devel/clocks.rst
27
diff --git a/target/arm/internals.h b/target/arm/internals.h
18
index XXXXXXX..XXXXXXX 100644
28
index XXXXXXX..XXXXXXX 100644
19
--- a/docs/devel/clocks.rst
29
--- a/target/arm/internals.h
20
+++ b/docs/devel/clocks.rst
30
+++ b/target/arm/internals.h
21
@@ -XXX,XX +XXX,XX @@ rather than simply passing it to a QEMUTimer function like
31
@@ -XXX,XX +XXX,XX @@ static inline TCR *regime_tcr(CPUARMState *env, ARMMMUIdx mmu_idx)
22
``timer_mod_ns()`` then you should be careful to avoid overflow
32
return &env->cp15.tcr_el[regime_el(env, mmu_idx)];
23
in those calculations, of course.)
24
25
+Obtaining tick counts
26
+---------------------
27
+
28
+For calculations where you need to know the number of ticks in
29
+a given duration, use ``clock_ns_to_ticks()``. This function handles
30
+possible non-whole-number-of-nanoseconds periods and avoids
31
+potential rounding errors. It will return '0' if the clock is stopped
32
+(i.e. it has period zero). If the inputs imply a tick count that
33
+overflows a 64-bit value (a very long duration for a clock with a
34
+very short period) the output value is truncated, so effectively
35
+the 64-bit output wraps around.
36
+
37
Changing a clock period
38
-----------------------
39
40
diff --git a/include/hw/clock.h b/include/hw/clock.h
41
index XXXXXXX..XXXXXXX 100644
42
--- a/include/hw/clock.h
43
+++ b/include/hw/clock.h
44
@@ -XXX,XX +XXX,XX @@ static inline uint64_t clock_ticks_to_ns(const Clock *clk, uint64_t ticks)
45
return ns_low >> 32 | ns_high << 32;
46
}
33
}
47
34
48
+/**
35
+/* Return the raw value of the TCR controlling this translation regime */
49
+ * clock_ns_to_ticks:
36
+static inline uint64_t regime_tcr_value(CPUARMState *env, ARMMMUIdx mmu_idx)
50
+ * @clk: the clock to query
51
+ * @ns: duration in nanoseconds
52
+ *
53
+ * Returns the number of ticks this clock would make in the given
54
+ * number of nanoseconds. Because a clock can have a period which
55
+ * is not a whole number of nanoseconds, it is important to use this
56
+ * function rather than attempting to obtain a "period in nanoseconds"
57
+ * value and then dividing the duration by that value.
58
+ *
59
+ * If the clock is stopped (ie it has period zero), returns 0.
60
+ *
61
+ * For some inputs the result could overflow a 64-bit value (because
62
+ * the clock's period is short and the duration is long). In these
63
+ * cases we truncate the result to a 64-bit value. This is on the
64
+ * assumption that generally the result is going to be used to report
65
+ * a 32-bit or 64-bit guest register value, so wrapping either cannot
66
+ * happen or is the desired behaviour.
67
+ */
68
+static inline uint64_t clock_ns_to_ticks(const Clock *clk, uint64_t ns)
69
+{
37
+{
70
+ /*
38
+ return regime_tcr(env, mmu_idx)->raw_tcr;
71
+ * ticks = duration_in_ns / period_in_ns
72
+ * = ns / (period / 2^32)
73
+ * = (ns * 2^32) / period
74
+ * The hi, lo inputs to divu128() are (ns << 32) as a 128 bit value.
75
+ */
76
+ uint64_t lo = ns << 32;
77
+ uint64_t hi = ns >> 32;
78
+ if (clk->period == 0) {
79
+ return 0;
80
+ }
81
+ /*
82
+ * Ignore divu128() return value as we've caught div-by-zero and don't
83
+ * need different behaviour for overflow.
84
+ */
85
+ divu128(&lo, &hi, clk->period);
86
+ return lo;
87
+}
39
+}
88
+
40
+
89
/**
41
/**
90
* clock_is_enabled:
42
* arm_num_brps: Return number of implemented breakpoints.
91
* @clk: a clock
43
* Note that the ID register BRPS field is "number of bps - 1",
44
diff --git a/target/arm/helper.c b/target/arm/helper.c
45
index XXXXXXX..XXXXXXX 100644
46
--- a/target/arm/helper.c
47
+++ b/target/arm/helper.c
48
@@ -XXX,XX +XXX,XX @@ static int vae1_tlbmask(CPUARMState *env)
49
static int tlbbits_for_regime(CPUARMState *env, ARMMMUIdx mmu_idx,
50
uint64_t addr)
51
{
52
- uint64_t tcr = regime_tcr(env, mmu_idx)->raw_tcr;
53
+ uint64_t tcr = regime_tcr_value(env, mmu_idx);
54
int tbi = aa64_va_parameter_tbi(tcr, mmu_idx);
55
int select = extract64(addr, 55, 1);
56
57
@@ -XXX,XX +XXX,XX @@ static int aa64_va_parameter_tcma(uint64_t tcr, ARMMMUIdx mmu_idx)
58
ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va,
59
ARMMMUIdx mmu_idx, bool data)
60
{
61
- uint64_t tcr = regime_tcr(env, mmu_idx)->raw_tcr;
62
+ uint64_t tcr = regime_tcr_value(env, mmu_idx);
63
bool epd, hpd, using16k, using64k, tsz_oob, ds;
64
int select, tsz, tbi, max_tsz, min_tsz, ps, sh;
65
ARMCPU *cpu = env_archcpu(env);
66
@@ -XXX,XX +XXX,XX @@ static CPUARMTBFlags rebuild_hflags_a64(CPUARMState *env, int el, int fp_el,
67
{
68
CPUARMTBFlags flags = {};
69
ARMMMUIdx stage1 = stage_1_mmu_idx(mmu_idx);
70
- uint64_t tcr = regime_tcr(env, mmu_idx)->raw_tcr;
71
+ uint64_t tcr = regime_tcr_value(env, mmu_idx);
72
uint64_t sctlr;
73
int tbii, tbid;
74
75
diff --git a/target/arm/ptw.c b/target/arm/ptw.c
76
index XXXXXXX..XXXXXXX 100644
77
--- a/target/arm/ptw.c
78
+++ b/target/arm/ptw.c
79
@@ -XXX,XX +XXX,XX @@ static int get_S1prot(CPUARMState *env, ARMMMUIdx mmu_idx, bool is_aa64,
80
static ARMVAParameters aa32_va_parameters(CPUARMState *env, uint32_t va,
81
ARMMMUIdx mmu_idx)
82
{
83
- uint64_t tcr = regime_tcr(env, mmu_idx)->raw_tcr;
84
+ uint64_t tcr = regime_tcr_value(env, mmu_idx);
85
uint32_t el = regime_el(env, mmu_idx);
86
int select, tsz;
87
bool epd, hpd;
88
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, uint64_t address,
89
uint32_t attrs;
90
int32_t stride;
91
int addrsize, inputsize, outputsize;
92
- TCR *tcr = regime_tcr(env, mmu_idx);
93
+ uint64_t tcr = regime_tcr_value(env, mmu_idx);
94
int ap, ns, xn, pxn;
95
uint32_t el = regime_el(env, mmu_idx);
96
uint64_t descaddrmask;
97
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, uint64_t address,
98
* For stage 2 translations the starting level is specified by the
99
* VTCR_EL2.SL0 field (whose interpretation depends on the page size)
100
*/
101
- uint32_t sl0 = extract32(tcr->raw_tcr, 6, 2);
102
- uint32_t sl2 = extract64(tcr->raw_tcr, 33, 1);
103
+ uint32_t sl0 = extract32(tcr, 6, 2);
104
+ uint32_t sl2 = extract64(tcr, 33, 1);
105
uint32_t startlevel;
106
bool ok;
107
108
diff --git a/target/arm/tlb_helper.c b/target/arm/tlb_helper.c
109
index XXXXXXX..XXXXXXX 100644
110
--- a/target/arm/tlb_helper.c
111
+++ b/target/arm/tlb_helper.c
112
@@ -XXX,XX +XXX,XX @@ bool regime_using_lpae_format(CPUARMState *env, ARMMMUIdx mmu_idx)
113
return true;
114
}
115
if (arm_feature(env, ARM_FEATURE_LPAE)
116
- && (regime_tcr(env, mmu_idx)->raw_tcr & TTBCR_EAE)) {
117
+ && (regime_tcr_value(env, mmu_idx) & TTBCR_EAE)) {
118
return true;
119
}
120
return false;
92
--
121
--
93
2.20.1
122
2.25.1
94
95
diff view generated by jsdifflib
1
The #defines INTERNAL and CASCADING represent different possible
1
In get_level1_table_address(), instead of using precalculated values
2
values for the TCCR.CSS register field; prefix them with CSS_ to make
2
of mask and base_mask from the TCR struct, calculate them directly
3
this more obvious, before we add more defines to represent the
3
(in the same way we currently do in vmsa_ttbcr_raw_write() to
4
other possible values of the field in the next commit.
4
populate the TCR struct fields).
5
5
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20210219223241.16344-2-peter.maydell@linaro.org
8
Message-id: 20220714132303.1287193-3-peter.maydell@linaro.org
9
---
9
---
10
hw/timer/renesas_tmr.c | 16 ++++++++--------
10
target/arm/ptw.c | 14 +++++++++-----
11
1 file changed, 8 insertions(+), 8 deletions(-)
11
1 file changed, 9 insertions(+), 5 deletions(-)
12
12
13
diff --git a/hw/timer/renesas_tmr.c b/hw/timer/renesas_tmr.c
13
diff --git a/target/arm/ptw.c b/target/arm/ptw.c
14
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/timer/renesas_tmr.c
15
--- a/target/arm/ptw.c
16
+++ b/hw/timer/renesas_tmr.c
16
+++ b/target/arm/ptw.c
17
@@ -XXX,XX +XXX,XX @@ REG8(TCCR, 10)
17
@@ -XXX,XX +XXX,XX @@ static bool get_level1_table_address(CPUARMState *env, ARMMMUIdx mmu_idx,
18
FIELD(TCCR, CSS, 3, 2)
18
uint32_t *table, uint32_t address)
19
FIELD(TCCR, TMRIS, 7, 1)
19
{
20
20
/* Note that we can only get here for an AArch32 PL0/PL1 lookup */
21
-#define INTERNAL 0x01
21
- TCR *tcr = regime_tcr(env, mmu_idx);
22
-#define CASCADING 0x03
22
+ uint64_t tcr = regime_tcr_value(env, mmu_idx);
23
+#define CSS_INTERNAL 0x01
23
+ int maskshift = extract32(tcr, 0, 3);
24
+#define CSS_CASCADING 0x03
24
+ uint32_t mask = ~(((uint32_t)0xffffffffu) >> maskshift);
25
#define CCLR_A 0x01
25
+ uint32_t base_mask;
26
#define CCLR_B 0x02
26
27
27
- if (address & tcr->mask) {
28
@@ -XXX,XX +XXX,XX @@ static void update_events(RTMRState *tmr, int ch)
28
- if (tcr->raw_tcr & TTBCR_PD1) {
29
/* event not happened */
29
+ if (address & mask) {
30
return ;
30
+ if (tcr & TTBCR_PD1) {
31
/* Translation table walk disabled for TTBR1 */
32
return false;
33
}
34
*table = regime_ttbr(env, mmu_idx, 1) & 0xffffc000;
35
} else {
36
- if (tcr->raw_tcr & TTBCR_PD0) {
37
+ if (tcr & TTBCR_PD0) {
38
/* Translation table walk disabled for TTBR0 */
39
return false;
40
}
41
- *table = regime_ttbr(env, mmu_idx, 0) & tcr->base_mask;
42
+ base_mask = ~((uint32_t)0x3fffu >> maskshift);
43
+ *table = regime_ttbr(env, mmu_idx, 0) & base_mask;
31
}
44
}
32
- if (FIELD_EX8(tmr->tccr[0], TCCR, CSS) == CASCADING) {
45
*table |= (address >> 18) & 0x3ffc;
33
+ if (FIELD_EX8(tmr->tccr[0], TCCR, CSS) == CSS_CASCADING) {
46
return true;
34
/* cascading mode */
35
if (ch == 1) {
36
tmr->next[ch] = none;
37
@@ -XXX,XX +XXX,XX @@ static uint16_t read_tcnt(RTMRState *tmr, unsigned size, int ch)
38
if (delta > 0) {
39
tmr->tick = now;
40
41
- if (FIELD_EX8(tmr->tccr[1], TCCR, CSS) == INTERNAL) {
42
+ if (FIELD_EX8(tmr->tccr[1], TCCR, CSS) == CSS_INTERNAL) {
43
/* timer1 count update */
44
elapsed = elapsed_time(tmr, 1, delta);
45
if (elapsed >= 0x100) {
46
@@ -XXX,XX +XXX,XX @@ static uint16_t read_tcnt(RTMRState *tmr, unsigned size, int ch)
47
tcnt[1] = tmr->tcnt[1] + (elapsed & 0xff);
48
}
49
switch (FIELD_EX8(tmr->tccr[0], TCCR, CSS)) {
50
- case INTERNAL:
51
+ case CSS_INTERNAL:
52
elapsed = elapsed_time(tmr, 0, delta);
53
tcnt[0] = tmr->tcnt[0] + elapsed;
54
break;
55
- case CASCADING:
56
+ case CSS_CASCADING:
57
if (ovf > 0) {
58
tcnt[0] = tmr->tcnt[0] + ovf;
59
}
60
@@ -XXX,XX +XXX,XX @@ static uint16_t issue_event(RTMRState *tmr, int ch, int sz,
61
qemu_irq_pulse(tmr->cmia[ch]);
62
}
63
if (sz == 8 && ch == 0 &&
64
- FIELD_EX8(tmr->tccr[1], TCCR, CSS) == CASCADING) {
65
+ FIELD_EX8(tmr->tccr[1], TCCR, CSS) == CSS_CASCADING) {
66
tmr->tcnt[1]++;
67
timer_events(tmr, 1);
68
}
69
@@ -XXX,XX +XXX,XX @@ static void timer_events(RTMRState *tmr, int ch)
70
uint16_t tcnt;
71
72
tmr->tcnt[ch] = read_tcnt(tmr, 1, ch);
73
- if (FIELD_EX8(tmr->tccr[0], TCCR, CSS) != CASCADING) {
74
+ if (FIELD_EX8(tmr->tccr[0], TCCR, CSS) != CSS_CASCADING) {
75
tmr->tcnt[ch] = issue_event(tmr, ch, 8,
76
tmr->tcnt[ch],
77
tmr->tcora[ch],
78
--
47
--
79
2.20.1
48
2.25.1
80
81
diff view generated by jsdifflib
1
From: Xuzhou Cheng <xuzhou.cheng@windriver.com>
1
The only caller of regime_tcr() is now regime_tcr_value(); fold the
2
two together, and use the shorter and more natural 'regime_tcr'
3
name for the new function.
2
4
3
There are some coding convention warnings in xilinx_spips.c,
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
as reported by:
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20220714132303.1287193-4-peter.maydell@linaro.org
8
---
9
target/arm/internals.h | 16 +++++-----------
10
target/arm/helper.c | 6 +++---
11
target/arm/ptw.c | 6 +++---
12
target/arm/tlb_helper.c | 2 +-
13
4 files changed, 12 insertions(+), 18 deletions(-)
5
14
6
$ ./scripts/checkpatch.pl hw/ssi/xilinx_spips.c
15
diff --git a/target/arm/internals.h b/target/arm/internals.h
7
8
Let's clean them up.
9
10
Signed-off-by: Xuzhou Cheng <xuzhou.cheng@windriver.com>
11
Signed-off-by: Bin Meng <bin.meng@windriver.com>
12
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
13
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
15
Message-id: 20210303135254.3970-5-bmeng.cn@gmail.com
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
---
18
hw/ssi/xilinx_spips.c | 23 ++++++++++++++---------
19
1 file changed, 14 insertions(+), 9 deletions(-)
20
21
diff --git a/hw/ssi/xilinx_spips.c b/hw/ssi/xilinx_spips.c
22
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
23
--- a/hw/ssi/xilinx_spips.c
17
--- a/target/arm/internals.h
24
+++ b/hw/ssi/xilinx_spips.c
18
+++ b/target/arm/internals.h
25
@@ -XXX,XX +XXX,XX @@
19
@@ -XXX,XX +XXX,XX @@ static inline uint64_t regime_sctlr(CPUARMState *env, ARMMMUIdx mmu_idx)
26
FIELD(GQSPI_FIFO_CTRL, GENERIC_FIFO_RESET, 0, 1)
20
return env->cp15.sctlr_el[regime_el(env, mmu_idx)];
27
#define R_GQSPI_GFIFO_THRESH (0x150 / 4)
28
#define R_GQSPI_DATA_STS (0x15c / 4)
29
-/* We use the snapshot register to hold the core state for the currently
30
+/*
31
+ * We use the snapshot register to hold the core state for the currently
32
* or most recently executed command. So the generic fifo format is defined
33
* for the snapshot register
34
*/
35
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_qspips_reset(DeviceState *d)
36
xlnx_zynqmp_qspips_update_ixr(s);
37
}
21
}
38
22
39
-/* N way (num) in place bit striper. Lay out row wise bits (MSB to LSB)
23
-/* Return the TCR controlling this translation regime */
40
+/*
24
-static inline TCR *regime_tcr(CPUARMState *env, ARMMMUIdx mmu_idx)
41
+ * N way (num) in place bit striper. Lay out row wise bits (MSB to LSB)
25
+/* Return the value of the TCR controlling this translation regime */
42
* column wise (from element 0 to N-1). num is the length of x, and dir
26
+static inline uint64_t regime_tcr(CPUARMState *env, ARMMMUIdx mmu_idx)
43
* reverses the direction of the transform. Best illustrated by example:
27
{
44
* Each digit in the below array is a single bit (num == 3):
28
if (mmu_idx == ARMMMUIdx_Stage2) {
45
@@ -XXX,XX +XXX,XX @@ static void xilinx_spips_flush_txfifo(XilinxSPIPS *s)
29
- return &env->cp15.vtcr_el2;
46
tx_rx[i] = tx;
30
+ return env->cp15.vtcr_el2.raw_tcr;
47
}
31
}
48
} else {
32
if (mmu_idx == ARMMMUIdx_Stage2_S) {
49
- /* Extract a dummy byte and generate dummy cycles according to the
33
/*
50
- * link state */
34
* Note: Secure stage 2 nominally shares fields from VTCR_EL2, but
51
+ /*
35
* those are not currently used by QEMU, so just return VSTCR_EL2.
52
+ * Extract a dummy byte and generate dummy cycles according to the
36
*/
53
+ * link state
37
- return &env->cp15.vstcr_el2;
54
+ */
38
+ return env->cp15.vstcr_el2.raw_tcr;
55
tx = fifo8_pop(&s->tx_fifo);
39
}
56
dummy_cycles = 8 / s->link_state;
40
- return &env->cp15.tcr_el[regime_el(env, mmu_idx)];
57
}
41
-}
58
@@ -XXX,XX +XXX,XX @@ static void xilinx_spips_flush_txfifo(XilinxSPIPS *s)
42
-
59
}
43
-/* Return the raw value of the TCR controlling this translation regime */
60
break;
44
-static inline uint64_t regime_tcr_value(CPUARMState *env, ARMMMUIdx mmu_idx)
61
case (SNOOP_ADDR):
45
-{
62
- /* Address has been transmitted, transmit dummy cycles now if
46
- return regime_tcr(env, mmu_idx)->raw_tcr;
63
- * needed */
47
+ return env->cp15.tcr_el[regime_el(env, mmu_idx)].raw_tcr;
64
+ /*
65
+ * Address has been transmitted, transmit dummy cycles now if needed
66
+ */
67
if (s->cmd_dummies < 0) {
68
s->snoop_state = SNOOP_NONE;
69
} else {
70
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_qspips_notify(void *opaque)
71
}
48
}
72
49
73
static uint64_t xilinx_spips_read(void *opaque, hwaddr addr,
50
/**
74
- unsigned size)
51
diff --git a/target/arm/helper.c b/target/arm/helper.c
75
+ unsigned size)
52
index XXXXXXX..XXXXXXX 100644
53
--- a/target/arm/helper.c
54
+++ b/target/arm/helper.c
55
@@ -XXX,XX +XXX,XX @@ static int vae1_tlbmask(CPUARMState *env)
56
static int tlbbits_for_regime(CPUARMState *env, ARMMMUIdx mmu_idx,
57
uint64_t addr)
76
{
58
{
77
XilinxSPIPS *s = opaque;
59
- uint64_t tcr = regime_tcr_value(env, mmu_idx);
78
uint32_t mask = ~0;
60
+ uint64_t tcr = regime_tcr(env, mmu_idx);
79
@@ -XXX,XX +XXX,XX @@ static uint64_t xlnx_zynqmp_qspips_read(void *opaque,
61
int tbi = aa64_va_parameter_tbi(tcr, mmu_idx);
80
}
62
int select = extract64(addr, 55, 1);
81
63
82
static void xilinx_spips_write(void *opaque, hwaddr addr,
64
@@ -XXX,XX +XXX,XX @@ static int aa64_va_parameter_tcma(uint64_t tcr, ARMMMUIdx mmu_idx)
83
- uint64_t value, unsigned size)
65
ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va,
84
+ uint64_t value, unsigned size)
66
ARMMMUIdx mmu_idx, bool data)
85
{
67
{
86
int mask = ~0;
68
- uint64_t tcr = regime_tcr_value(env, mmu_idx);
87
XilinxSPIPS *s = opaque;
69
+ uint64_t tcr = regime_tcr(env, mmu_idx);
88
@@ -XXX,XX +XXX,XX @@ static void xilinx_qspips_write(void *opaque, hwaddr addr,
70
bool epd, hpd, using16k, using64k, tsz_oob, ds;
89
}
71
int select, tsz, tbi, max_tsz, min_tsz, ps, sh;
90
72
ARMCPU *cpu = env_archcpu(env);
91
static void xlnx_zynqmp_qspips_write(void *opaque, hwaddr addr,
73
@@ -XXX,XX +XXX,XX @@ static CPUARMTBFlags rebuild_hflags_a64(CPUARMState *env, int el, int fp_el,
92
- uint64_t value, unsigned size)
93
+ uint64_t value, unsigned size)
94
{
74
{
95
XlnxZynqMPQSPIPS *s = XLNX_ZYNQMP_QSPIPS(opaque);
75
CPUARMTBFlags flags = {};
96
uint32_t reg = addr / 4;
76
ARMMMUIdx stage1 = stage_1_mmu_idx(mmu_idx);
77
- uint64_t tcr = regime_tcr_value(env, mmu_idx);
78
+ uint64_t tcr = regime_tcr(env, mmu_idx);
79
uint64_t sctlr;
80
int tbii, tbid;
81
82
diff --git a/target/arm/ptw.c b/target/arm/ptw.c
83
index XXXXXXX..XXXXXXX 100644
84
--- a/target/arm/ptw.c
85
+++ b/target/arm/ptw.c
86
@@ -XXX,XX +XXX,XX @@ static bool get_level1_table_address(CPUARMState *env, ARMMMUIdx mmu_idx,
87
uint32_t *table, uint32_t address)
88
{
89
/* Note that we can only get here for an AArch32 PL0/PL1 lookup */
90
- uint64_t tcr = regime_tcr_value(env, mmu_idx);
91
+ uint64_t tcr = regime_tcr(env, mmu_idx);
92
int maskshift = extract32(tcr, 0, 3);
93
uint32_t mask = ~(((uint32_t)0xffffffffu) >> maskshift);
94
uint32_t base_mask;
95
@@ -XXX,XX +XXX,XX @@ static int get_S1prot(CPUARMState *env, ARMMMUIdx mmu_idx, bool is_aa64,
96
static ARMVAParameters aa32_va_parameters(CPUARMState *env, uint32_t va,
97
ARMMMUIdx mmu_idx)
98
{
99
- uint64_t tcr = regime_tcr_value(env, mmu_idx);
100
+ uint64_t tcr = regime_tcr(env, mmu_idx);
101
uint32_t el = regime_el(env, mmu_idx);
102
int select, tsz;
103
bool epd, hpd;
104
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, uint64_t address,
105
uint32_t attrs;
106
int32_t stride;
107
int addrsize, inputsize, outputsize;
108
- uint64_t tcr = regime_tcr_value(env, mmu_idx);
109
+ uint64_t tcr = regime_tcr(env, mmu_idx);
110
int ap, ns, xn, pxn;
111
uint32_t el = regime_el(env, mmu_idx);
112
uint64_t descaddrmask;
113
diff --git a/target/arm/tlb_helper.c b/target/arm/tlb_helper.c
114
index XXXXXXX..XXXXXXX 100644
115
--- a/target/arm/tlb_helper.c
116
+++ b/target/arm/tlb_helper.c
117
@@ -XXX,XX +XXX,XX @@ bool regime_using_lpae_format(CPUARMState *env, ARMMMUIdx mmu_idx)
118
return true;
119
}
120
if (arm_feature(env, ARM_FEATURE_LPAE)
121
- && (regime_tcr_value(env, mmu_idx) & TTBCR_EAE)) {
122
+ && (regime_tcr(env, mmu_idx) & TTBCR_EAE)) {
123
return true;
124
}
125
return false;
97
--
126
--
98
2.20.1
127
2.25.1
99
100
diff view generated by jsdifflib
1
Test that when we change the scaling of the system counter that the
1
We have a bug in our handling of accesses to the AArch32 VTCR
2
system timer responds appropriately.
2
register on big-endian hosts: we were not adjusting the part of the
3
uint64_t field within TCR that the generated code would access. That
4
can be done with offsetoflow32(), by using an ARM_CP_STATE_BOTH cpreg
5
struct, or by defining a full set of read/write/reset functions --
6
the various other TCR cpreg structs used one or another of those
7
strategies, but for VTCR we did not, so on a big-endian host VTCR
8
accesses would touch the wrong half of the register.
9
10
Use offsetoflow32() in the VTCR register struct. This works even
11
though the field in the CPU struct is currently a struct TCR, because
12
the first field in that struct is the uint64_t raw_tcr.
13
14
None of the other TCR registers have this bug -- either they are
15
AArch64 only, or else they define resetfn, writefn, etc, and
16
expect to be passed the full struct pointer.
3
17
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
19
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
20
Message-id: 20220714132303.1287193-5-peter.maydell@linaro.org
7
---
21
---
8
tests/qtest/sse-timer-test.c | 32 ++++++++++++++++++++++++++++++++
22
target/arm/helper.c | 2 +-
9
1 file changed, 32 insertions(+)
23
1 file changed, 1 insertion(+), 1 deletion(-)
10
24
11
diff --git a/tests/qtest/sse-timer-test.c b/tests/qtest/sse-timer-test.c
25
diff --git a/target/arm/helper.c b/target/arm/helper.c
12
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX 100644
13
--- a/tests/qtest/sse-timer-test.c
27
--- a/target/arm/helper.c
14
+++ b/tests/qtest/sse-timer-test.c
28
+++ b/target/arm/helper.c
15
@@ -XXX,XX +XXX,XX @@ static void test_timer(void)
29
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo el2_cp_reginfo[] = {
16
g_assert_cmpuint(readl(TIMER_BASE + CNTP_AIVAL_HI), ==, 0x42);
30
.cp = 15, .opc1 = 4, .crn = 2, .crm = 1, .opc2 = 2,
17
}
31
.type = ARM_CP_ALIAS,
18
32
.access = PL2_RW, .accessfn = access_el3_aa32ns,
19
+static void test_timer_scale_change(void)
33
- .fieldoffset = offsetof(CPUARMState, cp15.vtcr_el2) },
20
+{
34
+ .fieldoffset = offsetoflow32(CPUARMState, cp15.vtcr_el2) },
21
+ /*
35
{ .name = "VTCR_EL2", .state = ARM_CP_STATE_AA64,
22
+ * Test that the timer responds correctly to counter
36
.opc0 = 3, .opc1 = 4, .crn = 2, .crm = 1, .opc2 = 2,
23
+ * scaling changes while it has an active timer.
37
.access = PL2_RW,
24
+ */
25
+ reset_counter_and_timer();
26
+ /* Give ourselves access to the timer, and enable the counter and timer */
27
+ writel(PERIPHNSPPC0, 1);
28
+ writel(COUNTER_BASE + CNTCR, 1);
29
+ writel(TIMER_BASE + CNTP_CTL, 1);
30
+ /* Set the CompareValue to 4000 ticks */
31
+ writel(TIMER_BASE + CNTP_CVAL_LO, 4000);
32
+ writel(TIMER_BASE + CNTP_CVAL_HI, 0);
33
+ /* Advance halfway and check ISTATUS is not set */
34
+ clock_step_ticks(2000);
35
+ g_assert_cmpuint(readl(TIMER_BASE + CNTP_CTL), ==, 1);
36
+ /* Reprogram the counter to run at 1/16th speed */
37
+ writel(COUNTER_BASE + CNTCR, 0);
38
+ writel(COUNTER_BASE + CNTSCR, 0x00100000); /* 1/16th normal speed */
39
+ writel(COUNTER_BASE + CNTCR, 5); /* EN, SCEN */
40
+ /* Advance to where the timer would have fired and check it has not */
41
+ clock_step_ticks(2000);
42
+ g_assert_cmpuint(readl(TIMER_BASE + CNTP_CTL), ==, 1);
43
+ /* Advance to where the timer must fire at the new clock rate */
44
+ clock_step_ticks(29996);
45
+ g_assert_cmpuint(readl(TIMER_BASE + CNTP_CTL), ==, 1);
46
+ clock_step_ticks(4);
47
+ g_assert_cmpuint(readl(TIMER_BASE + CNTP_CTL), ==, 5);
48
+}
49
+
50
int main(int argc, char **argv)
51
{
52
int r;
53
@@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv)
54
55
qtest_add_func("/sse-timer/counter", test_counter);
56
qtest_add_func("/sse-timer/timer", test_timer);
57
+ qtest_add_func("/sse-timer/timer-scale-change", test_timer_scale_change);
58
59
r = g_test_run();
60
61
--
38
--
62
2.20.1
39
2.25.1
63
64
diff view generated by jsdifflib
1
Add a test which tests various parts of the functionality of the
1
Change the representation of the VSTCR_EL2 and VTCR_EL2 registers in
2
SSE system timer.
2
the CPU state struct from struct TCR to uint64_t.
3
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Message-id: 20220714132303.1287193-6-peter.maydell@linaro.org
7
---
7
---
8
tests/qtest/sse-timer-test.c | 91 ++++++++++++++++++++++++++++++++++++
8
target/arm/cpu.h | 4 ++--
9
1 file changed, 91 insertions(+)
9
target/arm/internals.h | 4 ++--
10
target/arm/helper.c | 4 +---
11
target/arm/ptw.c | 14 +++++++-------
12
4 files changed, 12 insertions(+), 14 deletions(-)
10
13
11
diff --git a/tests/qtest/sse-timer-test.c b/tests/qtest/sse-timer-test.c
14
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
12
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
13
--- a/tests/qtest/sse-timer-test.c
16
--- a/target/arm/cpu.h
14
+++ b/tests/qtest/sse-timer-test.c
17
+++ b/target/arm/cpu.h
15
@@ -XXX,XX +XXX,XX @@ static void test_counter(void)
18
@@ -XXX,XX +XXX,XX @@ typedef struct CPUArchState {
16
g_assert_cmpuint(readl(COUNTER_BASE + CNTCV_HI), ==, 0);
19
uint64_t vsttbr_el2; /* Secure Virtualization Translation Table. */
20
/* MMU translation table base control. */
21
TCR tcr_el[4];
22
- TCR vtcr_el2; /* Virtualization Translation Control. */
23
- TCR vstcr_el2; /* Secure Virtualization Translation Control. */
24
+ uint64_t vtcr_el2; /* Virtualization Translation Control. */
25
+ uint64_t vstcr_el2; /* Secure Virtualization Translation Control. */
26
uint32_t c2_data; /* MPU data cacheable bits. */
27
uint32_t c2_insn; /* MPU instruction cacheable bits. */
28
union { /* MMU domain access control register
29
diff --git a/target/arm/internals.h b/target/arm/internals.h
30
index XXXXXXX..XXXXXXX 100644
31
--- a/target/arm/internals.h
32
+++ b/target/arm/internals.h
33
@@ -XXX,XX +XXX,XX @@ static inline uint64_t regime_sctlr(CPUARMState *env, ARMMMUIdx mmu_idx)
34
static inline uint64_t regime_tcr(CPUARMState *env, ARMMMUIdx mmu_idx)
35
{
36
if (mmu_idx == ARMMMUIdx_Stage2) {
37
- return env->cp15.vtcr_el2.raw_tcr;
38
+ return env->cp15.vtcr_el2;
39
}
40
if (mmu_idx == ARMMMUIdx_Stage2_S) {
41
/*
42
* Note: Secure stage 2 nominally shares fields from VTCR_EL2, but
43
* those are not currently used by QEMU, so just return VSTCR_EL2.
44
*/
45
- return env->cp15.vstcr_el2.raw_tcr;
46
+ return env->cp15.vstcr_el2;
47
}
48
return env->cp15.tcr_el[regime_el(env, mmu_idx)].raw_tcr;
17
}
49
}
18
50
diff --git a/target/arm/helper.c b/target/arm/helper.c
19
+static void test_timer(void)
51
index XXXXXXX..XXXXXXX 100644
20
+{
52
--- a/target/arm/helper.c
21
+ /* Basic timer functionality test */
53
+++ b/target/arm/helper.c
22
+
54
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo el2_cp_reginfo[] = {
23
+ reset_counter_and_timer();
55
{ .name = "VTCR_EL2", .state = ARM_CP_STATE_AA64,
24
+ /*
56
.opc0 = 3, .opc1 = 4, .crn = 2, .crm = 1, .opc2 = 2,
25
+ * The timer is behind a Peripheral Protection Controller, and
57
.access = PL2_RW,
26
+ * qtest accesses are always non-secure (no memory attributes),
58
- /* no .writefn needed as this can't cause an ASID change;
27
+ * so we must program the PPC to accept NS transactions. TIMER0
59
- * no .raw_writefn or .resetfn needed as we never use mask/base_mask
28
+ * is on port 0 of PPC0, controlled by bit 0 of this register.
60
- */
29
+ */
61
+ /* no .writefn needed as this can't cause an ASID change */
30
+ writel(PERIPHNSPPC0, 1);
62
.fieldoffset = offsetof(CPUARMState, cp15.vtcr_el2) },
31
+ /* We must enable the System Counter or the timer won't run. */
63
{ .name = "VTTBR", .state = ARM_CP_STATE_AA32,
32
+ writel(COUNTER_BASE + CNTCR, 1);
64
.cp = 15, .opc1 = 6, .crm = 2,
33
+
65
diff --git a/target/arm/ptw.c b/target/arm/ptw.c
34
+ /* Timer starts disabled and with a counter of 0 */
66
index XXXXXXX..XXXXXXX 100644
35
+ g_assert_cmpuint(readl(TIMER_BASE + CNTP_CTL), ==, 0);
67
--- a/target/arm/ptw.c
36
+ g_assert_cmpuint(readl(TIMER_BASE + CNTPCT_LO), ==, 0);
68
+++ b/target/arm/ptw.c
37
+ g_assert_cmpuint(readl(TIMER_BASE + CNTPCT_HI), ==, 0);
69
@@ -XXX,XX +XXX,XX @@ static hwaddr S1_ptw_translate(CPUARMState *env, ARMMMUIdx mmu_idx,
38
+
70
if (arm_is_secure_below_el3(env)) {
39
+ /* Turn it on */
71
/* Check if page table walk is to secure or non-secure PA space. */
40
+ writel(TIMER_BASE + CNTP_CTL, 1);
72
if (*is_secure) {
41
+
73
- *is_secure = !(env->cp15.vstcr_el2.raw_tcr & VSTCR_SW);
42
+ /* Is the timer ticking? */
74
+ *is_secure = !(env->cp15.vstcr_el2 & VSTCR_SW);
43
+ clock_step_ticks(100);
75
} else {
44
+ g_assert_cmpuint(readl(TIMER_BASE + CNTPCT_LO), ==, 100);
76
- *is_secure = !(env->cp15.vtcr_el2.raw_tcr & VTCR_NSW);
45
+ g_assert_cmpuint(readl(TIMER_BASE + CNTPCT_HI), ==, 0);
77
+ *is_secure = !(env->cp15.vtcr_el2 & VTCR_NSW);
46
+
78
}
47
+ /* Set the CompareValue to 4000 ticks */
79
} else {
48
+ writel(TIMER_BASE + CNTP_CVAL_LO, 4000);
80
assert(!*is_secure);
49
+ writel(TIMER_BASE + CNTP_CVAL_HI, 0);
81
@@ -XXX,XX +XXX,XX @@ bool get_phys_addr(CPUARMState *env, target_ulong address,
50
+
82
ipa_secure = attrs->secure;
51
+ /* Check TVAL view of the counter */
83
if (arm_is_secure_below_el3(env)) {
52
+ g_assert_cmpuint(readl(TIMER_BASE + CNTP_TVAL), ==, 3900);
84
if (ipa_secure) {
53
+
85
- attrs->secure = !(env->cp15.vstcr_el2.raw_tcr & VSTCR_SW);
54
+ /* Advance to the CompareValue mark and check ISTATUS is set */
86
+ attrs->secure = !(env->cp15.vstcr_el2 & VSTCR_SW);
55
+ clock_step_ticks(3900);
87
} else {
56
+ g_assert_cmpuint(readl(TIMER_BASE + CNTP_TVAL), ==, 0);
88
- attrs->secure = !(env->cp15.vtcr_el2.raw_tcr & VTCR_NSW);
57
+ g_assert_cmpuint(readl(TIMER_BASE + CNTP_CTL), ==, 5);
89
+ attrs->secure = !(env->cp15.vtcr_el2 & VTCR_NSW);
58
+
90
}
59
+ /* Now exercise the auto-reload part of the timer */
91
} else {
60
+ writel(TIMER_BASE + CNTP_AIVAL_RELOAD, 200);
92
assert(!ipa_secure);
61
+ writel(TIMER_BASE + CNTP_AIVAL_CTL, 1);
93
@@ -XXX,XX +XXX,XX @@ bool get_phys_addr(CPUARMState *env, target_ulong address,
62
+
94
if (arm_is_secure_below_el3(env)) {
63
+ /* Check AIVAL was reloaded and that ISTATUS is now clear */
95
if (ipa_secure) {
64
+ g_assert_cmpuint(readl(TIMER_BASE + CNTP_AIVAL_LO), ==, 4200);
96
attrs->secure =
65
+ g_assert_cmpuint(readl(TIMER_BASE + CNTP_AIVAL_HI), ==, 0);
97
- !(env->cp15.vstcr_el2.raw_tcr & (VSTCR_SA | VSTCR_SW));
66
+ g_assert_cmpuint(readl(TIMER_BASE + CNTP_CTL), ==, 1);
98
+ !(env->cp15.vstcr_el2 & (VSTCR_SA | VSTCR_SW));
67
+
99
} else {
68
+ /*
100
attrs->secure =
69
+ * Check that when we advance forward to the reload time the interrupt
101
- !((env->cp15.vtcr_el2.raw_tcr & (VTCR_NSA | VTCR_NSW))
70
+ * fires and the value reloads
102
- || (env->cp15.vstcr_el2.raw_tcr & (VSTCR_SA | VSTCR_SW)));
71
+ */
103
+ !((env->cp15.vtcr_el2 & (VTCR_NSA | VTCR_NSW))
72
+ clock_step_ticks(100);
104
+ || (env->cp15.vstcr_el2 & (VSTCR_SA | VSTCR_SW)));
73
+ g_assert_cmpuint(readl(TIMER_BASE + CNTP_CTL), ==, 1);
105
}
74
+ clock_step_ticks(100);
106
}
75
+ g_assert_cmpuint(readl(TIMER_BASE + CNTP_CTL), ==, 5);
107
return 0;
76
+ g_assert_cmpuint(readl(TIMER_BASE + CNTP_AIVAL_LO), ==, 4400);
77
+ g_assert_cmpuint(readl(TIMER_BASE + CNTP_AIVAL_HI), ==, 0);
78
+
79
+ clock_step_ticks(100);
80
+ g_assert_cmpuint(readl(TIMER_BASE + CNTP_CTL), ==, 5);
81
+ /* Check that writing 0 to CLR clears the interrupt */
82
+ writel(TIMER_BASE + CNTP_AIVAL_CTL, 1);
83
+ g_assert_cmpuint(readl(TIMER_BASE + CNTP_CTL), ==, 1);
84
+ /* Check that when we move forward to the reload time it fires again */
85
+ clock_step_ticks(100);
86
+ g_assert_cmpuint(readl(TIMER_BASE + CNTP_CTL), ==, 5);
87
+ g_assert_cmpuint(readl(TIMER_BASE + CNTP_AIVAL_LO), ==, 4600);
88
+ g_assert_cmpuint(readl(TIMER_BASE + CNTP_AIVAL_HI), ==, 0);
89
+
90
+ /*
91
+ * Step the clock far enough that we overflow the low half of the
92
+ * CNTPCT and AIVAL registers, and check that their high halves
93
+ * give the right values. We do the forward movement in
94
+ * non-autoinc mode because otherwise it takes forever as the
95
+ * timer has to emulate all the 'reload at t + N, t + 2N, etc'
96
+ * steps.
97
+ */
98
+ writel(TIMER_BASE + CNTP_AIVAL_CTL, 0);
99
+ clock_step_ticks(0x42ULL << 32);
100
+ g_assert_cmpuint(readl(TIMER_BASE + CNTPCT_LO), ==, 4400);
101
+ g_assert_cmpuint(readl(TIMER_BASE + CNTPCT_HI), ==, 0x42);
102
+
103
+ /* Turn on the autoinc again to check AIVAL_HI */
104
+ writel(TIMER_BASE + CNTP_AIVAL_CTL, 1);
105
+ g_assert_cmpuint(readl(TIMER_BASE + CNTP_AIVAL_LO), ==, 4600);
106
+ g_assert_cmpuint(readl(TIMER_BASE + CNTP_AIVAL_HI), ==, 0x42);
107
+}
108
+
109
int main(int argc, char **argv)
110
{
111
int r;
112
@@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv)
113
qtest_start("-machine mps3-an547");
114
115
qtest_add_func("/sse-timer/counter", test_counter);
116
+ qtest_add_func("/sse-timer/timer", test_timer);
117
118
r = g_test_run();
119
120
--
108
--
121
2.20.1
109
2.25.1
122
123
diff view generated by jsdifflib
1
The versions of the Secure Access Configuration Register Block
1
Change the representation of the TCR_EL* registers in the CPU state
2
and Non-secure Access Configuration Register Block in the SSE-300
2
struct from struct TCR to uint64_t. This allows us to drop the
3
are the same as those in the SSE-200, but the CIDR/PIDR ID
3
custom vmsa_ttbcr_raw_write() function, moving the "enforce RES0"
4
register values are different.
4
checks to their more usual location in the writefn
5
5
vmsa_ttbcr_write(). We also don't need the resetfn any more.
6
Plumb through the sse-version property and use it to select
7
the correct ID register values.
8
6
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20210219144617.4782-8-peter.maydell@linaro.org
9
Message-id: 20220714132303.1287193-7-peter.maydell@linaro.org
13
---
10
---
14
include/hw/misc/iotkit-secctl.h | 2 ++
11
target/arm/cpu.h | 8 +----
15
hw/arm/armsse.c | 2 ++
12
target/arm/internals.h | 6 ++--
16
hw/misc/iotkit-secctl.c | 50 +++++++++++++++++++++++++++++++--
13
target/arm/cpu.c | 2 +-
17
3 files changed, 52 insertions(+), 2 deletions(-)
14
target/arm/debug_helper.c | 2 +-
15
target/arm/helper.c | 75 +++++++++++----------------------------
16
target/arm/ptw.c | 2 +-
17
6 files changed, 27 insertions(+), 68 deletions(-)
18
18
19
diff --git a/include/hw/misc/iotkit-secctl.h b/include/hw/misc/iotkit-secctl.h
19
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
20
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
21
--- a/include/hw/misc/iotkit-secctl.h
21
--- a/target/arm/cpu.h
22
+++ b/include/hw/misc/iotkit-secctl.h
22
+++ b/target/arm/cpu.h
23
@@ -XXX,XX +XXX,XX @@ struct IoTKitSecCtl {
23
@@ -XXX,XX +XXX,XX @@ typedef struct ARMGenericTimer {
24
IoTKitSecCtlPPC apb[IOTS_NUM_APB_PPC];
24
#define GTIMER_HYPVIRT 4
25
IoTKitSecCtlPPC apbexp[IOTS_NUM_APB_EXP_PPC];
25
#define NUM_GTIMERS 5
26
IoTKitSecCtlPPC ahbexp[IOTS_NUM_APB_EXP_PPC];
26
27
+
27
-typedef struct {
28
+ uint32_t sse_version;
28
- uint64_t raw_tcr;
29
- uint32_t mask;
30
- uint32_t base_mask;
31
-} TCR;
32
-
33
#define VTCR_NSW (1u << 29)
34
#define VTCR_NSA (1u << 30)
35
#define VSTCR_SW VTCR_NSW
36
@@ -XXX,XX +XXX,XX @@ typedef struct CPUArchState {
37
uint64_t vttbr_el2; /* Virtualization Translation Table Base. */
38
uint64_t vsttbr_el2; /* Secure Virtualization Translation Table. */
39
/* MMU translation table base control. */
40
- TCR tcr_el[4];
41
+ uint64_t tcr_el[4];
42
uint64_t vtcr_el2; /* Virtualization Translation Control. */
43
uint64_t vstcr_el2; /* Secure Virtualization Translation Control. */
44
uint32_t c2_data; /* MPU data cacheable bits. */
45
diff --git a/target/arm/internals.h b/target/arm/internals.h
46
index XXXXXXX..XXXXXXX 100644
47
--- a/target/arm/internals.h
48
+++ b/target/arm/internals.h
49
@@ -XXX,XX +XXX,XX @@ unsigned int arm_pamax(ARMCPU *cpu);
50
*/
51
static inline bool extended_addresses_enabled(CPUARMState *env)
52
{
53
- TCR *tcr = &env->cp15.tcr_el[arm_is_secure(env) ? 3 : 1];
54
+ uint64_t tcr = env->cp15.tcr_el[arm_is_secure(env) ? 3 : 1];
55
return arm_el_is_aa64(env, 1) ||
56
- (arm_feature(env, ARM_FEATURE_LPAE) && (tcr->raw_tcr & TTBCR_EAE));
57
+ (arm_feature(env, ARM_FEATURE_LPAE) && (tcr & TTBCR_EAE));
58
}
59
60
/* Update a QEMU watchpoint based on the information the guest has set in the
61
@@ -XXX,XX +XXX,XX @@ static inline uint64_t regime_tcr(CPUARMState *env, ARMMMUIdx mmu_idx)
62
*/
63
return env->cp15.vstcr_el2;
64
}
65
- return env->cp15.tcr_el[regime_el(env, mmu_idx)].raw_tcr;
66
+ return env->cp15.tcr_el[regime_el(env, mmu_idx)];
67
}
68
69
/**
70
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
71
index XXXXXXX..XXXXXXX 100644
72
--- a/target/arm/cpu.c
73
+++ b/target/arm/cpu.c
74
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_reset(DeviceState *dev)
75
* Enable TBI0 but not TBI1.
76
* Note that this must match useronly_clean_ptr.
77
*/
78
- env->cp15.tcr_el[1].raw_tcr = 5 | (1ULL << 37);
79
+ env->cp15.tcr_el[1] = 5 | (1ULL << 37);
80
81
/* Enable MTE */
82
if (cpu_isar_feature(aa64_mte, cpu)) {
83
diff --git a/target/arm/debug_helper.c b/target/arm/debug_helper.c
84
index XXXXXXX..XXXXXXX 100644
85
--- a/target/arm/debug_helper.c
86
+++ b/target/arm/debug_helper.c
87
@@ -XXX,XX +XXX,XX @@ static uint32_t arm_debug_exception_fsr(CPUARMState *env)
88
using_lpae = true;
89
} else {
90
if (arm_feature(env, ARM_FEATURE_LPAE) &&
91
- (env->cp15.tcr_el[target_el].raw_tcr & TTBCR_EAE)) {
92
+ (env->cp15.tcr_el[target_el] & TTBCR_EAE)) {
93
using_lpae = true;
94
}
95
}
96
diff --git a/target/arm/helper.c b/target/arm/helper.c
97
index XXXXXXX..XXXXXXX 100644
98
--- a/target/arm/helper.c
99
+++ b/target/arm/helper.c
100
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo pmsav5_cp_reginfo[] = {
101
.fieldoffset = offsetof(CPUARMState, cp15.c6_region[7]) },
29
};
102
};
30
103
31
#endif
104
-static void vmsa_ttbcr_raw_write(CPUARMState *env, const ARMCPRegInfo *ri,
32
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
105
- uint64_t value)
33
index XXXXXXX..XXXXXXX 100644
106
+static void vmsa_ttbcr_write(CPUARMState *env, const ARMCPRegInfo *ri,
34
--- a/hw/arm/armsse.c
107
+ uint64_t value)
35
+++ b/hw/arm/armsse.c
108
{
36
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
109
- TCR *tcr = raw_ptr(env, ri);
37
}
110
- int maskshift = extract32(value, 0, 3);
38
111
+ ARMCPU *cpu = env_archcpu(env);
39
/* Security controller */
112
40
+ object_property_set_int(OBJECT(&s->secctl), "sse-version",
113
if (!arm_feature(env, ARM_FEATURE_V8)) {
41
+ info->sse_version, &error_abort);
114
if (arm_feature(env, ARM_FEATURE_LPAE) && (value & TTBCR_EAE)) {
42
if (!sysbus_realize(SYS_BUS_DEVICE(&s->secctl), errp)) {
115
- /* Pre ARMv8 bits [21:19], [15:14] and [6:3] are UNK/SBZP when
43
return;
116
- * using Long-desciptor translation table format */
44
}
117
+ /*
45
diff --git a/hw/misc/iotkit-secctl.c b/hw/misc/iotkit-secctl.c
118
+ * Pre ARMv8 bits [21:19], [15:14] and [6:3] are UNK/SBZP when
46
index XXXXXXX..XXXXXXX 100644
119
+ * using Long-descriptor translation table format
47
--- a/hw/misc/iotkit-secctl.c
120
+ */
48
+++ b/hw/misc/iotkit-secctl.c
121
value &= ~((7 << 19) | (3 << 14) | (0xf << 3));
49
@@ -XXX,XX +XXX,XX @@
122
} else if (arm_feature(env, ARM_FEATURE_EL3)) {
50
#include "hw/registerfields.h"
123
- /* In an implementation that includes the Security Extensions
51
#include "hw/irq.h"
124
+ /*
52
#include "hw/misc/iotkit-secctl.h"
125
+ * In an implementation that includes the Security Extensions
53
+#include "hw/arm/armsse-version.h"
126
* TTBCR has additional fields PD0 [4] and PD1 [5] for
54
+#include "hw/qdev-properties.h"
127
* Short-descriptor translation table format.
55
128
*/
56
/* Registers in the secure privilege control block */
129
@@ -XXX,XX +XXX,XX @@ static void vmsa_ttbcr_raw_write(CPUARMState *env, const ARMCPRegInfo *ri,
57
REG32(SECRESPCFG, 0x10)
130
}
58
@@ -XXX,XX +XXX,XX @@ static const uint8_t iotkit_secctl_ns_idregs[] = {
131
}
59
0x0d, 0xf0, 0x05, 0xb1,
132
133
- /* Update the masks corresponding to the TCR bank being written
134
- * Note that we always calculate mask and base_mask, but
135
- * they are only used for short-descriptor tables (ie if EAE is 0);
136
- * for long-descriptor tables the TCR fields are used differently
137
- * and the mask and base_mask values are meaningless.
138
- */
139
- tcr->raw_tcr = value;
140
- tcr->mask = ~(((uint32_t)0xffffffffu) >> maskshift);
141
- tcr->base_mask = ~((uint32_t)0x3fffu >> maskshift);
142
-}
143
-
144
-static void vmsa_ttbcr_write(CPUARMState *env, const ARMCPRegInfo *ri,
145
- uint64_t value)
146
-{
147
- ARMCPU *cpu = env_archcpu(env);
148
- TCR *tcr = raw_ptr(env, ri);
149
-
150
if (arm_feature(env, ARM_FEATURE_LPAE)) {
151
/* With LPAE the TTBCR could result in a change of ASID
152
* via the TTBCR.A1 bit, so do a TLB flush.
153
*/
154
tlb_flush(CPU(cpu));
155
}
156
- /* Preserve the high half of TCR_EL1, set via TTBCR2. */
157
- value = deposit64(tcr->raw_tcr, 0, 32, value);
158
- vmsa_ttbcr_raw_write(env, ri, value);
159
-}
160
-
161
-static void vmsa_ttbcr_reset(CPUARMState *env, const ARMCPRegInfo *ri)
162
-{
163
- TCR *tcr = raw_ptr(env, ri);
164
-
165
- /* Reset both the TCR as well as the masks corresponding to the bank of
166
- * the TCR being reset.
167
- */
168
- tcr->raw_tcr = 0;
169
- tcr->mask = 0;
170
- tcr->base_mask = 0xffffc000u;
171
+ raw_write(env, ri, value);
172
}
173
174
static void vmsa_tcr_el12_write(CPUARMState *env, const ARMCPRegInfo *ri,
175
uint64_t value)
176
{
177
ARMCPU *cpu = env_archcpu(env);
178
- TCR *tcr = raw_ptr(env, ri);
179
180
/* For AArch64 the A1 bit could result in a change of ASID, so TLB flush. */
181
tlb_flush(CPU(cpu));
182
- tcr->raw_tcr = value;
183
+ raw_write(env, ri, value);
184
}
185
186
static void vmsa_ttbr_write(CPUARMState *env, const ARMCPRegInfo *ri,
187
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo vmsa_cp_reginfo[] = {
188
.opc0 = 3, .crn = 2, .crm = 0, .opc1 = 0, .opc2 = 2,
189
.access = PL1_RW, .accessfn = access_tvm_trvm,
190
.writefn = vmsa_tcr_el12_write,
191
- .resetfn = vmsa_ttbcr_reset, .raw_writefn = raw_write,
192
+ .raw_writefn = raw_write,
193
+ .resetvalue = 0,
194
.fieldoffset = offsetof(CPUARMState, cp15.tcr_el[1]) },
195
{ .name = "TTBCR", .cp = 15, .crn = 2, .crm = 0, .opc1 = 0, .opc2 = 2,
196
.access = PL1_RW, .accessfn = access_tvm_trvm,
197
.type = ARM_CP_ALIAS, .writefn = vmsa_ttbcr_write,
198
- .raw_writefn = vmsa_ttbcr_raw_write,
199
- /* No offsetoflow32 -- pass the entire TCR to writefn/raw_writefn. */
200
- .bank_fieldoffsets = { offsetof(CPUARMState, cp15.tcr_el[3]),
201
- offsetof(CPUARMState, cp15.tcr_el[1])} },
202
+ .raw_writefn = raw_write,
203
+ .bank_fieldoffsets = { offsetoflow32(CPUARMState, cp15.tcr_el[3]),
204
+ offsetoflow32(CPUARMState, cp15.tcr_el[1])} },
60
};
205
};
61
206
62
+static const uint8_t iotkit_secctl_s_sse300_idregs[] = {
207
/* Note that unlike TTBCR, writing to TTBCR2 does not require flushing
63
+ 0x04, 0x00, 0x00, 0x00,
208
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo ttbcr2_reginfo = {
64
+ 0x52, 0xb8, 0x2b, 0x00,
209
.access = PL1_RW, .accessfn = access_tvm_trvm,
65
+ 0x0d, 0xf0, 0x05, 0xb1,
210
.type = ARM_CP_ALIAS,
66
+};
211
.bank_fieldoffsets = {
67
+
212
- offsetofhigh32(CPUARMState, cp15.tcr_el[3].raw_tcr),
68
+static const uint8_t iotkit_secctl_ns_sse300_idregs[] = {
213
- offsetofhigh32(CPUARMState, cp15.tcr_el[1].raw_tcr),
69
+ 0x04, 0x00, 0x00, 0x00,
214
+ offsetofhigh32(CPUARMState, cp15.tcr_el[3]),
70
+ 0x53, 0xb8, 0x2b, 0x00,
215
+ offsetofhigh32(CPUARMState, cp15.tcr_el[1]),
71
+ 0x0d, 0xf0, 0x05, 0xb1,
72
+};
73
+
74
+
75
/* The register sets for the various PPCs (AHB internal, APB internal,
76
* AHB expansion, APB expansion) are all set up so that they are
77
* in 16-aligned blocks so offsets 0xN0, 0xN4, 0xN8, 0xNC are PPCs
78
@@ -XXX,XX +XXX,XX @@ static MemTxResult iotkit_secctl_s_read(void *opaque, hwaddr addr,
79
case A_CID1:
80
case A_CID2:
81
case A_CID3:
82
- r = iotkit_secctl_s_idregs[(offset - A_PID4) / 4];
83
+ switch (s->sse_version) {
84
+ case ARMSSE_SSE300:
85
+ r = iotkit_secctl_s_sse300_idregs[(offset - A_PID4) / 4];
86
+ break;
87
+ default:
88
+ r = iotkit_secctl_s_idregs[(offset - A_PID4) / 4];
89
+ break;
90
+ }
91
break;
92
case A_SECPPCINTCLR:
93
case A_SECMSCINTCLR:
94
@@ -XXX,XX +XXX,XX @@ static MemTxResult iotkit_secctl_ns_read(void *opaque, hwaddr addr,
95
case A_CID1:
96
case A_CID2:
97
case A_CID3:
98
- r = iotkit_secctl_ns_idregs[(offset - A_PID4) / 4];
99
+ switch (s->sse_version) {
100
+ case ARMSSE_SSE300:
101
+ r = iotkit_secctl_ns_sse300_idregs[(offset - A_PID4) / 4];
102
+ break;
103
+ default:
104
+ r = iotkit_secctl_ns_idregs[(offset - A_PID4) / 4];
105
+ break;
106
+ }
107
break;
108
default:
109
qemu_log_mask(LOG_GUEST_ERROR,
110
@@ -XXX,XX +XXX,XX @@ static void iotkit_secctl_init(Object *obj)
111
sysbus_init_mmio(sbd, &s->ns_regs);
112
}
113
114
+static void iotkit_secctl_realize(DeviceState *dev, Error **errp)
115
+{
116
+ IoTKitSecCtl *s = IOTKIT_SECCTL(dev);
117
+
118
+ if (!armsse_version_valid(s->sse_version)) {
119
+ error_setg(errp, "invalid sse-version value %d", s->sse_version);
120
+ return;
121
+ }
122
+}
123
+
124
static const VMStateDescription iotkit_secctl_ppc_vmstate = {
125
.name = "iotkit-secctl-ppc",
126
.version_id = 1,
127
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription iotkit_secctl_vmstate = {
128
},
216
},
129
};
217
};
130
218
131
+static Property iotkit_secctl_props[] = {
219
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo el2_cp_reginfo[] = {
132
+ DEFINE_PROP_UINT32("sse-version", IoTKitSecCtl, sse_version, 0),
220
{ .name = "TCR_EL2", .state = ARM_CP_STATE_BOTH,
133
+ DEFINE_PROP_END_OF_LIST()
221
.opc0 = 3, .opc1 = 4, .crn = 2, .crm = 0, .opc2 = 2,
134
+};
222
.access = PL2_RW, .writefn = vmsa_tcr_el12_write,
135
+
223
- /* no .raw_writefn or .resetfn needed as we never use mask/base_mask */
136
static void iotkit_secctl_class_init(ObjectClass *klass, void *data)
224
.fieldoffset = offsetof(CPUARMState, cp15.tcr_el[2]) },
137
{
225
{ .name = "VTCR", .state = ARM_CP_STATE_AA32,
138
DeviceClass *dc = DEVICE_CLASS(klass);
226
.cp = 15, .opc1 = 4, .crn = 2, .crm = 1, .opc2 = 2,
139
227
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo el3_cp_reginfo[] = {
140
dc->vmsd = &iotkit_secctl_vmstate;
228
{ .name = "TCR_EL3", .state = ARM_CP_STATE_AA64,
141
dc->reset = iotkit_secctl_reset;
229
.opc0 = 3, .opc1 = 6, .crn = 2, .crm = 0, .opc2 = 2,
142
+ dc->realize = iotkit_secctl_realize;
230
.access = PL3_RW,
143
+ device_class_set_props(dc, iotkit_secctl_props);
231
- /* no .writefn needed as this can't cause an ASID change;
144
}
232
- * we must provide a .raw_writefn and .resetfn because we handle
145
233
- * reset and migration for the AArch32 TTBCR(S), which might be
146
static const TypeInfo iotkit_secctl_info = {
234
- * using mask and base_mask.
235
- */
236
- .resetfn = vmsa_ttbcr_reset, .raw_writefn = vmsa_ttbcr_raw_write,
237
+ /* no .writefn needed as this can't cause an ASID change */
238
+ .resetvalue = 0,
239
.fieldoffset = offsetof(CPUARMState, cp15.tcr_el[3]) },
240
{ .name = "ELR_EL3", .state = ARM_CP_STATE_AA64,
241
.type = ARM_CP_ALIAS,
242
diff --git a/target/arm/ptw.c b/target/arm/ptw.c
243
index XXXXXXX..XXXXXXX 100644
244
--- a/target/arm/ptw.c
245
+++ b/target/arm/ptw.c
246
@@ -XXX,XX +XXX,XX @@ bool get_phys_addr(CPUARMState *env, target_ulong address,
247
int r_el = regime_el(env, mmu_idx);
248
if (arm_el_is_aa64(env, r_el)) {
249
int pamax = arm_pamax(env_archcpu(env));
250
- uint64_t tcr = env->cp15.tcr_el[r_el].raw_tcr;
251
+ uint64_t tcr = env->cp15.tcr_el[r_el];
252
int addrtop, tbi;
253
254
tbi = aa64_va_parameter_tbi(tcr, mmu_idx);
147
--
255
--
148
2.20.1
256
2.25.1
149
150
diff view generated by jsdifflib
1
In the SSE-300 the CPU_WAIT and NMI_ENABLE registers have
1
In regime_tcr() we return the appropriate TCR register for the
2
moved offsets, so they are now where the SSE-200's WICCTRL
2
translation regime. For Secure EL2, we return the VSTCR_EL2 value,
3
and EWCTRL were. The SSE-300 does not have WICCTLR or EWCTRL
3
but in this translation regime some fields that control behaviour are
4
at all, and the old offsets are reserved:
4
in VTCR_EL2. When this code was originally written (as the comment
5
notes), QEMU didn't care about any of those fields, but we have since
6
added support for features such as LPA2 which do need the values from
7
those fields.
5
8
6
Offset SSE-200 SSE-300
9
Synthesize a TCR value by merging in the relevant VTCR_EL2 fields to
7
-----------------------------------
10
the VSTCR_EL2 value.
8
0x118 CPUWAIT reserved
9
0x118 NMI_ENABLE reserved
10
0x120 WICCTRL CPUWAIT
11
0x124 EWCTRL NMI_ENABLE
12
11
13
Handle this reshuffle, and the fact that SSE-300 has only
12
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1103
14
one CPU and so only one active bit in CPUWAIT.
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
Message-id: 20220714132303.1287193-8-peter.maydell@linaro.org
16
---
17
target/arm/cpu.h | 19 +++++++++++++++++++
18
target/arm/internals.h | 22 +++++++++++++++++++---
19
2 files changed, 38 insertions(+), 3 deletions(-)
15
20
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
17
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
18
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
19
Message-id: 20210219144617.4782-15-peter.maydell@linaro.org
20
---
21
hw/misc/iotkit-sysctl.c | 88 +++++++++++++++++++++++++++++++++++------
22
1 file changed, 76 insertions(+), 12 deletions(-)
23
24
diff --git a/hw/misc/iotkit-sysctl.c b/hw/misc/iotkit-sysctl.c
25
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
26
--- a/hw/misc/iotkit-sysctl.c
23
--- a/target/arm/cpu.h
27
+++ b/hw/misc/iotkit-sysctl.c
24
+++ b/target/arm/cpu.h
28
@@ -XXX,XX +XXX,XX @@ static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
25
@@ -XXX,XX +XXX,XX @@ FIELD(CPTR_EL3, TCPAC, 31, 1)
29
}
26
#define TTBCR_SH1 (1U << 28)
30
break;
27
#define TTBCR_EAE (1U << 31)
31
case A_CPUWAIT:
28
32
- r = s->cpuwait;
29
+FIELD(VTCR, T0SZ, 0, 6)
33
+ switch (s->sse_version) {
30
+FIELD(VTCR, SL0, 6, 2)
34
+ case ARMSSE_IOTKIT:
31
+FIELD(VTCR, IRGN0, 8, 2)
35
+ case ARMSSE_SSE200:
32
+FIELD(VTCR, ORGN0, 10, 2)
36
+ r = s->cpuwait;
33
+FIELD(VTCR, SH0, 12, 2)
37
+ break;
34
+FIELD(VTCR, TG0, 14, 2)
38
+ case ARMSSE_SSE300:
35
+FIELD(VTCR, PS, 16, 3)
39
+ /* In SSE300 this is reserved (for INITSVTOR2) */
36
+FIELD(VTCR, VS, 19, 1)
40
+ goto bad_offset;
37
+FIELD(VTCR, HA, 21, 1)
41
+ default:
38
+FIELD(VTCR, HD, 22, 1)
42
+ g_assert_not_reached();
39
+FIELD(VTCR, HWU59, 25, 1)
43
+ }
40
+FIELD(VTCR, HWU60, 26, 1)
44
break;
41
+FIELD(VTCR, HWU61, 27, 1)
45
case A_NMI_ENABLE:
42
+FIELD(VTCR, HWU62, 28, 1)
46
switch (s->sse_version) {
43
+FIELD(VTCR, NSW, 29, 1)
47
@@ -XXX,XX +XXX,XX @@ static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
44
+FIELD(VTCR, NSA, 30, 1)
48
case ARMSSE_SSE200:
45
+FIELD(VTCR, DS, 32, 1)
49
r = s->nmi_enable;
46
+FIELD(VTCR, SL2, 33, 1)
50
break;
47
+
51
+ case ARMSSE_SSE300:
48
/* Bit definitions for ARMv8 SPSR (PSTATE) format.
52
+ /* In SSE300 this is reserved (for INITSVTOR3) */
49
* Only these are valid when in AArch64 mode; in
53
+ goto bad_offset;
50
* AArch32 mode SPSRs are basically CPSR-format.
54
default:
51
diff --git a/target/arm/internals.h b/target/arm/internals.h
55
g_assert_not_reached();
52
index XXXXXXX..XXXXXXX 100644
56
}
53
--- a/target/arm/internals.h
57
break;
54
+++ b/target/arm/internals.h
58
case A_WICCTRL:
55
@@ -XXX,XX +XXX,XX @@ static inline uint64_t regime_sctlr(CPUARMState *env, ARMMMUIdx mmu_idx)
59
- r = s->wicctrl;
56
return env->cp15.sctlr_el[regime_el(env, mmu_idx)];
60
+ switch (s->sse_version) {
61
+ case ARMSSE_IOTKIT:
62
+ case ARMSSE_SSE200:
63
+ r = s->wicctrl;
64
+ break;
65
+ case ARMSSE_SSE300:
66
+ /* In SSE300 this offset is CPUWAIT */
67
+ r = s->cpuwait;
68
+ break;
69
+ default:
70
+ g_assert_not_reached();
71
+ }
72
break;
73
case A_EWCTRL:
74
switch (s->sse_version) {
75
@@ -XXX,XX +XXX,XX @@ static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
76
case ARMSSE_SSE200:
77
r = s->ewctrl;
78
break;
79
+ case ARMSSE_SSE300:
80
+ /* In SSE300 this offset is is NMI_ENABLE */
81
+ r = s->nmi_enable;
82
+ break;
83
default:
84
g_assert_not_reached();
85
}
86
@@ -XXX,XX +XXX,XX @@ static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
87
return r;
88
}
57
}
89
58
90
+static void cpuwait_write(IoTKitSysCtl *s, uint32_t value)
59
+/*
91
+{
60
+ * These are the fields in VTCR_EL2 which affect both the Secure stage 2
92
+ int num_cpus = (s->sse_version == ARMSSE_SSE300) ? 1 : 2;
61
+ * and the Non-Secure stage 2 translation regimes (and hence which are
93
+ int i;
62
+ * not present in VSTCR_EL2).
63
+ */
64
+#define VTCR_SHARED_FIELD_MASK \
65
+ (R_VTCR_IRGN0_MASK | R_VTCR_ORGN0_MASK | R_VTCR_SH0_MASK | \
66
+ R_VTCR_PS_MASK | R_VTCR_VS_MASK | R_VTCR_HA_MASK | R_VTCR_HD_MASK | \
67
+ R_VTCR_DS_MASK)
94
+
68
+
95
+ for (i = 0; i < num_cpus; i++) {
69
/* Return the value of the TCR controlling this translation regime */
96
+ uint32_t mask = 1 << i;
70
static inline uint64_t regime_tcr(CPUARMState *env, ARMMMUIdx mmu_idx)
97
+ if ((s->cpuwait & mask) && !(value & mask)) {
98
+ /* Powering up CPU 0 */
99
+ arm_set_cpu_on_and_reset(i);
100
+ }
101
+ }
102
+ s->cpuwait = value;
103
+}
104
+
105
static void iotkit_sysctl_write(void *opaque, hwaddr offset,
106
uint64_t value, unsigned size)
107
{
71
{
108
@@ -XXX,XX +XXX,XX @@ static void iotkit_sysctl_write(void *opaque, hwaddr offset,
72
@@ -XXX,XX +XXX,XX @@ static inline uint64_t regime_tcr(CPUARMState *env, ARMMMUIdx mmu_idx)
109
set_init_vtor(0, s->initsvtor0);
73
}
110
break;
74
if (mmu_idx == ARMMMUIdx_Stage2_S) {
111
case A_CPUWAIT:
75
/*
112
- if ((s->cpuwait & 1) && !(value & 1)) {
76
- * Note: Secure stage 2 nominally shares fields from VTCR_EL2, but
113
- /* Powering up CPU 0 */
77
- * those are not currently used by QEMU, so just return VSTCR_EL2.
114
- arm_set_cpu_on_and_reset(0);
78
+ * Secure stage 2 shares fields from VTCR_EL2. We merge those
115
+ switch (s->sse_version) {
79
+ * in with the VSTCR_EL2 value to synthesize a single VTCR_EL2 format
116
+ case ARMSSE_IOTKIT:
80
+ * value so the callers don't need to special case this.
117
+ case ARMSSE_SSE200:
81
+ *
118
+ cpuwait_write(s, value);
82
+ * If a future architecture change defines bits in VSTCR_EL2 that
119
+ break;
83
+ * overlap with these VTCR_EL2 fields we may need to revisit this.
120
+ case ARMSSE_SSE300:
84
*/
121
+ /* In SSE300 this is reserved (for INITSVTOR2) */
85
- return env->cp15.vstcr_el2;
122
+ goto bad_offset;
86
+ uint64_t v = env->cp15.vstcr_el2 & ~VTCR_SHARED_FIELD_MASK;
123
+ default:
87
+ v |= env->cp15.vtcr_el2 & VTCR_SHARED_FIELD_MASK;
124
+ g_assert_not_reached();
88
+ return v;
125
}
89
}
126
- if ((s->cpuwait & 2) && !(value & 2)) {
90
return env->cp15.tcr_el[regime_el(env, mmu_idx)];
127
- /* Powering up CPU 1 */
91
}
128
- arm_set_cpu_on_and_reset(1);
129
- }
130
- s->cpuwait = value;
131
break;
132
case A_WICCTRL:
133
- qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl WICCTRL unimplemented\n");
134
- s->wicctrl = value;
135
+ switch (s->sse_version) {
136
+ case ARMSSE_IOTKIT:
137
+ case ARMSSE_SSE200:
138
+ qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl WICCTRL unimplemented\n");
139
+ s->wicctrl = value;
140
+ break;
141
+ case ARMSSE_SSE300:
142
+ /* In SSE300 this offset is CPUWAIT */
143
+ cpuwait_write(s, value);
144
+ break;
145
+ default:
146
+ g_assert_not_reached();
147
+ }
148
break;
149
case A_SECDBGSET:
150
/* write-1-to-set */
151
@@ -XXX,XX +XXX,XX @@ static void iotkit_sysctl_write(void *opaque, hwaddr offset,
152
qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl EWCTRL unimplemented\n");
153
s->ewctrl = value;
154
break;
155
+ case ARMSSE_SSE300:
156
+ /* In SSE300 this offset is is NMI_ENABLE */
157
+ qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl NMI_ENABLE unimplemented\n");
158
+ s->nmi_enable = value;
159
+ break;
160
default:
161
g_assert_not_reached();
162
}
163
@@ -XXX,XX +XXX,XX @@ static void iotkit_sysctl_write(void *opaque, hwaddr offset,
164
qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl NMI_ENABLE unimplemented\n");
165
s->nmi_enable = value;
166
break;
167
+ case ARMSSE_SSE300:
168
+ /* In SSE300 this is reserved (for INITSVTOR3) */
169
+ goto bad_offset;
170
default:
171
g_assert_not_reached();
172
}
173
--
92
--
174
2.20.1
93
2.25.1
175
176
diff view generated by jsdifflib
1
From: Xuzhou Cheng <xuzhou.cheng@windriver.com>
1
From: Hao Wu <wuhaotsh@google.com>
2
2
3
Add a Xilinx CSU DMA module to ZynqMP SoC, and connent the stream
3
The correct bit for the CONV bit in NPCM7XX ADC is bit 13. This patch
4
link of GQSPI to CSU DMA.
4
fixes that in the module, and also lower the IRQ when the guest
5
is done handling an interrupt event from the ADC module.
5
6
6
Signed-off-by: Xuzhou Cheng <xuzhou.cheng@windriver.com>
7
Signed-off-by: Hao Wu <wuhaotsh@google.com>
7
Signed-off-by: Bin Meng <bin.meng@windriver.com>
8
Reviewed-by: Patrick Venture<venture@google.com>
8
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Message-id: 20210303135254.3970-4-bmeng.cn@gmail.com
10
Message-id: 20220714182836.89602-4-wuhaotsh@google.com
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
---
12
include/hw/arm/xlnx-zynqmp.h | 2 ++
13
hw/adc/npcm7xx_adc.c | 2 +-
13
hw/arm/xlnx-zynqmp.c | 12 ++++++++++++
14
tests/qtest/npcm7xx_adc-test.c | 2 +-
14
hw/arm/Kconfig | 1 +
15
2 files changed, 2 insertions(+), 2 deletions(-)
15
3 files changed, 15 insertions(+)
16
16
17
diff --git a/include/hw/arm/xlnx-zynqmp.h b/include/hw/arm/xlnx-zynqmp.h
17
diff --git a/hw/adc/npcm7xx_adc.c b/hw/adc/npcm7xx_adc.c
18
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
19
--- a/include/hw/arm/xlnx-zynqmp.h
19
--- a/hw/adc/npcm7xx_adc.c
20
+++ b/include/hw/arm/xlnx-zynqmp.h
20
+++ b/hw/adc/npcm7xx_adc.c
21
@@ -XXX,XX +XXX,XX @@ REG32(NPCM7XX_ADC_DATA, 0x4)
22
#define NPCM7XX_ADC_CON_INT BIT(18)
23
#define NPCM7XX_ADC_CON_EN BIT(17)
24
#define NPCM7XX_ADC_CON_RST BIT(16)
25
-#define NPCM7XX_ADC_CON_CONV BIT(14)
26
+#define NPCM7XX_ADC_CON_CONV BIT(13)
27
#define NPCM7XX_ADC_CON_DIV(rv) extract32(rv, 1, 8)
28
29
#define NPCM7XX_ADC_MAX_RESULT 1023
30
diff --git a/tests/qtest/npcm7xx_adc-test.c b/tests/qtest/npcm7xx_adc-test.c
31
index XXXXXXX..XXXXXXX 100644
32
--- a/tests/qtest/npcm7xx_adc-test.c
33
+++ b/tests/qtest/npcm7xx_adc-test.c
21
@@ -XXX,XX +XXX,XX @@
34
@@ -XXX,XX +XXX,XX @@
22
#include "target/arm/cpu.h"
35
#define CON_INT BIT(18)
23
#include "qom/object.h"
36
#define CON_EN BIT(17)
24
#include "net/can_emu.h"
37
#define CON_RST BIT(16)
25
+#include "hw/dma/xlnx_csu_dma.h"
38
-#define CON_CONV BIT(14)
26
39
+#define CON_CONV BIT(13)
27
#define TYPE_XLNX_ZYNQMP "xlnx,zynqmp"
40
#define CON_DIV(rv) extract32(rv, 1, 8)
28
OBJECT_DECLARE_SIMPLE_TYPE(XlnxZynqMPState, XLNX_ZYNQMP)
41
29
@@ -XXX,XX +XXX,XX @@ struct XlnxZynqMPState {
42
#define FST_RDST BIT(1)
30
XlnxZynqMPRTC rtc;
31
XlnxZDMA gdma[XLNX_ZYNQMP_NUM_GDMA_CH];
32
XlnxZDMA adma[XLNX_ZYNQMP_NUM_ADMA_CH];
33
+ XlnxCSUDMA qspi_dma;
34
35
char *boot_cpu;
36
ARMCPU *boot_cpu_ptr;
37
diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c
38
index XXXXXXX..XXXXXXX 100644
39
--- a/hw/arm/xlnx-zynqmp.c
40
+++ b/hw/arm/xlnx-zynqmp.c
41
@@ -XXX,XX +XXX,XX @@
42
#define QSPI_ADDR 0xff0f0000
43
#define LQSPI_ADDR 0xc0000000
44
#define QSPI_IRQ 15
45
+#define QSPI_DMA_ADDR 0xff0f0800
46
47
#define DP_ADDR 0xfd4a0000
48
#define DP_IRQ 113
49
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_init(Object *obj)
50
for (i = 0; i < XLNX_ZYNQMP_NUM_ADMA_CH; i++) {
51
object_initialize_child(obj, "adma[*]", &s->adma[i], TYPE_XLNX_ZDMA);
52
}
53
+
54
+ object_initialize_child(obj, "qspi-dma", &s->qspi_dma, TYPE_XLNX_CSU_DMA);
55
}
56
57
static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
58
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
59
sysbus_connect_irq(SYS_BUS_DEVICE(&s->adma[i]), 0,
60
gic_spi[adma_ch_intr[i]]);
61
}
62
+
63
+ if (!sysbus_realize(SYS_BUS_DEVICE(&s->qspi_dma), errp)) {
64
+ return;
65
+ }
66
+
67
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->qspi_dma), 0, QSPI_DMA_ADDR);
68
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->qspi_dma), 0, gic_spi[QSPI_IRQ]);
69
+ object_property_set_link(OBJECT(&s->qspi), "stream-connected-dma",
70
+ OBJECT(&s->qspi_dma), errp);
71
}
72
73
static Property xlnx_zynqmp_props[] = {
74
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
75
index XXXXXXX..XXXXXXX 100644
76
--- a/hw/arm/Kconfig
77
+++ b/hw/arm/Kconfig
78
@@ -XXX,XX +XXX,XX @@ config XLNX_ZYNQMP_ARM
79
select SSI_M25P80
80
select XILINX_AXI
81
select XILINX_SPIPS
82
+ select XLNX_CSU_DMA
83
select XLNX_ZYNQMP
84
select XLNX_ZDMA
85
86
--
43
--
87
2.20.1
44
2.25.1
88
89
diff view generated by jsdifflib
1
The Clock framework allows users to specify a callback which is
1
From: Hao Wu <wuhaotsh@google.com>
2
called after the clock's period has been updated. Some users need to
3
also have a callback which is called before the clock period is
4
updated.
5
2
6
As the first step in adding support for notifying Clock users on
3
Our sensor test requires both reading and writing from a sensor's
7
pre-update events, add an argument to the ClockCallback to specify
4
QOM property. So we need to make the input of ADC module R/W instead
8
what event is being notified, and add an argument to the various
5
of write only for that to work.
9
functions for registering a callback to specify which events are
10
of interest to that callback.
11
6
12
Note that the documentation update renders correct the previously
7
Signed-off-by: Hao Wu <wuhaotsh@google.com>
13
incorrect claim in 'Adding a new clock' that callbacks "will be
8
Reviewed-by: Titus Rwantare <titusr@google.com>
14
explained in a following section".
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Message-id: 20220714182836.89602-5-wuhaotsh@google.com
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
13
hw/adc/npcm7xx_adc.c | 2 +-
14
1 file changed, 1 insertion(+), 1 deletion(-)
15
15
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
18
Reviewed-by: Luc Michel <luc@lmichel.fr>
19
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
20
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
21
Message-id: 20210219144617.4782-2-peter.maydell@linaro.org
22
---
23
docs/devel/clocks.rst | 52 +++++++++++++++++++++++++++-----
24
include/hw/clock.h | 21 +++++++++++--
25
include/hw/qdev-clock.h | 17 ++++++++---
26
hw/adc/npcm7xx_adc.c | 2 +-
27
hw/arm/armsse.c | 9 +++---
28
hw/char/cadence_uart.c | 4 +--
29
hw/char/ibex_uart.c | 4 +--
30
hw/char/pl011.c | 5 +--
31
hw/core/clock.c | 21 ++++++++++---
32
hw/core/qdev-clock.c | 8 +++--
33
hw/mips/cps.c | 2 +-
34
hw/misc/bcm2835_cprman.c | 23 ++++++++------
35
hw/misc/npcm7xx_clk.c | 26 +++++++++++++---
36
hw/misc/npcm7xx_pwm.c | 2 +-
37
hw/misc/zynq_slcr.c | 5 +--
38
hw/timer/cmsdk-apb-dualtimer.c | 5 +--
39
hw/timer/cmsdk-apb-timer.c | 4 +--
40
hw/timer/npcm7xx_timer.c | 2 +-
41
hw/watchdog/cmsdk-apb-watchdog.c | 5 +--
42
target/mips/cpu.c | 2 +-
43
20 files changed, 161 insertions(+), 58 deletions(-)
44
45
diff --git a/docs/devel/clocks.rst b/docs/devel/clocks.rst
46
index XXXXXXX..XXXXXXX 100644
47
--- a/docs/devel/clocks.rst
48
+++ b/docs/devel/clocks.rst
49
@@ -XXX,XX +XXX,XX @@ Adding clocks to a device must be done during the init method of the Device
50
instance.
51
52
To add an input clock to a device, the function ``qdev_init_clock_in()``
53
-must be used. It takes the name, a callback and an opaque parameter
54
-for the callback (this will be explained in a following section).
55
+must be used. It takes the name, a callback, an opaque parameter
56
+for the callback and a mask of events when the callback should be
57
+called (this will be explained in a following section).
58
Output is simpler; only the name is required. Typically::
59
60
- qdev_init_clock_in(DEVICE(dev), "clk_in", clk_in_callback, dev);
61
+ qdev_init_clock_in(DEVICE(dev), "clk_in", clk_in_callback, dev, ClockUpdate);
62
qdev_init_clock_out(DEVICE(dev), "clk_out");
63
64
Both functions return the created Clock pointer, which should be saved in the
65
@@ -XXX,XX +XXX,XX @@ output.
66
* callback for the input clock (see "Callback on input clock
67
* change" section below for more information).
68
*/
69
- static void clk_in_callback(void *opaque);
70
+ static void clk_in_callback(void *opaque, ClockEvent event);
71
72
/*
73
* static array describing clocks:
74
@@ -XXX,XX +XXX,XX @@ output.
75
* the clk_out field of a MyDeviceState structure.
76
*/
77
static const ClockPortInitArray mydev_clocks = {
78
- QDEV_CLOCK_IN(MyDeviceState, clk_in, clk_in_callback),
79
+ QDEV_CLOCK_IN(MyDeviceState, clk_in, clk_in_callback, ClockUpdate),
80
QDEV_CLOCK_OUT(MyDeviceState, clk_out),
81
QDEV_CLOCK_END
82
};
83
@@ -XXX,XX +XXX,XX @@ nothing else to do. This value will be propagated to other clocks when
84
connecting the clocks together and devices will fetch the right value during
85
the first reset.
86
87
+Clock callbacks
88
+---------------
89
+
90
+You can give a clock a callback function in several ways:
91
+
92
+ * by passing it as an argument to ``qdev_init_clock_in()``
93
+ * as an argument to the ``QDEV_CLOCK_IN()`` macro initializing an
94
+ array to be passed to ``qdev_init_clocks()``
95
+ * by directly calling the ``clock_set_callback()`` function
96
+
97
+The callback function must be of this type:
98
+
99
+.. code-block:: c
100
+
101
+ typedef void ClockCallback(void *opaque, ClockEvent event);
102
+
103
+The ``opaque`` argument is the pointer passed to ``qdev_init_clock_in()``
104
+or ``clock_set_callback()``; for ``qdev_init_clocks()`` it is the
105
+``dev`` device pointer.
106
+
107
+The ``event`` argument specifies why the callback has been called.
108
+When you register the callback you specify a mask of ClockEvent values
109
+that you are interested in. The callback will only be called for those
110
+events.
111
+
112
+The events currently supported are:
113
+
114
+ * ``ClockUpdate`` : called after the input clock's period has changed
115
+
116
+Note that a clock only has one callback: it is not possible to register
117
+different functions for different events. You must register a single
118
+callback which listens for all of the events you are interested in,
119
+and use the ``event`` argument to identify which event has happened.
120
+
121
Retrieving clocks from a device
122
-------------------------------
123
124
@@ -XXX,XX +XXX,XX @@ object during device instance init. For example:
125
.. code-block:: c
126
127
clk = qdev_init_clock_in(DEVICE(dev), "clk-in", clk_in_callback,
128
- dev);
129
+ dev, ClockUpdate);
130
/* set initial value to 10ns / 100MHz */
131
clock_set_ns(clk, 10);
132
133
@@ -XXX,XX +XXX,XX @@ next lowest integer. This implies some inaccuracy due to the rounding,
134
so be cautious about using it in calculations.
135
136
It is also possible to register a callback on clock frequency changes.
137
-Here is an example:
138
+Here is an example, which assumes that ``clock_callback`` has been
139
+specified as the callback for the ``ClockUpdate`` event:
140
141
.. code-block:: c
142
143
- void clock_callback(void *opaque) {
144
+ void clock_callback(void *opaque, ClockEvent event) {
145
MyDeviceState *s = (MyDeviceState *) opaque;
146
/*
147
* 'opaque' is the argument passed to qdev_init_clock_in();
148
diff --git a/include/hw/clock.h b/include/hw/clock.h
149
index XXXXXXX..XXXXXXX 100644
150
--- a/include/hw/clock.h
151
+++ b/include/hw/clock.h
152
@@ -XXX,XX +XXX,XX @@
153
#define TYPE_CLOCK "clock"
154
OBJECT_DECLARE_SIMPLE_TYPE(Clock, CLOCK)
155
156
-typedef void ClockCallback(void *opaque);
157
+/*
158
+ * Argument to ClockCallback functions indicating why the callback
159
+ * has been called. A mask of these values logically ORed together
160
+ * is used to specify which events are interesting when the callback
161
+ * is registered, so these values must all be different bit values.
162
+ */
163
+typedef enum ClockEvent {
164
+ ClockUpdate = 1, /* Clock period has just updated */
165
+} ClockEvent;
166
+
167
+typedef void ClockCallback(void *opaque, ClockEvent event);
168
169
/*
170
* clock store a value representing the clock's period in 2^-32ns unit.
171
@@ -XXX,XX +XXX,XX @@ typedef void ClockCallback(void *opaque);
172
* @canonical_path: clock path string cache (used for trace purpose)
173
* @callback: called when clock changes
174
* @callback_opaque: argument for @callback
175
+ * @callback_events: mask of events when callback should be called
176
* @source: source (or parent in clock tree) of the clock
177
* @children: list of clocks connected to this one (it is their source)
178
* @sibling: structure used to form a clock list
179
@@ -XXX,XX +XXX,XX @@ struct Clock {
180
char *canonical_path;
181
ClockCallback *callback;
182
void *callback_opaque;
183
+ unsigned int callback_events;
184
185
/* Clocks are organized in a clock tree */
186
Clock *source;
187
@@ -XXX,XX +XXX,XX @@ Clock *clock_new(Object *parent, const char *name);
188
* @clk: the clock to register the callback into
189
* @cb: the callback function
190
* @opaque: the argument to the callback
191
+ * @events: the events the callback should be called for
192
+ * (logical OR of ClockEvent enum values)
193
*
194
* Register a callback called on every clock update.
195
+ * Note that a clock has only one callback: you cannot register
196
+ * different callback functions for different events.
197
*/
198
-void clock_set_callback(Clock *clk, ClockCallback *cb, void *opaque);
199
+void clock_set_callback(Clock *clk, ClockCallback *cb,
200
+ void *opaque, unsigned int events);
201
202
/**
203
* clock_clear_callback:
204
diff --git a/include/hw/qdev-clock.h b/include/hw/qdev-clock.h
205
index XXXXXXX..XXXXXXX 100644
206
--- a/include/hw/qdev-clock.h
207
+++ b/include/hw/qdev-clock.h
208
@@ -XXX,XX +XXX,XX @@
209
* @name: the name of the clock (can't be NULL).
210
* @callback: optional callback to be called on update or NULL.
211
* @opaque: argument for the callback
212
+ * @events: the events the callback should be called for
213
+ * (logical OR of ClockEvent enum values)
214
* @returns: a pointer to the newly added clock
215
*
216
* Add an input clock to device @dev as a clock named @name.
217
@@ -XXX,XX +XXX,XX @@
218
* The callback will be called with @opaque as opaque parameter.
219
*/
220
Clock *qdev_init_clock_in(DeviceState *dev, const char *name,
221
- ClockCallback *callback, void *opaque);
222
+ ClockCallback *callback, void *opaque,
223
+ unsigned int events);
224
225
/**
226
* qdev_init_clock_out:
227
@@ -XXX,XX +XXX,XX @@ void qdev_finalize_clocklist(DeviceState *dev);
228
* @output: indicates whether the clock is input or output
229
* @callback: for inputs, optional callback to be called on clock's update
230
* with device as opaque
231
+ * @callback_events: mask of ClockEvent values for when callback is called
232
* @offset: optional offset to store the ClockIn or ClockOut pointer in device
233
* state structure (0 means unused)
234
*/
235
@@ -XXX,XX +XXX,XX @@ struct ClockPortInitElem {
236
const char *name;
237
bool is_output;
238
ClockCallback *callback;
239
+ unsigned int callback_events;
240
size_t offset;
241
};
242
243
@@ -XXX,XX +XXX,XX @@ struct ClockPortInitElem {
244
(offsetof(devstate, field) + \
245
type_check(Clock *, typeof_field(devstate, field)))
246
247
-#define QDEV_CLOCK(out_not_in, devstate, field, cb) { \
248
+#define QDEV_CLOCK(out_not_in, devstate, field, cb, cbevents) { \
249
.name = (stringify(field)), \
250
.is_output = out_not_in, \
251
.callback = cb, \
252
+ .callback_events = cbevents, \
253
.offset = clock_offset_value(devstate, field), \
254
}
255
256
@@ -XXX,XX +XXX,XX @@ struct ClockPortInitElem {
257
* @field: a field in @_devstate (must be Clock*)
258
* @callback: (for input only) callback (or NULL) to be called with the device
259
* state as argument
260
+ * @cbevents: (for input only) ClockEvent mask for when callback is called
261
*
262
* The name of the clock will be derived from @field
263
*/
264
-#define QDEV_CLOCK_IN(devstate, field, callback) \
265
- QDEV_CLOCK(false, devstate, field, callback)
266
+#define QDEV_CLOCK_IN(devstate, field, callback, cbevents) \
267
+ QDEV_CLOCK(false, devstate, field, callback, cbevents)
268
269
#define QDEV_CLOCK_OUT(devstate, field) \
270
- QDEV_CLOCK(true, devstate, field, NULL)
271
+ QDEV_CLOCK(true, devstate, field, NULL, 0)
272
273
#define QDEV_CLOCK_END { .name = NULL }
274
275
diff --git a/hw/adc/npcm7xx_adc.c b/hw/adc/npcm7xx_adc.c
16
diff --git a/hw/adc/npcm7xx_adc.c b/hw/adc/npcm7xx_adc.c
276
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
277
--- a/hw/adc/npcm7xx_adc.c
18
--- a/hw/adc/npcm7xx_adc.c
278
+++ b/hw/adc/npcm7xx_adc.c
19
+++ b/hw/adc/npcm7xx_adc.c
279
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_adc_init(Object *obj)
20
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_adc_init(Object *obj)
280
memory_region_init_io(&s->iomem, obj, &npcm7xx_adc_ops, s,
281
TYPE_NPCM7XX_ADC, 4 * KiB);
282
sysbus_init_mmio(sbd, &s->iomem);
283
- s->clock = qdev_init_clock_in(DEVICE(s), "clock", NULL, NULL);
284
+ s->clock = qdev_init_clock_in(DEVICE(s), "clock", NULL, NULL, 0);
285
21
286
for (i = 0; i < NPCM7XX_ADC_NUM_INPUTS; ++i) {
22
for (i = 0; i < NPCM7XX_ADC_NUM_INPUTS; ++i) {
287
object_property_add_uint32_ptr(obj, "adci[*]",
23
object_property_add_uint32_ptr(obj, "adci[*]",
288
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
24
- &s->adci[i], OBJ_PROP_FLAG_WRITE);
289
index XXXXXXX..XXXXXXX 100644
25
+ &s->adci[i], OBJ_PROP_FLAG_READWRITE);
290
--- a/hw/arm/armsse.c
291
+++ b/hw/arm/armsse.c
292
@@ -XXX,XX +XXX,XX @@ static void armsse_forward_sec_resp_cfg(ARMSSE *s)
293
qdev_connect_gpio_out(dev_splitter, 2, s->sec_resp_cfg_in);
294
}
295
296
-static void armsse_mainclk_update(void *opaque)
297
+static void armsse_mainclk_update(void *opaque, ClockEvent event)
298
{
299
ARMSSE *s = ARM_SSE(opaque);
300
+
301
/*
302
* Set system_clock_scale from our Clock input; this is what
303
* controls the tick rate of the CPU SysTick timer.
304
@@ -XXX,XX +XXX,XX @@ static void armsse_init(Object *obj)
305
assert(info->num_cpus <= SSE_MAX_CPUS);
306
307
s->mainclk = qdev_init_clock_in(DEVICE(s), "MAINCLK",
308
- armsse_mainclk_update, s);
309
- s->s32kclk = qdev_init_clock_in(DEVICE(s), "S32KCLK", NULL, NULL);
310
+ armsse_mainclk_update, s, ClockUpdate);
311
+ s->s32kclk = qdev_init_clock_in(DEVICE(s), "S32KCLK", NULL, NULL, 0);
312
313
memory_region_init(&s->container, obj, "armsse-container", UINT64_MAX);
314
315
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
316
sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->container);
317
318
/* Set initial system_clock_scale from MAINCLK */
319
- armsse_mainclk_update(s);
320
+ armsse_mainclk_update(s, ClockUpdate);
321
}
322
323
static void armsse_idau_check(IDAUInterface *ii, uint32_t address,
324
diff --git a/hw/char/cadence_uart.c b/hw/char/cadence_uart.c
325
index XXXXXXX..XXXXXXX 100644
326
--- a/hw/char/cadence_uart.c
327
+++ b/hw/char/cadence_uart.c
328
@@ -XXX,XX +XXX,XX @@ static void cadence_uart_realize(DeviceState *dev, Error **errp)
329
uart_event, NULL, s, NULL, true);
330
}
331
332
-static void cadence_uart_refclk_update(void *opaque)
333
+static void cadence_uart_refclk_update(void *opaque, ClockEvent event)
334
{
335
CadenceUARTState *s = opaque;
336
337
@@ -XXX,XX +XXX,XX @@ static void cadence_uart_init(Object *obj)
338
sysbus_init_irq(sbd, &s->irq);
339
340
s->refclk = qdev_init_clock_in(DEVICE(obj), "refclk",
341
- cadence_uart_refclk_update, s);
342
+ cadence_uart_refclk_update, s, ClockUpdate);
343
/* initialize the frequency in case the clock remains unconnected */
344
clock_set_hz(s->refclk, UART_DEFAULT_REF_CLK);
345
346
diff --git a/hw/char/ibex_uart.c b/hw/char/ibex_uart.c
347
index XXXXXXX..XXXXXXX 100644
348
--- a/hw/char/ibex_uart.c
349
+++ b/hw/char/ibex_uart.c
350
@@ -XXX,XX +XXX,XX @@ static void ibex_uart_write(void *opaque, hwaddr addr,
351
}
26
}
352
}
27
object_property_add_uint32_ptr(obj, "vref",
353
28
&s->vref, OBJ_PROP_FLAG_WRITE);
354
-static void ibex_uart_clk_update(void *opaque)
355
+static void ibex_uart_clk_update(void *opaque, ClockEvent event)
356
{
357
IbexUartState *s = opaque;
358
359
@@ -XXX,XX +XXX,XX @@ static void ibex_uart_init(Object *obj)
360
IbexUartState *s = IBEX_UART(obj);
361
362
s->f_clk = qdev_init_clock_in(DEVICE(obj), "f_clock",
363
- ibex_uart_clk_update, s);
364
+ ibex_uart_clk_update, s, ClockUpdate);
365
clock_set_hz(s->f_clk, IBEX_UART_CLOCK);
366
367
sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->tx_watermark);
368
diff --git a/hw/char/pl011.c b/hw/char/pl011.c
369
index XXXXXXX..XXXXXXX 100644
370
--- a/hw/char/pl011.c
371
+++ b/hw/char/pl011.c
372
@@ -XXX,XX +XXX,XX @@ static void pl011_event(void *opaque, QEMUChrEvent event)
373
pl011_put_fifo(opaque, 0x400);
374
}
375
376
-static void pl011_clock_update(void *opaque)
377
+static void pl011_clock_update(void *opaque, ClockEvent event)
378
{
379
PL011State *s = PL011(opaque);
380
381
@@ -XXX,XX +XXX,XX @@ static void pl011_init(Object *obj)
382
sysbus_init_irq(sbd, &s->irq[i]);
383
}
384
385
- s->clk = qdev_init_clock_in(DEVICE(obj), "clk", pl011_clock_update, s);
386
+ s->clk = qdev_init_clock_in(DEVICE(obj), "clk", pl011_clock_update, s,
387
+ ClockUpdate);
388
389
s->read_trigger = 1;
390
s->ifl = 0x12;
391
diff --git a/hw/core/clock.c b/hw/core/clock.c
392
index XXXXXXX..XXXXXXX 100644
393
--- a/hw/core/clock.c
394
+++ b/hw/core/clock.c
395
@@ -XXX,XX +XXX,XX @@ Clock *clock_new(Object *parent, const char *name)
396
return clk;
397
}
398
399
-void clock_set_callback(Clock *clk, ClockCallback *cb, void *opaque)
400
+void clock_set_callback(Clock *clk, ClockCallback *cb, void *opaque,
401
+ unsigned int events)
402
{
403
clk->callback = cb;
404
clk->callback_opaque = opaque;
405
+ clk->callback_events = events;
406
}
407
408
void clock_clear_callback(Clock *clk)
409
{
410
- clock_set_callback(clk, NULL, NULL);
411
+ clock_set_callback(clk, NULL, NULL, 0);
412
}
413
414
bool clock_set(Clock *clk, uint64_t period)
415
@@ -XXX,XX +XXX,XX @@ bool clock_set(Clock *clk, uint64_t period)
416
return true;
417
}
418
419
+static void clock_call_callback(Clock *clk, ClockEvent event)
420
+{
421
+ /*
422
+ * Call the Clock's callback for this event, if it has one and
423
+ * is interested in this event.
424
+ */
425
+ if (clk->callback && (clk->callback_events & event)) {
426
+ clk->callback(clk->callback_opaque, event);
427
+ }
428
+}
429
+
430
static void clock_propagate_period(Clock *clk, bool call_callbacks)
431
{
432
Clock *child;
433
@@ -XXX,XX +XXX,XX @@ static void clock_propagate_period(Clock *clk, bool call_callbacks)
434
trace_clock_update(CLOCK_PATH(child), CLOCK_PATH(clk),
435
CLOCK_PERIOD_TO_HZ(clk->period),
436
call_callbacks);
437
- if (call_callbacks && child->callback) {
438
- child->callback(child->callback_opaque);
439
+ if (call_callbacks) {
440
+ clock_call_callback(child, ClockUpdate);
441
}
442
clock_propagate_period(child, call_callbacks);
443
}
444
diff --git a/hw/core/qdev-clock.c b/hw/core/qdev-clock.c
445
index XXXXXXX..XXXXXXX 100644
446
--- a/hw/core/qdev-clock.c
447
+++ b/hw/core/qdev-clock.c
448
@@ -XXX,XX +XXX,XX @@ Clock *qdev_init_clock_out(DeviceState *dev, const char *name)
449
}
450
451
Clock *qdev_init_clock_in(DeviceState *dev, const char *name,
452
- ClockCallback *callback, void *opaque)
453
+ ClockCallback *callback, void *opaque,
454
+ unsigned int events)
455
{
456
NamedClockList *ncl;
457
458
@@ -XXX,XX +XXX,XX @@ Clock *qdev_init_clock_in(DeviceState *dev, const char *name,
459
ncl = qdev_init_clocklist(dev, name, false, NULL);
460
461
if (callback) {
462
- clock_set_callback(ncl->clock, callback, opaque);
463
+ clock_set_callback(ncl->clock, callback, opaque, events);
464
}
465
return ncl->clock;
466
}
467
@@ -XXX,XX +XXX,XX @@ void qdev_init_clocks(DeviceState *dev, const ClockPortInitArray clocks)
468
if (elem->is_output) {
469
*clkp = qdev_init_clock_out(dev, elem->name);
470
} else {
471
- *clkp = qdev_init_clock_in(dev, elem->name, elem->callback, dev);
472
+ *clkp = qdev_init_clock_in(dev, elem->name, elem->callback, dev,
473
+ elem->callback_events);
474
}
475
}
476
}
477
diff --git a/hw/mips/cps.c b/hw/mips/cps.c
478
index XXXXXXX..XXXXXXX 100644
479
--- a/hw/mips/cps.c
480
+++ b/hw/mips/cps.c
481
@@ -XXX,XX +XXX,XX @@ static void mips_cps_init(Object *obj)
482
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
483
MIPSCPSState *s = MIPS_CPS(obj);
484
485
- s->clock = qdev_init_clock_in(DEVICE(obj), "clk-in", NULL, NULL);
486
+ s->clock = qdev_init_clock_in(DEVICE(obj), "clk-in", NULL, NULL, 0);
487
/*
488
* Cover entire address space as there do not seem to be any
489
* constraints for the base address of CPC and GIC.
490
diff --git a/hw/misc/bcm2835_cprman.c b/hw/misc/bcm2835_cprman.c
491
index XXXXXXX..XXXXXXX 100644
492
--- a/hw/misc/bcm2835_cprman.c
493
+++ b/hw/misc/bcm2835_cprman.c
494
@@ -XXX,XX +XXX,XX @@ static void pll_update(CprmanPllState *pll)
495
clock_update_hz(pll->out, freq);
496
}
497
498
-static void pll_xosc_update(void *opaque)
499
+static void pll_xosc_update(void *opaque, ClockEvent event)
500
{
501
pll_update(CPRMAN_PLL(opaque));
502
}
503
@@ -XXX,XX +XXX,XX @@ static void pll_init(Object *obj)
504
{
505
CprmanPllState *s = CPRMAN_PLL(obj);
506
507
- s->xosc_in = qdev_init_clock_in(DEVICE(s), "xosc-in", pll_xosc_update, s);
508
+ s->xosc_in = qdev_init_clock_in(DEVICE(s), "xosc-in", pll_xosc_update,
509
+ s, ClockUpdate);
510
s->out = qdev_init_clock_out(DEVICE(s), "out");
511
}
512
513
@@ -XXX,XX +XXX,XX @@ static void pll_update_all_channels(BCM2835CprmanState *s,
514
}
515
}
516
517
-static void pll_channel_pll_in_update(void *opaque)
518
+static void pll_channel_pll_in_update(void *opaque, ClockEvent event)
519
{
520
pll_channel_update(CPRMAN_PLL_CHANNEL(opaque));
521
}
522
@@ -XXX,XX +XXX,XX @@ static void pll_channel_init(Object *obj)
523
CprmanPllChannelState *s = CPRMAN_PLL_CHANNEL(obj);
524
525
s->pll_in = qdev_init_clock_in(DEVICE(s), "pll-in",
526
- pll_channel_pll_in_update, s);
527
+ pll_channel_pll_in_update, s,
528
+ ClockUpdate);
529
s->out = qdev_init_clock_out(DEVICE(s), "out");
530
}
531
532
@@ -XXX,XX +XXX,XX @@ static void clock_mux_update(CprmanClockMuxState *mux)
533
clock_update_hz(mux->out, freq);
534
}
535
536
-static void clock_mux_src_update(void *opaque)
537
+static void clock_mux_src_update(void *opaque, ClockEvent event)
538
{
539
CprmanClockMuxState **backref = opaque;
540
CprmanClockMuxState *s = *backref;
541
@@ -XXX,XX +XXX,XX @@ static void clock_mux_init(Object *obj)
542
s->backref[i] = s;
543
s->srcs[i] = qdev_init_clock_in(DEVICE(s), name,
544
clock_mux_src_update,
545
- &s->backref[i]);
546
+ &s->backref[i],
547
+ ClockUpdate);
548
g_free(name);
549
}
550
551
@@ -XXX,XX +XXX,XX @@ static void dsi0hsck_mux_update(CprmanDsi0HsckMuxState *s)
552
clock_update(s->out, clock_get(src));
553
}
554
555
-static void dsi0hsck_mux_in_update(void *opaque)
556
+static void dsi0hsck_mux_in_update(void *opaque, ClockEvent event)
557
{
558
dsi0hsck_mux_update(CPRMAN_DSI0HSCK_MUX(opaque));
559
}
560
@@ -XXX,XX +XXX,XX @@ static void dsi0hsck_mux_init(Object *obj)
561
CprmanDsi0HsckMuxState *s = CPRMAN_DSI0HSCK_MUX(obj);
562
DeviceState *dev = DEVICE(obj);
563
564
- s->plla_in = qdev_init_clock_in(dev, "plla-in", dsi0hsck_mux_in_update, s);
565
- s->plld_in = qdev_init_clock_in(dev, "plld-in", dsi0hsck_mux_in_update, s);
566
+ s->plla_in = qdev_init_clock_in(dev, "plla-in", dsi0hsck_mux_in_update,
567
+ s, ClockUpdate);
568
+ s->plld_in = qdev_init_clock_in(dev, "plld-in", dsi0hsck_mux_in_update,
569
+ s, ClockUpdate);
570
s->out = qdev_init_clock_out(DEVICE(s), "out");
571
}
572
573
diff --git a/hw/misc/npcm7xx_clk.c b/hw/misc/npcm7xx_clk.c
574
index XXXXXXX..XXXXXXX 100644
575
--- a/hw/misc/npcm7xx_clk.c
576
+++ b/hw/misc/npcm7xx_clk.c
577
@@ -XXX,XX +XXX,XX @@ static const DividerInitInfo divider_init_info_list[] = {
578
},
579
};
580
581
+static void npcm7xx_clk_update_pll_cb(void *opaque, ClockEvent event)
582
+{
583
+ npcm7xx_clk_update_pll(opaque);
584
+}
585
+
586
static void npcm7xx_clk_pll_init(Object *obj)
587
{
588
NPCM7xxClockPLLState *pll = NPCM7XX_CLOCK_PLL(obj);
589
590
pll->clock_in = qdev_init_clock_in(DEVICE(pll), "clock-in",
591
- npcm7xx_clk_update_pll, pll);
592
+ npcm7xx_clk_update_pll_cb, pll,
593
+ ClockUpdate);
594
pll->clock_out = qdev_init_clock_out(DEVICE(pll), "clock-out");
595
}
596
597
+static void npcm7xx_clk_update_sel_cb(void *opaque, ClockEvent event)
598
+{
599
+ npcm7xx_clk_update_sel(opaque);
600
+}
601
+
602
static void npcm7xx_clk_sel_init(Object *obj)
603
{
604
int i;
605
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_clk_sel_init(Object *obj)
606
for (i = 0; i < NPCM7XX_CLK_SEL_MAX_INPUT; ++i) {
607
sel->clock_in[i] = qdev_init_clock_in(DEVICE(sel),
608
g_strdup_printf("clock-in[%d]", i),
609
- npcm7xx_clk_update_sel, sel);
610
+ npcm7xx_clk_update_sel_cb, sel, ClockUpdate);
611
}
612
sel->clock_out = qdev_init_clock_out(DEVICE(sel), "clock-out");
613
}
614
+
615
+static void npcm7xx_clk_update_divider_cb(void *opaque, ClockEvent event)
616
+{
617
+ npcm7xx_clk_update_divider(opaque);
618
+}
619
+
620
static void npcm7xx_clk_divider_init(Object *obj)
621
{
622
NPCM7xxClockDividerState *div = NPCM7XX_CLOCK_DIVIDER(obj);
623
624
div->clock_in = qdev_init_clock_in(DEVICE(div), "clock-in",
625
- npcm7xx_clk_update_divider, div);
626
+ npcm7xx_clk_update_divider_cb,
627
+ div, ClockUpdate);
628
div->clock_out = qdev_init_clock_out(DEVICE(div), "clock-out");
629
}
630
631
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_clk_init_clock_hierarchy(NPCM7xxCLKState *s)
632
{
633
int i;
634
635
- s->clkref = qdev_init_clock_in(DEVICE(s), "clkref", NULL, NULL);
636
+ s->clkref = qdev_init_clock_in(DEVICE(s), "clkref", NULL, NULL, 0);
637
638
/* First pass: init all converter modules */
639
QEMU_BUILD_BUG_ON(ARRAY_SIZE(pll_init_info_list) != NPCM7XX_CLOCK_NR_PLLS);
640
diff --git a/hw/misc/npcm7xx_pwm.c b/hw/misc/npcm7xx_pwm.c
641
index XXXXXXX..XXXXXXX 100644
642
--- a/hw/misc/npcm7xx_pwm.c
643
+++ b/hw/misc/npcm7xx_pwm.c
644
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_pwm_init(Object *obj)
645
memory_region_init_io(&s->iomem, obj, &npcm7xx_pwm_ops, s,
646
TYPE_NPCM7XX_PWM, 4 * KiB);
647
sysbus_init_mmio(sbd, &s->iomem);
648
- s->clock = qdev_init_clock_in(DEVICE(s), "clock", NULL, NULL);
649
+ s->clock = qdev_init_clock_in(DEVICE(s), "clock", NULL, NULL, 0);
650
651
for (i = 0; i < NPCM7XX_PWM_PER_MODULE; ++i) {
652
object_property_add_uint32_ptr(obj, "freq[*]",
653
diff --git a/hw/misc/zynq_slcr.c b/hw/misc/zynq_slcr.c
654
index XXXXXXX..XXXXXXX 100644
655
--- a/hw/misc/zynq_slcr.c
656
+++ b/hw/misc/zynq_slcr.c
657
@@ -XXX,XX +XXX,XX @@ static void zynq_slcr_propagate_clocks(ZynqSLCRState *s)
658
clock_propagate(s->uart1_ref_clk);
659
}
660
661
-static void zynq_slcr_ps_clk_callback(void *opaque)
662
+static void zynq_slcr_ps_clk_callback(void *opaque, ClockEvent event)
663
{
664
ZynqSLCRState *s = (ZynqSLCRState *) opaque;
665
+
666
zynq_slcr_compute_clocks(s);
667
zynq_slcr_propagate_clocks(s);
668
}
669
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps slcr_ops = {
670
};
671
672
static const ClockPortInitArray zynq_slcr_clocks = {
673
- QDEV_CLOCK_IN(ZynqSLCRState, ps_clk, zynq_slcr_ps_clk_callback),
674
+ QDEV_CLOCK_IN(ZynqSLCRState, ps_clk, zynq_slcr_ps_clk_callback, ClockUpdate),
675
QDEV_CLOCK_OUT(ZynqSLCRState, uart0_ref_clk),
676
QDEV_CLOCK_OUT(ZynqSLCRState, uart1_ref_clk),
677
QDEV_CLOCK_END
678
diff --git a/hw/timer/cmsdk-apb-dualtimer.c b/hw/timer/cmsdk-apb-dualtimer.c
679
index XXXXXXX..XXXXXXX 100644
680
--- a/hw/timer/cmsdk-apb-dualtimer.c
681
+++ b/hw/timer/cmsdk-apb-dualtimer.c
682
@@ -XXX,XX +XXX,XX @@ static void cmsdk_apb_dualtimer_reset(DeviceState *dev)
683
s->timeritop = 0;
684
}
685
686
-static void cmsdk_apb_dualtimer_clk_update(void *opaque)
687
+static void cmsdk_apb_dualtimer_clk_update(void *opaque, ClockEvent event)
688
{
689
CMSDKAPBDualTimer *s = CMSDK_APB_DUALTIMER(opaque);
690
int i;
691
@@ -XXX,XX +XXX,XX @@ static void cmsdk_apb_dualtimer_init(Object *obj)
692
sysbus_init_irq(sbd, &s->timermod[i].timerint);
693
}
694
s->timclk = qdev_init_clock_in(DEVICE(s), "TIMCLK",
695
- cmsdk_apb_dualtimer_clk_update, s);
696
+ cmsdk_apb_dualtimer_clk_update, s,
697
+ ClockUpdate);
698
}
699
700
static void cmsdk_apb_dualtimer_realize(DeviceState *dev, Error **errp)
701
diff --git a/hw/timer/cmsdk-apb-timer.c b/hw/timer/cmsdk-apb-timer.c
702
index XXXXXXX..XXXXXXX 100644
703
--- a/hw/timer/cmsdk-apb-timer.c
704
+++ b/hw/timer/cmsdk-apb-timer.c
705
@@ -XXX,XX +XXX,XX @@ static void cmsdk_apb_timer_reset(DeviceState *dev)
706
ptimer_transaction_commit(s->timer);
707
}
708
709
-static void cmsdk_apb_timer_clk_update(void *opaque)
710
+static void cmsdk_apb_timer_clk_update(void *opaque, ClockEvent event)
711
{
712
CMSDKAPBTimer *s = CMSDK_APB_TIMER(opaque);
713
714
@@ -XXX,XX +XXX,XX @@ static void cmsdk_apb_timer_init(Object *obj)
715
sysbus_init_mmio(sbd, &s->iomem);
716
sysbus_init_irq(sbd, &s->timerint);
717
s->pclk = qdev_init_clock_in(DEVICE(s), "pclk",
718
- cmsdk_apb_timer_clk_update, s);
719
+ cmsdk_apb_timer_clk_update, s, ClockUpdate);
720
}
721
722
static void cmsdk_apb_timer_realize(DeviceState *dev, Error **errp)
723
diff --git a/hw/timer/npcm7xx_timer.c b/hw/timer/npcm7xx_timer.c
724
index XXXXXXX..XXXXXXX 100644
725
--- a/hw/timer/npcm7xx_timer.c
726
+++ b/hw/timer/npcm7xx_timer.c
727
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_timer_init(Object *obj)
728
sysbus_init_mmio(sbd, &s->iomem);
729
qdev_init_gpio_out_named(dev, &w->reset_signal,
730
NPCM7XX_WATCHDOG_RESET_GPIO_OUT, 1);
731
- s->clock = qdev_init_clock_in(dev, "clock", NULL, NULL);
732
+ s->clock = qdev_init_clock_in(dev, "clock", NULL, NULL, 0);
733
}
734
735
static const VMStateDescription vmstate_npcm7xx_base_timer = {
736
diff --git a/hw/watchdog/cmsdk-apb-watchdog.c b/hw/watchdog/cmsdk-apb-watchdog.c
737
index XXXXXXX..XXXXXXX 100644
738
--- a/hw/watchdog/cmsdk-apb-watchdog.c
739
+++ b/hw/watchdog/cmsdk-apb-watchdog.c
740
@@ -XXX,XX +XXX,XX @@ static void cmsdk_apb_watchdog_reset(DeviceState *dev)
741
ptimer_transaction_commit(s->timer);
742
}
743
744
-static void cmsdk_apb_watchdog_clk_update(void *opaque)
745
+static void cmsdk_apb_watchdog_clk_update(void *opaque, ClockEvent event)
746
{
747
CMSDKAPBWatchdog *s = CMSDK_APB_WATCHDOG(opaque);
748
749
@@ -XXX,XX +XXX,XX @@ static void cmsdk_apb_watchdog_init(Object *obj)
750
sysbus_init_mmio(sbd, &s->iomem);
751
sysbus_init_irq(sbd, &s->wdogint);
752
s->wdogclk = qdev_init_clock_in(DEVICE(s), "WDOGCLK",
753
- cmsdk_apb_watchdog_clk_update, s);
754
+ cmsdk_apb_watchdog_clk_update, s,
755
+ ClockUpdate);
756
757
s->is_luminary = false;
758
s->id = cmsdk_apb_watchdog_id;
759
diff --git a/target/mips/cpu.c b/target/mips/cpu.c
760
index XXXXXXX..XXXXXXX 100644
761
--- a/target/mips/cpu.c
762
+++ b/target/mips/cpu.c
763
@@ -XXX,XX +XXX,XX @@ static void mips_cpu_initfn(Object *obj)
764
MIPSCPUClass *mcc = MIPS_CPU_GET_CLASS(obj);
765
766
cpu_set_cpustate_pointers(cpu);
767
- cpu->clock = qdev_init_clock_in(DEVICE(obj), "clk-in", NULL, cpu);
768
+ cpu->clock = qdev_init_clock_in(DEVICE(obj), "clk-in", NULL, cpu, 0);
769
env->cpu_model = mcc->cpu_def;
770
}
771
772
--
29
--
773
2.20.1
30
2.25.1
774
775
diff view generated by jsdifflib
Deleted patch
1
Add a new callback event type ClockPreUpdate, which is called on
2
period changes before the period is updated.
3
1
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Luc Michel <luc@lmichel.fr>
6
Reviewed-by: Hao Wu <wuhaotsh@google.com>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Message-id: 20210219144617.4782-3-peter.maydell@linaro.org
10
---
11
docs/devel/clocks.rst | 9 ++++++++-
12
include/hw/clock.h | 1 +
13
hw/core/clock.c | 3 +++
14
3 files changed, 12 insertions(+), 1 deletion(-)
15
16
diff --git a/docs/devel/clocks.rst b/docs/devel/clocks.rst
17
index XXXXXXX..XXXXXXX 100644
18
--- a/docs/devel/clocks.rst
19
+++ b/docs/devel/clocks.rst
20
@@ -XXX,XX +XXX,XX @@ events.
21
22
The events currently supported are:
23
24
- * ``ClockUpdate`` : called after the input clock's period has changed
25
+ * ``ClockPreUpdate`` : called when the input clock's period is about to
26
+ update. This is useful if the device needs to do some action for
27
+ which it needs to know the old value of the clock period. During
28
+ this callback, Clock API functions like ``clock_get()`` or
29
+ ``clock_ticks_to_ns()`` will use the old period.
30
+ * ``ClockUpdate`` : called after the input clock's period has changed.
31
+ During this callback, Clock API functions like ``clock_ticks_to_ns()``
32
+ will use the new period.
33
34
Note that a clock only has one callback: it is not possible to register
35
different functions for different events. You must register a single
36
diff --git a/include/hw/clock.h b/include/hw/clock.h
37
index XXXXXXX..XXXXXXX 100644
38
--- a/include/hw/clock.h
39
+++ b/include/hw/clock.h
40
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_SIMPLE_TYPE(Clock, CLOCK)
41
*/
42
typedef enum ClockEvent {
43
ClockUpdate = 1, /* Clock period has just updated */
44
+ ClockPreUpdate = 2, /* Clock period is about to update */
45
} ClockEvent;
46
47
typedef void ClockCallback(void *opaque, ClockEvent event);
48
diff --git a/hw/core/clock.c b/hw/core/clock.c
49
index XXXXXXX..XXXXXXX 100644
50
--- a/hw/core/clock.c
51
+++ b/hw/core/clock.c
52
@@ -XXX,XX +XXX,XX @@ static void clock_propagate_period(Clock *clk, bool call_callbacks)
53
54
QLIST_FOREACH(child, &clk->children, sibling) {
55
if (child->period != clk->period) {
56
+ if (call_callbacks) {
57
+ clock_call_callback(child, ClockPreUpdate);
58
+ }
59
child->period = clk->period;
60
trace_clock_update(CLOCK_PATH(child), CLOCK_PATH(clk),
61
CLOCK_PERIOD_TO_HZ(clk->period),
62
--
63
2.20.1
64
65
diff view generated by jsdifflib
Deleted patch
1
Use the new clock_ns_to_ticks() function in npcm7xx_timer where
2
appropriate.
3
1
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Luc Michel <luc@lmichel.fr>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Reviewed-by: Hao Wu <wuhaotsh@google.com>
8
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Message-id: 20210219144617.4782-5-peter.maydell@linaro.org
10
---
11
hw/timer/npcm7xx_timer.c | 4 ++--
12
1 file changed, 2 insertions(+), 2 deletions(-)
13
14
diff --git a/hw/timer/npcm7xx_timer.c b/hw/timer/npcm7xx_timer.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/timer/npcm7xx_timer.c
17
+++ b/hw/timer/npcm7xx_timer.c
18
@@ -XXX,XX +XXX,XX @@ static int64_t npcm7xx_timer_count_to_ns(NPCM7xxTimer *t, uint32_t count)
19
/* Convert a time interval in nanoseconds to a timer cycle count. */
20
static uint32_t npcm7xx_timer_ns_to_count(NPCM7xxTimer *t, int64_t ns)
21
{
22
- return ns / clock_ticks_to_ns(t->ctrl->clock,
23
- npcm7xx_tcsr_prescaler(t->tcsr));
24
+ return clock_ns_to_ticks(t->ctrl->clock, ns) /
25
+ npcm7xx_tcsr_prescaler(t->tcsr);
26
}
27
28
static uint32_t npcm7xx_watchdog_timer_prescaler(const NPCM7xxWatchdogTimer *t)
29
--
30
2.20.1
31
32
diff view generated by jsdifflib
Deleted patch
1
We model Arm "Subsystems for Embedded" SoC subsystems using generic
2
code which is split into various sub-devices which are configurable
3
by QOM properties to handle the behaviour differences between the SSE
4
subsystems we implement. Currently the only sub-device which needs
5
to change is the IOTKIT_SYSCTL device, and we do this with a mix of
6
properties that directly specify divergent behaviours (eg
7
CPUWAIT_RST) and passing it the SYS_VERSION register value as a way
8
for it to distinguish IoTKit from SSE-200.
9
1
10
The "pass SYS_VERSION" approach is already a bit hacky, since the
11
IOTKIT_SYSCTL device has to know that the different part of the
12
register value happens to be bits [31:28]. For SSE-300 this register
13
is renamed SOC_IDENTITY and has a different format entirely, all of
14
whose fields can be configured by the SoC integrator when they
15
integrate the SSE into their SoC, and so "pass SYS_VERSION" breaks
16
down completely.
17
18
Switch to using a simple integer property representing an
19
internal-to-QEMU enumeration of the SSE flavour. For the moment we
20
only need this in IOTKIT_SYSCTL, but as we add SSE-300 support a few
21
of the other devices will also need to know.
22
23
We define and permit a value for the SSE-300 so we can start using
24
it in subsequent commits which add SSE-300 support.
25
26
The now-redundant is_sse200 flag in IoTKitSysCtl will be removed
27
in the following commit.
28
29
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
30
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
31
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
32
Message-id: 20210219144617.4782-6-peter.maydell@linaro.org
33
---
34
include/hw/arm/armsse-version.h | 42 +++++++++++++++++++++++++++++++++
35
include/hw/misc/iotkit-sysctl.h | 7 +++---
36
hw/arm/armsse.c | 8 +++++--
37
hw/misc/iotkit-sysctl.c | 11 +++++----
38
4 files changed, 58 insertions(+), 10 deletions(-)
39
create mode 100644 include/hw/arm/armsse-version.h
40
41
diff --git a/include/hw/arm/armsse-version.h b/include/hw/arm/armsse-version.h
42
new file mode 100644
43
index XXXXXXX..XXXXXXX
44
--- /dev/null
45
+++ b/include/hw/arm/armsse-version.h
46
@@ -XXX,XX +XXX,XX @@
47
+/*
48
+ * ARM SSE (Subsystems for Embedded): IoTKit, SSE-200
49
+ *
50
+ * Copyright (c) 2020 Linaro Limited
51
+ * Written by Peter Maydell
52
+ *
53
+ * This program is free software; you can redistribute it and/or modify
54
+ * it under the terms of the GNU General Public License version 2 or
55
+ * (at your option) any later version.
56
+ */
57
+
58
+#ifndef ARMSSE_VERSION_H
59
+#define ARMSSE_VERSION_H
60
+
61
+
62
+/*
63
+ * Define an enumeration of the possible values of the sse-version
64
+ * property implemented by various sub-devices of the SSE, and
65
+ * a validation function that checks that a valid value has been passed.
66
+ * These are arbitrary QEMU-internal values (nobody should be creating
67
+ * the sub-devices of the SSE except for the SSE object itself), but
68
+ * we pick obvious numbers for the benefit of people debugging with gdb.
69
+ */
70
+enum {
71
+ ARMSSE_IOTKIT = 0,
72
+ ARMSSE_SSE200 = 200,
73
+ ARMSSE_SSE300 = 300,
74
+};
75
+
76
+static inline bool armsse_version_valid(uint32_t sse_version)
77
+{
78
+ switch (sse_version) {
79
+ case ARMSSE_IOTKIT:
80
+ case ARMSSE_SSE200:
81
+ case ARMSSE_SSE300:
82
+ return true;
83
+ default:
84
+ return false;
85
+ }
86
+}
87
+
88
+#endif
89
diff --git a/include/hw/misc/iotkit-sysctl.h b/include/hw/misc/iotkit-sysctl.h
90
index XXXXXXX..XXXXXXX 100644
91
--- a/include/hw/misc/iotkit-sysctl.h
92
+++ b/include/hw/misc/iotkit-sysctl.h
93
@@ -XXX,XX +XXX,XX @@
94
* "system control register" blocks.
95
*
96
* QEMU interface:
97
- * + QOM property "SYS_VERSION": value of the SYS_VERSION register of the
98
- * system information block of the SSE
99
- * (used to identify whether to provide SSE-200-only registers)
100
+ * + QOM property "sse-version": indicates which SSE version this is part of
101
+ * (used to identify whether to provide SSE-200-only registers, etc)
102
* + sysbus MMIO region 0: the system information register bank
103
* + sysbus MMIO region 1: the system control register bank
104
*/
105
@@ -XXX,XX +XXX,XX @@ struct IoTKitSysCtl {
106
uint32_t pdcm_pd_sram3_sense;
107
108
/* Properties */
109
- uint32_t sys_version;
110
+ uint32_t sse_version;
111
uint32_t cpuwait_rst;
112
uint32_t initsvtor0_rst;
113
uint32_t initsvtor1_rst;
114
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
115
index XXXXXXX..XXXXXXX 100644
116
--- a/hw/arm/armsse.c
117
+++ b/hw/arm/armsse.c
118
@@ -XXX,XX +XXX,XX @@
119
#include "migration/vmstate.h"
120
#include "hw/registerfields.h"
121
#include "hw/arm/armsse.h"
122
+#include "hw/arm/armsse-version.h"
123
#include "hw/arm/boot.h"
124
#include "hw/irq.h"
125
#include "hw/qdev-clock.h"
126
@@ -XXX,XX +XXX,XX @@ typedef enum SysConfigFormat {
127
128
struct ARMSSEInfo {
129
const char *name;
130
+ uint32_t sse_version;
131
int sram_banks;
132
int num_cpus;
133
uint32_t sys_version;
134
@@ -XXX,XX +XXX,XX @@ static Property armsse_properties[] = {
135
static const ARMSSEInfo armsse_variants[] = {
136
{
137
.name = TYPE_IOTKIT,
138
+ .sse_version = ARMSSE_IOTKIT,
139
.sram_banks = 1,
140
.num_cpus = 1,
141
.sys_version = 0x41743,
142
@@ -XXX,XX +XXX,XX @@ static const ARMSSEInfo armsse_variants[] = {
143
},
144
{
145
.name = TYPE_SSE200,
146
+ .sse_version = ARMSSE_SSE200,
147
.sram_banks = 4,
148
.num_cpus = 2,
149
.sys_version = 0x22041743,
150
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
151
/* System information registers */
152
sysbus_mmio_map(SYS_BUS_DEVICE(&s->sysinfo), 0, 0x40020000);
153
/* System control registers */
154
- object_property_set_int(OBJECT(&s->sysctl), "SYS_VERSION",
155
- info->sys_version, &error_abort);
156
+ object_property_set_int(OBJECT(&s->sysctl), "sse-version",
157
+ info->sse_version, &error_abort);
158
object_property_set_int(OBJECT(&s->sysctl), "CPUWAIT_RST",
159
info->cpuwait_rst, &error_abort);
160
object_property_set_int(OBJECT(&s->sysctl), "INITSVTOR0_RST",
161
diff --git a/hw/misc/iotkit-sysctl.c b/hw/misc/iotkit-sysctl.c
162
index XXXXXXX..XXXXXXX 100644
163
--- a/hw/misc/iotkit-sysctl.c
164
+++ b/hw/misc/iotkit-sysctl.c
165
@@ -XXX,XX +XXX,XX @@
166
#include "hw/registerfields.h"
167
#include "hw/misc/iotkit-sysctl.h"
168
#include "hw/qdev-properties.h"
169
+#include "hw/arm/armsse-version.h"
170
#include "target/arm/arm-powerctl.h"
171
#include "target/arm/cpu.h"
172
173
@@ -XXX,XX +XXX,XX @@ static void iotkit_sysctl_realize(DeviceState *dev, Error **errp)
174
{
175
IoTKitSysCtl *s = IOTKIT_SYSCTL(dev);
176
177
- /* The top 4 bits of the SYS_VERSION register tell us if we're an SSE-200 */
178
- if (extract32(s->sys_version, 28, 4) == 2) {
179
- s->is_sse200 = true;
180
+ if (!armsse_version_valid(s->sse_version)) {
181
+ error_setg(errp, "invalid sse-version value %d", s->sse_version);
182
+ return;
183
}
184
+
185
+ s->is_sse200 = s->sse_version == ARMSSE_SSE200;
186
}
187
188
static bool sse200_needed(void *opaque)
189
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription iotkit_sysctl_vmstate = {
190
};
191
192
static Property iotkit_sysctl_props[] = {
193
- DEFINE_PROP_UINT32("SYS_VERSION", IoTKitSysCtl, sys_version, 0),
194
+ DEFINE_PROP_UINT32("sse-version", IoTKitSysCtl, sse_version, 0),
195
DEFINE_PROP_UINT32("CPUWAIT_RST", IoTKitSysCtl, cpuwait_rst, 0),
196
DEFINE_PROP_UINT32("INITSVTOR0_RST", IoTKitSysCtl, initsvtor0_rst,
197
0x10000000),
198
--
199
2.20.1
200
201
diff view generated by jsdifflib
Deleted patch
1
Remove the is_sse200 flag in favour of just directly testing the new
2
sse_version field.
3
1
4
Since some of these registers exist in the SSE-300 but some do not or
5
have different behaviour, we expand out the if() statements in the
6
read and write functions into switch()es, so we have an easy place to
7
put SSE-300 specific behaviour.
8
9
(Until we do add the SSE-300 behaviour, the thing preventing us
10
reaching the "unreachable" default cases is that armsse.c doesn't
11
yet pass us an ARMSSE_SSE300 version.)
12
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
15
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
16
Message-id: 20210219144617.4782-7-peter.maydell@linaro.org
17
---
18
include/hw/misc/iotkit-sysctl.h | 2 -
19
hw/misc/iotkit-sysctl.c | 256 +++++++++++++++++++++++---------
20
2 files changed, 187 insertions(+), 71 deletions(-)
21
22
diff --git a/include/hw/misc/iotkit-sysctl.h b/include/hw/misc/iotkit-sysctl.h
23
index XXXXXXX..XXXXXXX 100644
24
--- a/include/hw/misc/iotkit-sysctl.h
25
+++ b/include/hw/misc/iotkit-sysctl.h
26
@@ -XXX,XX +XXX,XX @@ struct IoTKitSysCtl {
27
uint32_t cpuwait_rst;
28
uint32_t initsvtor0_rst;
29
uint32_t initsvtor1_rst;
30
-
31
- bool is_sse200;
32
};
33
34
#endif
35
diff --git a/hw/misc/iotkit-sysctl.c b/hw/misc/iotkit-sysctl.c
36
index XXXXXXX..XXXXXXX 100644
37
--- a/hw/misc/iotkit-sysctl.c
38
+++ b/hw/misc/iotkit-sysctl.c
39
@@ -XXX,XX +XXX,XX @@ static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
40
r = s->secure_debug;
41
break;
42
case A_SCSECCTRL:
43
- if (!s->is_sse200) {
44
+ switch (s->sse_version) {
45
+ case ARMSSE_IOTKIT:
46
goto bad_offset;
47
+ case ARMSSE_SSE200:
48
+ r = s->scsecctrl;
49
+ break;
50
+ default:
51
+ g_assert_not_reached();
52
}
53
- r = s->scsecctrl;
54
break;
55
case A_FCLK_DIV:
56
- if (!s->is_sse200) {
57
+ switch (s->sse_version) {
58
+ case ARMSSE_IOTKIT:
59
goto bad_offset;
60
+ case ARMSSE_SSE200:
61
+ r = s->fclk_div;
62
+ break;
63
+ default:
64
+ g_assert_not_reached();
65
}
66
- r = s->fclk_div;
67
break;
68
case A_SYSCLK_DIV:
69
- if (!s->is_sse200) {
70
+ switch (s->sse_version) {
71
+ case ARMSSE_IOTKIT:
72
goto bad_offset;
73
+ case ARMSSE_SSE200:
74
+ r = s->sysclk_div;
75
+ break;
76
+ default:
77
+ g_assert_not_reached();
78
}
79
- r = s->sysclk_div;
80
break;
81
case A_CLOCK_FORCE:
82
- if (!s->is_sse200) {
83
+ switch (s->sse_version) {
84
+ case ARMSSE_IOTKIT:
85
goto bad_offset;
86
+ case ARMSSE_SSE200:
87
+ r = s->clock_force;
88
+ break;
89
+ default:
90
+ g_assert_not_reached();
91
}
92
- r = s->clock_force;
93
break;
94
case A_RESET_SYNDROME:
95
r = s->reset_syndrome;
96
@@ -XXX,XX +XXX,XX @@ static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
97
r = s->initsvtor0;
98
break;
99
case A_INITSVTOR1:
100
- if (!s->is_sse200) {
101
+ switch (s->sse_version) {
102
+ case ARMSSE_IOTKIT:
103
goto bad_offset;
104
+ case ARMSSE_SSE200:
105
+ r = s->initsvtor1;
106
+ break;
107
+ default:
108
+ g_assert_not_reached();
109
}
110
- r = s->initsvtor1;
111
break;
112
case A_CPUWAIT:
113
r = s->cpuwait;
114
break;
115
case A_NMI_ENABLE:
116
- /* In IoTKit this is named BUSWAIT but is marked reserved, R/O, zero */
117
- if (!s->is_sse200) {
118
+ switch (s->sse_version) {
119
+ case ARMSSE_IOTKIT:
120
+ /* In IoTKit this is named BUSWAIT but marked reserved, R/O, zero */
121
r = 0;
122
break;
123
+ case ARMSSE_SSE200:
124
+ r = s->nmi_enable;
125
+ break;
126
+ default:
127
+ g_assert_not_reached();
128
}
129
- r = s->nmi_enable;
130
break;
131
case A_WICCTRL:
132
r = s->wicctrl;
133
break;
134
case A_EWCTRL:
135
- if (!s->is_sse200) {
136
+ switch (s->sse_version) {
137
+ case ARMSSE_IOTKIT:
138
goto bad_offset;
139
+ case ARMSSE_SSE200:
140
+ r = s->ewctrl;
141
+ break;
142
+ default:
143
+ g_assert_not_reached();
144
}
145
- r = s->ewctrl;
146
break;
147
case A_PDCM_PD_SYS_SENSE:
148
- if (!s->is_sse200) {
149
+ switch (s->sse_version) {
150
+ case ARMSSE_IOTKIT:
151
goto bad_offset;
152
+ case ARMSSE_SSE200:
153
+ r = s->pdcm_pd_sys_sense;
154
+ break;
155
+ default:
156
+ g_assert_not_reached();
157
}
158
- r = s->pdcm_pd_sys_sense;
159
break;
160
case A_PDCM_PD_SRAM0_SENSE:
161
- if (!s->is_sse200) {
162
+ switch (s->sse_version) {
163
+ case ARMSSE_IOTKIT:
164
goto bad_offset;
165
+ case ARMSSE_SSE200:
166
+ r = s->pdcm_pd_sram0_sense;
167
+ break;
168
+ default:
169
+ g_assert_not_reached();
170
}
171
- r = s->pdcm_pd_sram0_sense;
172
break;
173
case A_PDCM_PD_SRAM1_SENSE:
174
- if (!s->is_sse200) {
175
+ switch (s->sse_version) {
176
+ case ARMSSE_IOTKIT:
177
goto bad_offset;
178
+ case ARMSSE_SSE200:
179
+ r = s->pdcm_pd_sram1_sense;
180
+ break;
181
+ default:
182
+ g_assert_not_reached();
183
}
184
- r = s->pdcm_pd_sram1_sense;
185
break;
186
case A_PDCM_PD_SRAM2_SENSE:
187
- if (!s->is_sse200) {
188
+ switch (s->sse_version) {
189
+ case ARMSSE_IOTKIT:
190
goto bad_offset;
191
+ case ARMSSE_SSE200:
192
+ r = s->pdcm_pd_sram2_sense;
193
+ break;
194
+ default:
195
+ g_assert_not_reached();
196
}
197
- r = s->pdcm_pd_sram2_sense;
198
break;
199
case A_PDCM_PD_SRAM3_SENSE:
200
- if (!s->is_sse200) {
201
+ switch (s->sse_version) {
202
+ case ARMSSE_IOTKIT:
203
goto bad_offset;
204
+ case ARMSSE_SSE200:
205
+ r = s->pdcm_pd_sram3_sense;
206
+ break;
207
+ default:
208
+ g_assert_not_reached();
209
}
210
- r = s->pdcm_pd_sram3_sense;
211
break;
212
case A_PID4 ... A_CID3:
213
r = sysctl_id[(offset - A_PID4) / 4];
214
@@ -XXX,XX +XXX,XX @@ static void iotkit_sysctl_write(void *opaque, hwaddr offset,
215
}
216
break;
217
case A_SCSECCTRL:
218
- if (!s->is_sse200) {
219
+ switch (s->sse_version) {
220
+ case ARMSSE_IOTKIT:
221
goto bad_offset;
222
+ case ARMSSE_SSE200:
223
+ qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl SCSECCTRL unimplemented\n");
224
+ s->scsecctrl = value;
225
+ break;
226
+ default:
227
+ g_assert_not_reached();
228
}
229
- qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl SCSECCTRL unimplemented\n");
230
- s->scsecctrl = value;
231
break;
232
case A_FCLK_DIV:
233
- if (!s->is_sse200) {
234
+ switch (s->sse_version) {
235
+ case ARMSSE_IOTKIT:
236
goto bad_offset;
237
+ case ARMSSE_SSE200:
238
+ qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl FCLK_DIV unimplemented\n");
239
+ s->fclk_div = value;
240
+ break;
241
+ default:
242
+ g_assert_not_reached();
243
}
244
- qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl FCLK_DIV unimplemented\n");
245
- s->fclk_div = value;
246
break;
247
case A_SYSCLK_DIV:
248
- if (!s->is_sse200) {
249
+ switch (s->sse_version) {
250
+ case ARMSSE_IOTKIT:
251
goto bad_offset;
252
+ case ARMSSE_SSE200:
253
+ qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl SYSCLK_DIV unimplemented\n");
254
+ s->sysclk_div = value;
255
+ break;
256
+ default:
257
+ g_assert_not_reached();
258
}
259
- qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl SYSCLK_DIV unimplemented\n");
260
- s->sysclk_div = value;
261
break;
262
case A_CLOCK_FORCE:
263
- if (!s->is_sse200) {
264
+ switch (s->sse_version) {
265
+ case ARMSSE_IOTKIT:
266
goto bad_offset;
267
+ case ARMSSE_SSE200:
268
+ qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl CLOCK_FORCE unimplemented\n");
269
+ s->clock_force = value;
270
+ break;
271
+ default:
272
+ g_assert_not_reached();
273
}
274
- qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl CLOCK_FORCE unimplemented\n");
275
- s->clock_force = value;
276
break;
277
case A_INITSVTOR1:
278
- if (!s->is_sse200) {
279
+ switch (s->sse_version) {
280
+ case ARMSSE_IOTKIT:
281
goto bad_offset;
282
+ case ARMSSE_SSE200:
283
+ s->initsvtor1 = value;
284
+ set_init_vtor(1, s->initsvtor1);
285
+ break;
286
+ default:
287
+ g_assert_not_reached();
288
}
289
- s->initsvtor1 = value;
290
- set_init_vtor(1, s->initsvtor1);
291
break;
292
case A_EWCTRL:
293
- if (!s->is_sse200) {
294
+ switch (s->sse_version) {
295
+ case ARMSSE_IOTKIT:
296
goto bad_offset;
297
+ case ARMSSE_SSE200:
298
+ qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl EWCTRL unimplemented\n");
299
+ s->ewctrl = value;
300
+ break;
301
+ default:
302
+ g_assert_not_reached();
303
}
304
- qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl EWCTRL unimplemented\n");
305
- s->ewctrl = value;
306
break;
307
case A_PDCM_PD_SYS_SENSE:
308
- if (!s->is_sse200) {
309
+ switch (s->sse_version) {
310
+ case ARMSSE_IOTKIT:
311
goto bad_offset;
312
+ case ARMSSE_SSE200:
313
+ qemu_log_mask(LOG_UNIMP,
314
+ "IoTKit SysCtl PDCM_PD_SYS_SENSE unimplemented\n");
315
+ s->pdcm_pd_sys_sense = value;
316
+ break;
317
+ default:
318
+ g_assert_not_reached();
319
}
320
- qemu_log_mask(LOG_UNIMP,
321
- "IoTKit SysCtl PDCM_PD_SYS_SENSE unimplemented\n");
322
- s->pdcm_pd_sys_sense = value;
323
break;
324
case A_PDCM_PD_SRAM0_SENSE:
325
- if (!s->is_sse200) {
326
+ switch (s->sse_version) {
327
+ case ARMSSE_IOTKIT:
328
goto bad_offset;
329
+ case ARMSSE_SSE200:
330
+ qemu_log_mask(LOG_UNIMP,
331
+ "IoTKit SysCtl PDCM_PD_SRAM0_SENSE unimplemented\n");
332
+ s->pdcm_pd_sram0_sense = value;
333
+ break;
334
+ default:
335
+ g_assert_not_reached();
336
}
337
- qemu_log_mask(LOG_UNIMP,
338
- "IoTKit SysCtl PDCM_PD_SRAM0_SENSE unimplemented\n");
339
- s->pdcm_pd_sram0_sense = value;
340
break;
341
case A_PDCM_PD_SRAM1_SENSE:
342
- if (!s->is_sse200) {
343
+ switch (s->sse_version) {
344
+ case ARMSSE_IOTKIT:
345
goto bad_offset;
346
+ case ARMSSE_SSE200:
347
+ qemu_log_mask(LOG_UNIMP,
348
+ "IoTKit SysCtl PDCM_PD_SRAM1_SENSE unimplemented\n");
349
+ s->pdcm_pd_sram1_sense = value;
350
+ break;
351
+ default:
352
+ g_assert_not_reached();
353
}
354
- qemu_log_mask(LOG_UNIMP,
355
- "IoTKit SysCtl PDCM_PD_SRAM1_SENSE unimplemented\n");
356
- s->pdcm_pd_sram1_sense = value;
357
break;
358
case A_PDCM_PD_SRAM2_SENSE:
359
- if (!s->is_sse200) {
360
+ switch (s->sse_version) {
361
+ case ARMSSE_IOTKIT:
362
goto bad_offset;
363
+ case ARMSSE_SSE200:
364
+ qemu_log_mask(LOG_UNIMP,
365
+ "IoTKit SysCtl PDCM_PD_SRAM2_SENSE unimplemented\n");
366
+ s->pdcm_pd_sram2_sense = value;
367
+ break;
368
+ default:
369
+ g_assert_not_reached();
370
}
371
- qemu_log_mask(LOG_UNIMP,
372
- "IoTKit SysCtl PDCM_PD_SRAM2_SENSE unimplemented\n");
373
- s->pdcm_pd_sram2_sense = value;
374
break;
375
case A_PDCM_PD_SRAM3_SENSE:
376
- if (!s->is_sse200) {
377
+ switch (s->sse_version) {
378
+ case ARMSSE_IOTKIT:
379
goto bad_offset;
380
+ case ARMSSE_SSE200:
381
+ qemu_log_mask(LOG_UNIMP,
382
+ "IoTKit SysCtl PDCM_PD_SRAM3_SENSE unimplemented\n");
383
+ s->pdcm_pd_sram3_sense = value;
384
+ break;
385
+ default:
386
+ g_assert_not_reached();
387
}
388
- qemu_log_mask(LOG_UNIMP,
389
- "IoTKit SysCtl PDCM_PD_SRAM3_SENSE unimplemented\n");
390
- s->pdcm_pd_sram3_sense = value;
391
break;
392
case A_NMI_ENABLE:
393
/* In IoTKit this is BUSWAIT: reserved, R/O, zero */
394
- if (!s->is_sse200) {
395
+ switch (s->sse_version) {
396
+ case ARMSSE_IOTKIT:
397
goto ro_offset;
398
+ case ARMSSE_SSE200:
399
+ qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl NMI_ENABLE unimplemented\n");
400
+ s->nmi_enable = value;
401
+ break;
402
+ default:
403
+ g_assert_not_reached();
404
}
405
- qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl NMI_ENABLE unimplemented\n");
406
- s->nmi_enable = value;
407
break;
408
case A_SECDBGSTAT:
409
case A_PID4 ... A_CID3:
410
@@ -XXX,XX +XXX,XX @@ static void iotkit_sysctl_realize(DeviceState *dev, Error **errp)
411
error_setg(errp, "invalid sse-version value %d", s->sse_version);
412
return;
413
}
414
-
415
- s->is_sse200 = s->sse_version == ARMSSE_SSE200;
416
}
417
418
static bool sse200_needed(void *opaque)
419
{
420
IoTKitSysCtl *s = IOTKIT_SYSCTL(opaque);
421
422
- return s->is_sse200;
423
+ return s->sse_version == ARMSSE_SSE200;
424
}
425
426
static const VMStateDescription iotkit_sysctl_sse200_vmstate = {
427
--
428
2.20.1
429
430
diff view generated by jsdifflib
Deleted patch
1
The version of the SYSINFO Register Block in the SSE-300 has
2
different CIDR/PIDR register values to the SSE-200; pass in
3
the sse-version property and use it to select the correct
4
ID register values.
5
1
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20210219144617.4782-9-peter.maydell@linaro.org
10
---
11
include/hw/misc/iotkit-sysinfo.h | 1 +
12
hw/arm/armsse.c | 2 ++
13
hw/misc/iotkit-sysinfo.c | 29 +++++++++++++++++++++++++++--
14
3 files changed, 30 insertions(+), 2 deletions(-)
15
16
diff --git a/include/hw/misc/iotkit-sysinfo.h b/include/hw/misc/iotkit-sysinfo.h
17
index XXXXXXX..XXXXXXX 100644
18
--- a/include/hw/misc/iotkit-sysinfo.h
19
+++ b/include/hw/misc/iotkit-sysinfo.h
20
@@ -XXX,XX +XXX,XX @@ struct IoTKitSysInfo {
21
/* Properties */
22
uint32_t sys_version;
23
uint32_t sys_config;
24
+ uint32_t sse_version;
25
};
26
27
#endif
28
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
29
index XXXXXXX..XXXXXXX 100644
30
--- a/hw/arm/armsse.c
31
+++ b/hw/arm/armsse.c
32
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
33
armsse_sys_config_value(s, info), errp)) {
34
return;
35
}
36
+ object_property_set_int(OBJECT(&s->sysinfo), "sse-version",
37
+ info->sse_version, &error_abort);
38
if (!sysbus_realize(SYS_BUS_DEVICE(&s->sysinfo), errp)) {
39
return;
40
}
41
diff --git a/hw/misc/iotkit-sysinfo.c b/hw/misc/iotkit-sysinfo.c
42
index XXXXXXX..XXXXXXX 100644
43
--- a/hw/misc/iotkit-sysinfo.c
44
+++ b/hw/misc/iotkit-sysinfo.c
45
@@ -XXX,XX +XXX,XX @@
46
#include "hw/registerfields.h"
47
#include "hw/misc/iotkit-sysinfo.h"
48
#include "hw/qdev-properties.h"
49
+#include "hw/arm/armsse-version.h"
50
51
REG32(SYS_VERSION, 0x0)
52
REG32(SYS_CONFIG, 0x4)
53
@@ -XXX,XX +XXX,XX @@ static const int sysinfo_id[] = {
54
0x0d, 0xf0, 0x05, 0xb1, /* CID0..CID3 */
55
};
56
57
+static const int sysinfo_sse300_id[] = {
58
+ 0x04, 0x00, 0x00, 0x00, /* PID4..PID7 */
59
+ 0x58, 0xb8, 0x1b, 0x00, /* PID0..PID3 */
60
+ 0x0d, 0xf0, 0x05, 0xb1, /* CID0..CID3 */
61
+};
62
+
63
static uint64_t iotkit_sysinfo_read(void *opaque, hwaddr offset,
64
unsigned size)
65
{
66
@@ -XXX,XX +XXX,XX @@ static uint64_t iotkit_sysinfo_read(void *opaque, hwaddr offset,
67
r = s->sys_config;
68
break;
69
case A_PID4 ... A_CID3:
70
- r = sysinfo_id[(offset - A_PID4) / 4];
71
+ switch (s->sse_version) {
72
+ case ARMSSE_SSE300:
73
+ r = sysinfo_sse300_id[(offset - A_PID4) / 4];
74
+ break;
75
+ default:
76
+ r = sysinfo_id[(offset - A_PID4) / 4];
77
+ break;
78
+ }
79
break;
80
default:
81
qemu_log_mask(LOG_GUEST_ERROR,
82
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps iotkit_sysinfo_ops = {
83
static Property iotkit_sysinfo_props[] = {
84
DEFINE_PROP_UINT32("SYS_VERSION", IoTKitSysInfo, sys_version, 0),
85
DEFINE_PROP_UINT32("SYS_CONFIG", IoTKitSysInfo, sys_config, 0),
86
+ DEFINE_PROP_UINT32("sse-version", IoTKitSysInfo, sse_version, 0),
87
DEFINE_PROP_END_OF_LIST()
88
};
89
90
@@ -XXX,XX +XXX,XX @@ static void iotkit_sysinfo_init(Object *obj)
91
sysbus_init_mmio(sbd, &s->iomem);
92
}
93
94
+static void iotkit_sysinfo_realize(DeviceState *dev, Error **errp)
95
+{
96
+ IoTKitSysInfo *s = IOTKIT_SYSINFO(dev);
97
+
98
+ if (!armsse_version_valid(s->sse_version)) {
99
+ error_setg(errp, "invalid sse-version value %d", s->sse_version);
100
+ return;
101
+ }
102
+}
103
+
104
static void iotkit_sysinfo_class_init(ObjectClass *klass, void *data)
105
{
106
DeviceClass *dc = DEVICE_CLASS(klass);
107
@@ -XXX,XX +XXX,XX @@ static void iotkit_sysinfo_class_init(ObjectClass *klass, void *data)
108
* This device has no guest-modifiable state and so it
109
* does not need a reset function or VMState.
110
*/
111
-
112
+ dc->realize = iotkit_sysinfo_realize;
113
device_class_set_props(dc, iotkit_sysinfo_props);
114
}
115
116
--
117
2.20.1
118
119
diff view generated by jsdifflib
Deleted patch
1
In the SSE-300, the format of the SYS_CONFIG0 register has changed again;
2
pass through the correct value to the SYSINFO register block device.
3
1
4
We drop the old SysConfigFormat enum, which was implemented in the
5
hope that different flavours of SSE would share the same format;
6
since they all seem to be different and we now have an sse_version
7
enum to key off, just use that.
8
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20210219144617.4782-10-peter.maydell@linaro.org
13
---
14
hw/arm/armsse.c | 21 +++++++++------------
15
1 file changed, 9 insertions(+), 12 deletions(-)
16
17
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/arm/armsse.c
20
+++ b/hw/arm/armsse.c
21
@@ -XXX,XX +XXX,XX @@
22
#include "hw/irq.h"
23
#include "hw/qdev-clock.h"
24
25
-/* Format of the System Information block SYS_CONFIG register */
26
-typedef enum SysConfigFormat {
27
- IoTKitFormat,
28
- SSE200Format,
29
-} SysConfigFormat;
30
-
31
struct ARMSSEInfo {
32
const char *name;
33
uint32_t sse_version;
34
@@ -XXX,XX +XXX,XX @@ struct ARMSSEInfo {
35
int num_cpus;
36
uint32_t sys_version;
37
uint32_t cpuwait_rst;
38
- SysConfigFormat sys_config_format;
39
bool has_mhus;
40
bool has_ppus;
41
bool has_cachectrl;
42
@@ -XXX,XX +XXX,XX @@ static const ARMSSEInfo armsse_variants[] = {
43
.num_cpus = 1,
44
.sys_version = 0x41743,
45
.cpuwait_rst = 0,
46
- .sys_config_format = IoTKitFormat,
47
.has_mhus = false,
48
.has_ppus = false,
49
.has_cachectrl = false,
50
@@ -XXX,XX +XXX,XX @@ static const ARMSSEInfo armsse_variants[] = {
51
.num_cpus = 2,
52
.sys_version = 0x22041743,
53
.cpuwait_rst = 2,
54
- .sys_config_format = SSE200Format,
55
.has_mhus = true,
56
.has_ppus = true,
57
.has_cachectrl = true,
58
@@ -XXX,XX +XXX,XX @@ static uint32_t armsse_sys_config_value(ARMSSE *s, const ARMSSEInfo *info)
59
/* Return the SYS_CONFIG value for this SSE */
60
uint32_t sys_config;
61
62
- switch (info->sys_config_format) {
63
- case IoTKitFormat:
64
+ switch (info->sse_version) {
65
+ case ARMSSE_IOTKIT:
66
sys_config = 0;
67
sys_config = deposit32(sys_config, 0, 4, info->sram_banks);
68
sys_config = deposit32(sys_config, 4, 4, s->sram_addr_width - 12);
69
break;
70
- case SSE200Format:
71
+ case ARMSSE_SSE200:
72
sys_config = 0;
73
sys_config = deposit32(sys_config, 0, 4, info->sram_banks);
74
sys_config = deposit32(sys_config, 4, 5, s->sram_addr_width);
75
@@ -XXX,XX +XXX,XX @@ static uint32_t armsse_sys_config_value(ARMSSE *s, const ARMSSEInfo *info)
76
sys_config = deposit32(sys_config, 28, 4, 2);
77
}
78
break;
79
+ case ARMSSE_SSE300:
80
+ sys_config = 0;
81
+ sys_config = deposit32(sys_config, 0, 4, info->sram_banks);
82
+ sys_config = deposit32(sys_config, 4, 5, s->sram_addr_width);
83
+ sys_config = deposit32(sys_config, 16, 3, 3); /* CPU0 = Cortex-M55 */
84
+ break;
85
default:
86
g_assert_not_reached();
87
}
88
--
89
2.20.1
90
91
diff view generated by jsdifflib
Deleted patch
1
For SSE-300, the SYSINFO register block has two new registers:
2
1
3
* SYS_CONFIG1 indicates the config for a potential CPU2 and CPU3;
4
since the SSE-300 can only be configured with a single CPU it
5
is always zero
6
7
* IIDR is the subsystem implementation identity register;
8
its value is set by the SoC integrator, so we plumb this in from
9
the armsse.c code as we do with SYS_VERSION and SYS_CONFIG
10
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
13
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
14
Message-id: 20210219144617.4782-11-peter.maydell@linaro.org
15
---
16
include/hw/misc/iotkit-sysinfo.h | 1 +
17
hw/arm/armsse.c | 5 +++++
18
hw/misc/iotkit-sysinfo.c | 22 ++++++++++++++++++++++
19
3 files changed, 28 insertions(+)
20
21
diff --git a/include/hw/misc/iotkit-sysinfo.h b/include/hw/misc/iotkit-sysinfo.h
22
index XXXXXXX..XXXXXXX 100644
23
--- a/include/hw/misc/iotkit-sysinfo.h
24
+++ b/include/hw/misc/iotkit-sysinfo.h
25
@@ -XXX,XX +XXX,XX @@ struct IoTKitSysInfo {
26
uint32_t sys_version;
27
uint32_t sys_config;
28
uint32_t sse_version;
29
+ uint32_t iidr;
30
};
31
32
#endif
33
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
34
index XXXXXXX..XXXXXXX 100644
35
--- a/hw/arm/armsse.c
36
+++ b/hw/arm/armsse.c
37
@@ -XXX,XX +XXX,XX @@ struct ARMSSEInfo {
38
int sram_banks;
39
int num_cpus;
40
uint32_t sys_version;
41
+ uint32_t iidr;
42
uint32_t cpuwait_rst;
43
bool has_mhus;
44
bool has_ppus;
45
@@ -XXX,XX +XXX,XX @@ static const ARMSSEInfo armsse_variants[] = {
46
.sram_banks = 1,
47
.num_cpus = 1,
48
.sys_version = 0x41743,
49
+ .iidr = 0,
50
.cpuwait_rst = 0,
51
.has_mhus = false,
52
.has_ppus = false,
53
@@ -XXX,XX +XXX,XX @@ static const ARMSSEInfo armsse_variants[] = {
54
.sram_banks = 4,
55
.num_cpus = 2,
56
.sys_version = 0x22041743,
57
+ .iidr = 0,
58
.cpuwait_rst = 2,
59
.has_mhus = true,
60
.has_ppus = true,
61
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
62
}
63
object_property_set_int(OBJECT(&s->sysinfo), "sse-version",
64
info->sse_version, &error_abort);
65
+ object_property_set_int(OBJECT(&s->sysinfo), "IIDR",
66
+ info->iidr, &error_abort);
67
if (!sysbus_realize(SYS_BUS_DEVICE(&s->sysinfo), errp)) {
68
return;
69
}
70
diff --git a/hw/misc/iotkit-sysinfo.c b/hw/misc/iotkit-sysinfo.c
71
index XXXXXXX..XXXXXXX 100644
72
--- a/hw/misc/iotkit-sysinfo.c
73
+++ b/hw/misc/iotkit-sysinfo.c
74
@@ -XXX,XX +XXX,XX @@
75
76
REG32(SYS_VERSION, 0x0)
77
REG32(SYS_CONFIG, 0x4)
78
+REG32(SYS_CONFIG1, 0x8)
79
+REG32(IIDR, 0xfc8)
80
REG32(PID4, 0xfd0)
81
REG32(PID5, 0xfd4)
82
REG32(PID6, 0xfd8)
83
@@ -XXX,XX +XXX,XX @@ static uint64_t iotkit_sysinfo_read(void *opaque, hwaddr offset,
84
case A_SYS_CONFIG:
85
r = s->sys_config;
86
break;
87
+ case A_SYS_CONFIG1:
88
+ switch (s->sse_version) {
89
+ case ARMSSE_SSE300:
90
+ return 0;
91
+ break;
92
+ default:
93
+ goto bad_read;
94
+ }
95
+ break;
96
+ case A_IIDR:
97
+ switch (s->sse_version) {
98
+ case ARMSSE_SSE300:
99
+ return s->iidr;
100
+ break;
101
+ default:
102
+ goto bad_read;
103
+ }
104
+ break;
105
case A_PID4 ... A_CID3:
106
switch (s->sse_version) {
107
case ARMSSE_SSE300:
108
@@ -XXX,XX +XXX,XX @@ static uint64_t iotkit_sysinfo_read(void *opaque, hwaddr offset,
109
}
110
break;
111
default:
112
+ bad_read:
113
qemu_log_mask(LOG_GUEST_ERROR,
114
"IoTKit SysInfo read: bad offset %x\n", (int)offset);
115
r = 0;
116
@@ -XXX,XX +XXX,XX @@ static Property iotkit_sysinfo_props[] = {
117
DEFINE_PROP_UINT32("SYS_VERSION", IoTKitSysInfo, sys_version, 0),
118
DEFINE_PROP_UINT32("SYS_CONFIG", IoTKitSysInfo, sys_config, 0),
119
DEFINE_PROP_UINT32("sse-version", IoTKitSysInfo, sse_version, 0),
120
+ DEFINE_PROP_UINT32("IIDR", IoTKitSysInfo, iidr, 0),
121
DEFINE_PROP_END_OF_LIST()
122
};
123
124
--
125
2.20.1
126
127
diff view generated by jsdifflib
Deleted patch
1
The SSE-300 includes a counter module; implement a model of it.
2
1
3
This counter is documented in the SSE-123 Example Subsystem
4
Technical Reference Manual:
5
https://developer.arm.com/documentation/101370/latest/
6
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20210219144617.4782-12-peter.maydell@linaro.org
11
---
12
include/hw/timer/sse-counter.h | 105 ++++++++
13
hw/timer/sse-counter.c | 474 +++++++++++++++++++++++++++++++++
14
MAINTAINERS | 2 +
15
hw/arm/Kconfig | 1 +
16
hw/timer/Kconfig | 3 +
17
hw/timer/meson.build | 1 +
18
hw/timer/trace-events | 7 +
19
7 files changed, 593 insertions(+)
20
create mode 100644 include/hw/timer/sse-counter.h
21
create mode 100644 hw/timer/sse-counter.c
22
23
diff --git a/include/hw/timer/sse-counter.h b/include/hw/timer/sse-counter.h
24
new file mode 100644
25
index XXXXXXX..XXXXXXX
26
--- /dev/null
27
+++ b/include/hw/timer/sse-counter.h
28
@@ -XXX,XX +XXX,XX @@
29
+/*
30
+ * Arm SSE Subsystem System Counter
31
+ *
32
+ * Copyright (c) 2020 Linaro Limited
33
+ * Written by Peter Maydell
34
+ *
35
+ * This program is free software; you can redistribute it and/or modify
36
+ * it under the terms of the GNU General Public License version 2 or
37
+ * (at your option) any later version.
38
+ */
39
+
40
+/*
41
+ * This is a model of the "System counter" which is documented in
42
+ * the Arm SSE-123 Example Subsystem Technical Reference Manual:
43
+ * https://developer.arm.com/documentation/101370/latest/
44
+ *
45
+ * QEMU interface:
46
+ * + Clock input "CLK": clock
47
+ * + sysbus MMIO region 0: the control register frame
48
+ * + sysbus MMIO region 1: the status register frame
49
+ *
50
+ * Consumers of the system counter's timestamp, such as the SSE
51
+ * System Timer device, can also use the APIs sse_counter_for_timestamp(),
52
+ * sse_counter_tick_to_time() and sse_counter_register_consumer() to
53
+ * interact with an instance of the System Counter. Generally the
54
+ * consumer device should have a QOM link property which the board
55
+ * code can set to the appropriate instance of the system counter.
56
+ */
57
+
58
+#ifndef SSE_COUNTER_H
59
+#define SSE_COUNTER_H
60
+
61
+#include "hw/sysbus.h"
62
+#include "qom/object.h"
63
+#include "qemu/notify.h"
64
+
65
+#define TYPE_SSE_COUNTER "sse-counter"
66
+OBJECT_DECLARE_SIMPLE_TYPE(SSECounter, SSE_COUNTER)
67
+
68
+struct SSECounter {
69
+ /*< private >*/
70
+ SysBusDevice parent_obj;
71
+
72
+ /*< public >*/
73
+ MemoryRegion control_mr;
74
+ MemoryRegion status_mr;
75
+ Clock *clk;
76
+ NotifierList notifier_list;
77
+
78
+ uint32_t cntcr;
79
+ uint32_t cntscr0;
80
+
81
+ /*
82
+ * These are used for handling clock frequency changes: they are a
83
+ * tuple of (QEMU_CLOCK_VIRTUAL timestamp, CNTCV at that time),
84
+ * taken when the clock frequency changes. sse_cntcv() needs them
85
+ * to calculate the current CNTCV.
86
+ */
87
+ uint64_t ns_then;
88
+ uint64_t ticks_then;
89
+};
90
+
91
+/*
92
+ * These functions are the interface by which a consumer of
93
+ * the system timestamp (such as the SSE system timer device)
94
+ * can communicate with the SSECounter.
95
+ */
96
+
97
+/**
98
+ * sse_counter_for_timestamp:
99
+ * @counter: SSECounter
100
+ * @ns: timestamp of QEMU_CLOCK_VIRTUAL in nanoseconds
101
+ *
102
+ * Returns the value of the timestamp counter at the specified
103
+ * point in time (assuming that no changes to scale factor, enable, etc
104
+ * happen in the meantime).
105
+ */
106
+uint64_t sse_counter_for_timestamp(SSECounter *counter, uint64_t ns);
107
+
108
+/**
109
+ * sse_counter_tick_to_time:
110
+ * @counter: SSECounter
111
+ * @tick: tick value
112
+ *
113
+ * Returns the time (a QEMU_CLOCK_VIRTUAL timestamp in nanoseconds)
114
+ * when the timestamp counter will reach the specified tick count.
115
+ * If the counter is not currently running, returns UINT64_MAX.
116
+ */
117
+uint64_t sse_counter_tick_to_time(SSECounter *counter, uint64_t tick);
118
+
119
+/**
120
+ * sse_counter_register_consumer:
121
+ * @counter: SSECounter
122
+ * @notifier: Notifier which is notified on counter changes
123
+ *
124
+ * Registers @notifier with the SSECounter. When the counter's
125
+ * configuration changes in a way that might invalidate information
126
+ * previously returned via sse_counter_for_timestamp() or
127
+ * sse_counter_tick_to_time(), the notifier will be called.
128
+ * Devices which consume the timestamp counter can use this as
129
+ * a cue to recalculate timer events.
130
+ */
131
+void sse_counter_register_consumer(SSECounter *counter, Notifier *notifier);
132
+
133
+#endif
134
diff --git a/hw/timer/sse-counter.c b/hw/timer/sse-counter.c
135
new file mode 100644
136
index XXXXXXX..XXXXXXX
137
--- /dev/null
138
+++ b/hw/timer/sse-counter.c
139
@@ -XXX,XX +XXX,XX @@
140
+/*
141
+ * Arm SSE Subsystem System Counter
142
+ *
143
+ * Copyright (c) 2020 Linaro Limited
144
+ * Written by Peter Maydell
145
+ *
146
+ * This program is free software; you can redistribute it and/or modify
147
+ * it under the terms of the GNU General Public License version 2 or
148
+ * (at your option) any later version.
149
+ */
150
+
151
+/*
152
+ * This is a model of the "System counter" which is documented in
153
+ * the Arm SSE-123 Example Subsystem Technical Reference Manual:
154
+ * https://developer.arm.com/documentation/101370/latest/
155
+ *
156
+ * The system counter is a non-stop 64-bit up-counter. It provides
157
+ * this count value to other devices like the SSE system timer,
158
+ * which are driven by this system timestamp rather than directly
159
+ * from a clock. Internally to the counter the count is actually
160
+ * 88-bit precision (64.24 fixed point), with a programmable scale factor.
161
+ *
162
+ * The hardware has the optional feature that it supports dynamic
163
+ * clock switching, where two clock inputs are connected, and which
164
+ * one is used is selected via a CLKSEL input signal. Since the
165
+ * users of this device in QEMU don't use this feature, we only model
166
+ * the HWCLKSW=0 configuration.
167
+ */
168
+#include "qemu/osdep.h"
169
+#include "qemu/log.h"
170
+#include "qemu/timer.h"
171
+#include "qapi/error.h"
172
+#include "trace.h"
173
+#include "hw/timer/sse-counter.h"
174
+#include "hw/sysbus.h"
175
+#include "hw/irq.h"
176
+#include "hw/registerfields.h"
177
+#include "hw/clock.h"
178
+#include "hw/qdev-clock.h"
179
+#include "migration/vmstate.h"
180
+
181
+/* Registers in the control frame */
182
+REG32(CNTCR, 0x0)
183
+ FIELD(CNTCR, EN, 0, 1)
184
+ FIELD(CNTCR, HDBG, 1, 1)
185
+ FIELD(CNTCR, SCEN, 2, 1)
186
+ FIELD(CNTCR, INTRMASK, 3, 1)
187
+ FIELD(CNTCR, PSLVERRDIS, 4, 1)
188
+ FIELD(CNTCR, INTRCLR, 5, 1)
189
+/*
190
+ * Although CNTCR defines interrupt-related bits, the counter doesn't
191
+ * appear to actually have an interrupt output. So INTRCLR is
192
+ * effectively a RAZ/WI bit, as are the reserved bits [31:6].
193
+ */
194
+#define CNTCR_VALID_MASK (R_CNTCR_EN_MASK | R_CNTCR_HDBG_MASK | \
195
+ R_CNTCR_SCEN_MASK | R_CNTCR_INTRMASK_MASK | \
196
+ R_CNTCR_PSLVERRDIS_MASK)
197
+REG32(CNTSR, 0x4)
198
+REG32(CNTCV_LO, 0x8)
199
+REG32(CNTCV_HI, 0xc)
200
+REG32(CNTSCR, 0x10) /* Aliased with CNTSCR0 */
201
+REG32(CNTID, 0x1c)
202
+ FIELD(CNTID, CNTSC, 0, 4)
203
+ FIELD(CNTID, CNTCS, 16, 1)
204
+ FIELD(CNTID, CNTSELCLK, 17, 2)
205
+ FIELD(CNTID, CNTSCR_OVR, 19, 1)
206
+REG32(CNTSCR0, 0xd0)
207
+REG32(CNTSCR1, 0xd4)
208
+
209
+/* Registers in the status frame */
210
+REG32(STATUS_CNTCV_LO, 0x0)
211
+REG32(STATUS_CNTCV_HI, 0x4)
212
+
213
+/* Standard ID registers, present in both frames */
214
+REG32(PID4, 0xFD0)
215
+REG32(PID5, 0xFD4)
216
+REG32(PID6, 0xFD8)
217
+REG32(PID7, 0xFDC)
218
+REG32(PID0, 0xFE0)
219
+REG32(PID1, 0xFE4)
220
+REG32(PID2, 0xFE8)
221
+REG32(PID3, 0xFEC)
222
+REG32(CID0, 0xFF0)
223
+REG32(CID1, 0xFF4)
224
+REG32(CID2, 0xFF8)
225
+REG32(CID3, 0xFFC)
226
+
227
+/* PID/CID values */
228
+static const int control_id[] = {
229
+ 0x04, 0x00, 0x00, 0x00, /* PID4..PID7 */
230
+ 0xba, 0xb0, 0x0b, 0x00, /* PID0..PID3 */
231
+ 0x0d, 0xf0, 0x05, 0xb1, /* CID0..CID3 */
232
+};
233
+
234
+static const int status_id[] = {
235
+ 0x04, 0x00, 0x00, 0x00, /* PID4..PID7 */
236
+ 0xbb, 0xb0, 0x0b, 0x00, /* PID0..PID3 */
237
+ 0x0d, 0xf0, 0x05, 0xb1, /* CID0..CID3 */
238
+};
239
+
240
+static void sse_counter_notify_users(SSECounter *s)
241
+{
242
+ /*
243
+ * Notify users of the count timestamp that they may
244
+ * need to recalculate.
245
+ */
246
+ notifier_list_notify(&s->notifier_list, NULL);
247
+}
248
+
249
+static bool sse_counter_enabled(SSECounter *s)
250
+{
251
+ return (s->cntcr & R_CNTCR_EN_MASK) != 0;
252
+}
253
+
254
+uint64_t sse_counter_tick_to_time(SSECounter *s, uint64_t tick)
255
+{
256
+ if (!sse_counter_enabled(s)) {
257
+ return UINT64_MAX;
258
+ }
259
+
260
+ tick -= s->ticks_then;
261
+
262
+ if (s->cntcr & R_CNTCR_SCEN_MASK) {
263
+ /* Adjust the tick count to account for the scale factor */
264
+ tick = muldiv64(tick, 0x01000000, s->cntscr0);
265
+ }
266
+
267
+ return s->ns_then + clock_ticks_to_ns(s->clk, tick);
268
+}
269
+
270
+void sse_counter_register_consumer(SSECounter *s, Notifier *notifier)
271
+{
272
+ /*
273
+ * For the moment we assume that both we and the devices
274
+ * which consume us last for the life of the simulation,
275
+ * and so there is no mechanism for removing a notifier.
276
+ */
277
+ notifier_list_add(&s->notifier_list, notifier);
278
+}
279
+
280
+uint64_t sse_counter_for_timestamp(SSECounter *s, uint64_t now)
281
+{
282
+ /* Return the CNTCV value for a particular timestamp (clock ns value). */
283
+ uint64_t ticks;
284
+
285
+ if (!sse_counter_enabled(s)) {
286
+ /* Counter is disabled and does not increment */
287
+ return s->ticks_then;
288
+ }
289
+
290
+ ticks = clock_ns_to_ticks(s->clk, now - s->ns_then);
291
+ if (s->cntcr & R_CNTCR_SCEN_MASK) {
292
+ /*
293
+ * Scaling is enabled. The CNTSCR value is the amount added to
294
+ * the underlying 88-bit counter for every tick of the
295
+ * underlying clock; CNTCV is the top 64 bits of that full
296
+ * 88-bit value. Multiplying the tick count by CNTSCR tells us
297
+ * how much the full 88-bit counter has moved on; we then
298
+ * divide that by 0x01000000 to find out how much the 64-bit
299
+ * visible portion has advanced. muldiv64() gives us the
300
+ * necessary at-least-88-bit precision for the intermediate
301
+ * result.
302
+ */
303
+ ticks = muldiv64(ticks, s->cntscr0, 0x01000000);
304
+ }
305
+ return s->ticks_then + ticks;
306
+}
307
+
308
+static uint64_t sse_cntcv(SSECounter *s)
309
+{
310
+ /* Return the CNTCV value for the current time */
311
+ return sse_counter_for_timestamp(s, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
312
+}
313
+
314
+static void sse_write_cntcv(SSECounter *s, uint32_t value, unsigned startbit)
315
+{
316
+ /*
317
+ * Write one 32-bit half of the counter value; startbit is the
318
+ * bit position of this half in the 64-bit word, either 0 or 32.
319
+ */
320
+ uint64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
321
+ uint64_t cntcv = sse_counter_for_timestamp(s, now);
322
+
323
+ cntcv = deposit64(cntcv, startbit, 32, value);
324
+ s->ticks_then = cntcv;
325
+ s->ns_then = now;
326
+ sse_counter_notify_users(s);
327
+}
328
+
329
+static uint64_t sse_counter_control_read(void *opaque, hwaddr offset,
330
+ unsigned size)
331
+{
332
+ SSECounter *s = SSE_COUNTER(opaque);
333
+ uint64_t r;
334
+
335
+ switch (offset) {
336
+ case A_CNTCR:
337
+ r = s->cntcr;
338
+ break;
339
+ case A_CNTSR:
340
+ /*
341
+ * The only bit here is DBGH, indicating that the counter has been
342
+ * halted via the Halt-on-Debug signal. We don't implement halting
343
+ * debug, so the whole register always reads as zero.
344
+ */
345
+ r = 0;
346
+ break;
347
+ case A_CNTCV_LO:
348
+ r = extract64(sse_cntcv(s), 0, 32);
349
+ break;
350
+ case A_CNTCV_HI:
351
+ r = extract64(sse_cntcv(s), 32, 32);
352
+ break;
353
+ case A_CNTID:
354
+ /*
355
+ * For our implementation:
356
+ * - CNTSCR can only be written when CNTCR.EN == 0
357
+ * - HWCLKSW=0, so selected clock is always CLK0
358
+ * - counter scaling is implemented
359
+ */
360
+ r = (1 << R_CNTID_CNTSELCLK_SHIFT) | (1 << R_CNTID_CNTSC_SHIFT);
361
+ break;
362
+ case A_CNTSCR:
363
+ case A_CNTSCR0:
364
+ r = s->cntscr0;
365
+ break;
366
+ case A_CNTSCR1:
367
+ /* If HWCLKSW == 0, CNTSCR1 is RAZ/WI */
368
+ r = 0;
369
+ break;
370
+ case A_PID4 ... A_CID3:
371
+ r = control_id[(offset - A_PID4) / 4];
372
+ break;
373
+ default:
374
+ qemu_log_mask(LOG_GUEST_ERROR,
375
+ "SSE System Counter control frame read: bad offset 0x%x",
376
+ (unsigned)offset);
377
+ r = 0;
378
+ break;
379
+ }
380
+
381
+ trace_sse_counter_control_read(offset, r, size);
382
+ return r;
383
+}
384
+
385
+static void sse_counter_control_write(void *opaque, hwaddr offset,
386
+ uint64_t value, unsigned size)
387
+{
388
+ SSECounter *s = SSE_COUNTER(opaque);
389
+
390
+ trace_sse_counter_control_write(offset, value, size);
391
+
392
+ switch (offset) {
393
+ case A_CNTCR:
394
+ /*
395
+ * Although CNTCR defines interrupt-related bits, the counter doesn't
396
+ * appear to actually have an interrupt output. So INTRCLR is
397
+ * effectively a RAZ/WI bit, as are the reserved bits [31:6].
398
+ * The documentation does not explicitly say so, but we assume
399
+ * that changing the scale factor while the counter is enabled
400
+ * by toggling CNTCR.SCEN has the same behaviour (making the counter
401
+ * value UNKNOWN) as changing it by writing to CNTSCR, and so we
402
+ * don't need to try to recalculate for that case.
403
+ */
404
+ value &= CNTCR_VALID_MASK;
405
+ if ((value ^ s->cntcr) & R_CNTCR_EN_MASK) {
406
+ /*
407
+ * Whether the counter is being enabled or disabled, the
408
+ * required action is the same: sync the (ns_then, ticks_then)
409
+ * tuple.
410
+ */
411
+ uint64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
412
+ s->ticks_then = sse_counter_for_timestamp(s, now);
413
+ s->ns_then = now;
414
+ sse_counter_notify_users(s);
415
+ }
416
+ s->cntcr = value;
417
+ break;
418
+ case A_CNTCV_LO:
419
+ sse_write_cntcv(s, value, 0);
420
+ break;
421
+ case A_CNTCV_HI:
422
+ sse_write_cntcv(s, value, 32);
423
+ break;
424
+ case A_CNTSCR:
425
+ case A_CNTSCR0:
426
+ /*
427
+ * If the scale registers are changed when the counter is enabled,
428
+ * the count value becomes UNKNOWN. So we don't try to recalculate
429
+ * anything here but only do it on a write to CNTCR.EN.
430
+ */
431
+ s->cntscr0 = value;
432
+ break;
433
+ case A_CNTSCR1:
434
+ /* If HWCLKSW == 0, CNTSCR1 is RAZ/WI */
435
+ break;
436
+ case A_CNTSR:
437
+ case A_CNTID:
438
+ case A_PID4 ... A_CID3:
439
+ qemu_log_mask(LOG_GUEST_ERROR,
440
+ "SSE System Counter control frame: write to RO offset 0x%x\n",
441
+ (unsigned)offset);
442
+ break;
443
+ default:
444
+ qemu_log_mask(LOG_GUEST_ERROR,
445
+ "SSE System Counter control frame: write to bad offset 0x%x\n",
446
+ (unsigned)offset);
447
+ break;
448
+ }
449
+}
450
+
451
+static uint64_t sse_counter_status_read(void *opaque, hwaddr offset,
452
+ unsigned size)
453
+{
454
+ SSECounter *s = SSE_COUNTER(opaque);
455
+ uint64_t r;
456
+
457
+ switch (offset) {
458
+ case A_STATUS_CNTCV_LO:
459
+ r = extract64(sse_cntcv(s), 0, 32);
460
+ break;
461
+ case A_STATUS_CNTCV_HI:
462
+ r = extract64(sse_cntcv(s), 32, 32);
463
+ break;
464
+ case A_PID4 ... A_CID3:
465
+ r = status_id[(offset - A_PID4) / 4];
466
+ break;
467
+ default:
468
+ qemu_log_mask(LOG_GUEST_ERROR,
469
+ "SSE System Counter status frame read: bad offset 0x%x",
470
+ (unsigned)offset);
471
+ r = 0;
472
+ break;
473
+ }
474
+
475
+ trace_sse_counter_status_read(offset, r, size);
476
+ return r;
477
+}
478
+
479
+static void sse_counter_status_write(void *opaque, hwaddr offset,
480
+ uint64_t value, unsigned size)
481
+{
482
+ trace_sse_counter_status_write(offset, value, size);
483
+
484
+ switch (offset) {
485
+ case A_STATUS_CNTCV_LO:
486
+ case A_STATUS_CNTCV_HI:
487
+ case A_PID4 ... A_CID3:
488
+ qemu_log_mask(LOG_GUEST_ERROR,
489
+ "SSE System Counter status frame: write to RO offset 0x%x\n",
490
+ (unsigned)offset);
491
+ break;
492
+ default:
493
+ qemu_log_mask(LOG_GUEST_ERROR,
494
+ "SSE System Counter status frame: write to bad offset 0x%x\n",
495
+ (unsigned)offset);
496
+ break;
497
+ }
498
+}
499
+
500
+static const MemoryRegionOps sse_counter_control_ops = {
501
+ .read = sse_counter_control_read,
502
+ .write = sse_counter_control_write,
503
+ .endianness = DEVICE_LITTLE_ENDIAN,
504
+ .valid.min_access_size = 4,
505
+ .valid.max_access_size = 4,
506
+};
507
+
508
+static const MemoryRegionOps sse_counter_status_ops = {
509
+ .read = sse_counter_status_read,
510
+ .write = sse_counter_status_write,
511
+ .endianness = DEVICE_LITTLE_ENDIAN,
512
+ .valid.min_access_size = 4,
513
+ .valid.max_access_size = 4,
514
+};
515
+
516
+static void sse_counter_reset(DeviceState *dev)
517
+{
518
+ SSECounter *s = SSE_COUNTER(dev);
519
+
520
+ trace_sse_counter_reset();
521
+
522
+ s->cntcr = 0;
523
+ s->cntscr0 = 0x01000000;
524
+ s->ns_then = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
525
+ s->ticks_then = 0;
526
+}
527
+
528
+static void sse_clk_callback(void *opaque, ClockEvent event)
529
+{
530
+ SSECounter *s = SSE_COUNTER(opaque);
531
+ uint64_t now;
532
+
533
+ switch (event) {
534
+ case ClockPreUpdate:
535
+ /*
536
+ * Before the clock period updates, set (ticks_then, ns_then)
537
+ * to the current time and tick count (as calculated with
538
+ * the old clock period).
539
+ */
540
+ if (sse_counter_enabled(s)) {
541
+ now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
542
+ s->ticks_then = sse_counter_for_timestamp(s, now);
543
+ s->ns_then = now;
544
+ }
545
+ break;
546
+ case ClockUpdate:
547
+ sse_counter_notify_users(s);
548
+ break;
549
+ default:
550
+ break;
551
+ }
552
+}
553
+
554
+static void sse_counter_init(Object *obj)
555
+{
556
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
557
+ SSECounter *s = SSE_COUNTER(obj);
558
+
559
+ notifier_list_init(&s->notifier_list);
560
+
561
+ s->clk = qdev_init_clock_in(DEVICE(obj), "CLK", sse_clk_callback, s,
562
+ ClockPreUpdate | ClockUpdate);
563
+ memory_region_init_io(&s->control_mr, obj, &sse_counter_control_ops,
564
+ s, "sse-counter-control", 0x1000);
565
+ memory_region_init_io(&s->status_mr, obj, &sse_counter_status_ops,
566
+ s, "sse-counter-status", 0x1000);
567
+ sysbus_init_mmio(sbd, &s->control_mr);
568
+ sysbus_init_mmio(sbd, &s->status_mr);
569
+}
570
+
571
+static void sse_counter_realize(DeviceState *dev, Error **errp)
572
+{
573
+ SSECounter *s = SSE_COUNTER(dev);
574
+
575
+ if (!clock_has_source(s->clk)) {
576
+ error_setg(errp, "SSE system counter: CLK must be connected");
577
+ return;
578
+ }
579
+}
580
+
581
+static const VMStateDescription sse_counter_vmstate = {
582
+ .name = "sse-counter",
583
+ .version_id = 1,
584
+ .minimum_version_id = 1,
585
+ .fields = (VMStateField[]) {
586
+ VMSTATE_CLOCK(clk, SSECounter),
587
+ VMSTATE_END_OF_LIST()
588
+ }
589
+};
590
+
591
+static void sse_counter_class_init(ObjectClass *klass, void *data)
592
+{
593
+ DeviceClass *dc = DEVICE_CLASS(klass);
594
+
595
+ dc->realize = sse_counter_realize;
596
+ dc->vmsd = &sse_counter_vmstate;
597
+ dc->reset = sse_counter_reset;
598
+}
599
+
600
+static const TypeInfo sse_counter_info = {
601
+ .name = TYPE_SSE_COUNTER,
602
+ .parent = TYPE_SYS_BUS_DEVICE,
603
+ .instance_size = sizeof(SSECounter),
604
+ .instance_init = sse_counter_init,
605
+ .class_init = sse_counter_class_init,
606
+};
607
+
608
+static void sse_counter_register_types(void)
609
+{
610
+ type_register_static(&sse_counter_info);
611
+}
612
+
613
+type_init(sse_counter_register_types);
614
diff --git a/MAINTAINERS b/MAINTAINERS
615
index XXXXXXX..XXXXXXX 100644
616
--- a/MAINTAINERS
617
+++ b/MAINTAINERS
618
@@ -XXX,XX +XXX,XX @@ F: hw/misc/armsse-cpuid.c
619
F: include/hw/misc/armsse-cpuid.h
620
F: hw/misc/armsse-mhu.c
621
F: include/hw/misc/armsse-mhu.h
622
+F: hw/timer/sse-counter.c
623
+F: include/hw/timer/sse-counter.h
624
F: docs/system/arm/mps2.rst
625
626
Musca
627
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
628
index XXXXXXX..XXXXXXX 100644
629
--- a/hw/arm/Kconfig
630
+++ b/hw/arm/Kconfig
631
@@ -XXX,XX +XXX,XX @@ config ARMSSE
632
select TZ_MSC
633
select TZ_PPC
634
select UNIMP
635
+ select SSE_COUNTER
636
637
config ARMSSE_CPUID
638
bool
639
diff --git a/hw/timer/Kconfig b/hw/timer/Kconfig
640
index XXXXXXX..XXXXXXX 100644
641
--- a/hw/timer/Kconfig
642
+++ b/hw/timer/Kconfig
643
@@ -XXX,XX +XXX,XX @@ config RENESAS_TMR
644
config RENESAS_CMT
645
bool
646
647
+config SSE_COUNTER
648
+ bool
649
+
650
config AVR_TIMER16
651
bool
652
diff --git a/hw/timer/meson.build b/hw/timer/meson.build
653
index XXXXXXX..XXXXXXX 100644
654
--- a/hw/timer/meson.build
655
+++ b/hw/timer/meson.build
656
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_PXA2XX', if_true: files('pxa2xx_timer.c'))
657
softmmu_ss.add(when: 'CONFIG_RASPI', if_true: files('bcm2835_systmr.c'))
658
softmmu_ss.add(when: 'CONFIG_SH4', if_true: files('sh_timer.c'))
659
softmmu_ss.add(when: 'CONFIG_SLAVIO', if_true: files('slavio_timer.c'))
660
+softmmu_ss.add(when: 'CONFIG_SSE_COUNTER', if_true: files('sse-counter.c'))
661
softmmu_ss.add(when: 'CONFIG_STM32F2XX_TIMER', if_true: files('stm32f2xx_timer.c'))
662
softmmu_ss.add(when: 'CONFIG_XILINX', if_true: files('xilinx_timer.c'))
663
664
diff --git a/hw/timer/trace-events b/hw/timer/trace-events
665
index XXXXXXX..XXXXXXX 100644
666
--- a/hw/timer/trace-events
667
+++ b/hw/timer/trace-events
668
@@ -XXX,XX +XXX,XX @@ avr_timer16_interrupt_count(uint8_t cnt) "count: %u"
669
avr_timer16_interrupt_overflow(const char *reason) "overflow: %s"
670
avr_timer16_next_alarm(uint64_t delay_ns) "next alarm: %" PRIu64 " ns from now"
671
avr_timer16_clksrc_update(uint64_t freq_hz, uint64_t period_ns, uint64_t delay_s) "timer frequency: %" PRIu64 " Hz, period: %" PRIu64 " ns (%" PRId64 " us)"
672
+
673
+# sse_counter.c
674
+sse_counter_control_read(uint64_t offset, uint64_t data, unsigned size) "SSE system counter control frame read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
675
+sse_counter_control_write(uint64_t offset, uint64_t data, unsigned size) "SSE system counter control framen write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
676
+sse_counter_status_read(uint64_t offset, uint64_t data, unsigned size) "SSE system counter status frame read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
677
+sse_counter_status_write(uint64_t offset, uint64_t data, unsigned size) "SSE system counter status frame write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
678
+sse_counter_reset(void) "SSE system counter: reset"
679
--
680
2.20.1
681
682
diff view generated by jsdifflib
Deleted patch
1
The SSE-300 includes some timers which are a different kind to
2
those in the SSE-200. Model them.
3
1
4
These timers are documented in the SSE-123 Example Subsystem
5
Technical Reference Manual:
6
https://developer.arm.com/documentation/101370/latest/
7
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20210219144617.4782-13-peter.maydell@linaro.org
12
---
13
include/hw/timer/sse-timer.h | 53 ++++
14
hw/timer/sse-timer.c | 470 +++++++++++++++++++++++++++++++++++
15
MAINTAINERS | 2 +
16
hw/arm/Kconfig | 1 +
17
hw/timer/Kconfig | 3 +
18
hw/timer/meson.build | 1 +
19
hw/timer/trace-events | 5 +
20
7 files changed, 535 insertions(+)
21
create mode 100644 include/hw/timer/sse-timer.h
22
create mode 100644 hw/timer/sse-timer.c
23
24
diff --git a/include/hw/timer/sse-timer.h b/include/hw/timer/sse-timer.h
25
new file mode 100644
26
index XXXXXXX..XXXXXXX
27
--- /dev/null
28
+++ b/include/hw/timer/sse-timer.h
29
@@ -XXX,XX +XXX,XX @@
30
+/*
31
+ * Arm SSE Subsystem System Timer
32
+ *
33
+ * Copyright (c) 2020 Linaro Limited
34
+ * Written by Peter Maydell
35
+ *
36
+ * This program is free software; you can redistribute it and/or modify
37
+ * it under the terms of the GNU General Public License version 2 or
38
+ * (at your option) any later version.
39
+ */
40
+
41
+/*
42
+ * This is a model of the "System timer" which is documented in
43
+ * the Arm SSE-123 Example Subsystem Technical Reference Manual:
44
+ * https://developer.arm.com/documentation/101370/latest/
45
+ *
46
+ * QEMU interface:
47
+ * + QOM property "counter": link property to be set to the
48
+ * TYPE_SSE_COUNTER timestamp counter device this timer runs off
49
+ * + sysbus MMIO region 0: the register bank
50
+ * + sysbus IRQ 0: timer interrupt
51
+ */
52
+
53
+#ifndef SSE_TIMER_H
54
+#define SSE_TIMER_H
55
+
56
+#include "hw/sysbus.h"
57
+#include "qom/object.h"
58
+#include "hw/timer/sse-counter.h"
59
+
60
+#define TYPE_SSE_TIMER "sse-timer"
61
+OBJECT_DECLARE_SIMPLE_TYPE(SSETimer, SSE_TIMER)
62
+
63
+struct SSETimer {
64
+ /*< private >*/
65
+ SysBusDevice parent_obj;
66
+
67
+ /*< public >*/
68
+ MemoryRegion iomem;
69
+ qemu_irq irq;
70
+ SSECounter *counter;
71
+ QEMUTimer timer;
72
+ Notifier counter_notifier;
73
+
74
+ uint32_t cntfrq;
75
+ uint32_t cntp_ctl;
76
+ uint64_t cntp_cval;
77
+ uint64_t cntp_aival;
78
+ uint32_t cntp_aival_ctl;
79
+ uint32_t cntp_aival_reload;
80
+};
81
+
82
+#endif
83
diff --git a/hw/timer/sse-timer.c b/hw/timer/sse-timer.c
84
new file mode 100644
85
index XXXXXXX..XXXXXXX
86
--- /dev/null
87
+++ b/hw/timer/sse-timer.c
88
@@ -XXX,XX +XXX,XX @@
89
+/*
90
+ * Arm SSE Subsystem System Timer
91
+ *
92
+ * Copyright (c) 2020 Linaro Limited
93
+ * Written by Peter Maydell
94
+ *
95
+ * This program is free software; you can redistribute it and/or modify
96
+ * it under the terms of the GNU General Public License version 2 or
97
+ * (at your option) any later version.
98
+ */
99
+
100
+/*
101
+ * This is a model of the "System timer" which is documented in
102
+ * the Arm SSE-123 Example Subsystem Technical Reference Manual:
103
+ * https://developer.arm.com/documentation/101370/latest/
104
+ *
105
+ * The timer is based around a simple 64-bit incrementing counter
106
+ * (readable from CNTPCT_HI/LO). The timer fires when
107
+ * Counter - CompareValue >= 0.
108
+ * The CompareValue is guest-writable, via CNTP_CVAL_HI/LO.
109
+ * CNTP_TVAL is an alternative view of the CompareValue defined by
110
+ * TimerValue = CompareValue[31:0] - Counter[31:0]
111
+ * which can be both read and written.
112
+ * This part is similar to the generic timer in an Arm A-class CPU.
113
+ *
114
+ * The timer also has a separate auto-increment timer. When this
115
+ * timer is enabled, then the AutoIncrValue is set to:
116
+ * AutoIncrValue = Reload + Counter
117
+ * and this timer fires when
118
+ * Counter - AutoIncrValue >= 0
119
+ * at which point, an interrupt is generated and the new AutoIncrValue
120
+ * is calculated.
121
+ * When the auto-increment timer is enabled, interrupt generation
122
+ * via the compare/timervalue registers is disabled.
123
+ */
124
+#include "qemu/osdep.h"
125
+#include "qemu/log.h"
126
+#include "qemu/timer.h"
127
+#include "qapi/error.h"
128
+#include "trace.h"
129
+#include "hw/timer/sse-timer.h"
130
+#include "hw/timer/sse-counter.h"
131
+#include "hw/sysbus.h"
132
+#include "hw/irq.h"
133
+#include "hw/registerfields.h"
134
+#include "hw/clock.h"
135
+#include "hw/qdev-clock.h"
136
+#include "hw/qdev-properties.h"
137
+#include "migration/vmstate.h"
138
+
139
+REG32(CNTPCT_LO, 0x0)
140
+REG32(CNTPCT_HI, 0x4)
141
+REG32(CNTFRQ, 0x10)
142
+REG32(CNTP_CVAL_LO, 0x20)
143
+REG32(CNTP_CVAL_HI, 0x24)
144
+REG32(CNTP_TVAL, 0x28)
145
+REG32(CNTP_CTL, 0x2c)
146
+ FIELD(CNTP_CTL, ENABLE, 0, 1)
147
+ FIELD(CNTP_CTL, IMASK, 1, 1)
148
+ FIELD(CNTP_CTL, ISTATUS, 2, 1)
149
+REG32(CNTP_AIVAL_LO, 0x40)
150
+REG32(CNTP_AIVAL_HI, 0x44)
151
+REG32(CNTP_AIVAL_RELOAD, 0x48)
152
+REG32(CNTP_AIVAL_CTL, 0x4c)
153
+ FIELD(CNTP_AIVAL_CTL, EN, 0, 1)
154
+ FIELD(CNTP_AIVAL_CTL, CLR, 1, 1)
155
+REG32(CNTP_CFG, 0x50)
156
+ FIELD(CNTP_CFG, AIVAL, 0, 4)
157
+#define R_CNTP_CFG_AIVAL_IMPLEMENTED 1
158
+REG32(PID4, 0xFD0)
159
+REG32(PID5, 0xFD4)
160
+REG32(PID6, 0xFD8)
161
+REG32(PID7, 0xFDC)
162
+REG32(PID0, 0xFE0)
163
+REG32(PID1, 0xFE4)
164
+REG32(PID2, 0xFE8)
165
+REG32(PID3, 0xFEC)
166
+REG32(CID0, 0xFF0)
167
+REG32(CID1, 0xFF4)
168
+REG32(CID2, 0xFF8)
169
+REG32(CID3, 0xFFC)
170
+
171
+/* PID/CID values */
172
+static const int timer_id[] = {
173
+ 0x04, 0x00, 0x00, 0x00, /* PID4..PID7 */
174
+ 0xb7, 0xb0, 0x0b, 0x00, /* PID0..PID3 */
175
+ 0x0d, 0xf0, 0x05, 0xb1, /* CID0..CID3 */
176
+};
177
+
178
+static bool sse_is_autoinc(SSETimer *s)
179
+{
180
+ return (s->cntp_aival_ctl & R_CNTP_AIVAL_CTL_EN_MASK) != 0;
181
+}
182
+
183
+static bool sse_enabled(SSETimer *s)
184
+{
185
+ return (s->cntp_ctl & R_CNTP_CTL_ENABLE_MASK) != 0;
186
+}
187
+
188
+static uint64_t sse_cntpct(SSETimer *s)
189
+{
190
+ /* Return the CNTPCT value for the current time */
191
+ return sse_counter_for_timestamp(s->counter,
192
+ qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
193
+}
194
+
195
+static bool sse_timer_status(SSETimer *s)
196
+{
197
+ /*
198
+ * Return true if timer condition is met. This is used for both
199
+ * the CNTP_CTL.ISTATUS bit and for whether (unless masked) we
200
+ * assert our IRQ.
201
+ * The documentation is unclear about the behaviour of ISTATUS when
202
+ * in autoincrement mode; we assume that it follows CNTP_AIVAL_CTL.CLR
203
+ * (ie whether the autoincrement timer is asserting the interrupt).
204
+ */
205
+ if (!sse_enabled(s)) {
206
+ return false;
207
+ }
208
+
209
+ if (sse_is_autoinc(s)) {
210
+ return s->cntp_aival_ctl & R_CNTP_AIVAL_CTL_CLR_MASK;
211
+ } else {
212
+ return sse_cntpct(s) >= s->cntp_cval;
213
+ }
214
+}
215
+
216
+static void sse_update_irq(SSETimer *s)
217
+{
218
+ bool irqstate = (!(s->cntp_ctl & R_CNTP_CTL_IMASK_MASK) &&
219
+ sse_timer_status(s));
220
+
221
+ qemu_set_irq(s->irq, irqstate);
222
+}
223
+
224
+static void sse_set_timer(SSETimer *s, uint64_t nexttick)
225
+{
226
+ /* Set the timer to expire at nexttick */
227
+ uint64_t expiry = sse_counter_tick_to_time(s->counter, nexttick);
228
+
229
+ if (expiry <= INT64_MAX) {
230
+ timer_mod_ns(&s->timer, expiry);
231
+ } else {
232
+ /*
233
+ * nexttick is so far in the future that it would overflow the
234
+ * signed 64-bit range of a QEMUTimer. Since timer_mod_ns()
235
+ * expiry times are absolute, not relative, we are never going
236
+ * to be able to set the timer to this value, so we must just
237
+ * assume that guest execution can never run so long that it
238
+ * reaches the theoretical point when the timer fires.
239
+ * This is also the code path for "counter is not running",
240
+ * which is signalled by expiry == UINT64_MAX.
241
+ */
242
+ timer_del(&s->timer);
243
+ }
244
+}
245
+
246
+static void sse_recalc_timer(SSETimer *s)
247
+{
248
+ /* Recalculate the normal timer */
249
+ uint64_t count, nexttick;
250
+
251
+ if (sse_is_autoinc(s)) {
252
+ return;
253
+ }
254
+
255
+ if (!sse_enabled(s)) {
256
+ timer_del(&s->timer);
257
+ return;
258
+ }
259
+
260
+ count = sse_cntpct(s);
261
+
262
+ if (count >= s->cntp_cval) {
263
+ /*
264
+ * Timer condition already met. In theory we have a transition when
265
+ * the count rolls back over to 0, but that is so far in the future
266
+ * that it is not representable as a timer_mod() expiry, so in
267
+ * fact sse_set_timer() will always just delete the timer.
268
+ */
269
+ nexttick = UINT64_MAX;
270
+ } else {
271
+ /* Next transition is when count hits cval */
272
+ nexttick = s->cntp_cval;
273
+ }
274
+ sse_set_timer(s, nexttick);
275
+ sse_update_irq(s);
276
+}
277
+
278
+static void sse_autoinc(SSETimer *s)
279
+{
280
+ /* Auto-increment the AIVAL, and set the timer accordingly */
281
+ s->cntp_aival = sse_cntpct(s) + s->cntp_aival_reload;
282
+ sse_set_timer(s, s->cntp_aival);
283
+}
284
+
285
+static void sse_timer_cb(void *opaque)
286
+{
287
+ SSETimer *s = SSE_TIMER(opaque);
288
+
289
+ if (sse_is_autoinc(s)) {
290
+ uint64_t count = sse_cntpct(s);
291
+
292
+ if (count >= s->cntp_aival) {
293
+ /* Timer condition met, set CLR and do another autoinc */
294
+ s->cntp_aival_ctl |= R_CNTP_AIVAL_CTL_CLR_MASK;
295
+ s->cntp_aival = count + s->cntp_aival_reload;
296
+ }
297
+ sse_set_timer(s, s->cntp_aival);
298
+ sse_update_irq(s);
299
+ } else {
300
+ sse_recalc_timer(s);
301
+ }
302
+}
303
+
304
+static uint64_t sse_timer_read(void *opaque, hwaddr offset, unsigned size)
305
+{
306
+ SSETimer *s = SSE_TIMER(opaque);
307
+ uint64_t r;
308
+
309
+ switch (offset) {
310
+ case A_CNTPCT_LO:
311
+ r = extract64(sse_cntpct(s), 0, 32);
312
+ break;
313
+ case A_CNTPCT_HI:
314
+ r = extract64(sse_cntpct(s), 32, 32);
315
+ break;
316
+ case A_CNTFRQ:
317
+ r = s->cntfrq;
318
+ break;
319
+ case A_CNTP_CVAL_LO:
320
+ r = extract64(s->cntp_cval, 0, 32);
321
+ break;
322
+ case A_CNTP_CVAL_HI:
323
+ r = extract64(s->cntp_cval, 32, 32);
324
+ break;
325
+ case A_CNTP_TVAL:
326
+ r = extract64(s->cntp_cval - sse_cntpct(s), 0, 32);
327
+ break;
328
+ case A_CNTP_CTL:
329
+ r = s->cntp_ctl;
330
+ if (sse_timer_status(s)) {
331
+ r |= R_CNTP_CTL_ISTATUS_MASK;
332
+ }
333
+ break;
334
+ case A_CNTP_AIVAL_LO:
335
+ r = extract64(s->cntp_aival, 0, 32);
336
+ break;
337
+ case A_CNTP_AIVAL_HI:
338
+ r = extract64(s->cntp_aival, 32, 32);
339
+ break;
340
+ case A_CNTP_AIVAL_RELOAD:
341
+ r = s->cntp_aival_reload;
342
+ break;
343
+ case A_CNTP_AIVAL_CTL:
344
+ /*
345
+ * All the bits of AIVAL_CTL are documented as WO, but this is probably
346
+ * a documentation error. We implement them as readable.
347
+ */
348
+ r = s->cntp_aival_ctl;
349
+ break;
350
+ case A_CNTP_CFG:
351
+ r = R_CNTP_CFG_AIVAL_IMPLEMENTED << R_CNTP_CFG_AIVAL_SHIFT;
352
+ break;
353
+ case A_PID4 ... A_CID3:
354
+ r = timer_id[(offset - A_PID4) / 4];
355
+ break;
356
+ default:
357
+ qemu_log_mask(LOG_GUEST_ERROR,
358
+ "SSE System Timer read: bad offset 0x%x",
359
+ (unsigned) offset);
360
+ r = 0;
361
+ break;
362
+ }
363
+
364
+ trace_sse_timer_read(offset, r, size);
365
+ return r;
366
+}
367
+
368
+static void sse_timer_write(void *opaque, hwaddr offset, uint64_t value,
369
+ unsigned size)
370
+{
371
+ SSETimer *s = SSE_TIMER(opaque);
372
+
373
+ trace_sse_timer_write(offset, value, size);
374
+
375
+ switch (offset) {
376
+ case A_CNTFRQ:
377
+ s->cntfrq = value;
378
+ break;
379
+ case A_CNTP_CVAL_LO:
380
+ s->cntp_cval = deposit64(s->cntp_cval, 0, 32, value);
381
+ sse_recalc_timer(s);
382
+ break;
383
+ case A_CNTP_CVAL_HI:
384
+ s->cntp_cval = deposit64(s->cntp_cval, 32, 32, value);
385
+ sse_recalc_timer(s);
386
+ break;
387
+ case A_CNTP_TVAL:
388
+ s->cntp_cval = sse_cntpct(s) + sextract64(value, 0, 32);
389
+ sse_recalc_timer(s);
390
+ break;
391
+ case A_CNTP_CTL:
392
+ {
393
+ uint32_t old_ctl = s->cntp_ctl;
394
+ value &= R_CNTP_CTL_ENABLE_MASK | R_CNTP_CTL_IMASK_MASK;
395
+ s->cntp_ctl = value;
396
+ if ((old_ctl ^ s->cntp_ctl) & R_CNTP_CTL_ENABLE_MASK) {
397
+ if (sse_enabled(s)) {
398
+ if (sse_is_autoinc(s)) {
399
+ sse_autoinc(s);
400
+ } else {
401
+ sse_recalc_timer(s);
402
+ }
403
+ }
404
+ }
405
+ sse_update_irq(s);
406
+ break;
407
+ }
408
+ case A_CNTP_AIVAL_RELOAD:
409
+ s->cntp_aival_reload = value;
410
+ break;
411
+ case A_CNTP_AIVAL_CTL:
412
+ {
413
+ uint32_t old_ctl = s->cntp_aival_ctl;
414
+
415
+ /* EN bit is writeable; CLR bit is write-0-to-clear, write-1-ignored */
416
+ s->cntp_aival_ctl &= ~R_CNTP_AIVAL_CTL_EN_MASK;
417
+ s->cntp_aival_ctl |= value & R_CNTP_AIVAL_CTL_EN_MASK;
418
+ if (!(value & R_CNTP_AIVAL_CTL_CLR_MASK)) {
419
+ s->cntp_aival_ctl &= ~R_CNTP_AIVAL_CTL_CLR_MASK;
420
+ }
421
+ if ((old_ctl ^ s->cntp_aival_ctl) & R_CNTP_AIVAL_CTL_EN_MASK) {
422
+ /* Auto-increment toggled on/off */
423
+ if (sse_enabled(s)) {
424
+ if (sse_is_autoinc(s)) {
425
+ sse_autoinc(s);
426
+ } else {
427
+ sse_recalc_timer(s);
428
+ }
429
+ }
430
+ }
431
+ sse_update_irq(s);
432
+ break;
433
+ }
434
+ case A_CNTPCT_LO:
435
+ case A_CNTPCT_HI:
436
+ case A_CNTP_CFG:
437
+ case A_CNTP_AIVAL_LO:
438
+ case A_CNTP_AIVAL_HI:
439
+ case A_PID4 ... A_CID3:
440
+ qemu_log_mask(LOG_GUEST_ERROR,
441
+ "SSE System Timer write: write to RO offset 0x%x\n",
442
+ (unsigned)offset);
443
+ break;
444
+ default:
445
+ qemu_log_mask(LOG_GUEST_ERROR,
446
+ "SSE System Timer write: bad offset 0x%x\n",
447
+ (unsigned)offset);
448
+ break;
449
+ }
450
+}
451
+
452
+static const MemoryRegionOps sse_timer_ops = {
453
+ .read = sse_timer_read,
454
+ .write = sse_timer_write,
455
+ .endianness = DEVICE_LITTLE_ENDIAN,
456
+ .valid.min_access_size = 4,
457
+ .valid.max_access_size = 4,
458
+};
459
+
460
+static void sse_timer_reset(DeviceState *dev)
461
+{
462
+ SSETimer *s = SSE_TIMER(dev);
463
+
464
+ trace_sse_timer_reset();
465
+
466
+ timer_del(&s->timer);
467
+ s->cntfrq = 0;
468
+ s->cntp_ctl = 0;
469
+ s->cntp_cval = 0;
470
+ s->cntp_aival = 0;
471
+ s->cntp_aival_ctl = 0;
472
+ s->cntp_aival_reload = 0;
473
+}
474
+
475
+static void sse_timer_counter_callback(Notifier *notifier, void *data)
476
+{
477
+ SSETimer *s = container_of(notifier, SSETimer, counter_notifier);
478
+
479
+ /* System counter told us we need to recalculate */
480
+ if (sse_enabled(s)) {
481
+ if (sse_is_autoinc(s)) {
482
+ sse_set_timer(s, s->cntp_aival);
483
+ } else {
484
+ sse_recalc_timer(s);
485
+ }
486
+ }
487
+}
488
+
489
+static void sse_timer_init(Object *obj)
490
+{
491
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
492
+ SSETimer *s = SSE_TIMER(obj);
493
+
494
+ memory_region_init_io(&s->iomem, obj, &sse_timer_ops,
495
+ s, "sse-timer", 0x1000);
496
+ sysbus_init_mmio(sbd, &s->iomem);
497
+ sysbus_init_irq(sbd, &s->irq);
498
+}
499
+
500
+static void sse_timer_realize(DeviceState *dev, Error **errp)
501
+{
502
+ SSETimer *s = SSE_TIMER(dev);
503
+
504
+ if (!s->counter) {
505
+ error_setg(errp, "counter property was not set");
506
+ }
507
+
508
+ s->counter_notifier.notify = sse_timer_counter_callback;
509
+ sse_counter_register_consumer(s->counter, &s->counter_notifier);
510
+
511
+ timer_init_ns(&s->timer, QEMU_CLOCK_VIRTUAL, sse_timer_cb, s);
512
+}
513
+
514
+static const VMStateDescription sse_timer_vmstate = {
515
+ .name = "sse-timer",
516
+ .version_id = 1,
517
+ .minimum_version_id = 1,
518
+ .fields = (VMStateField[]) {
519
+ VMSTATE_TIMER(timer, SSETimer),
520
+ VMSTATE_UINT32(cntfrq, SSETimer),
521
+ VMSTATE_UINT32(cntp_ctl, SSETimer),
522
+ VMSTATE_UINT64(cntp_cval, SSETimer),
523
+ VMSTATE_UINT64(cntp_aival, SSETimer),
524
+ VMSTATE_UINT32(cntp_aival_ctl, SSETimer),
525
+ VMSTATE_UINT32(cntp_aival_reload, SSETimer),
526
+ VMSTATE_END_OF_LIST()
527
+ }
528
+};
529
+
530
+static Property sse_timer_properties[] = {
531
+ DEFINE_PROP_LINK("counter", SSETimer, counter, TYPE_SSE_COUNTER, SSECounter *),
532
+ DEFINE_PROP_END_OF_LIST(),
533
+};
534
+
535
+static void sse_timer_class_init(ObjectClass *klass, void *data)
536
+{
537
+ DeviceClass *dc = DEVICE_CLASS(klass);
538
+
539
+ dc->realize = sse_timer_realize;
540
+ dc->vmsd = &sse_timer_vmstate;
541
+ dc->reset = sse_timer_reset;
542
+ device_class_set_props(dc, sse_timer_properties);
543
+}
544
+
545
+static const TypeInfo sse_timer_info = {
546
+ .name = TYPE_SSE_TIMER,
547
+ .parent = TYPE_SYS_BUS_DEVICE,
548
+ .instance_size = sizeof(SSETimer),
549
+ .instance_init = sse_timer_init,
550
+ .class_init = sse_timer_class_init,
551
+};
552
+
553
+static void sse_timer_register_types(void)
554
+{
555
+ type_register_static(&sse_timer_info);
556
+}
557
+
558
+type_init(sse_timer_register_types);
559
diff --git a/MAINTAINERS b/MAINTAINERS
560
index XXXXXXX..XXXXXXX 100644
561
--- a/MAINTAINERS
562
+++ b/MAINTAINERS
563
@@ -XXX,XX +XXX,XX @@ F: hw/misc/armsse-mhu.c
564
F: include/hw/misc/armsse-mhu.h
565
F: hw/timer/sse-counter.c
566
F: include/hw/timer/sse-counter.h
567
+F: hw/timer/sse-timer.c
568
+F: include/hw/timer/sse-timer.h
569
F: docs/system/arm/mps2.rst
570
571
Musca
572
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
573
index XXXXXXX..XXXXXXX 100644
574
--- a/hw/arm/Kconfig
575
+++ b/hw/arm/Kconfig
576
@@ -XXX,XX +XXX,XX @@ config ARMSSE
577
select TZ_PPC
578
select UNIMP
579
select SSE_COUNTER
580
+ select SSE_TIMER
581
582
config ARMSSE_CPUID
583
bool
584
diff --git a/hw/timer/Kconfig b/hw/timer/Kconfig
585
index XXXXXXX..XXXXXXX 100644
586
--- a/hw/timer/Kconfig
587
+++ b/hw/timer/Kconfig
588
@@ -XXX,XX +XXX,XX @@ config RENESAS_CMT
589
config SSE_COUNTER
590
bool
591
592
+config SSE_TIMER
593
+ bool
594
+
595
config AVR_TIMER16
596
bool
597
diff --git a/hw/timer/meson.build b/hw/timer/meson.build
598
index XXXXXXX..XXXXXXX 100644
599
--- a/hw/timer/meson.build
600
+++ b/hw/timer/meson.build
601
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_RASPI', if_true: files('bcm2835_systmr.c'))
602
softmmu_ss.add(when: 'CONFIG_SH4', if_true: files('sh_timer.c'))
603
softmmu_ss.add(when: 'CONFIG_SLAVIO', if_true: files('slavio_timer.c'))
604
softmmu_ss.add(when: 'CONFIG_SSE_COUNTER', if_true: files('sse-counter.c'))
605
+softmmu_ss.add(when: 'CONFIG_SSE_TIMER', if_true: files('sse-timer.c'))
606
softmmu_ss.add(when: 'CONFIG_STM32F2XX_TIMER', if_true: files('stm32f2xx_timer.c'))
607
softmmu_ss.add(when: 'CONFIG_XILINX', if_true: files('xilinx_timer.c'))
608
609
diff --git a/hw/timer/trace-events b/hw/timer/trace-events
610
index XXXXXXX..XXXXXXX 100644
611
--- a/hw/timer/trace-events
612
+++ b/hw/timer/trace-events
613
@@ -XXX,XX +XXX,XX @@ sse_counter_control_write(uint64_t offset, uint64_t data, unsigned size) "SSE sy
614
sse_counter_status_read(uint64_t offset, uint64_t data, unsigned size) "SSE system counter status frame read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
615
sse_counter_status_write(uint64_t offset, uint64_t data, unsigned size) "SSE system counter status frame write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
616
sse_counter_reset(void) "SSE system counter: reset"
617
+
618
+# sse_timer.c
619
+sse_timer_read(uint64_t offset, uint64_t data, unsigned size) "SSE system timer read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
620
+sse_timer_write(uint64_t offset, uint64_t data, unsigned size) "SSE system timer write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
621
+sse_timer_reset(void) "SSE system timer: reset"
622
--
623
2.20.1
624
625
diff view generated by jsdifflib
Deleted patch
1
The SSE-300's iokit-sysctl device is similar to the SSE-200, but
2
some registers have moved address or have different behaviours.
3
In this commit we add case statements for the registers where
4
the SSE-300 and SSE-200 have the same behaviour. Some registers
5
are the same on all SSE versions and so need no code change at all.
6
Putting both of these categories together covers:
7
1
8
0x0 SECDBGSTAT
9
0x4 SECDBGSET
10
0x8 SECDBGCLR
11
0xc SCSECCTRL
12
0x10 CLK_CFG0 -- this is like SSE-200 FCLK_DIV but with a
13
different set of clocks being controlled; our implementation
14
is a dummy reads-as-written anyway
15
0x14 CLK_CFG1 -- similar to SSE-200 SYSCLK_DIV; our implementation
16
is a dummy
17
0x18 CLK_FORCE -- similar to SSE-200 but different bit allocations;
18
we have a dummy implementation
19
0x100 RESET_SYNDROME -- bit allocation differs from SSE-200 but our
20
implementation is a dummy
21
0x104 RESET_MASK -- bit allocation differs from SSE-200 but our
22
implementation is a dummy
23
0x108 SWRESET
24
0x10c GRETREG
25
0x200 PDCM_PD_SYS_SENSE -- some bit allocations differ, but our
26
implementation is a dummy
27
28
We also need to migrate the state of these registers which are shared
29
between the SSE-200 and SSE-300, so update the vmstate 'needed'
30
function to do this.
31
32
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
33
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
34
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
35
Message-id: 20210219144617.4782-14-peter.maydell@linaro.org
36
---
37
hw/misc/iotkit-sysctl.c | 12 +++++++++++-
38
1 file changed, 11 insertions(+), 1 deletion(-)
39
40
diff --git a/hw/misc/iotkit-sysctl.c b/hw/misc/iotkit-sysctl.c
41
index XXXXXXX..XXXXXXX 100644
42
--- a/hw/misc/iotkit-sysctl.c
43
+++ b/hw/misc/iotkit-sysctl.c
44
@@ -XXX,XX +XXX,XX @@ static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
45
case ARMSSE_IOTKIT:
46
goto bad_offset;
47
case ARMSSE_SSE200:
48
+ case ARMSSE_SSE300:
49
r = s->scsecctrl;
50
break;
51
default:
52
@@ -XXX,XX +XXX,XX @@ static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
53
case ARMSSE_IOTKIT:
54
goto bad_offset;
55
case ARMSSE_SSE200:
56
+ case ARMSSE_SSE300:
57
r = s->fclk_div;
58
break;
59
default:
60
@@ -XXX,XX +XXX,XX @@ static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
61
case ARMSSE_IOTKIT:
62
goto bad_offset;
63
case ARMSSE_SSE200:
64
+ case ARMSSE_SSE300:
65
r = s->sysclk_div;
66
break;
67
default:
68
@@ -XXX,XX +XXX,XX @@ static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
69
case ARMSSE_IOTKIT:
70
goto bad_offset;
71
case ARMSSE_SSE200:
72
+ case ARMSSE_SSE300:
73
r = s->clock_force;
74
break;
75
default:
76
@@ -XXX,XX +XXX,XX @@ static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
77
case ARMSSE_IOTKIT:
78
goto bad_offset;
79
case ARMSSE_SSE200:
80
+ case ARMSSE_SSE300:
81
r = s->pdcm_pd_sys_sense;
82
break;
83
default:
84
@@ -XXX,XX +XXX,XX @@ static void iotkit_sysctl_write(void *opaque, hwaddr offset,
85
case ARMSSE_IOTKIT:
86
goto bad_offset;
87
case ARMSSE_SSE200:
88
+ case ARMSSE_SSE300:
89
qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl SCSECCTRL unimplemented\n");
90
s->scsecctrl = value;
91
break;
92
@@ -XXX,XX +XXX,XX @@ static void iotkit_sysctl_write(void *opaque, hwaddr offset,
93
case ARMSSE_IOTKIT:
94
goto bad_offset;
95
case ARMSSE_SSE200:
96
+ case ARMSSE_SSE300:
97
qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl FCLK_DIV unimplemented\n");
98
s->fclk_div = value;
99
break;
100
@@ -XXX,XX +XXX,XX @@ static void iotkit_sysctl_write(void *opaque, hwaddr offset,
101
case ARMSSE_IOTKIT:
102
goto bad_offset;
103
case ARMSSE_SSE200:
104
+ case ARMSSE_SSE300:
105
qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl SYSCLK_DIV unimplemented\n");
106
s->sysclk_div = value;
107
break;
108
@@ -XXX,XX +XXX,XX @@ static void iotkit_sysctl_write(void *opaque, hwaddr offset,
109
case ARMSSE_IOTKIT:
110
goto bad_offset;
111
case ARMSSE_SSE200:
112
+ case ARMSSE_SSE300:
113
qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl CLOCK_FORCE unimplemented\n");
114
s->clock_force = value;
115
break;
116
@@ -XXX,XX +XXX,XX @@ static void iotkit_sysctl_write(void *opaque, hwaddr offset,
117
case ARMSSE_IOTKIT:
118
goto bad_offset;
119
case ARMSSE_SSE200:
120
+ case ARMSSE_SSE300:
121
qemu_log_mask(LOG_UNIMP,
122
"IoTKit SysCtl PDCM_PD_SYS_SENSE unimplemented\n");
123
s->pdcm_pd_sys_sense = value;
124
@@ -XXX,XX +XXX,XX @@ static bool sse200_needed(void *opaque)
125
{
126
IoTKitSysCtl *s = IOTKIT_SYSCTL(opaque);
127
128
- return s->sse_version == ARMSSE_SSE200;
129
+ return s->sse_version != ARMSSE_IOTKIT;
130
}
131
132
static const VMStateDescription iotkit_sysctl_sse200_vmstate = {
133
--
134
2.20.1
135
136
diff view generated by jsdifflib
Deleted patch
1
The SSE-300 has only one CPU and so no INITSVTOR1. It does
2
have INITSVTOR0, but unlike the SSE-200 this register now
3
has a LOCK bit which can be set to 1 to prevent any further
4
writes to the register. Implement these differences.
5
1
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20210219144617.4782-16-peter.maydell@linaro.org
10
---
11
hw/misc/iotkit-sysctl.c | 27 +++++++++++++++++++++++++--
12
1 file changed, 25 insertions(+), 2 deletions(-)
13
14
diff --git a/hw/misc/iotkit-sysctl.c b/hw/misc/iotkit-sysctl.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/misc/iotkit-sysctl.c
17
+++ b/hw/misc/iotkit-sysctl.c
18
@@ -XXX,XX +XXX,XX @@ REG32(SWRESET, 0x108)
19
FIELD(SWRESET, SWRESETREQ, 9, 1)
20
REG32(GRETREG, 0x10c)
21
REG32(INITSVTOR0, 0x110)
22
+ FIELD(INITSVTOR0, LOCK, 0, 1)
23
+ FIELD(INITSVTOR0, VTOR, 7, 25)
24
REG32(INITSVTOR1, 0x114)
25
REG32(CPUWAIT, 0x118)
26
REG32(NMI_ENABLE, 0x11c) /* BUSWAIT in IoTKit */
27
@@ -XXX,XX +XXX,XX @@ static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
28
case ARMSSE_SSE200:
29
r = s->initsvtor1;
30
break;
31
+ case ARMSSE_SSE300:
32
+ goto bad_offset;
33
default:
34
g_assert_not_reached();
35
}
36
@@ -XXX,XX +XXX,XX @@ static void iotkit_sysctl_write(void *opaque, hwaddr offset,
37
s->gretreg = value;
38
break;
39
case A_INITSVTOR0:
40
- s->initsvtor0 = value;
41
- set_init_vtor(0, s->initsvtor0);
42
+ switch (s->sse_version) {
43
+ case ARMSSE_SSE300:
44
+ /* SSE300 has a LOCK bit which prevents further writes when set */
45
+ if (s->initsvtor0 & R_INITSVTOR0_LOCK_MASK) {
46
+ qemu_log_mask(LOG_GUEST_ERROR,
47
+ "IoTKit INITSVTOR0 write when register locked\n");
48
+ break;
49
+ }
50
+ s->initsvtor0 = value;
51
+ set_init_vtor(0, s->initsvtor0 & R_INITSVTOR0_VTOR_MASK);
52
+ break;
53
+ case ARMSSE_IOTKIT:
54
+ case ARMSSE_SSE200:
55
+ s->initsvtor0 = value;
56
+ set_init_vtor(0, s->initsvtor0);
57
+ break;
58
+ default:
59
+ g_assert_not_reached();
60
+ }
61
break;
62
case A_CPUWAIT:
63
switch (s->sse_version) {
64
@@ -XXX,XX +XXX,XX @@ static void iotkit_sysctl_write(void *opaque, hwaddr offset,
65
s->initsvtor1 = value;
66
set_init_vtor(1, s->initsvtor1);
67
break;
68
+ case ARMSSE_SSE300:
69
+ goto bad_offset;
70
default:
71
g_assert_not_reached();
72
}
73
--
74
2.20.1
75
76
diff view generated by jsdifflib
Deleted patch
1
The SSE-300 has a new PWRCTRL register at offset 0x1fc (previously
2
reserved). This register controls accessibility of some registers
3
in the Power Policy Units (PPUs). Since QEMU doesn't implement
4
the PPUs, we don't need to implement any real behaviour for this
5
register, so we just handle the UNLOCK bit which controls whether
6
writes to the register itself are permitted and otherwise make it
7
be reads-as-written.
8
1
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20210219144617.4782-17-peter.maydell@linaro.org
13
---
14
include/hw/misc/iotkit-sysctl.h | 1 +
15
hw/misc/iotkit-sysctl.c | 52 +++++++++++++++++++++++++++++++++
16
2 files changed, 53 insertions(+)
17
18
diff --git a/include/hw/misc/iotkit-sysctl.h b/include/hw/misc/iotkit-sysctl.h
19
index XXXXXXX..XXXXXXX 100644
20
--- a/include/hw/misc/iotkit-sysctl.h
21
+++ b/include/hw/misc/iotkit-sysctl.h
22
@@ -XXX,XX +XXX,XX @@ struct IoTKitSysCtl {
23
uint32_t initsvtor1;
24
uint32_t nmi_enable;
25
uint32_t ewctrl;
26
+ uint32_t pwrctrl;
27
uint32_t pdcm_pd_sys_sense;
28
uint32_t pdcm_pd_sram0_sense;
29
uint32_t pdcm_pd_sram1_sense;
30
diff --git a/hw/misc/iotkit-sysctl.c b/hw/misc/iotkit-sysctl.c
31
index XXXXXXX..XXXXXXX 100644
32
--- a/hw/misc/iotkit-sysctl.c
33
+++ b/hw/misc/iotkit-sysctl.c
34
@@ -XXX,XX +XXX,XX @@ REG32(CPUWAIT, 0x118)
35
REG32(NMI_ENABLE, 0x11c) /* BUSWAIT in IoTKit */
36
REG32(WICCTRL, 0x120)
37
REG32(EWCTRL, 0x124)
38
+REG32(PWRCTRL, 0x1fc)
39
+ FIELD(PWRCTRL, PPU_ACCESS_UNLOCK, 0, 1)
40
+ FIELD(PWRCTRL, PPU_ACCESS_FILTER, 1, 1)
41
REG32(PDCM_PD_SYS_SENSE, 0x200)
42
REG32(PDCM_PD_SRAM0_SENSE, 0x20c)
43
REG32(PDCM_PD_SRAM1_SENSE, 0x210)
44
@@ -XXX,XX +XXX,XX @@ static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
45
g_assert_not_reached();
46
}
47
break;
48
+ case A_PWRCTRL:
49
+ switch (s->sse_version) {
50
+ case ARMSSE_IOTKIT:
51
+ case ARMSSE_SSE200:
52
+ goto bad_offset;
53
+ case ARMSSE_SSE300:
54
+ r = s->pwrctrl;
55
+ break;
56
+ default:
57
+ g_assert_not_reached();
58
+ }
59
+ break;
60
case A_PDCM_PD_SYS_SENSE:
61
switch (s->sse_version) {
62
case ARMSSE_IOTKIT:
63
@@ -XXX,XX +XXX,XX @@ static void iotkit_sysctl_write(void *opaque, hwaddr offset,
64
g_assert_not_reached();
65
}
66
break;
67
+ case A_PWRCTRL:
68
+ switch (s->sse_version) {
69
+ case ARMSSE_IOTKIT:
70
+ case ARMSSE_SSE200:
71
+ goto bad_offset;
72
+ case ARMSSE_SSE300:
73
+ if (!(s->pwrctrl & R_PWRCTRL_PPU_ACCESS_UNLOCK_MASK)) {
74
+ qemu_log_mask(LOG_GUEST_ERROR,
75
+ "IoTKit PWRCTRL write when register locked\n");
76
+ break;
77
+ }
78
+ s->pwrctrl = value;
79
+ break;
80
+ default:
81
+ g_assert_not_reached();
82
+ }
83
+ break;
84
case A_PDCM_PD_SYS_SENSE:
85
switch (s->sse_version) {
86
case ARMSSE_IOTKIT:
87
@@ -XXX,XX +XXX,XX @@ static void iotkit_sysctl_reset(DeviceState *dev)
88
s->clock_force = 0;
89
s->nmi_enable = 0;
90
s->ewctrl = 0;
91
+ s->pwrctrl = 0x3;
92
s->pdcm_pd_sys_sense = 0x7f;
93
s->pdcm_pd_sram0_sense = 0;
94
s->pdcm_pd_sram1_sense = 0;
95
@@ -XXX,XX +XXX,XX @@ static void iotkit_sysctl_realize(DeviceState *dev, Error **errp)
96
}
97
}
98
99
+static bool sse300_needed(void *opaque)
100
+{
101
+ IoTKitSysCtl *s = IOTKIT_SYSCTL(opaque);
102
+
103
+ return s->sse_version == ARMSSE_SSE300;
104
+}
105
+
106
+static const VMStateDescription iotkit_sysctl_sse300_vmstate = {
107
+ .name = "iotkit-sysctl/sse-300",
108
+ .version_id = 1,
109
+ .minimum_version_id = 1,
110
+ .needed = sse300_needed,
111
+ .fields = (VMStateField[]) {
112
+ VMSTATE_UINT32(pwrctrl, IoTKitSysCtl),
113
+ VMSTATE_END_OF_LIST()
114
+ }
115
+};
116
+
117
static bool sse200_needed(void *opaque)
118
{
119
IoTKitSysCtl *s = IOTKIT_SYSCTL(opaque);
120
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription iotkit_sysctl_vmstate = {
121
},
122
.subsections = (const VMStateDescription*[]) {
123
&iotkit_sysctl_sse200_vmstate,
124
+ &iotkit_sysctl_sse300_vmstate,
125
NULL
126
}
127
};
128
--
129
2.20.1
130
131
diff view generated by jsdifflib
Deleted patch
1
The sysctl PDCM_PD_*_SENSE registers control various power domains in
2
the system and allow the guest to configure which conditions keep a
3
power domain awake and what power state to use when the domain is in
4
a low power state. QEMU doesn't model power domains, so for us these
5
registers are dummy reads-as-written implementations.
6
1
7
The SSE-300 has a different power domain setup, so the set of
8
registers is slightly different:
9
10
Offset SSE-200 SSE-300
11
---------------------------------------------------
12
0x200 PDCM_PD_SYS_SENSE PDCM_PD_SYS_SENSE
13
0x204 reserved PDCM_PD_CPU0_SENSE
14
0x208 reserved reserved
15
0x20c PDCM_PD_SRAM0_SENSE reserved
16
0x210 PDCM_PD_SRAM1_SENSE reserved
17
0x214 PDCM_PD_SRAM2_SENSE PDCM_PD_VMR0_SENSE
18
0x218 PDCM_PD_SRAM3_SENSE PDCM_PD_VMR1_SENSE
19
20
Offsets 0x200 and 0x208 are the same for both, so handled in a
21
previous commit; here we deal with 0x204, 0x20c, 0x210, 0x214, 0x218.
22
23
(We can safely add new lines to the SSE300 vmstate because no board
24
uses this device in an SSE300 yet.)
25
26
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
27
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
28
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
29
Message-id: 20210219144617.4782-18-peter.maydell@linaro.org
30
---
31
include/hw/misc/iotkit-sysctl.h | 3 ++
32
hw/misc/iotkit-sysctl.c | 61 +++++++++++++++++++++++++++++++--
33
2 files changed, 62 insertions(+), 2 deletions(-)
34
35
diff --git a/include/hw/misc/iotkit-sysctl.h b/include/hw/misc/iotkit-sysctl.h
36
index XXXXXXX..XXXXXXX 100644
37
--- a/include/hw/misc/iotkit-sysctl.h
38
+++ b/include/hw/misc/iotkit-sysctl.h
39
@@ -XXX,XX +XXX,XX @@ struct IoTKitSysCtl {
40
uint32_t pdcm_pd_sram1_sense;
41
uint32_t pdcm_pd_sram2_sense;
42
uint32_t pdcm_pd_sram3_sense;
43
+ uint32_t pdcm_pd_cpu0_sense;
44
+ uint32_t pdcm_pd_vmr0_sense;
45
+ uint32_t pdcm_pd_vmr1_sense;
46
47
/* Properties */
48
uint32_t sse_version;
49
diff --git a/hw/misc/iotkit-sysctl.c b/hw/misc/iotkit-sysctl.c
50
index XXXXXXX..XXXXXXX 100644
51
--- a/hw/misc/iotkit-sysctl.c
52
+++ b/hw/misc/iotkit-sysctl.c
53
@@ -XXX,XX +XXX,XX @@ REG32(PWRCTRL, 0x1fc)
54
FIELD(PWRCTRL, PPU_ACCESS_UNLOCK, 0, 1)
55
FIELD(PWRCTRL, PPU_ACCESS_FILTER, 1, 1)
56
REG32(PDCM_PD_SYS_SENSE, 0x200)
57
+REG32(PDCM_PD_CPU0_SENSE, 0x204)
58
REG32(PDCM_PD_SRAM0_SENSE, 0x20c)
59
REG32(PDCM_PD_SRAM1_SENSE, 0x210)
60
-REG32(PDCM_PD_SRAM2_SENSE, 0x214)
61
-REG32(PDCM_PD_SRAM3_SENSE, 0x218)
62
+REG32(PDCM_PD_SRAM2_SENSE, 0x214) /* PDCM_PD_VMR0_SENSE on SSE300 */
63
+REG32(PDCM_PD_SRAM3_SENSE, 0x218) /* PDCM_PD_VMR1_SENSE on SSE300 */
64
REG32(PID4, 0xfd0)
65
REG32(PID5, 0xfd4)
66
REG32(PID6, 0xfd8)
67
@@ -XXX,XX +XXX,XX @@ static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
68
g_assert_not_reached();
69
}
70
break;
71
+ case A_PDCM_PD_CPU0_SENSE:
72
+ switch (s->sse_version) {
73
+ case ARMSSE_IOTKIT:
74
+ case ARMSSE_SSE200:
75
+ goto bad_offset;
76
+ case ARMSSE_SSE300:
77
+ r = s->pdcm_pd_cpu0_sense;
78
+ break;
79
+ default:
80
+ g_assert_not_reached();
81
+ }
82
+ break;
83
case A_PDCM_PD_SRAM0_SENSE:
84
switch (s->sse_version) {
85
case ARMSSE_IOTKIT:
86
@@ -XXX,XX +XXX,XX @@ static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
87
case ARMSSE_SSE200:
88
r = s->pdcm_pd_sram0_sense;
89
break;
90
+ case ARMSSE_SSE300:
91
+ goto bad_offset;
92
default:
93
g_assert_not_reached();
94
}
95
@@ -XXX,XX +XXX,XX @@ static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
96
case ARMSSE_SSE200:
97
r = s->pdcm_pd_sram1_sense;
98
break;
99
+ case ARMSSE_SSE300:
100
+ goto bad_offset;
101
default:
102
g_assert_not_reached();
103
}
104
@@ -XXX,XX +XXX,XX @@ static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
105
case ARMSSE_SSE200:
106
r = s->pdcm_pd_sram2_sense;
107
break;
108
+ case ARMSSE_SSE300:
109
+ r = s->pdcm_pd_vmr0_sense;
110
+ break;
111
default:
112
g_assert_not_reached();
113
}
114
@@ -XXX,XX +XXX,XX @@ static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
115
case ARMSSE_SSE200:
116
r = s->pdcm_pd_sram3_sense;
117
break;
118
+ case ARMSSE_SSE300:
119
+ r = s->pdcm_pd_vmr1_sense;
120
+ break;
121
default:
122
g_assert_not_reached();
123
}
124
@@ -XXX,XX +XXX,XX @@ static void iotkit_sysctl_write(void *opaque, hwaddr offset,
125
g_assert_not_reached();
126
}
127
break;
128
+ case A_PDCM_PD_CPU0_SENSE:
129
+ switch (s->sse_version) {
130
+ case ARMSSE_IOTKIT:
131
+ case ARMSSE_SSE200:
132
+ goto bad_offset;
133
+ case ARMSSE_SSE300:
134
+ qemu_log_mask(LOG_UNIMP,
135
+ "IoTKit SysCtl PDCM_PD_CPU0_SENSE unimplemented\n");
136
+ s->pdcm_pd_cpu0_sense = value;
137
+ break;
138
+ default:
139
+ g_assert_not_reached();
140
+ }
141
+ break;
142
case A_PDCM_PD_SRAM0_SENSE:
143
switch (s->sse_version) {
144
case ARMSSE_IOTKIT:
145
@@ -XXX,XX +XXX,XX @@ static void iotkit_sysctl_write(void *opaque, hwaddr offset,
146
"IoTKit SysCtl PDCM_PD_SRAM0_SENSE unimplemented\n");
147
s->pdcm_pd_sram0_sense = value;
148
break;
149
+ case ARMSSE_SSE300:
150
+ goto bad_offset;
151
default:
152
g_assert_not_reached();
153
}
154
@@ -XXX,XX +XXX,XX @@ static void iotkit_sysctl_write(void *opaque, hwaddr offset,
155
"IoTKit SysCtl PDCM_PD_SRAM1_SENSE unimplemented\n");
156
s->pdcm_pd_sram1_sense = value;
157
break;
158
+ case ARMSSE_SSE300:
159
+ goto bad_offset;
160
default:
161
g_assert_not_reached();
162
}
163
@@ -XXX,XX +XXX,XX @@ static void iotkit_sysctl_write(void *opaque, hwaddr offset,
164
"IoTKit SysCtl PDCM_PD_SRAM2_SENSE unimplemented\n");
165
s->pdcm_pd_sram2_sense = value;
166
break;
167
+ case ARMSSE_SSE300:
168
+ qemu_log_mask(LOG_UNIMP,
169
+ "IoTKit SysCtl PDCM_PD_VMR0_SENSE unimplemented\n");
170
+ s->pdcm_pd_vmr0_sense = value;
171
+ break;
172
default:
173
g_assert_not_reached();
174
}
175
@@ -XXX,XX +XXX,XX @@ static void iotkit_sysctl_write(void *opaque, hwaddr offset,
176
"IoTKit SysCtl PDCM_PD_SRAM3_SENSE unimplemented\n");
177
s->pdcm_pd_sram3_sense = value;
178
break;
179
+ case ARMSSE_SSE300:
180
+ qemu_log_mask(LOG_UNIMP,
181
+ "IoTKit SysCtl PDCM_PD_VMR1_SENSE unimplemented\n");
182
+ s->pdcm_pd_vmr1_sense = value;
183
+ break;
184
default:
185
g_assert_not_reached();
186
}
187
@@ -XXX,XX +XXX,XX @@ static void iotkit_sysctl_reset(DeviceState *dev)
188
s->pdcm_pd_sram1_sense = 0;
189
s->pdcm_pd_sram2_sense = 0;
190
s->pdcm_pd_sram3_sense = 0;
191
+ s->pdcm_pd_cpu0_sense = 0;
192
+ s->pdcm_pd_vmr0_sense = 0;
193
+ s->pdcm_pd_vmr1_sense = 0;
194
}
195
196
static void iotkit_sysctl_init(Object *obj)
197
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription iotkit_sysctl_sse300_vmstate = {
198
.needed = sse300_needed,
199
.fields = (VMStateField[]) {
200
VMSTATE_UINT32(pwrctrl, IoTKitSysCtl),
201
+ VMSTATE_UINT32(pdcm_pd_cpu0_sense, IoTKitSysCtl),
202
+ VMSTATE_UINT32(pdcm_pd_vmr0_sense, IoTKitSysCtl),
203
+ VMSTATE_UINT32(pdcm_pd_vmr1_sense, IoTKitSysCtl),
204
VMSTATE_END_OF_LIST()
205
}
206
};
207
--
208
2.20.1
209
210
diff view generated by jsdifflib
Deleted patch
1
The SSE-200 and SSE-300 have different PID register values from the
2
IoTKit for the sysctl register block. We incorrectly implemented the
3
SSE-200 with the same PID values as IoTKit. Fix the SSE-200 bug and
4
report these register values for SSE-300.
5
1
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20210219144617.4782-19-peter.maydell@linaro.org
10
---
11
hw/misc/iotkit-sysctl.c | 21 +++++++++++++++++++--
12
1 file changed, 19 insertions(+), 2 deletions(-)
13
14
diff --git a/hw/misc/iotkit-sysctl.c b/hw/misc/iotkit-sysctl.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/misc/iotkit-sysctl.c
17
+++ b/hw/misc/iotkit-sysctl.c
18
@@ -XXX,XX +XXX,XX @@ REG32(CID2, 0xff8)
19
REG32(CID3, 0xffc)
20
21
/* PID/CID values */
22
-static const int sysctl_id[] = {
23
+static const int iotkit_sysctl_id[] = {
24
0x04, 0x00, 0x00, 0x00, /* PID4..PID7 */
25
0x54, 0xb8, 0x0b, 0x00, /* PID0..PID3 */
26
0x0d, 0xf0, 0x05, 0xb1, /* CID0..CID3 */
27
};
28
29
+/* Also used by the SSE300 */
30
+static const int sse200_sysctl_id[] = {
31
+ 0x04, 0x00, 0x00, 0x00, /* PID4..PID7 */
32
+ 0x54, 0xb8, 0x1b, 0x00, /* PID0..PID3 */
33
+ 0x0d, 0xf0, 0x05, 0xb1, /* CID0..CID3 */
34
+};
35
+
36
/*
37
* Set the initial secure vector table offset address for the core.
38
* This will take effect when the CPU next resets.
39
@@ -XXX,XX +XXX,XX @@ static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
40
}
41
break;
42
case A_PID4 ... A_CID3:
43
- r = sysctl_id[(offset - A_PID4) / 4];
44
+ switch (s->sse_version) {
45
+ case ARMSSE_IOTKIT:
46
+ r = iotkit_sysctl_id[(offset - A_PID4) / 4];
47
+ break;
48
+ case ARMSSE_SSE200:
49
+ case ARMSSE_SSE300:
50
+ r = sse200_sysctl_id[(offset - A_PID4) / 4];
51
+ break;
52
+ default:
53
+ g_assert_not_reached();
54
+ }
55
break;
56
case A_SECDBGSET:
57
case A_SECDBGCLR:
58
--
59
2.20.1
60
61
diff view generated by jsdifflib
Deleted patch
1
The ARMSSE_CPUID and ARMSSE_MHU Kconfig stanzas are for the devices
2
implemented by hw/misc/cpuid.c and hw/misc/armsse-mhu.c. Move them
3
to hw/misc/Kconfig where they belong.
4
1
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20210219144617.4782-20-peter.maydell@linaro.org
10
---
11
hw/arm/Kconfig | 6 ------
12
hw/misc/Kconfig | 6 ++++++
13
2 files changed, 6 insertions(+), 6 deletions(-)
14
15
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
16
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/arm/Kconfig
18
+++ b/hw/arm/Kconfig
19
@@ -XXX,XX +XXX,XX @@ config ARMSSE
20
select UNIMP
21
select SSE_COUNTER
22
select SSE_TIMER
23
-
24
-config ARMSSE_CPUID
25
- bool
26
-
27
-config ARMSSE_MHU
28
- bool
29
diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig
30
index XXXXXXX..XXXXXXX 100644
31
--- a/hw/misc/Kconfig
32
+++ b/hw/misc/Kconfig
33
@@ -XXX,XX +XXX,XX @@ config APPLESMC
34
bool
35
depends on ISA_BUS
36
37
+config ARMSSE_CPUID
38
+ bool
39
+
40
+config ARMSSE_MHU
41
+ bool
42
+
43
config MAX111X
44
bool
45
46
--
47
2.20.1
48
49
diff view generated by jsdifflib
Deleted patch
1
The SSE-300 has a new register block CPU<N>_PWRCTRL. There is one
2
instance of this per CPU in the system (so just one for the SSE-300),
3
and as well as the usual CIDR/PIDR ID registers it has just one
4
register, CPUPWRCFG. This register allows the guest to configure
5
behaviour of the system in power-down and deep-sleep states. Since
6
QEMU does not model those, we make the register a dummy
7
reads-as-written implementation.
8
1
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20210219144617.4782-21-peter.maydell@linaro.org
13
---
14
include/hw/misc/armsse-cpu-pwrctrl.h | 40 +++++++
15
hw/misc/armsse-cpu-pwrctrl.c | 149 +++++++++++++++++++++++++++
16
MAINTAINERS | 2 +
17
hw/arm/Kconfig | 1 +
18
hw/misc/Kconfig | 3 +
19
hw/misc/meson.build | 1 +
20
hw/misc/trace-events | 4 +
21
7 files changed, 200 insertions(+)
22
create mode 100644 include/hw/misc/armsse-cpu-pwrctrl.h
23
create mode 100644 hw/misc/armsse-cpu-pwrctrl.c
24
25
diff --git a/include/hw/misc/armsse-cpu-pwrctrl.h b/include/hw/misc/armsse-cpu-pwrctrl.h
26
new file mode 100644
27
index XXXXXXX..XXXXXXX
28
--- /dev/null
29
+++ b/include/hw/misc/armsse-cpu-pwrctrl.h
30
@@ -XXX,XX +XXX,XX @@
31
+/*
32
+ * ARM SSE CPU PWRCTRL register block
33
+ *
34
+ * Copyright (c) 2021 Linaro Limited
35
+ * Written by Peter Maydell
36
+ *
37
+ * This program is free software; you can redistribute it and/or modify
38
+ * it under the terms of the GNU General Public License version 2 or
39
+ * (at your option) any later version.
40
+ */
41
+
42
+/*
43
+ * This is a model of the "CPU<N>_PWRCTRL block" which is part of the
44
+ * Arm Corstone SSE-300 Example Subsystem and documented in
45
+ * https://developer.arm.com/documentation/101773/0000
46
+ *
47
+ * QEMU interface:
48
+ * + sysbus MMIO region 0: the register bank
49
+ */
50
+
51
+#ifndef HW_MISC_ARMSSE_CPU_PWRCTRL_H
52
+#define HW_MISC_ARMSSE_CPU_PWRCTRL_H
53
+
54
+#include "hw/sysbus.h"
55
+#include "qom/object.h"
56
+
57
+#define TYPE_ARMSSE_CPU_PWRCTRL "armsse-cpu-pwrctrl"
58
+OBJECT_DECLARE_SIMPLE_TYPE(ARMSSECPUPwrCtrl, ARMSSE_CPU_PWRCTRL)
59
+
60
+struct ARMSSECPUPwrCtrl {
61
+ /*< private >*/
62
+ SysBusDevice parent_obj;
63
+
64
+ /*< public >*/
65
+ MemoryRegion iomem;
66
+
67
+ uint32_t cpupwrcfg;
68
+};
69
+
70
+#endif
71
diff --git a/hw/misc/armsse-cpu-pwrctrl.c b/hw/misc/armsse-cpu-pwrctrl.c
72
new file mode 100644
73
index XXXXXXX..XXXXXXX
74
--- /dev/null
75
+++ b/hw/misc/armsse-cpu-pwrctrl.c
76
@@ -XXX,XX +XXX,XX @@
77
+/*
78
+ * Arm SSE CPU PWRCTRL register block
79
+ *
80
+ * Copyright (c) 2021 Linaro Limited
81
+ * Written by Peter Maydell
82
+ *
83
+ * This program is free software; you can redistribute it and/or modify
84
+ * it under the terms of the GNU General Public License version 2 or
85
+ * (at your option) any later version.
86
+ */
87
+
88
+/*
89
+ * This is a model of the "CPU<N>_PWRCTRL block" which is part of the
90
+ * Arm Corstone SSE-300 Example Subsystem and documented in
91
+ * https://developer.arm.com/documentation/101773/0000
92
+ */
93
+
94
+#include "qemu/osdep.h"
95
+#include "qemu/log.h"
96
+#include "qemu/module.h"
97
+#include "trace.h"
98
+#include "qapi/error.h"
99
+#include "migration/vmstate.h"
100
+#include "hw/sysbus.h"
101
+#include "hw/registerfields.h"
102
+#include "hw/misc/armsse-cpu-pwrctrl.h"
103
+
104
+REG32(CPUPWRCFG, 0x0)
105
+REG32(PID4, 0xfd0)
106
+REG32(PID5, 0xfd4)
107
+REG32(PID6, 0xfd8)
108
+REG32(PID7, 0xfdc)
109
+REG32(PID0, 0xfe0)
110
+REG32(PID1, 0xfe4)
111
+REG32(PID2, 0xfe8)
112
+REG32(PID3, 0xfec)
113
+REG32(CID0, 0xff0)
114
+REG32(CID1, 0xff4)
115
+REG32(CID2, 0xff8)
116
+REG32(CID3, 0xffc)
117
+
118
+/* PID/CID values */
119
+static const int cpu_pwrctrl_id[] = {
120
+ 0x04, 0x00, 0x00, 0x00, /* PID4..PID7 */
121
+ 0x5a, 0xb8, 0x0b, 0x00, /* PID0..PID3 */
122
+ 0x0d, 0xf0, 0x05, 0xb1, /* CID0..CID3 */
123
+};
124
+
125
+static uint64_t pwrctrl_read(void *opaque, hwaddr offset, unsigned size)
126
+{
127
+ ARMSSECPUPwrCtrl *s = ARMSSE_CPU_PWRCTRL(opaque);
128
+ uint64_t r;
129
+
130
+ switch (offset) {
131
+ case A_CPUPWRCFG:
132
+ r = s->cpupwrcfg;
133
+ break;
134
+ case A_PID4 ... A_CID3:
135
+ r = cpu_pwrctrl_id[(offset - A_PID4) / 4];
136
+ break;
137
+ default:
138
+ qemu_log_mask(LOG_GUEST_ERROR,
139
+ "SSE CPU_PWRCTRL read: bad offset %x\n", (int)offset);
140
+ r = 0;
141
+ break;
142
+ }
143
+ trace_armsse_cpu_pwrctrl_read(offset, r, size);
144
+ return r;
145
+}
146
+
147
+static void pwrctrl_write(void *opaque, hwaddr offset,
148
+ uint64_t value, unsigned size)
149
+{
150
+ ARMSSECPUPwrCtrl *s = ARMSSE_CPU_PWRCTRL(opaque);
151
+
152
+ trace_armsse_cpu_pwrctrl_write(offset, value, size);
153
+
154
+ switch (offset) {
155
+ case A_CPUPWRCFG:
156
+ qemu_log_mask(LOG_UNIMP,
157
+ "SSE CPU_PWRCTRL: CPUPWRCFG unimplemented\n");
158
+ s->cpupwrcfg = value;
159
+ break;
160
+ default:
161
+ qemu_log_mask(LOG_GUEST_ERROR,
162
+ "SSE CPU_PWRCTRL write: bad offset 0x%x\n", (int)offset);
163
+ break;
164
+ }
165
+}
166
+
167
+static const MemoryRegionOps pwrctrl_ops = {
168
+ .read = pwrctrl_read,
169
+ .write = pwrctrl_write,
170
+ .endianness = DEVICE_LITTLE_ENDIAN,
171
+ .impl.min_access_size = 4,
172
+ .impl.max_access_size = 4,
173
+ .valid.min_access_size = 4,
174
+ .valid.max_access_size = 4,
175
+};
176
+
177
+static void pwrctrl_reset(DeviceState *dev)
178
+{
179
+ ARMSSECPUPwrCtrl *s = ARMSSE_CPU_PWRCTRL(dev);
180
+
181
+ s->cpupwrcfg = 0;
182
+}
183
+
184
+static const VMStateDescription pwrctrl_vmstate = {
185
+ .name = "armsse-cpu-pwrctrl",
186
+ .version_id = 1,
187
+ .minimum_version_id = 1,
188
+ .fields = (VMStateField[]) {
189
+ VMSTATE_UINT32(cpupwrcfg, ARMSSECPUPwrCtrl),
190
+ VMSTATE_END_OF_LIST()
191
+ },
192
+};
193
+
194
+static void pwrctrl_init(Object *obj)
195
+{
196
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
197
+ ARMSSECPUPwrCtrl *s = ARMSSE_CPU_PWRCTRL(obj);
198
+
199
+ memory_region_init_io(&s->iomem, obj, &pwrctrl_ops,
200
+ s, "armsse-cpu-pwrctrl", 0x1000);
201
+ sysbus_init_mmio(sbd, &s->iomem);
202
+}
203
+
204
+static void pwrctrl_class_init(ObjectClass *klass, void *data)
205
+{
206
+ DeviceClass *dc = DEVICE_CLASS(klass);
207
+
208
+ dc->reset = pwrctrl_reset;
209
+ dc->vmsd = &pwrctrl_vmstate;
210
+}
211
+
212
+static const TypeInfo pwrctrl_info = {
213
+ .name = TYPE_ARMSSE_CPU_PWRCTRL,
214
+ .parent = TYPE_SYS_BUS_DEVICE,
215
+ .instance_size = sizeof(ARMSSECPUPwrCtrl),
216
+ .instance_init = pwrctrl_init,
217
+ .class_init = pwrctrl_class_init,
218
+};
219
+
220
+static void pwrctrl_register_types(void)
221
+{
222
+ type_register_static(&pwrctrl_info);
223
+}
224
+
225
+type_init(pwrctrl_register_types);
226
diff --git a/MAINTAINERS b/MAINTAINERS
227
index XXXXXXX..XXXXXXX 100644
228
--- a/MAINTAINERS
229
+++ b/MAINTAINERS
230
@@ -XXX,XX +XXX,XX @@ F: hw/misc/iotkit-sysctl.c
231
F: include/hw/misc/iotkit-sysctl.h
232
F: hw/misc/iotkit-sysinfo.c
233
F: include/hw/misc/iotkit-sysinfo.h
234
+F: hw/misc/armsse-cpu-pwrctrl.c
235
+F: include/hw/misc/armsse-cpu-pwrctrl.h
236
F: hw/misc/armsse-cpuid.c
237
F: include/hw/misc/armsse-cpuid.h
238
F: hw/misc/armsse-mhu.c
239
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
240
index XXXXXXX..XXXXXXX 100644
241
--- a/hw/arm/Kconfig
242
+++ b/hw/arm/Kconfig
243
@@ -XXX,XX +XXX,XX @@ config ARM11MPCORE
244
config ARMSSE
245
bool
246
select ARM_V7M
247
+ select ARMSSE_CPU_PWRCTRL
248
select ARMSSE_CPUID
249
select ARMSSE_MHU
250
select CMSDK_APB_TIMER
251
diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig
252
index XXXXXXX..XXXXXXX 100644
253
--- a/hw/misc/Kconfig
254
+++ b/hw/misc/Kconfig
255
@@ -XXX,XX +XXX,XX @@ config ARMSSE_CPUID
256
config ARMSSE_MHU
257
bool
258
259
+config ARMSSE_CPU_PWRCTRL
260
+ bool
261
+
262
config MAX111X
263
bool
264
265
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
266
index XXXXXXX..XXXXXXX 100644
267
--- a/hw/misc/meson.build
268
+++ b/hw/misc/meson.build
269
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_TZ_MSC', if_true: files('tz-msc.c'))
270
softmmu_ss.add(when: 'CONFIG_TZ_PPC', if_true: files('tz-ppc.c'))
271
softmmu_ss.add(when: 'CONFIG_IOTKIT_SECCTL', if_true: files('iotkit-secctl.c'))
272
softmmu_ss.add(when: 'CONFIG_IOTKIT_SYSINFO', if_true: files('iotkit-sysinfo.c'))
273
+softmmu_ss.add(when: 'CONFIG_ARMSSE_CPU_PWRCTRL', if_true: files('armsse-cpu-pwrctrl.c'))
274
softmmu_ss.add(when: 'CONFIG_ARMSSE_CPUID', if_true: files('armsse-cpuid.c'))
275
softmmu_ss.add(when: 'CONFIG_ARMSSE_MHU', if_true: files('armsse-mhu.c'))
276
277
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
278
index XXXXXXX..XXXXXXX 100644
279
--- a/hw/misc/trace-events
280
+++ b/hw/misc/trace-events
281
@@ -XXX,XX +XXX,XX @@ iotkit_sysctl_read(uint64_t offset, uint64_t data, unsigned size) "IoTKit SysCtl
282
iotkit_sysctl_write(uint64_t offset, uint64_t data, unsigned size) "IoTKit SysCtl write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
283
iotkit_sysctl_reset(void) "IoTKit SysCtl: reset"
284
285
+# armsse-cpu-pwrctrl.c
286
+armsse_cpu_pwrctrl_read(uint64_t offset, uint64_t data, unsigned size) "SSE-300 CPU_PWRCTRL read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
287
+armsse_cpu_pwrctrl_write(uint64_t offset, uint64_t data, unsigned size) "SSE-300 CPU_PWRCTRL write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
288
+
289
# armsse-cpuid.c
290
armsse_cpuid_read(uint64_t offset, uint64_t data, unsigned size) "SSE-200 CPU_IDENTITY read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
291
armsse_cpuid_write(uint64_t offset, uint64_t data, unsigned size) "SSE-200 CPU_IDENTITY write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
292
--
293
2.20.1
294
295
diff view generated by jsdifflib
Deleted patch
1
Convert the apb_ppc0 and apb_ppc1 fields in the ARMSSE state struct
2
to use an array instead of two separate fields. We already had one
3
place in the code that wanted to be able to refer to the PPC by
4
index, and we're about to add more code like that.
5
1
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20210219144617.4782-22-peter.maydell@linaro.org
11
---
12
include/hw/arm/armsse.h | 6 +++---
13
hw/arm/armsse.c | 32 ++++++++++++++++++--------------
14
2 files changed, 21 insertions(+), 17 deletions(-)
15
16
diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
17
index XXXXXXX..XXXXXXX 100644
18
--- a/include/hw/arm/armsse.h
19
+++ b/include/hw/arm/armsse.h
20
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_TYPE(ARMSSE, ARMSSEClass,
21
/* We have an IRQ splitter and an OR gate input for each external PPC
22
* and the 2 internal PPCs
23
*/
24
+#define NUM_INTERNAL_PPCS 2
25
#define NUM_EXTERNAL_PPCS (IOTS_NUM_AHB_EXP_PPC + IOTS_NUM_APB_EXP_PPC)
26
-#define NUM_PPCS (NUM_EXTERNAL_PPCS + 2)
27
+#define NUM_PPCS (NUM_EXTERNAL_PPCS + NUM_INTERNAL_PPCS)
28
29
#define MAX_SRAM_BANKS 4
30
#if MAX_SRAM_BANKS > IOTS_NUM_MPC
31
@@ -XXX,XX +XXX,XX @@ struct ARMSSE {
32
ARMv7MState armv7m[SSE_MAX_CPUS];
33
CPUClusterState cluster[SSE_MAX_CPUS];
34
IoTKitSecCtl secctl;
35
- TZPPC apb_ppc0;
36
- TZPPC apb_ppc1;
37
+ TZPPC apb_ppc[NUM_INTERNAL_PPCS];
38
TZMPC mpc[IOTS_NUM_MPC];
39
CMSDKAPBTimer timer0;
40
CMSDKAPBTimer timer1;
41
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
42
index XXXXXXX..XXXXXXX 100644
43
--- a/hw/arm/armsse.c
44
+++ b/hw/arm/armsse.c
45
@@ -XXX,XX +XXX,XX @@ static void armsse_init(Object *obj)
46
}
47
48
object_initialize_child(obj, "secctl", &s->secctl, TYPE_IOTKIT_SECCTL);
49
- object_initialize_child(obj, "apb-ppc0", &s->apb_ppc0, TYPE_TZ_PPC);
50
- object_initialize_child(obj, "apb-ppc1", &s->apb_ppc1, TYPE_TZ_PPC);
51
+
52
+ for (i = 0; i < ARRAY_SIZE(s->apb_ppc); i++) {
53
+ g_autofree char *name = g_strdup_printf("apb-ppc%d", i);
54
+ object_initialize_child(obj, name, &s->apb_ppc[i], TYPE_TZ_PPC);
55
+ }
56
+
57
for (i = 0; i < info->sram_banks; i++) {
58
char *name = g_strdup_printf("mpc%d", i);
59
object_initialize_child(obj, name, &s->mpc[i], TYPE_TZ_MPC);
60
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
61
sysbus_connect_irq(SYS_BUS_DEVICE(&s->timer0), 0,
62
armsse_get_common_irq_in(s, 3));
63
mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->timer0), 0);
64
- object_property_set_link(OBJECT(&s->apb_ppc0), "port[0]", OBJECT(mr),
65
+ object_property_set_link(OBJECT(&s->apb_ppc[0]), "port[0]", OBJECT(mr),
66
&error_abort);
67
68
qdev_connect_clock_in(DEVICE(&s->timer1), "pclk", s->mainclk);
69
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
70
sysbus_connect_irq(SYS_BUS_DEVICE(&s->timer1), 0,
71
armsse_get_common_irq_in(s, 4));
72
mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->timer1), 0);
73
- object_property_set_link(OBJECT(&s->apb_ppc0), "port[1]", OBJECT(mr),
74
+ object_property_set_link(OBJECT(&s->apb_ppc[0]), "port[1]", OBJECT(mr),
75
&error_abort);
76
77
qdev_connect_clock_in(DEVICE(&s->dualtimer), "TIMCLK", s->mainclk);
78
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
79
sysbus_connect_irq(SYS_BUS_DEVICE(&s->dualtimer), 0,
80
armsse_get_common_irq_in(s, 5));
81
mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->dualtimer), 0);
82
- object_property_set_link(OBJECT(&s->apb_ppc0), "port[2]", OBJECT(mr),
83
+ object_property_set_link(OBJECT(&s->apb_ppc[0]), "port[2]", OBJECT(mr),
84
&error_abort);
85
86
if (info->has_mhus) {
87
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
88
}
89
port = g_strdup_printf("port[%d]", i + 3);
90
mr = sysbus_mmio_get_region(mhu_sbd, 0);
91
- object_property_set_link(OBJECT(&s->apb_ppc0), port, OBJECT(mr),
92
+ object_property_set_link(OBJECT(&s->apb_ppc[0]), port, OBJECT(mr),
93
&error_abort);
94
g_free(port);
95
96
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
97
}
98
}
99
100
- if (!sysbus_realize(SYS_BUS_DEVICE(&s->apb_ppc0), errp)) {
101
+ if (!sysbus_realize(SYS_BUS_DEVICE(&s->apb_ppc[0]), errp)) {
102
return;
103
}
104
105
- sbd_apb_ppc0 = SYS_BUS_DEVICE(&s->apb_ppc0);
106
- dev_apb_ppc0 = DEVICE(&s->apb_ppc0);
107
+ sbd_apb_ppc0 = SYS_BUS_DEVICE(&s->apb_ppc[0]);
108
+ dev_apb_ppc0 = DEVICE(&s->apb_ppc[0]);
109
110
mr = sysbus_mmio_get_region(sbd_apb_ppc0, 0);
111
memory_region_add_subregion(&s->container, 0x40000000, mr);
112
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
113
sysbus_connect_irq(SYS_BUS_DEVICE(&s->s32ktimer), 0,
114
armsse_get_common_irq_in(s, 2));
115
mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->s32ktimer), 0);
116
- object_property_set_link(OBJECT(&s->apb_ppc1), "port[0]", OBJECT(mr),
117
+ object_property_set_link(OBJECT(&s->apb_ppc[1]), "port[0]", OBJECT(mr),
118
&error_abort);
119
120
- if (!sysbus_realize(SYS_BUS_DEVICE(&s->apb_ppc1), errp)) {
121
+ if (!sysbus_realize(SYS_BUS_DEVICE(&s->apb_ppc[1]), errp)) {
122
return;
123
}
124
- mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->apb_ppc1), 0);
125
+ mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->apb_ppc[1]), 0);
126
memory_region_add_subregion(&s->container, 0x4002f000, mr);
127
128
- dev_apb_ppc1 = DEVICE(&s->apb_ppc1);
129
+ dev_apb_ppc1 = DEVICE(&s->apb_ppc[1]);
130
qdev_connect_gpio_out_named(dev_secctl, "apb_ppc1_nonsec", 0,
131
qdev_get_gpio_in_named(dev_apb_ppc1,
132
"cfg_nonsec", 0));
133
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
134
DeviceState *devs = DEVICE(&s->ppc_irq_splitter[i]);
135
char *gpioname = g_strdup_printf("apb_ppc%d_irq_status",
136
i - NUM_EXTERNAL_PPCS);
137
- TZPPC *ppc = (i == NUM_EXTERNAL_PPCS) ? &s->apb_ppc0 : &s->apb_ppc1;
138
+ TZPPC *ppc = &s->apb_ppc[i - NUM_EXTERNAL_PPCS];
139
140
qdev_connect_gpio_out(devs, 0,
141
qdev_get_gpio_in_named(dev_secctl, gpioname, 0));
142
--
143
2.20.1
144
145
diff view generated by jsdifflib
Deleted patch
1
The SSE uses 32 interrupts for its own devices, and then passes through
2
its expansion IRQ inputs to the CPU's interrupts 33 and upward.
3
Add a define for the number of IRQs the SSE uses for itself, instead
4
of hardcoding 32.
5
1
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20210219144617.4782-23-peter.maydell@linaro.org
11
---
12
include/hw/arm/armsse.h | 5 ++++-
13
hw/arm/armsse.c | 4 ++--
14
2 files changed, 6 insertions(+), 3 deletions(-)
15
16
diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
17
index XXXXXXX..XXXXXXX 100644
18
--- a/include/hw/arm/armsse.h
19
+++ b/include/hw/arm/armsse.h
20
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_TYPE(ARMSSE, ARMSSEClass,
21
#define RAM3_PPU 6
22
#define NUM_PPUS 7
23
24
+/* Number of CPU IRQs used by the SSE itself */
25
+#define NUM_SSE_IRQS 32
26
+
27
struct ARMSSE {
28
/*< private >*/
29
SysBusDevice parent_obj;
30
@@ -XXX,XX +XXX,XX @@ struct ARMSSE {
31
qemu_or_irq mpc_irq_orgate;
32
qemu_or_irq nmi_orgate;
33
34
- SplitIRQ cpu_irq_splitter[32];
35
+ SplitIRQ cpu_irq_splitter[NUM_SSE_IRQS];
36
37
CMSDKAPBDualTimer dualtimer;
38
39
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
40
index XXXXXXX..XXXXXXX 100644
41
--- a/hw/arm/armsse.c
42
+++ b/hw/arm/armsse.c
43
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
44
int j;
45
char *gpioname;
46
47
- qdev_prop_set_uint32(cpudev, "num-irq", s->exp_numirq + 32);
48
+ qdev_prop_set_uint32(cpudev, "num-irq", s->exp_numirq + NUM_SSE_IRQS);
49
/*
50
* In real hardware the initial Secure VTOR is set from the INITSVTOR*
51
* registers in the IoT Kit System Control Register block. In QEMU
52
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
53
/* Connect EXP_IRQ/EXP_CPUn_IRQ GPIOs to the NVIC's lines 32 and up */
54
s->exp_irqs[i] = g_new(qemu_irq, s->exp_numirq);
55
for (j = 0; j < s->exp_numirq; j++) {
56
- s->exp_irqs[i][j] = qdev_get_gpio_in(cpudev, j + 32);
57
+ s->exp_irqs[i][j] = qdev_get_gpio_in(cpudev, j + NUM_SSE_IRQS);
58
}
59
if (i == 0) {
60
gpioname = g_strdup("EXP_IRQ");
61
--
62
2.20.1
63
64
diff view generated by jsdifflib
Deleted patch
1
Move the CMSDK dualtimer device handling into the data-driven
2
device placement framework.
3
1
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20210219144617.4782-25-peter.maydell@linaro.org
8
---
9
hw/arm/armsse.c | 35 +++++++++++++++++++++--------------
10
1 file changed, 21 insertions(+), 14 deletions(-)
11
12
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/arm/armsse.c
15
+++ b/hw/arm/armsse.c
16
@@ -XXX,XX +XXX,XX @@ static const ARMSSEDeviceInfo sse200_devices[] = {
17
.ppc_port = 1,
18
.irq = 4,
19
},
20
+ {
21
+ .name = "dualtimer",
22
+ .type = TYPE_CMSDK_APB_DUALTIMER,
23
+ .index = 0,
24
+ .addr = 0x40002000,
25
+ .ppc = 0,
26
+ .ppc_port = 2,
27
+ .irq = 5,
28
+ },
29
{
30
.name = NULL,
31
}
32
@@ -XXX,XX +XXX,XX @@ static void armsse_init(Object *obj)
33
object_initialize_child(obj, devinfo->name,
34
&s->timer[devinfo->index],
35
TYPE_CMSDK_APB_TIMER);
36
+ } else if (!strcmp(devinfo->type, TYPE_CMSDK_APB_DUALTIMER)) {
37
+ assert(devinfo->index == 0);
38
+ object_initialize_child(obj, devinfo->name, &s->dualtimer,
39
+ TYPE_CMSDK_APB_DUALTIMER);
40
} else {
41
g_assert_not_reached();
42
}
43
@@ -XXX,XX +XXX,XX @@ static void armsse_init(Object *obj)
44
}
45
object_initialize_child(obj, "s32ktimer", &s->s32ktimer,
46
TYPE_CMSDK_APB_TIMER);
47
- object_initialize_child(obj, "dualtimer", &s->dualtimer,
48
- TYPE_CMSDK_APB_DUALTIMER);
49
object_initialize_child(obj, "s32kwatchdog", &s->s32kwatchdog,
50
TYPE_CMSDK_APB_WATCHDOG);
51
object_initialize_child(obj, "nswatchdog", &s->nswatchdog,
52
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
53
return;
54
}
55
mr = sysbus_mmio_get_region(sbd, 0);
56
+ } else if (!strcmp(devinfo->type, TYPE_CMSDK_APB_DUALTIMER)) {
57
+ sbd = SYS_BUS_DEVICE(&s->dualtimer);
58
+
59
+ qdev_connect_clock_in(DEVICE(sbd), "TIMCLK", s->mainclk);
60
+ if (!sysbus_realize(sbd, errp)) {
61
+ return;
62
+ }
63
+ mr = sysbus_mmio_get_region(sbd, 0);
64
} else {
65
g_assert_not_reached();
66
}
67
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
68
}
69
}
70
71
- qdev_connect_clock_in(DEVICE(&s->dualtimer), "TIMCLK", s->mainclk);
72
- if (!sysbus_realize(SYS_BUS_DEVICE(&s->dualtimer), errp)) {
73
- return;
74
- }
75
- sysbus_connect_irq(SYS_BUS_DEVICE(&s->dualtimer), 0,
76
- armsse_get_common_irq_in(s, 5));
77
- mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->dualtimer), 0);
78
- object_property_set_link(OBJECT(&s->apb_ppc[0]), "port[2]", OBJECT(mr),
79
- &error_abort);
80
-
81
if (info->has_mhus) {
82
/*
83
* An SSE-200 with only one CPU should have only one MHU created,
84
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
85
sbd_apb_ppc0 = SYS_BUS_DEVICE(&s->apb_ppc[0]);
86
dev_apb_ppc0 = DEVICE(&s->apb_ppc[0]);
87
88
- mr = sysbus_mmio_get_region(sbd_apb_ppc0, 2);
89
- memory_region_add_subregion(&s->container, 0x40002000, mr);
90
if (info->has_mhus) {
91
mr = sysbus_mmio_get_region(sbd_apb_ppc0, 3);
92
memory_region_add_subregion(&s->container, 0x40003000, mr);
93
--
94
2.20.1
95
96
diff view generated by jsdifflib
Deleted patch
1
Move the CMSDK watchdog device handling into the data-driven device
2
placement framework. This is slightly more complicated because these
3
devices might wire their IRQs up to the NMI line, and because one of
4
them uses the slow 32KHz clock rather than the main clock.
5
1
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20210219144617.4782-26-peter.maydell@linaro.org
10
---
11
include/hw/arm/armsse.h | 4 +-
12
hw/arm/armsse.c | 109 ++++++++++++++++++++++++----------------
13
2 files changed, 66 insertions(+), 47 deletions(-)
14
15
diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
16
index XXXXXXX..XXXXXXX 100644
17
--- a/include/hw/arm/armsse.h
18
+++ b/include/hw/arm/armsse.h
19
@@ -XXX,XX +XXX,XX @@ struct ARMSSE {
20
21
CMSDKAPBDualTimer dualtimer;
22
23
- CMSDKAPBWatchdog s32kwatchdog;
24
- CMSDKAPBWatchdog nswatchdog;
25
- CMSDKAPBWatchdog swatchdog;
26
+ CMSDKAPBWatchdog cmsdk_watchdog[3];
27
28
IoTKitSysCtl sysctl;
29
IoTKitSysCtl sysinfo;
30
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
31
index XXXXXXX..XXXXXXX 100644
32
--- a/hw/arm/armsse.c
33
+++ b/hw/arm/armsse.c
34
@@ -XXX,XX +XXX,XX @@
35
36
#define NO_IRQ -1
37
#define NO_PPC -1
38
+/*
39
+ * Special values for ARMSSEDeviceInfo::irq to indicate that this
40
+ * device uses one of the inputs to the OR gate that feeds into the
41
+ * CPU NMI input.
42
+ */
43
+#define NMI_0 10000
44
+#define NMI_1 10001
45
46
typedef struct ARMSSEDeviceInfo {
47
const char *name; /* name to use for the QOM object; NULL terminates list */
48
@@ -XXX,XX +XXX,XX @@ typedef struct ARMSSEDeviceInfo {
49
hwaddr addr;
50
int ppc; /* Index of APB PPC this device is wired up to, or NO_PPC */
51
int ppc_port; /* Port number of this device on the PPC */
52
- int irq; /* NO_IRQ, or 0..NUM_SSE_IRQS-1 */
53
+ int irq; /* NO_IRQ, or 0..NUM_SSE_IRQS-1, or NMI_0 or NMI_1 */
54
+ bool slowclk; /* true if device uses the slow 32KHz clock */
55
} ARMSSEDeviceInfo;
56
57
struct ARMSSEInfo {
58
@@ -XXX,XX +XXX,XX @@ static const ARMSSEDeviceInfo sse200_devices[] = {
59
.ppc_port = 2,
60
.irq = 5,
61
},
62
+ {
63
+ .name = "s32kwatchdog",
64
+ .type = TYPE_CMSDK_APB_WATCHDOG,
65
+ .index = 0,
66
+ .addr = 0x5002e000,
67
+ .ppc = NO_PPC,
68
+ .irq = NMI_0,
69
+ .slowclk = true,
70
+ },
71
+ {
72
+ .name = "nswatchdog",
73
+ .type = TYPE_CMSDK_APB_WATCHDOG,
74
+ .index = 1,
75
+ .addr = 0x40081000,
76
+ .ppc = NO_PPC,
77
+ .irq = 1,
78
+ },
79
+ {
80
+ .name = "swatchdog",
81
+ .type = TYPE_CMSDK_APB_WATCHDOG,
82
+ .index = 2,
83
+ .addr = 0x50081000,
84
+ .ppc = NO_PPC,
85
+ .irq = NMI_1,
86
+ },
87
{
88
.name = NULL,
89
}
90
@@ -XXX,XX +XXX,XX @@ static void armsse_init(Object *obj)
91
assert(devinfo->index == 0);
92
object_initialize_child(obj, devinfo->name, &s->dualtimer,
93
TYPE_CMSDK_APB_DUALTIMER);
94
+ } else if (!strcmp(devinfo->type, TYPE_CMSDK_APB_WATCHDOG)) {
95
+ assert(devinfo->index < ARRAY_SIZE(s->cmsdk_watchdog));
96
+ object_initialize_child(obj, devinfo->name,
97
+ &s->cmsdk_watchdog[devinfo->index],
98
+ TYPE_CMSDK_APB_WATCHDOG);
99
} else {
100
g_assert_not_reached();
101
}
102
@@ -XXX,XX +XXX,XX @@ static void armsse_init(Object *obj)
103
object_initialize_child(obj, name, splitter, TYPE_SPLIT_IRQ);
104
g_free(name);
105
}
106
+
107
object_initialize_child(obj, "s32ktimer", &s->s32ktimer,
108
TYPE_CMSDK_APB_TIMER);
109
- object_initialize_child(obj, "s32kwatchdog", &s->s32kwatchdog,
110
- TYPE_CMSDK_APB_WATCHDOG);
111
- object_initialize_child(obj, "nswatchdog", &s->nswatchdog,
112
- TYPE_CMSDK_APB_WATCHDOG);
113
- object_initialize_child(obj, "swatchdog", &s->swatchdog,
114
- TYPE_CMSDK_APB_WATCHDOG);
115
object_initialize_child(obj, "armsse-sysctl", &s->sysctl,
116
TYPE_IOTKIT_SYSCTL);
117
object_initialize_child(obj, "armsse-sysinfo", &s->sysinfo,
118
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
119
qdev_connect_gpio_out(DEVICE(&s->mpc_irq_orgate), 0,
120
armsse_get_common_irq_in(s, 9));
121
122
+ /* This OR gate wires together outputs from the secure watchdogs to NMI */
123
+ if (!object_property_set_int(OBJECT(&s->nmi_orgate), "num-lines", 2,
124
+ errp)) {
125
+ return;
126
+ }
127
+ if (!qdev_realize(DEVICE(&s->nmi_orgate), NULL, errp)) {
128
+ return;
129
+ }
130
+ qdev_connect_gpio_out(DEVICE(&s->nmi_orgate), 0,
131
+ qdev_get_gpio_in_named(DEVICE(&s->armv7m), "NMI", 0));
132
+
133
/* Devices behind APB PPC0:
134
* 0x40000000: timer0
135
* 0x40001000: timer1
136
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
137
return;
138
}
139
mr = sysbus_mmio_get_region(sbd, 0);
140
+ } else if (!strcmp(devinfo->type, TYPE_CMSDK_APB_WATCHDOG)) {
141
+ sbd = SYS_BUS_DEVICE(&s->cmsdk_watchdog[devinfo->index]);
142
+
143
+ qdev_connect_clock_in(DEVICE(sbd), "WDOGCLK",
144
+ devinfo->slowclk ? s->s32kclk : s->mainclk);
145
+ if (!sysbus_realize(sbd, errp)) {
146
+ return;
147
+ }
148
+ mr = sysbus_mmio_get_region(sbd, 0);
149
} else {
150
g_assert_not_reached();
151
}
152
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
153
case 0 ... NUM_SSE_IRQS - 1:
154
irq = armsse_get_common_irq_in(s, devinfo->irq);
155
break;
156
+ case NMI_0:
157
+ case NMI_1:
158
+ irq = qdev_get_gpio_in(DEVICE(&s->nmi_orgate),
159
+ devinfo->irq - NMI_0);
160
+ break;
161
default:
162
g_assert_not_reached();
163
}
164
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
165
}
166
}
167
168
- /* This OR gate wires together outputs from the secure watchdogs to NMI */
169
- if (!object_property_set_int(OBJECT(&s->nmi_orgate), "num-lines", 2,
170
- errp)) {
171
- return;
172
- }
173
- if (!qdev_realize(DEVICE(&s->nmi_orgate), NULL, errp)) {
174
- return;
175
- }
176
- qdev_connect_gpio_out(DEVICE(&s->nmi_orgate), 0,
177
- qdev_get_gpio_in_named(DEVICE(&s->armv7m), "NMI", 0));
178
-
179
- qdev_connect_clock_in(DEVICE(&s->s32kwatchdog), "WDOGCLK", s->s32kclk);
180
- if (!sysbus_realize(SYS_BUS_DEVICE(&s->s32kwatchdog), errp)) {
181
- return;
182
- }
183
- sysbus_connect_irq(SYS_BUS_DEVICE(&s->s32kwatchdog), 0,
184
- qdev_get_gpio_in(DEVICE(&s->nmi_orgate), 0));
185
- sysbus_mmio_map(SYS_BUS_DEVICE(&s->s32kwatchdog), 0, 0x5002e000);
186
-
187
- /* 0x40080000 .. 0x4008ffff : ARMSSE second Base peripheral region */
188
-
189
- qdev_connect_clock_in(DEVICE(&s->nswatchdog), "WDOGCLK", s->mainclk);
190
- if (!sysbus_realize(SYS_BUS_DEVICE(&s->nswatchdog), errp)) {
191
- return;
192
- }
193
- sysbus_connect_irq(SYS_BUS_DEVICE(&s->nswatchdog), 0,
194
- armsse_get_common_irq_in(s, 1));
195
- sysbus_mmio_map(SYS_BUS_DEVICE(&s->nswatchdog), 0, 0x40081000);
196
-
197
- qdev_connect_clock_in(DEVICE(&s->swatchdog), "WDOGCLK", s->mainclk);
198
- if (!sysbus_realize(SYS_BUS_DEVICE(&s->swatchdog), errp)) {
199
- return;
200
- }
201
- sysbus_connect_irq(SYS_BUS_DEVICE(&s->swatchdog), 0,
202
- qdev_get_gpio_in(DEVICE(&s->nmi_orgate), 1));
203
- sysbus_mmio_map(SYS_BUS_DEVICE(&s->swatchdog), 0, 0x50081000);
204
-
205
for (i = 0; i < ARRAY_SIZE(s->ppc_irq_splitter); i++) {
206
Object *splitter = OBJECT(&s->ppc_irq_splitter[i]);
207
208
--
209
2.20.1
210
211
diff view generated by jsdifflib
Deleted patch
1
Move the CMSDK timer that uses the S32K slow clock into the data-driven
2
device placement framework.
3
1
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20210219144617.4782-27-peter.maydell@linaro.org
8
---
9
include/hw/arm/armsse.h | 3 +--
10
hw/arm/armsse.c | 31 ++++++++++++-------------------
11
2 files changed, 13 insertions(+), 21 deletions(-)
12
13
diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
14
index XXXXXXX..XXXXXXX 100644
15
--- a/include/hw/arm/armsse.h
16
+++ b/include/hw/arm/armsse.h
17
@@ -XXX,XX +XXX,XX @@ struct ARMSSE {
18
IoTKitSecCtl secctl;
19
TZPPC apb_ppc[NUM_INTERNAL_PPCS];
20
TZMPC mpc[IOTS_NUM_MPC];
21
- CMSDKAPBTimer timer[2];
22
- CMSDKAPBTimer s32ktimer;
23
+ CMSDKAPBTimer timer[3];
24
qemu_or_irq ppc_irq_orgate;
25
SplitIRQ sec_resp_splitter;
26
SplitIRQ ppc_irq_splitter[NUM_PPCS];
27
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
28
index XXXXXXX..XXXXXXX 100644
29
--- a/hw/arm/armsse.c
30
+++ b/hw/arm/armsse.c
31
@@ -XXX,XX +XXX,XX @@ static const ARMSSEDeviceInfo sse200_devices[] = {
32
.ppc_port = 1,
33
.irq = 4,
34
},
35
+ {
36
+ .name = "s32ktimer",
37
+ .type = TYPE_CMSDK_APB_TIMER,
38
+ .index = 2,
39
+ .addr = 0x4002f000,
40
+ .ppc = 1,
41
+ .ppc_port = 0,
42
+ .irq = 2,
43
+ .slowclk = true,
44
+ },
45
{
46
.name = "dualtimer",
47
.type = TYPE_CMSDK_APB_DUALTIMER,
48
@@ -XXX,XX +XXX,XX @@ static void armsse_init(Object *obj)
49
g_free(name);
50
}
51
52
- object_initialize_child(obj, "s32ktimer", &s->s32ktimer,
53
- TYPE_CMSDK_APB_TIMER);
54
object_initialize_child(obj, "armsse-sysctl", &s->sysctl,
55
TYPE_IOTKIT_SYSCTL);
56
object_initialize_child(obj, "armsse-sysinfo", &s->sysinfo,
57
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
58
if (!strcmp(devinfo->type, TYPE_CMSDK_APB_TIMER)) {
59
sbd = SYS_BUS_DEVICE(&s->timer[devinfo->index]);
60
61
- qdev_connect_clock_in(DEVICE(sbd), "pclk", s->mainclk);
62
+ qdev_connect_clock_in(DEVICE(sbd), "pclk",
63
+ devinfo->slowclk ? s->s32kclk : s->mainclk);
64
if (!sysbus_realize(sbd, errp)) {
65
return;
66
}
67
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
68
}
69
}
70
71
- /* 0x40020000 .. 0x4002ffff : ARMSSE system control peripheral region */
72
- /* Devices behind APB PPC1:
73
- * 0x4002f000: S32K timer
74
- */
75
- qdev_connect_clock_in(DEVICE(&s->s32ktimer), "pclk", s->s32kclk);
76
- if (!sysbus_realize(SYS_BUS_DEVICE(&s->s32ktimer), errp)) {
77
- return;
78
- }
79
- sysbus_connect_irq(SYS_BUS_DEVICE(&s->s32ktimer), 0,
80
- armsse_get_common_irq_in(s, 2));
81
- mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->s32ktimer), 0);
82
- object_property_set_link(OBJECT(&s->apb_ppc[1]), "port[0]", OBJECT(mr),
83
- &error_abort);
84
-
85
if (!sysbus_realize(SYS_BUS_DEVICE(&s->apb_ppc[1]), errp)) {
86
return;
87
}
88
- mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->apb_ppc[1]), 0);
89
- memory_region_add_subregion(&s->container, 0x4002f000, mr);
90
91
dev_apb_ppc1 = DEVICE(&s->apb_ppc[1]);
92
qdev_connect_gpio_out_named(dev_secctl, "apb_ppc1_nonsec", 0,
93
--
94
2.20.1
95
96
diff view generated by jsdifflib
Deleted patch
1
Move the sysinfo register block into the data-driven framework.
2
1
3
While we are moving the code for configuring this device around,
4
regularize on using &error_abortw when setting the integer
5
properties: they are all simple DEFINE_PROP_UINT32 properties so the
6
setting can never fail.
7
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20210219144617.4782-28-peter.maydell@linaro.org
12
---
13
hw/arm/armsse.c | 47 ++++++++++++++++++++++++++++-------------------
14
1 file changed, 28 insertions(+), 19 deletions(-)
15
16
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/arm/armsse.c
19
+++ b/hw/arm/armsse.c
20
@@ -XXX,XX +XXX,XX @@ static const ARMSSEDeviceInfo sse200_devices[] = {
21
.ppc = NO_PPC,
22
.irq = NMI_1,
23
},
24
+ {
25
+ .name = "armsse-sysinfo",
26
+ .type = TYPE_IOTKIT_SYSINFO,
27
+ .index = 0,
28
+ .addr = 0x40020000,
29
+ .ppc = NO_PPC,
30
+ .irq = NO_IRQ,
31
+ },
32
{
33
.name = NULL,
34
}
35
@@ -XXX,XX +XXX,XX @@ static void armsse_init(Object *obj)
36
object_initialize_child(obj, devinfo->name,
37
&s->cmsdk_watchdog[devinfo->index],
38
TYPE_CMSDK_APB_WATCHDOG);
39
+ } else if (!strcmp(devinfo->type, TYPE_IOTKIT_SYSINFO)) {
40
+ assert(devinfo->index == 0);
41
+ object_initialize_child(obj, devinfo->name, &s->sysinfo,
42
+ TYPE_IOTKIT_SYSINFO);
43
} else {
44
g_assert_not_reached();
45
}
46
@@ -XXX,XX +XXX,XX @@ static void armsse_init(Object *obj)
47
48
object_initialize_child(obj, "armsse-sysctl", &s->sysctl,
49
TYPE_IOTKIT_SYSCTL);
50
- object_initialize_child(obj, "armsse-sysinfo", &s->sysinfo,
51
- TYPE_IOTKIT_SYSINFO);
52
if (info->has_mhus) {
53
object_initialize_child(obj, "mhu0", &s->mhu[0], TYPE_ARMSSE_MHU);
54
object_initialize_child(obj, "mhu1", &s->mhu[1], TYPE_ARMSSE_MHU);
55
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
56
return;
57
}
58
mr = sysbus_mmio_get_region(sbd, 0);
59
+ } else if (!strcmp(devinfo->type, TYPE_IOTKIT_SYSINFO)) {
60
+ sbd = SYS_BUS_DEVICE(&s->sysinfo);
61
+
62
+ object_property_set_int(OBJECT(&s->sysinfo), "SYS_VERSION",
63
+ info->sys_version, &error_abort);
64
+ object_property_set_int(OBJECT(&s->sysinfo), "SYS_CONFIG",
65
+ armsse_sys_config_value(s, info),
66
+ &error_abort);
67
+ object_property_set_int(OBJECT(&s->sysinfo), "sse-version",
68
+ info->sse_version, &error_abort);
69
+ object_property_set_int(OBJECT(&s->sysinfo), "IIDR",
70
+ info->iidr, &error_abort);
71
+ if (!sysbus_realize(sbd, errp)) {
72
+ return;
73
+ }
74
+ mr = sysbus_mmio_get_region(sbd, 0);
75
} else {
76
g_assert_not_reached();
77
}
78
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
79
memory_region_add_subregion(&s->container, devinfo->addr, mr);
80
}
81
82
- if (!object_property_set_int(OBJECT(&s->sysinfo), "SYS_VERSION",
83
- info->sys_version, errp)) {
84
- return;
85
- }
86
- if (!object_property_set_int(OBJECT(&s->sysinfo), "SYS_CONFIG",
87
- armsse_sys_config_value(s, info), errp)) {
88
- return;
89
- }
90
- object_property_set_int(OBJECT(&s->sysinfo), "sse-version",
91
- info->sse_version, &error_abort);
92
- object_property_set_int(OBJECT(&s->sysinfo), "IIDR",
93
- info->iidr, &error_abort);
94
- if (!sysbus_realize(SYS_BUS_DEVICE(&s->sysinfo), errp)) {
95
- return;
96
- }
97
- /* System information registers */
98
- sysbus_mmio_map(SYS_BUS_DEVICE(&s->sysinfo), 0, 0x40020000);
99
/* System control registers */
100
object_property_set_int(OBJECT(&s->sysctl), "sse-version",
101
info->sse_version, &error_abort);
102
--
103
2.20.1
104
105
diff view generated by jsdifflib
Deleted patch
1
Move the sysctl register block into the data-driven device placement
2
framework.
3
1
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20210219144617.4782-29-peter.maydell@linaro.org
8
---
9
hw/arm/armsse.c | 44 ++++++++++++++++++++++++++++----------------
10
1 file changed, 28 insertions(+), 16 deletions(-)
11
12
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/arm/armsse.c
15
+++ b/hw/arm/armsse.c
16
@@ -XXX,XX +XXX,XX @@ static const ARMSSEDeviceInfo sse200_devices[] = {
17
.ppc = NO_PPC,
18
.irq = NO_IRQ,
19
},
20
+ {
21
+ .name = "armsse-sysctl",
22
+ .type = TYPE_IOTKIT_SYSCTL,
23
+ .index = 0,
24
+ .addr = 0x50021000,
25
+ .ppc = NO_PPC,
26
+ .irq = NO_IRQ,
27
+ },
28
{
29
.name = NULL,
30
}
31
@@ -XXX,XX +XXX,XX @@ static void armsse_init(Object *obj)
32
assert(devinfo->index == 0);
33
object_initialize_child(obj, devinfo->name, &s->sysinfo,
34
TYPE_IOTKIT_SYSINFO);
35
+ } else if (!strcmp(devinfo->type, TYPE_IOTKIT_SYSCTL)) {
36
+ assert(devinfo->index == 0);
37
+ object_initialize_child(obj, devinfo->name, &s->sysctl,
38
+ TYPE_IOTKIT_SYSCTL);
39
} else {
40
g_assert_not_reached();
41
}
42
@@ -XXX,XX +XXX,XX @@ static void armsse_init(Object *obj)
43
g_free(name);
44
}
45
46
- object_initialize_child(obj, "armsse-sysctl", &s->sysctl,
47
- TYPE_IOTKIT_SYSCTL);
48
if (info->has_mhus) {
49
object_initialize_child(obj, "mhu0", &s->mhu[0], TYPE_ARMSSE_MHU);
50
object_initialize_child(obj, "mhu1", &s->mhu[1], TYPE_ARMSSE_MHU);
51
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
52
return;
53
}
54
mr = sysbus_mmio_get_region(sbd, 0);
55
+ } else if (!strcmp(devinfo->type, TYPE_IOTKIT_SYSCTL)) {
56
+ /* System control registers */
57
+ sbd = SYS_BUS_DEVICE(&s->sysctl);
58
+
59
+ object_property_set_int(OBJECT(&s->sysctl), "sse-version",
60
+ info->sse_version, &error_abort);
61
+ object_property_set_int(OBJECT(&s->sysctl), "CPUWAIT_RST",
62
+ info->cpuwait_rst, &error_abort);
63
+ object_property_set_int(OBJECT(&s->sysctl), "INITSVTOR0_RST",
64
+ s->init_svtor, &error_abort);
65
+ object_property_set_int(OBJECT(&s->sysctl), "INITSVTOR1_RST",
66
+ s->init_svtor, &error_abort);
67
+ if (!sysbus_realize(sbd, errp)) {
68
+ return;
69
+ }
70
+ mr = sysbus_mmio_get_region(sbd, 0);
71
} else {
72
g_assert_not_reached();
73
}
74
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
75
memory_region_add_subregion(&s->container, devinfo->addr, mr);
76
}
77
78
- /* System control registers */
79
- object_property_set_int(OBJECT(&s->sysctl), "sse-version",
80
- info->sse_version, &error_abort);
81
- object_property_set_int(OBJECT(&s->sysctl), "CPUWAIT_RST",
82
- info->cpuwait_rst, &error_abort);
83
- object_property_set_int(OBJECT(&s->sysctl), "INITSVTOR0_RST",
84
- s->init_svtor, &error_abort);
85
- object_property_set_int(OBJECT(&s->sysctl), "INITSVTOR1_RST",
86
- s->init_svtor, &error_abort);
87
- if (!sysbus_realize(SYS_BUS_DEVICE(&s->sysctl), errp)) {
88
- return;
89
- }
90
- sysbus_mmio_map(SYS_BUS_DEVICE(&s->sysctl), 0, 0x50021000);
91
-
92
if (info->has_ppus) {
93
/* CPUnCORE_PPU for each CPU */
94
for (i = 0; i < info->num_cpus; i++) {
95
--
96
2.20.1
97
98
diff view generated by jsdifflib
Deleted patch
1
Move the PPUs into the data-driven device placement framework.
2
We don't implement them, so they are just TYPE_UNIMPLEMENTED stubs.
3
1
4
Because the SSE-200 and the IotKit diverge here (the IoTKit does
5
not have the PPUs) we need to separate out the ARMSSEDeviceInfo
6
for the two variants, and only add the PPUs to the SSE-200.
7
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20210219144617.4782-30-peter.maydell@linaro.org
12
---
13
include/hw/arm/armsse.h | 10 +-
14
hw/arm/armsse.c | 222 +++++++++++++++++++++++++++++-----------
15
2 files changed, 165 insertions(+), 67 deletions(-)
16
17
diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
18
index XXXXXXX..XXXXXXX 100644
19
--- a/include/hw/arm/armsse.h
20
+++ b/include/hw/arm/armsse.h
21
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_TYPE(ARMSSE, ARMSSEClass,
22
23
#define SSE_MAX_CPUS 2
24
25
-/* These define what each PPU in the ppu[] index is for */
26
-#define CPU0CORE_PPU 0
27
-#define CPU1CORE_PPU 1
28
-#define DBG_PPU 2
29
-#define RAM0_PPU 3
30
-#define RAM1_PPU 4
31
-#define RAM2_PPU 5
32
-#define RAM3_PPU 6
33
#define NUM_PPUS 7
34
35
/* Number of CPU IRQs used by the SSE itself */
36
@@ -XXX,XX +XXX,XX @@ struct ARMSSE {
37
IoTKitSysCtl sysinfo;
38
39
ARMSSEMHU mhu[2];
40
- UnimplementedDeviceState ppu[NUM_PPUS];
41
+ UnimplementedDeviceState unimp[NUM_PPUS];
42
UnimplementedDeviceState cachectrl[SSE_MAX_CPUS];
43
UnimplementedDeviceState cpusecctrl[SSE_MAX_CPUS];
44
45
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
46
index XXXXXXX..XXXXXXX 100644
47
--- a/hw/arm/armsse.c
48
+++ b/hw/arm/armsse.c
49
@@ -XXX,XX +XXX,XX @@ typedef struct ARMSSEDeviceInfo {
50
const char *type; /* QOM type name */
51
unsigned int index; /* Which of the N devices of this type is this ? */
52
hwaddr addr;
53
+ hwaddr size; /* only needed for TYPE_UNIMPLEMENTED_DEVICE */
54
int ppc; /* Index of APB PPC this device is wired up to, or NO_PPC */
55
int ppc_port; /* Port number of this device on the PPC */
56
int irq; /* NO_IRQ, or 0..NUM_SSE_IRQS-1, or NMI_0 or NMI_1 */
57
@@ -XXX,XX +XXX,XX @@ struct ARMSSEInfo {
58
uint32_t iidr;
59
uint32_t cpuwait_rst;
60
bool has_mhus;
61
- bool has_ppus;
62
bool has_cachectrl;
63
bool has_cpusecctrl;
64
bool has_cpuid;
65
@@ -XXX,XX +XXX,XX @@ static Property armsse_properties[] = {
66
DEFINE_PROP_END_OF_LIST()
67
};
68
69
-static const ARMSSEDeviceInfo sse200_devices[] = {
70
+static const ARMSSEDeviceInfo iotkit_devices[] = {
71
{
72
.name = "timer0",
73
.type = TYPE_CMSDK_APB_TIMER,
74
@@ -XXX,XX +XXX,XX @@ static const ARMSSEDeviceInfo sse200_devices[] = {
75
}
76
};
77
78
+static const ARMSSEDeviceInfo sse200_devices[] = {
79
+ {
80
+ .name = "timer0",
81
+ .type = TYPE_CMSDK_APB_TIMER,
82
+ .index = 0,
83
+ .addr = 0x40000000,
84
+ .ppc = 0,
85
+ .ppc_port = 0,
86
+ .irq = 3,
87
+ },
88
+ {
89
+ .name = "timer1",
90
+ .type = TYPE_CMSDK_APB_TIMER,
91
+ .index = 1,
92
+ .addr = 0x40001000,
93
+ .ppc = 0,
94
+ .ppc_port = 1,
95
+ .irq = 4,
96
+ },
97
+ {
98
+ .name = "s32ktimer",
99
+ .type = TYPE_CMSDK_APB_TIMER,
100
+ .index = 2,
101
+ .addr = 0x4002f000,
102
+ .ppc = 1,
103
+ .ppc_port = 0,
104
+ .irq = 2,
105
+ .slowclk = true,
106
+ },
107
+ {
108
+ .name = "dualtimer",
109
+ .type = TYPE_CMSDK_APB_DUALTIMER,
110
+ .index = 0,
111
+ .addr = 0x40002000,
112
+ .ppc = 0,
113
+ .ppc_port = 2,
114
+ .irq = 5,
115
+ },
116
+ {
117
+ .name = "s32kwatchdog",
118
+ .type = TYPE_CMSDK_APB_WATCHDOG,
119
+ .index = 0,
120
+ .addr = 0x5002e000,
121
+ .ppc = NO_PPC,
122
+ .irq = NMI_0,
123
+ .slowclk = true,
124
+ },
125
+ {
126
+ .name = "nswatchdog",
127
+ .type = TYPE_CMSDK_APB_WATCHDOG,
128
+ .index = 1,
129
+ .addr = 0x40081000,
130
+ .ppc = NO_PPC,
131
+ .irq = 1,
132
+ },
133
+ {
134
+ .name = "swatchdog",
135
+ .type = TYPE_CMSDK_APB_WATCHDOG,
136
+ .index = 2,
137
+ .addr = 0x50081000,
138
+ .ppc = NO_PPC,
139
+ .irq = NMI_1,
140
+ },
141
+ {
142
+ .name = "armsse-sysinfo",
143
+ .type = TYPE_IOTKIT_SYSINFO,
144
+ .index = 0,
145
+ .addr = 0x40020000,
146
+ .ppc = NO_PPC,
147
+ .irq = NO_IRQ,
148
+ },
149
+ {
150
+ .name = "armsse-sysctl",
151
+ .type = TYPE_IOTKIT_SYSCTL,
152
+ .index = 0,
153
+ .addr = 0x50021000,
154
+ .ppc = NO_PPC,
155
+ .irq = NO_IRQ,
156
+ },
157
+ {
158
+ .name = "CPU0CORE_PPU",
159
+ .type = TYPE_UNIMPLEMENTED_DEVICE,
160
+ .index = 0,
161
+ .addr = 0x50023000,
162
+ .size = 0x1000,
163
+ .ppc = NO_PPC,
164
+ .irq = NO_IRQ,
165
+ },
166
+ {
167
+ .name = "CPU1CORE_PPU",
168
+ .type = TYPE_UNIMPLEMENTED_DEVICE,
169
+ .index = 1,
170
+ .addr = 0x50025000,
171
+ .size = 0x1000,
172
+ .ppc = NO_PPC,
173
+ .irq = NO_IRQ,
174
+ },
175
+ {
176
+ .name = "DBG_PPU",
177
+ .type = TYPE_UNIMPLEMENTED_DEVICE,
178
+ .index = 2,
179
+ .addr = 0x50029000,
180
+ .size = 0x1000,
181
+ .ppc = NO_PPC,
182
+ .irq = NO_IRQ,
183
+ },
184
+ {
185
+ .name = "RAM0_PPU",
186
+ .type = TYPE_UNIMPLEMENTED_DEVICE,
187
+ .index = 3,
188
+ .addr = 0x5002a000,
189
+ .size = 0x1000,
190
+ .ppc = NO_PPC,
191
+ .irq = NO_IRQ,
192
+ },
193
+ {
194
+ .name = "RAM1_PPU",
195
+ .type = TYPE_UNIMPLEMENTED_DEVICE,
196
+ .index = 4,
197
+ .addr = 0x5002b000,
198
+ .size = 0x1000,
199
+ .ppc = NO_PPC,
200
+ .irq = NO_IRQ,
201
+ },
202
+ {
203
+ .name = "RAM2_PPU",
204
+ .type = TYPE_UNIMPLEMENTED_DEVICE,
205
+ .index = 5,
206
+ .addr = 0x5002c000,
207
+ .size = 0x1000,
208
+ .ppc = NO_PPC,
209
+ .irq = NO_IRQ,
210
+ },
211
+ {
212
+ .name = "RAM3_PPU",
213
+ .type = TYPE_UNIMPLEMENTED_DEVICE,
214
+ .index = 6,
215
+ .addr = 0x5002d000,
216
+ .size = 0x1000,
217
+ .ppc = NO_PPC,
218
+ .irq = NO_IRQ,
219
+ },
220
+ {
221
+ .name = NULL,
222
+ }
223
+};
224
+
225
static const ARMSSEInfo armsse_variants[] = {
226
{
227
.name = TYPE_IOTKIT,
228
@@ -XXX,XX +XXX,XX @@ static const ARMSSEInfo armsse_variants[] = {
229
.iidr = 0,
230
.cpuwait_rst = 0,
231
.has_mhus = false,
232
- .has_ppus = false,
233
.has_cachectrl = false,
234
.has_cpusecctrl = false,
235
.has_cpuid = false,
236
.props = iotkit_properties,
237
- .devinfo = sse200_devices,
238
+ .devinfo = iotkit_devices,
239
},
240
{
241
.name = TYPE_SSE200,
242
@@ -XXX,XX +XXX,XX @@ static const ARMSSEInfo armsse_variants[] = {
243
.iidr = 0,
244
.cpuwait_rst = 2,
245
.has_mhus = true,
246
- .has_ppus = true,
247
.has_cachectrl = true,
248
.has_cpusecctrl = true,
249
.has_cpuid = true,
250
@@ -XXX,XX +XXX,XX @@ static void armsse_init(Object *obj)
251
assert(devinfo->index == 0);
252
object_initialize_child(obj, devinfo->name, &s->sysctl,
253
TYPE_IOTKIT_SYSCTL);
254
+ } else if (!strcmp(devinfo->type, TYPE_UNIMPLEMENTED_DEVICE)) {
255
+ assert(devinfo->index < ARRAY_SIZE(s->unimp));
256
+ object_initialize_child(obj, devinfo->name,
257
+ &s->unimp[devinfo->index],
258
+ TYPE_UNIMPLEMENTED_DEVICE);
259
} else {
260
g_assert_not_reached();
261
}
262
@@ -XXX,XX +XXX,XX @@ static void armsse_init(Object *obj)
263
object_initialize_child(obj, "mhu0", &s->mhu[0], TYPE_ARMSSE_MHU);
264
object_initialize_child(obj, "mhu1", &s->mhu[1], TYPE_ARMSSE_MHU);
265
}
266
- if (info->has_ppus) {
267
- for (i = 0; i < info->num_cpus; i++) {
268
- char *name = g_strdup_printf("CPU%dCORE_PPU", i);
269
- int ppuidx = CPU0CORE_PPU + i;
270
-
271
- object_initialize_child(obj, name, &s->ppu[ppuidx],
272
- TYPE_UNIMPLEMENTED_DEVICE);
273
- g_free(name);
274
- }
275
- object_initialize_child(obj, "DBG_PPU", &s->ppu[DBG_PPU],
276
- TYPE_UNIMPLEMENTED_DEVICE);
277
- for (i = 0; i < info->sram_banks; i++) {
278
- char *name = g_strdup_printf("RAM%d_PPU", i);
279
- int ppuidx = RAM0_PPU + i;
280
-
281
- object_initialize_child(obj, name, &s->ppu[ppuidx],
282
- TYPE_UNIMPLEMENTED_DEVICE);
283
- g_free(name);
284
- }
285
- }
286
if (info->has_cachectrl) {
287
for (i = 0; i < info->num_cpus; i++) {
288
char *name = g_strdup_printf("cachectrl%d", i);
289
@@ -XXX,XX +XXX,XX @@ static qemu_irq armsse_get_common_irq_in(ARMSSE *s, int irqno)
290
}
291
}
292
293
-static void map_ppu(ARMSSE *s, int ppuidx, const char *name, hwaddr addr)
294
-{
295
- /* Map a PPU unimplemented device stub */
296
- DeviceState *dev = DEVICE(&s->ppu[ppuidx]);
297
-
298
- qdev_prop_set_string(dev, "name", name);
299
- qdev_prop_set_uint64(dev, "size", 0x1000);
300
- sysbus_realize(SYS_BUS_DEVICE(dev), &error_fatal);
301
- sysbus_mmio_map(SYS_BUS_DEVICE(&s->ppu[ppuidx]), 0, addr);
302
-}
303
-
304
static void armsse_realize(DeviceState *dev, Error **errp)
305
{
306
ARMSSE *s = ARM_SSE(dev);
307
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
308
return;
309
}
310
mr = sysbus_mmio_get_region(sbd, 0);
311
+ } else if (!strcmp(devinfo->type, TYPE_UNIMPLEMENTED_DEVICE)) {
312
+ sbd = SYS_BUS_DEVICE(&s->unimp[devinfo->index]);
313
+
314
+ qdev_prop_set_string(DEVICE(sbd), "name", devinfo->name);
315
+ qdev_prop_set_uint64(DEVICE(sbd), "size", devinfo->size);
316
+ if (!sysbus_realize(sbd, errp)) {
317
+ return;
318
+ }
319
+ mr = sysbus_mmio_get_region(sbd, 0);
320
} else {
321
g_assert_not_reached();
322
}
323
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
324
memory_region_add_subregion(&s->container, devinfo->addr, mr);
325
}
326
327
- if (info->has_ppus) {
328
- /* CPUnCORE_PPU for each CPU */
329
- for (i = 0; i < info->num_cpus; i++) {
330
- char *name = g_strdup_printf("CPU%dCORE_PPU", i);
331
-
332
- map_ppu(s, CPU0CORE_PPU + i, name, 0x50023000 + i * 0x2000);
333
- /*
334
- * We don't support CPU debug so don't create the
335
- * CPU0DEBUG_PPU at 0x50024000 and 0x50026000.
336
- */
337
- g_free(name);
338
- }
339
- map_ppu(s, DBG_PPU, "DBG_PPU", 0x50029000);
340
-
341
- for (i = 0; i < info->sram_banks; i++) {
342
- char *name = g_strdup_printf("RAM%d_PPU", i);
343
-
344
- map_ppu(s, RAM0_PPU + i, name, 0x5002a000 + i * 0x1000);
345
- g_free(name);
346
- }
347
- }
348
-
349
for (i = 0; i < ARRAY_SIZE(s->ppc_irq_splitter); i++) {
350
Object *splitter = OBJECT(&s->ppc_irq_splitter[i]);
351
352
--
353
2.20.1
354
355
diff view generated by jsdifflib
Deleted patch
1
We forgot to implement a TYPE_UNIMPLEMENTED_DEVICE stub
2
for the SYS_PPU in the SSE-200, which is at 0x50022000.
3
1
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20210219144617.4782-31-peter.maydell@linaro.org
8
---
9
include/hw/arm/armsse.h | 2 +-
10
hw/arm/armsse.c | 9 +++++++++
11
2 files changed, 10 insertions(+), 1 deletion(-)
12
13
diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
14
index XXXXXXX..XXXXXXX 100644
15
--- a/include/hw/arm/armsse.h
16
+++ b/include/hw/arm/armsse.h
17
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_TYPE(ARMSSE, ARMSSEClass,
18
19
#define SSE_MAX_CPUS 2
20
21
-#define NUM_PPUS 7
22
+#define NUM_PPUS 8
23
24
/* Number of CPU IRQs used by the SSE itself */
25
#define NUM_SSE_IRQS 32
26
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
27
index XXXXXXX..XXXXXXX 100644
28
--- a/hw/arm/armsse.c
29
+++ b/hw/arm/armsse.c
30
@@ -XXX,XX +XXX,XX @@ static const ARMSSEDeviceInfo sse200_devices[] = {
31
.ppc = NO_PPC,
32
.irq = NO_IRQ,
33
},
34
+ {
35
+ .name = "SYS_PPU",
36
+ .type = TYPE_UNIMPLEMENTED_DEVICE,
37
+ .index = 7,
38
+ .addr = 0x50022000,
39
+ .size = 0x1000,
40
+ .ppc = NO_PPC,
41
+ .irq = NO_IRQ,
42
+ },
43
{
44
.name = NULL,
45
}
46
--
47
2.20.1
48
49
diff view generated by jsdifflib
Deleted patch
1
The SSE-300 has a slightly different set of shared-per-CPU interrupts,
2
allow the irq_is_common[] array to be different per SSE variant.
3
1
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20210219144617.4782-32-peter.maydell@linaro.org
9
---
10
hw/arm/armsse.c | 39 +++++++++++++++++++++------------------
11
1 file changed, 21 insertions(+), 18 deletions(-)
12
13
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/arm/armsse.c
16
+++ b/hw/arm/armsse.c
17
@@ -XXX,XX +XXX,XX @@ struct ARMSSEInfo {
18
bool has_cpuid;
19
Property *props;
20
const ARMSSEDeviceInfo *devinfo;
21
+ const bool *irq_is_common;
22
};
23
24
static Property iotkit_properties[] = {
25
@@ -XXX,XX +XXX,XX @@ static const ARMSSEDeviceInfo sse200_devices[] = {
26
}
27
};
28
29
+/* Is internal IRQ n shared between CPUs in a multi-core SSE ? */
30
+static const bool sse200_irq_is_common[32] = {
31
+ [0 ... 5] = true,
32
+ /* 6, 7: per-CPU MHU interrupts */
33
+ [8 ... 12] = true,
34
+ /* 13: per-CPU icache interrupt */
35
+ /* 14: reserved */
36
+ [15 ... 20] = true,
37
+ /* 21: reserved */
38
+ [22 ... 26] = true,
39
+ /* 27: reserved */
40
+ /* 28, 29: per-CPU CTI interrupts */
41
+ /* 30, 31: reserved */
42
+};
43
+
44
static const ARMSSEInfo armsse_variants[] = {
45
{
46
.name = TYPE_IOTKIT,
47
@@ -XXX,XX +XXX,XX @@ static const ARMSSEInfo armsse_variants[] = {
48
.has_cpuid = false,
49
.props = iotkit_properties,
50
.devinfo = iotkit_devices,
51
+ .irq_is_common = sse200_irq_is_common,
52
},
53
{
54
.name = TYPE_SSE200,
55
@@ -XXX,XX +XXX,XX @@ static const ARMSSEInfo armsse_variants[] = {
56
.has_cpuid = true,
57
.props = armsse_properties,
58
.devinfo = sse200_devices,
59
+ .irq_is_common = sse200_irq_is_common,
60
},
61
};
62
63
@@ -XXX,XX +XXX,XX @@ static uint32_t armsse_sys_config_value(ARMSSE *s, const ARMSSEInfo *info)
64
/* Clock frequency in HZ of the 32KHz "slow clock" */
65
#define S32KCLK (32 * 1000)
66
67
-/* Is internal IRQ n shared between CPUs in a multi-core SSE ? */
68
-static bool irq_is_common[32] = {
69
- [0 ... 5] = true,
70
- /* 6, 7: per-CPU MHU interrupts */
71
- [8 ... 12] = true,
72
- /* 13: per-CPU icache interrupt */
73
- /* 14: reserved */
74
- [15 ... 20] = true,
75
- /* 21: reserved */
76
- [22 ... 26] = true,
77
- /* 27: reserved */
78
- /* 28, 29: per-CPU CTI interrupts */
79
- /* 30, 31: reserved */
80
-};
81
-
82
/*
83
* Create an alias region in @container of @size bytes starting at @base
84
* which mirrors the memory starting at @orig.
85
@@ -XXX,XX +XXX,XX @@ static void armsse_init(Object *obj)
86
}
87
if (info->num_cpus > 1) {
88
for (i = 0; i < ARRAY_SIZE(s->cpu_irq_splitter); i++) {
89
- if (irq_is_common[i]) {
90
+ if (info->irq_is_common[i]) {
91
char *name = g_strdup_printf("cpu-irq-splitter%d", i);
92
SplitIRQ *splitter = &s->cpu_irq_splitter[i];
93
94
@@ -XXX,XX +XXX,XX @@ static qemu_irq armsse_get_common_irq_in(ARMSSE *s, int irqno)
95
ARMSSEClass *asc = ARM_SSE_GET_CLASS(s);
96
const ARMSSEInfo *info = asc->info;
97
98
- assert(irq_is_common[irqno]);
99
+ assert(info->irq_is_common[irqno]);
100
101
if (info->num_cpus == 1) {
102
/* Only one CPU -- just connect directly to it */
103
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
104
/* Wire up the splitters that connect common IRQs to all CPUs */
105
if (info->num_cpus > 1) {
106
for (i = 0; i < ARRAY_SIZE(s->cpu_irq_splitter); i++) {
107
- if (irq_is_common[i]) {
108
+ if (info->irq_is_common[i]) {
109
Object *splitter = OBJECT(&s->cpu_irq_splitter[i]);
110
DeviceState *devs = DEVICE(splitter);
111
int cpunum;
112
--
113
2.20.1
114
115
diff view generated by jsdifflib
Deleted patch
1
The SSE-300 has a system counter device; add support for SSE
2
variants having this device.
3
1
4
As with the existing devices like the cache control block, CPUID
5
block, etc, we don't try to make the MMIO addresses configurable. We
6
can do that if and when we need to model a future SSE variant which
7
has the counter in a different location.
8
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20210219144617.4782-33-peter.maydell@linaro.org
13
---
14
include/hw/arm/armsse.h | 3 +++
15
hw/arm/armsse.c | 27 +++++++++++++++++++++++++++
16
2 files changed, 30 insertions(+)
17
18
diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
19
index XXXXXXX..XXXXXXX 100644
20
--- a/include/hw/arm/armsse.h
21
+++ b/include/hw/arm/armsse.h
22
@@ -XXX,XX +XXX,XX @@
23
#include "hw/misc/tz-mpc.h"
24
#include "hw/timer/cmsdk-apb-timer.h"
25
#include "hw/timer/cmsdk-apb-dualtimer.h"
26
+#include "hw/timer/sse-counter.h"
27
#include "hw/watchdog/cmsdk-apb-watchdog.h"
28
#include "hw/misc/iotkit-sysctl.h"
29
#include "hw/misc/iotkit-sysinfo.h"
30
@@ -XXX,XX +XXX,XX @@ struct ARMSSE {
31
32
CMSDKAPBWatchdog cmsdk_watchdog[3];
33
34
+ SSECounter sse_counter;
35
+
36
IoTKitSysCtl sysctl;
37
IoTKitSysCtl sysinfo;
38
39
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
40
index XXXXXXX..XXXXXXX 100644
41
--- a/hw/arm/armsse.c
42
+++ b/hw/arm/armsse.c
43
@@ -XXX,XX +XXX,XX @@ struct ARMSSEInfo {
44
bool has_cachectrl;
45
bool has_cpusecctrl;
46
bool has_cpuid;
47
+ bool has_sse_counter;
48
Property *props;
49
const ARMSSEDeviceInfo *devinfo;
50
const bool *irq_is_common;
51
@@ -XXX,XX +XXX,XX @@ static const ARMSSEInfo armsse_variants[] = {
52
.has_cachectrl = false,
53
.has_cpusecctrl = false,
54
.has_cpuid = false,
55
+ .has_sse_counter = false,
56
.props = iotkit_properties,
57
.devinfo = iotkit_devices,
58
.irq_is_common = sse200_irq_is_common,
59
@@ -XXX,XX +XXX,XX @@ static const ARMSSEInfo armsse_variants[] = {
60
.has_cachectrl = true,
61
.has_cpusecctrl = true,
62
.has_cpuid = true,
63
+ .has_sse_counter = false,
64
.props = armsse_properties,
65
.devinfo = sse200_devices,
66
.irq_is_common = sse200_irq_is_common,
67
@@ -XXX,XX +XXX,XX @@ static void armsse_init(Object *obj)
68
g_free(name);
69
}
70
}
71
+ if (info->has_sse_counter) {
72
+ object_initialize_child(obj, "sse-counter", &s->sse_counter,
73
+ TYPE_SSE_COUNTER);
74
+ }
75
+
76
object_initialize_child(obj, "nmi-orgate", &s->nmi_orgate, TYPE_OR_IRQ);
77
object_initialize_child(obj, "ppc-irq-orgate", &s->ppc_irq_orgate,
78
TYPE_OR_IRQ);
79
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
80
qdev_connect_gpio_out(DEVICE(&s->nmi_orgate), 0,
81
qdev_get_gpio_in_named(DEVICE(&s->armv7m), "NMI", 0));
82
83
+ /* The SSE-300 has a System Counter / System Timestamp Generator */
84
+ if (info->has_sse_counter) {
85
+ SysBusDevice *sbd = SYS_BUS_DEVICE(&s->sse_counter);
86
+
87
+ qdev_connect_clock_in(DEVICE(sbd), "CLK", s->mainclk);
88
+ if (!sysbus_realize(sbd, errp)) {
89
+ return;
90
+ }
91
+ /*
92
+ * The control frame is only in the Secure region;
93
+ * the status frame is in the NS region (and visible in the
94
+ * S region via the alias mapping).
95
+ */
96
+ memory_region_add_subregion(&s->container, 0x58100000,
97
+ sysbus_mmio_get_region(sbd, 0));
98
+ memory_region_add_subregion(&s->container, 0x48101000,
99
+ sysbus_mmio_get_region(sbd, 1));
100
+ }
101
+
102
/* Devices behind APB PPC0:
103
* 0x40000000: timer0
104
* 0x40001000: timer1
105
--
106
2.20.1
107
108
diff view generated by jsdifflib
Deleted patch
1
The SSE-300 has four timers of type TYPE_SSE_TIMER; add support in
2
the code for having these in an ARMSSEDeviceInfo array.
3
1
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20210219144617.4782-34-peter.maydell@linaro.org
9
---
10
include/hw/arm/armsse.h | 2 ++
11
hw/arm/armsse.c | 15 +++++++++++++++
12
2 files changed, 17 insertions(+)
13
14
diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
15
index XXXXXXX..XXXXXXX 100644
16
--- a/include/hw/arm/armsse.h
17
+++ b/include/hw/arm/armsse.h
18
@@ -XXX,XX +XXX,XX @@
19
#include "hw/timer/cmsdk-apb-timer.h"
20
#include "hw/timer/cmsdk-apb-dualtimer.h"
21
#include "hw/timer/sse-counter.h"
22
+#include "hw/timer/sse-timer.h"
23
#include "hw/watchdog/cmsdk-apb-watchdog.h"
24
#include "hw/misc/iotkit-sysctl.h"
25
#include "hw/misc/iotkit-sysinfo.h"
26
@@ -XXX,XX +XXX,XX @@ struct ARMSSE {
27
CMSDKAPBWatchdog cmsdk_watchdog[3];
28
29
SSECounter sse_counter;
30
+ SSETimer sse_timer[4];
31
32
IoTKitSysCtl sysctl;
33
IoTKitSysCtl sysinfo;
34
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
35
index XXXXXXX..XXXXXXX 100644
36
--- a/hw/arm/armsse.c
37
+++ b/hw/arm/armsse.c
38
@@ -XXX,XX +XXX,XX @@ static void armsse_init(Object *obj)
39
assert(devinfo->index == 0);
40
object_initialize_child(obj, devinfo->name, &s->dualtimer,
41
TYPE_CMSDK_APB_DUALTIMER);
42
+ } else if (!strcmp(devinfo->type, TYPE_SSE_TIMER)) {
43
+ assert(devinfo->index < ARRAY_SIZE(s->sse_timer));
44
+ object_initialize_child(obj, devinfo->name,
45
+ &s->sse_timer[devinfo->index],
46
+ TYPE_SSE_TIMER);
47
} else if (!strcmp(devinfo->type, TYPE_CMSDK_APB_WATCHDOG)) {
48
assert(devinfo->index < ARRAY_SIZE(s->cmsdk_watchdog));
49
object_initialize_child(obj, devinfo->name,
50
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
51
return;
52
}
53
mr = sysbus_mmio_get_region(sbd, 0);
54
+ } else if (!strcmp(devinfo->type, TYPE_SSE_TIMER)) {
55
+ sbd = SYS_BUS_DEVICE(&s->sse_timer[devinfo->index]);
56
+
57
+ assert(info->has_sse_counter);
58
+ object_property_set_link(OBJECT(sbd), "counter",
59
+ OBJECT(&s->sse_counter), &error_abort);
60
+ if (!sysbus_realize(sbd, errp)) {
61
+ return;
62
+ }
63
+ mr = sysbus_mmio_get_region(sbd, 0);
64
} else if (!strcmp(devinfo->type, TYPE_CMSDK_APB_WATCHDOG)) {
65
sbd = SYS_BUS_DEVICE(&s->cmsdk_watchdog[devinfo->index]);
66
67
--
68
2.20.1
69
70
diff view generated by jsdifflib
Deleted patch
1
Support SSE variants like the SSE-300 with an ARMSSE_CPU_PWRCTRL register
2
block. Because this block is per-CPU and does not clash with any of the
3
SSE-200 devices, we handle it with a has_cpu_pwrctrl flag like the
4
existing has_cachectrl, has_cpusectrl and has_cpuid, rather than
5
trying to add per-CPU-device support to the devinfo array handling code.
6
1
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20210219144617.4782-35-peter.maydell@linaro.org
11
---
12
include/hw/arm/armsse.h | 3 +++
13
hw/arm/armsse.c | 26 ++++++++++++++++++++++++++
14
2 files changed, 29 insertions(+)
15
16
diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
17
index XXXXXXX..XXXXXXX 100644
18
--- a/include/hw/arm/armsse.h
19
+++ b/include/hw/arm/armsse.h
20
@@ -XXX,XX +XXX,XX @@
21
#include "hw/misc/iotkit-sysinfo.h"
22
#include "hw/misc/armsse-cpuid.h"
23
#include "hw/misc/armsse-mhu.h"
24
+#include "hw/misc/armsse-cpu-pwrctrl.h"
25
#include "hw/misc/unimp.h"
26
#include "hw/or-irq.h"
27
#include "hw/clock.h"
28
@@ -XXX,XX +XXX,XX @@ struct ARMSSE {
29
30
ARMSSECPUID cpuid[SSE_MAX_CPUS];
31
32
+ ARMSSECPUPwrCtrl cpu_pwrctrl[SSE_MAX_CPUS];
33
+
34
/*
35
* 'container' holds all devices seen by all CPUs.
36
* 'cpu_container[i]' is the view that CPU i has: this has the
37
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
38
index XXXXXXX..XXXXXXX 100644
39
--- a/hw/arm/armsse.c
40
+++ b/hw/arm/armsse.c
41
@@ -XXX,XX +XXX,XX @@ struct ARMSSEInfo {
42
bool has_cachectrl;
43
bool has_cpusecctrl;
44
bool has_cpuid;
45
+ bool has_cpu_pwrctrl;
46
bool has_sse_counter;
47
Property *props;
48
const ARMSSEDeviceInfo *devinfo;
49
@@ -XXX,XX +XXX,XX @@ static const ARMSSEInfo armsse_variants[] = {
50
.has_cachectrl = false,
51
.has_cpusecctrl = false,
52
.has_cpuid = false,
53
+ .has_cpu_pwrctrl = false,
54
.has_sse_counter = false,
55
.props = iotkit_properties,
56
.devinfo = iotkit_devices,
57
@@ -XXX,XX +XXX,XX @@ static const ARMSSEInfo armsse_variants[] = {
58
.has_cachectrl = true,
59
.has_cpusecctrl = true,
60
.has_cpuid = true,
61
+ .has_cpu_pwrctrl = false,
62
.has_sse_counter = false,
63
.props = armsse_properties,
64
.devinfo = sse200_devices,
65
@@ -XXX,XX +XXX,XX @@ static void armsse_init(Object *obj)
66
g_free(name);
67
}
68
}
69
+ if (info->has_cpu_pwrctrl) {
70
+ for (i = 0; i < info->num_cpus; i++) {
71
+ char *name = g_strdup_printf("cpu_pwrctrl%d", i);
72
+
73
+ object_initialize_child(obj, name, &s->cpu_pwrctrl[i],
74
+ TYPE_ARMSSE_CPU_PWRCTRL);
75
+ g_free(name);
76
+ }
77
+ }
78
if (info->has_sse_counter) {
79
object_initialize_child(obj, "sse-counter", &s->sse_counter,
80
TYPE_SSE_COUNTER);
81
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
82
* 0x50010000: L1 icache control registers
83
* 0x50011000: CPUSECCTRL (CPU local security control registers)
84
* 0x4001f000 and 0x5001f000: CPU_IDENTITY register block
85
+ * The SSE-300 has an extra:
86
+ * 0x40012000 and 0x50012000: CPU_PWRCTRL register block
87
*/
88
if (info->has_cachectrl) {
89
for (i = 0; i < info->num_cpus; i++) {
90
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
91
memory_region_add_subregion(&s->cpu_container[i], 0x4001F000, mr);
92
}
93
}
94
+ if (info->has_cpu_pwrctrl) {
95
+ for (i = 0; i < info->num_cpus; i++) {
96
+ MemoryRegion *mr;
97
+
98
+ if (!sysbus_realize(SYS_BUS_DEVICE(&s->cpu_pwrctrl[i]), errp)) {
99
+ return;
100
+ }
101
+
102
+ mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->cpu_pwrctrl[i]), 0);
103
+ memory_region_add_subregion(&s->cpu_container[i], 0x40012000, mr);
104
+ }
105
+ }
106
107
if (!sysbus_realize(SYS_BUS_DEVICE(&s->apb_ppc[1]), errp)) {
108
return;
109
--
110
2.20.1
111
112
diff view generated by jsdifflib
Deleted patch
1
Now we have sufficiently parameterised the code, we can add SSE-300
2
support by adding a new entry to the armsse_variants[] array.
3
1
4
Note that the main watchdog (unlike the s32k watchdog) in the SSE-300
5
is a different device from the CMSDK watchdog; we don't have a model
6
of it so we leave it as a TYPE_UNIMPLEMENTED_DEVICE stub.
7
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20210219144617.4782-36-peter.maydell@linaro.org
12
---
13
include/hw/arm/armsse.h | 1 +
14
hw/arm/armsse.c | 152 ++++++++++++++++++++++++++++++++++++++++
15
2 files changed, 153 insertions(+)
16
17
diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
18
index XXXXXXX..XXXXXXX 100644
19
--- a/include/hw/arm/armsse.h
20
+++ b/include/hw/arm/armsse.h
21
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_TYPE(ARMSSE, ARMSSEClass,
22
*/
23
#define TYPE_IOTKIT "iotkit"
24
#define TYPE_SSE200 "sse-200"
25
+#define TYPE_SSE300 "sse-300"
26
27
/* We have an IRQ splitter and an OR gate input for each external PPC
28
* and the 2 internal PPCs
29
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
30
index XXXXXXX..XXXXXXX 100644
31
--- a/hw/arm/armsse.c
32
+++ b/hw/arm/armsse.c
33
@@ -XXX,XX +XXX,XX @@ static const ARMSSEDeviceInfo sse200_devices[] = {
34
}
35
};
36
37
+static const ARMSSEDeviceInfo sse300_devices[] = {
38
+ {
39
+ .name = "timer0",
40
+ .type = TYPE_SSE_TIMER,
41
+ .index = 0,
42
+ .addr = 0x48000000,
43
+ .ppc = 0,
44
+ .ppc_port = 0,
45
+ .irq = 3,
46
+ },
47
+ {
48
+ .name = "timer1",
49
+ .type = TYPE_SSE_TIMER,
50
+ .index = 1,
51
+ .addr = 0x48001000,
52
+ .ppc = 0,
53
+ .ppc_port = 1,
54
+ .irq = 4,
55
+ },
56
+ {
57
+ .name = "timer2",
58
+ .type = TYPE_SSE_TIMER,
59
+ .index = 2,
60
+ .addr = 0x48002000,
61
+ .ppc = 0,
62
+ .ppc_port = 2,
63
+ .irq = 5,
64
+ },
65
+ {
66
+ .name = "timer3",
67
+ .type = TYPE_SSE_TIMER,
68
+ .index = 3,
69
+ .addr = 0x48003000,
70
+ .ppc = 0,
71
+ .ppc_port = 5,
72
+ .irq = 27,
73
+ },
74
+ {
75
+ .name = "s32ktimer",
76
+ .type = TYPE_CMSDK_APB_TIMER,
77
+ .index = 0,
78
+ .addr = 0x4802f000,
79
+ .ppc = 1,
80
+ .ppc_port = 0,
81
+ .irq = 2,
82
+ .slowclk = true,
83
+ },
84
+ {
85
+ .name = "s32kwatchdog",
86
+ .type = TYPE_CMSDK_APB_WATCHDOG,
87
+ .index = 0,
88
+ .addr = 0x4802e000,
89
+ .ppc = NO_PPC,
90
+ .irq = NMI_0,
91
+ .slowclk = true,
92
+ },
93
+ {
94
+ .name = "watchdog",
95
+ .type = TYPE_UNIMPLEMENTED_DEVICE,
96
+ .index = 0,
97
+ .addr = 0x48040000,
98
+ .size = 0x2000,
99
+ .ppc = NO_PPC,
100
+ .irq = NO_IRQ,
101
+ },
102
+ {
103
+ .name = "armsse-sysinfo",
104
+ .type = TYPE_IOTKIT_SYSINFO,
105
+ .index = 0,
106
+ .addr = 0x48020000,
107
+ .ppc = NO_PPC,
108
+ .irq = NO_IRQ,
109
+ },
110
+ {
111
+ .name = "armsse-sysctl",
112
+ .type = TYPE_IOTKIT_SYSCTL,
113
+ .index = 0,
114
+ .addr = 0x58021000,
115
+ .ppc = NO_PPC,
116
+ .irq = NO_IRQ,
117
+ },
118
+ {
119
+ .name = "SYS_PPU",
120
+ .type = TYPE_UNIMPLEMENTED_DEVICE,
121
+ .index = 1,
122
+ .addr = 0x58022000,
123
+ .size = 0x1000,
124
+ .ppc = NO_PPC,
125
+ .irq = NO_IRQ,
126
+ },
127
+ {
128
+ .name = "CPU0CORE_PPU",
129
+ .type = TYPE_UNIMPLEMENTED_DEVICE,
130
+ .index = 2,
131
+ .addr = 0x50023000,
132
+ .size = 0x1000,
133
+ .ppc = NO_PPC,
134
+ .irq = NO_IRQ,
135
+ },
136
+ {
137
+ .name = "MGMT_PPU",
138
+ .type = TYPE_UNIMPLEMENTED_DEVICE,
139
+ .index = 3,
140
+ .addr = 0x50028000,
141
+ .size = 0x1000,
142
+ .ppc = NO_PPC,
143
+ .irq = NO_IRQ,
144
+ },
145
+ {
146
+ .name = "DEBUG_PPU",
147
+ .type = TYPE_UNIMPLEMENTED_DEVICE,
148
+ .index = 4,
149
+ .addr = 0x50029000,
150
+ .size = 0x1000,
151
+ .ppc = NO_PPC,
152
+ .irq = NO_IRQ,
153
+ },
154
+ {
155
+ .name = NULL,
156
+ }
157
+};
158
+
159
/* Is internal IRQ n shared between CPUs in a multi-core SSE ? */
160
static const bool sse200_irq_is_common[32] = {
161
[0 ... 5] = true,
162
@@ -XXX,XX +XXX,XX @@ static const bool sse200_irq_is_common[32] = {
163
/* 30, 31: reserved */
164
};
165
166
+static const bool sse300_irq_is_common[32] = {
167
+ [0 ... 5] = true,
168
+ /* 6, 7: per-CPU MHU interrupts */
169
+ [8 ... 12] = true,
170
+ /* 13: reserved */
171
+ [14 ... 16] = true,
172
+ /* 17-25: reserved */
173
+ [26 ... 27] = true,
174
+ /* 28, 29: per-CPU CTI interrupts */
175
+ /* 30, 31: reserved */
176
+};
177
+
178
static const ARMSSEInfo armsse_variants[] = {
179
{
180
.name = TYPE_IOTKIT,
181
@@ -XXX,XX +XXX,XX @@ static const ARMSSEInfo armsse_variants[] = {
182
.devinfo = sse200_devices,
183
.irq_is_common = sse200_irq_is_common,
184
},
185
+ {
186
+ .name = TYPE_SSE300,
187
+ .sse_version = ARMSSE_SSE300,
188
+ .sram_banks = 2,
189
+ .num_cpus = 1,
190
+ .sys_version = 0x7e00043b,
191
+ .iidr = 0x74a0043b,
192
+ .cpuwait_rst = 0,
193
+ .has_mhus = false,
194
+ .has_cachectrl = false,
195
+ .has_cpusecctrl = true,
196
+ .has_cpuid = true,
197
+ .has_cpu_pwrctrl = true,
198
+ .has_sse_counter = true,
199
+ .props = armsse_properties,
200
+ .devinfo = sse300_devices,
201
+ .irq_is_common = sse300_irq_is_common,
202
+ },
203
};
204
205
static uint32_t armsse_sys_config_value(ARMSSE *s, const ARMSSEInfo *info)
206
--
207
2.20.1
208
209
diff view generated by jsdifflib
Deleted patch
1
The AN547 puts the combined UART overflow IRQ at 48, not 47 like the
2
other images. Make this setting board-specific.
3
1
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20210219144617.4782-37-peter.maydell@linaro.org
9
---
10
hw/arm/mps2-tz.c | 6 +++++-
11
1 file changed, 5 insertions(+), 1 deletion(-)
12
13
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/arm/mps2-tz.c
16
+++ b/hw/arm/mps2-tz.c
17
@@ -XXX,XX +XXX,XX @@ struct MPS2TZMachineClass {
18
uint32_t fpgaio_num_leds; /* Number of LEDs in FPGAIO LED0 register */
19
bool fpgaio_has_switches; /* Does FPGAIO have SWITCH register? */
20
int numirq; /* Number of external interrupts */
21
+ int uart_overflow_irq; /* number of the combined UART overflow IRQ */
22
const RAMInfo *raminfo;
23
const char *armsse_type;
24
};
25
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
26
&error_fatal);
27
qdev_realize(DEVICE(&mms->uart_irq_orgate), NULL, &error_fatal);
28
qdev_connect_gpio_out(DEVICE(&mms->uart_irq_orgate), 0,
29
- get_sse_irq_in(mms, 47));
30
+ get_sse_irq_in(mms, mmc->uart_overflow_irq));
31
32
/* Most of the devices in the FPGA are behind Peripheral Protection
33
* Controllers. The required order for initializing things is:
34
@@ -XXX,XX +XXX,XX @@ static void mps2tz_an505_class_init(ObjectClass *oc, void *data)
35
mmc->fpgaio_num_leds = 2;
36
mmc->fpgaio_has_switches = false;
37
mmc->numirq = 92;
38
+ mmc->uart_overflow_irq = 47;
39
mmc->raminfo = an505_raminfo;
40
mmc->armsse_type = TYPE_IOTKIT;
41
mps2tz_set_default_ram_info(mmc);
42
@@ -XXX,XX +XXX,XX @@ static void mps2tz_an521_class_init(ObjectClass *oc, void *data)
43
mmc->fpgaio_num_leds = 2;
44
mmc->fpgaio_has_switches = false;
45
mmc->numirq = 92;
46
+ mmc->uart_overflow_irq = 47;
47
mmc->raminfo = an505_raminfo; /* AN521 is the same as AN505 here */
48
mmc->armsse_type = TYPE_SSE200;
49
mps2tz_set_default_ram_info(mmc);
50
@@ -XXX,XX +XXX,XX @@ static void mps3tz_an524_class_init(ObjectClass *oc, void *data)
51
mmc->fpgaio_num_leds = 10;
52
mmc->fpgaio_has_switches = true;
53
mmc->numirq = 95;
54
+ mmc->uart_overflow_irq = 47;
55
mmc->raminfo = an524_raminfo;
56
mmc->armsse_type = TYPE_SSE200;
57
mps2tz_set_default_ram_info(mmc);
58
--
59
2.20.1
60
61
diff view generated by jsdifflib
Deleted patch
1
We've already broken migration compatibility for all the MPS
2
boards, so we might as well take advantage of this to simplify
3
the vmstate for the FPGAIO device by folding the counters
4
subsection into the main vmstate description.
5
1
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20210219144617.4782-38-peter.maydell@linaro.org
10
---
11
hw/misc/mps2-fpgaio.c | 30 +++++-------------------------
12
1 file changed, 5 insertions(+), 25 deletions(-)
13
14
diff --git a/hw/misc/mps2-fpgaio.c b/hw/misc/mps2-fpgaio.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/misc/mps2-fpgaio.c
17
+++ b/hw/misc/mps2-fpgaio.c
18
@@ -XXX,XX +XXX,XX @@ static void mps2_fpgaio_realize(DeviceState *dev, Error **errp)
19
}
20
}
21
22
-static bool mps2_fpgaio_counters_needed(void *opaque)
23
-{
24
- /* Currently vmstate.c insists all subsections have a 'needed' function */
25
- return true;
26
-}
27
-
28
-static const VMStateDescription mps2_fpgaio_counters_vmstate = {
29
- .name = "mps2-fpgaio/counters",
30
+static const VMStateDescription mps2_fpgaio_vmstate = {
31
+ .name = "mps2-fpgaio",
32
.version_id = 2,
33
.minimum_version_id = 2,
34
- .needed = mps2_fpgaio_counters_needed,
35
.fields = (VMStateField[]) {
36
+ VMSTATE_UINT32(led0, MPS2FPGAIO),
37
+ VMSTATE_UINT32(prescale, MPS2FPGAIO),
38
+ VMSTATE_UINT32(misc, MPS2FPGAIO),
39
VMSTATE_INT64(clk1hz_tick_offset, MPS2FPGAIO),
40
VMSTATE_INT64(clk100hz_tick_offset, MPS2FPGAIO),
41
VMSTATE_UINT32(counter, MPS2FPGAIO),
42
VMSTATE_UINT32(pscntr, MPS2FPGAIO),
43
VMSTATE_INT64(pscntr_sync_ticks, MPS2FPGAIO),
44
VMSTATE_END_OF_LIST()
45
- }
46
-};
47
-
48
-static const VMStateDescription mps2_fpgaio_vmstate = {
49
- .name = "mps2-fpgaio",
50
- .version_id = 1,
51
- .minimum_version_id = 1,
52
- .fields = (VMStateField[]) {
53
- VMSTATE_UINT32(led0, MPS2FPGAIO),
54
- VMSTATE_UINT32(prescale, MPS2FPGAIO),
55
- VMSTATE_UINT32(misc, MPS2FPGAIO),
56
- VMSTATE_END_OF_LIST()
57
},
58
- .subsections = (const VMStateDescription*[]) {
59
- &mps2_fpgaio_counters_vmstate,
60
- NULL
61
- }
62
};
63
64
static Property mps2_fpgaio_properties[] = {
65
--
66
2.20.1
67
68
diff view generated by jsdifflib
Deleted patch
1
For the AN547 image, the FPGAIO block has an extra DBGCTRL register,
2
which is used to control the SPNIDEN, SPIDEN, NPIDEN and DBGEN inputs
3
to the CPU. These signals control when the CPU permits use of the
4
external debug interface. Our CPU models don't implement the
5
external debug interface, so we model the register as
6
reads-as-written.
7
1
8
Implement the register, with a property defining whether it is
9
present, and allow mps2-tz boards to specify that it is present.
10
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
13
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
Message-id: 20210219144617.4782-39-peter.maydell@linaro.org
16
---
17
include/hw/misc/mps2-fpgaio.h | 2 ++
18
hw/arm/mps2-tz.c | 5 +++++
19
hw/misc/mps2-fpgaio.c | 22 ++++++++++++++++++++--
20
3 files changed, 27 insertions(+), 2 deletions(-)
21
22
diff --git a/include/hw/misc/mps2-fpgaio.h b/include/hw/misc/mps2-fpgaio.h
23
index XXXXXXX..XXXXXXX 100644
24
--- a/include/hw/misc/mps2-fpgaio.h
25
+++ b/include/hw/misc/mps2-fpgaio.h
26
@@ -XXX,XX +XXX,XX @@ struct MPS2FPGAIO {
27
LEDState *led[MPS2FPGAIO_MAX_LEDS];
28
uint32_t num_leds;
29
bool has_switches;
30
+ bool has_dbgctrl;
31
32
uint32_t led0;
33
uint32_t prescale;
34
uint32_t misc;
35
+ uint32_t dbgctrl;
36
37
/* QEMU_CLOCK_VIRTUAL time at which counter and pscntr were last synced */
38
int64_t pscntr_sync_ticks;
39
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
40
index XXXXXXX..XXXXXXX 100644
41
--- a/hw/arm/mps2-tz.c
42
+++ b/hw/arm/mps2-tz.c
43
@@ -XXX,XX +XXX,XX @@ struct MPS2TZMachineClass {
44
const uint32_t *oscclk;
45
uint32_t fpgaio_num_leds; /* Number of LEDs in FPGAIO LED0 register */
46
bool fpgaio_has_switches; /* Does FPGAIO have SWITCH register? */
47
+ bool fpgaio_has_dbgctrl; /* Does FPGAIO have DBGCTRL register? */
48
int numirq; /* Number of external interrupts */
49
int uart_overflow_irq; /* number of the combined UART overflow IRQ */
50
const RAMInfo *raminfo;
51
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_fpgaio(MPS2TZMachineState *mms, void *opaque,
52
object_initialize_child(OBJECT(mms), "fpgaio", fpgaio, TYPE_MPS2_FPGAIO);
53
qdev_prop_set_uint32(DEVICE(fpgaio), "num-leds", mmc->fpgaio_num_leds);
54
qdev_prop_set_bit(DEVICE(fpgaio), "has-switches", mmc->fpgaio_has_switches);
55
+ qdev_prop_set_bit(DEVICE(fpgaio), "has-dbgctrl", mmc->fpgaio_has_dbgctrl);
56
sysbus_realize(SYS_BUS_DEVICE(fpgaio), &error_fatal);
57
return sysbus_mmio_get_region(SYS_BUS_DEVICE(fpgaio), 0);
58
}
59
@@ -XXX,XX +XXX,XX @@ static void mps2tz_an505_class_init(ObjectClass *oc, void *data)
60
mmc->len_oscclk = ARRAY_SIZE(an505_oscclk);
61
mmc->fpgaio_num_leds = 2;
62
mmc->fpgaio_has_switches = false;
63
+ mmc->fpgaio_has_dbgctrl = false;
64
mmc->numirq = 92;
65
mmc->uart_overflow_irq = 47;
66
mmc->raminfo = an505_raminfo;
67
@@ -XXX,XX +XXX,XX @@ static void mps2tz_an521_class_init(ObjectClass *oc, void *data)
68
mmc->len_oscclk = ARRAY_SIZE(an505_oscclk);
69
mmc->fpgaio_num_leds = 2;
70
mmc->fpgaio_has_switches = false;
71
+ mmc->fpgaio_has_dbgctrl = false;
72
mmc->numirq = 92;
73
mmc->uart_overflow_irq = 47;
74
mmc->raminfo = an505_raminfo; /* AN521 is the same as AN505 here */
75
@@ -XXX,XX +XXX,XX @@ static void mps3tz_an524_class_init(ObjectClass *oc, void *data)
76
mmc->len_oscclk = ARRAY_SIZE(an524_oscclk);
77
mmc->fpgaio_num_leds = 10;
78
mmc->fpgaio_has_switches = true;
79
+ mmc->fpgaio_has_dbgctrl = false;
80
mmc->numirq = 95;
81
mmc->uart_overflow_irq = 47;
82
mmc->raminfo = an524_raminfo;
83
diff --git a/hw/misc/mps2-fpgaio.c b/hw/misc/mps2-fpgaio.c
84
index XXXXXXX..XXXXXXX 100644
85
--- a/hw/misc/mps2-fpgaio.c
86
+++ b/hw/misc/mps2-fpgaio.c
87
@@ -XXX,XX +XXX,XX @@
88
#include "qemu/timer.h"
89
90
REG32(LED0, 0)
91
+REG32(DBGCTRL, 4)
92
REG32(BUTTON, 8)
93
REG32(CLK1HZ, 0x10)
94
REG32(CLK100HZ, 0x14)
95
@@ -XXX,XX +XXX,XX @@ static uint64_t mps2_fpgaio_read(void *opaque, hwaddr offset, unsigned size)
96
case A_LED0:
97
r = s->led0;
98
break;
99
+ case A_DBGCTRL:
100
+ if (!s->has_dbgctrl) {
101
+ goto bad_offset;
102
+ }
103
+ r = s->dbgctrl;
104
+ break;
105
case A_BUTTON:
106
/* User-pressable board buttons. We don't model that, so just return
107
* zeroes.
108
@@ -XXX,XX +XXX,XX @@ static void mps2_fpgaio_write(void *opaque, hwaddr offset, uint64_t value,
109
}
110
}
111
break;
112
+ case A_DBGCTRL:
113
+ if (!s->has_dbgctrl) {
114
+ goto bad_offset;
115
+ }
116
+ qemu_log_mask(LOG_UNIMP,
117
+ "MPS2 FPGAIO: DBGCTRL unimplemented\n");
118
+ s->dbgctrl = value;
119
+ break;
120
case A_PRESCALE:
121
resync_counter(s);
122
s->prescale = value;
123
@@ -XXX,XX +XXX,XX @@ static void mps2_fpgaio_write(void *opaque, hwaddr offset, uint64_t value,
124
s->pscntr = value;
125
break;
126
default:
127
+ bad_offset:
128
qemu_log_mask(LOG_GUEST_ERROR,
129
"MPS2 FPGAIO write: bad offset 0x%x\n", (int) offset);
130
break;
131
@@ -XXX,XX +XXX,XX @@ static void mps2_fpgaio_realize(DeviceState *dev, Error **errp)
132
133
static const VMStateDescription mps2_fpgaio_vmstate = {
134
.name = "mps2-fpgaio",
135
- .version_id = 2,
136
- .minimum_version_id = 2,
137
+ .version_id = 3,
138
+ .minimum_version_id = 3,
139
.fields = (VMStateField[]) {
140
VMSTATE_UINT32(led0, MPS2FPGAIO),
141
VMSTATE_UINT32(prescale, MPS2FPGAIO),
142
VMSTATE_UINT32(misc, MPS2FPGAIO),
143
+ VMSTATE_UINT32(dbgctrl, MPS2FPGAIO),
144
VMSTATE_INT64(clk1hz_tick_offset, MPS2FPGAIO),
145
VMSTATE_INT64(clk100hz_tick_offset, MPS2FPGAIO),
146
VMSTATE_UINT32(counter, MPS2FPGAIO),
147
@@ -XXX,XX +XXX,XX @@ static Property mps2_fpgaio_properties[] = {
148
/* Number of LEDs controlled by LED0 register */
149
DEFINE_PROP_UINT32("num-leds", MPS2FPGAIO, num_leds, 2),
150
DEFINE_PROP_BOOL("has-switches", MPS2FPGAIO, has_switches, false),
151
+ DEFINE_PROP_BOOL("has-dbgctrl", MPS2FPGAIO, has_dbgctrl, false),
152
DEFINE_PROP_END_OF_LIST(),
153
};
154
155
--
156
2.20.1
157
158
diff view generated by jsdifflib
Deleted patch
1
Implement the minor changes required to the SCC block for AN547 images:
2
* CFG2 and CFG5 exist (like AN524)
3
* CFG3 is reserved (like AN524)
4
* CFG0 bit 1 is CPU_WAIT; we don't implement it, but note this
5
in the TODO comment
6
1
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20210219144617.4782-40-peter.maydell@linaro.org
11
---
12
hw/misc/mps2-scc.c | 15 +++++++++------
13
1 file changed, 9 insertions(+), 6 deletions(-)
14
15
diff --git a/hw/misc/mps2-scc.c b/hw/misc/mps2-scc.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/misc/mps2-scc.c
18
+++ b/hw/misc/mps2-scc.c
19
@@ -XXX,XX +XXX,XX @@ static uint64_t mps2_scc_read(void *opaque, hwaddr offset, unsigned size)
20
r = s->cfg1;
21
break;
22
case A_CFG2:
23
- if (scc_partno(s) != 0x524) {
24
+ if (scc_partno(s) != 0x524 && scc_partno(s) != 0x547) {
25
/* CFG2 reserved on other boards */
26
goto bad_offset;
27
}
28
r = s->cfg2;
29
break;
30
case A_CFG3:
31
- if (scc_partno(s) == 0x524) {
32
+ if (scc_partno(s) == 0x524 && scc_partno(s) == 0x547) {
33
/* CFG3 reserved on AN524 */
34
goto bad_offset;
35
}
36
@@ -XXX,XX +XXX,XX @@ static uint64_t mps2_scc_read(void *opaque, hwaddr offset, unsigned size)
37
r = s->cfg4;
38
break;
39
case A_CFG5:
40
- if (scc_partno(s) != 0x524) {
41
+ if (scc_partno(s) != 0x524 && scc_partno(s) != 0x547) {
42
/* CFG5 reserved on other boards */
43
goto bad_offset;
44
}
45
@@ -XXX,XX +XXX,XX @@ static void mps2_scc_write(void *opaque, hwaddr offset, uint64_t value,
46
47
switch (offset) {
48
case A_CFG0:
49
- /* TODO on some boards bit 0 controls RAM remapping */
50
+ /*
51
+ * TODO on some boards bit 0 controls RAM remapping;
52
+ * on others bit 1 is CPU_WAIT.
53
+ */
54
s->cfg0 = value;
55
break;
56
case A_CFG1:
57
@@ -XXX,XX +XXX,XX @@ static void mps2_scc_write(void *opaque, hwaddr offset, uint64_t value,
58
}
59
break;
60
case A_CFG2:
61
- if (scc_partno(s) != 0x524) {
62
+ if (scc_partno(s) != 0x524 && scc_partno(s) != 0x547) {
63
/* CFG2 reserved on other boards */
64
goto bad_offset;
65
}
66
@@ -XXX,XX +XXX,XX @@ static void mps2_scc_write(void *opaque, hwaddr offset, uint64_t value,
67
s->cfg2 = value;
68
break;
69
case A_CFG5:
70
- if (scc_partno(s) != 0x524) {
71
+ if (scc_partno(s) != 0x524 && scc_partno(s) != 0x547) {
72
/* CFG5 reserved on other boards */
73
goto bad_offset;
74
}
75
--
76
2.20.1
77
78
diff view generated by jsdifflib
Deleted patch
1
The AN547 runs the APB peripherals outside the SSE-300 on a different
2
and slightly slower clock than it runs the SSE-300 with. Support
3
making the APB peripheral clock frequency board-specific. (For our
4
implementation only the UARTs actually take a clock.)
5
1
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20210219144617.4782-41-peter.maydell@linaro.org
11
---
12
hw/arm/mps2-tz.c | 6 +++++-
13
1 file changed, 5 insertions(+), 1 deletion(-)
14
15
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/arm/mps2-tz.c
18
+++ b/hw/arm/mps2-tz.c
19
@@ -XXX,XX +XXX,XX @@ struct MPS2TZMachineClass {
20
MPS2TZFPGAType fpga_type;
21
uint32_t scc_id;
22
uint32_t sysclk_frq; /* Main SYSCLK frequency in Hz */
23
+ uint32_t apb_periph_frq; /* APB peripheral frequency in Hz */
24
uint32_t len_oscclk;
25
const uint32_t *oscclk;
26
uint32_t fpgaio_num_leds; /* Number of LEDs in FPGAIO LED0 register */
27
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_uart(MPS2TZMachineState *mms, void *opaque,
28
29
object_initialize_child(OBJECT(mms), name, uart, TYPE_CMSDK_APB_UART);
30
qdev_prop_set_chr(DEVICE(uart), "chardev", serial_hd(i));
31
- qdev_prop_set_uint32(DEVICE(uart), "pclk-frq", mmc->sysclk_frq);
32
+ qdev_prop_set_uint32(DEVICE(uart), "pclk-frq", mmc->apb_periph_frq);
33
sysbus_realize(SYS_BUS_DEVICE(uart), &error_fatal);
34
s = SYS_BUS_DEVICE(uart);
35
sysbus_connect_irq(s, 0, get_sse_irq_in(mms, irqs[0]));
36
@@ -XXX,XX +XXX,XX @@ static void mps2tz_an505_class_init(ObjectClass *oc, void *data)
37
mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m33");
38
mmc->scc_id = 0x41045050;
39
mmc->sysclk_frq = 20 * 1000 * 1000; /* 20MHz */
40
+ mmc->apb_periph_frq = mmc->sysclk_frq;
41
mmc->oscclk = an505_oscclk;
42
mmc->len_oscclk = ARRAY_SIZE(an505_oscclk);
43
mmc->fpgaio_num_leds = 2;
44
@@ -XXX,XX +XXX,XX @@ static void mps2tz_an521_class_init(ObjectClass *oc, void *data)
45
mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m33");
46
mmc->scc_id = 0x41045210;
47
mmc->sysclk_frq = 20 * 1000 * 1000; /* 20MHz */
48
+ mmc->apb_periph_frq = mmc->sysclk_frq;
49
mmc->oscclk = an505_oscclk; /* AN521 is the same as AN505 here */
50
mmc->len_oscclk = ARRAY_SIZE(an505_oscclk);
51
mmc->fpgaio_num_leds = 2;
52
@@ -XXX,XX +XXX,XX @@ static void mps3tz_an524_class_init(ObjectClass *oc, void *data)
53
mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m33");
54
mmc->scc_id = 0x41045240;
55
mmc->sysclk_frq = 32 * 1000 * 1000; /* 32MHz */
56
+ mmc->apb_periph_frq = mmc->sysclk_frq;
57
mmc->oscclk = an524_oscclk;
58
mmc->len_oscclk = ARRAY_SIZE(an524_oscclk);
59
mmc->fpgaio_num_leds = 10;
60
--
61
2.20.1
62
63
diff view generated by jsdifflib
Deleted patch
1
The AN547 configures the SSE-300 with a different initsvtor0
2
setting from its default; make this a board-specific setting.
3
1
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20210219144617.4782-42-peter.maydell@linaro.org
9
---
10
hw/arm/mps2-tz.c | 5 +++++
11
1 file changed, 5 insertions(+)
12
13
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/arm/mps2-tz.c
16
+++ b/hw/arm/mps2-tz.c
17
@@ -XXX,XX +XXX,XX @@ struct MPS2TZMachineClass {
18
bool fpgaio_has_dbgctrl; /* Does FPGAIO have DBGCTRL register? */
19
int numirq; /* Number of external interrupts */
20
int uart_overflow_irq; /* number of the combined UART overflow IRQ */
21
+ uint32_t init_svtor; /* init-svtor setting for SSE */
22
const RAMInfo *raminfo;
23
const char *armsse_type;
24
};
25
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
26
object_property_set_link(OBJECT(&mms->iotkit), "memory",
27
OBJECT(system_memory), &error_abort);
28
qdev_prop_set_uint32(iotkitdev, "EXP_NUMIRQ", mmc->numirq);
29
+ qdev_prop_set_uint32(iotkitdev, "init-svtor", mmc->init_svtor);
30
qdev_connect_clock_in(iotkitdev, "MAINCLK", mms->sysclk);
31
qdev_connect_clock_in(iotkitdev, "S32KCLK", mms->s32kclk);
32
sysbus_realize(SYS_BUS_DEVICE(&mms->iotkit), &error_fatal);
33
@@ -XXX,XX +XXX,XX @@ static void mps2tz_an505_class_init(ObjectClass *oc, void *data)
34
mmc->fpgaio_has_dbgctrl = false;
35
mmc->numirq = 92;
36
mmc->uart_overflow_irq = 47;
37
+ mmc->init_svtor = 0x10000000;
38
mmc->raminfo = an505_raminfo;
39
mmc->armsse_type = TYPE_IOTKIT;
40
mps2tz_set_default_ram_info(mmc);
41
@@ -XXX,XX +XXX,XX @@ static void mps2tz_an521_class_init(ObjectClass *oc, void *data)
42
mmc->fpgaio_has_dbgctrl = false;
43
mmc->numirq = 92;
44
mmc->uart_overflow_irq = 47;
45
+ mmc->init_svtor = 0x10000000;
46
mmc->raminfo = an505_raminfo; /* AN521 is the same as AN505 here */
47
mmc->armsse_type = TYPE_SSE200;
48
mps2tz_set_default_ram_info(mmc);
49
@@ -XXX,XX +XXX,XX @@ static void mps3tz_an524_class_init(ObjectClass *oc, void *data)
50
mmc->fpgaio_has_dbgctrl = false;
51
mmc->numirq = 95;
52
mmc->uart_overflow_irq = 47;
53
+ mmc->init_svtor = 0x10000000;
54
mmc->raminfo = an524_raminfo;
55
mmc->armsse_type = TYPE_SSE200;
56
mps2tz_set_default_ram_info(mmc);
57
--
58
2.20.1
59
60
diff view generated by jsdifflib
1
Add support for the mps3-an547 board; this is an SSE-300 based
1
The architecture requires that for faults on loads and stores which
2
FPGA image that runs on the MPS3.
2
do writeback, the syndrome information does not have the ISS
3
instruction syndrome information (i.e. ISV is 0). We got this wrong
4
for the load and store instructions covered by disas_ldst_reg_imm9().
5
Calculate iss_valid correctly so that if the insn is a writeback one
6
it is false.
3
7
8
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1057
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20210219144617.4782-43-peter.maydell@linaro.org
11
Message-id: 20220715123323.1550983-1-peter.maydell@linaro.org
8
---
12
---
9
hw/arm/mps2-tz.c | 146 ++++++++++++++++++++++++++++++++++++++++++++++-
13
target/arm/translate-a64.c | 4 +++-
10
1 file changed, 144 insertions(+), 2 deletions(-)
14
1 file changed, 3 insertions(+), 1 deletion(-)
11
15
12
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
16
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
13
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/arm/mps2-tz.c
18
--- a/target/arm/translate-a64.c
15
+++ b/hw/arm/mps2-tz.c
19
+++ b/target/arm/translate-a64.c
16
@@ -XXX,XX +XXX,XX @@
20
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_reg_imm9(DisasContext *s, uint32_t insn,
17
* "mps2-an505" -- Cortex-M33 as documented in ARM Application Note AN505
21
bool is_store = false;
18
* "mps2-an521" -- Dual Cortex-M33 as documented in Application Note AN521
22
bool is_extended = false;
19
* "mps2-an524" -- Dual Cortex-M33 as documented in Application Note AN524
23
bool is_unpriv = (idx == 2);
20
+ * "mps2-an547" -- Single Cortex-M55 as documented in Application Note AN547
24
- bool iss_valid = !is_vector;
21
*
25
+ bool iss_valid;
22
* Links to the TRM for the board itself and to the various Application
26
bool post_index;
23
* Notes which document the FPGA images can be found here:
27
bool writeback;
24
@@ -XXX,XX +XXX,XX @@
28
int memidx;
25
* https://developer.arm.com/documentation/dai0521/latest/
29
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_reg_imm9(DisasContext *s, uint32_t insn,
26
* Application Note AN524:
27
* https://developer.arm.com/documentation/dai0524/latest/
28
+ * Application Note AN547:
29
+ * https://developer.arm.com/-/media/Arm%20Developer%20Community/PDF/DAI0547B_SSE300_PLUS_U55_FPGA_for_mps3.pdf
30
*
31
* The AN505 defers to the Cortex-M33 processor ARMv8M IoT Kit FVP User Guide
32
* (ARM ECM0601256) for the details of some of the device layout:
33
@@ -XXX,XX +XXX,XX @@
34
* Similarly, the AN521 and AN524 use the SSE-200, and the SSE-200 TRM defines
35
* most of the device layout:
36
* https://developer.arm.com/documentation/101104/latest/
37
+ * and the AN547 uses the SSE-300, whose layout is in the SSE-300 TRM:
38
+ * https://developer.arm.com/documentation/101773/latest/
39
*/
40
41
#include "qemu/osdep.h"
42
@@ -XXX,XX +XXX,XX @@
43
#include "hw/qdev-clock.h"
44
#include "qom/object.h"
45
46
-#define MPS2TZ_NUMIRQ_MAX 95
47
-#define MPS2TZ_RAM_MAX 4
48
+#define MPS2TZ_NUMIRQ_MAX 96
49
+#define MPS2TZ_RAM_MAX 5
50
51
typedef enum MPS2TZFPGAType {
52
FPGA_AN505,
53
FPGA_AN521,
54
FPGA_AN524,
55
+ FPGA_AN547,
56
} MPS2TZFPGAType;
57
58
/*
59
@@ -XXX,XX +XXX,XX @@ struct MPS2TZMachineState {
60
#define TYPE_MPS2TZ_AN505_MACHINE MACHINE_TYPE_NAME("mps2-an505")
61
#define TYPE_MPS2TZ_AN521_MACHINE MACHINE_TYPE_NAME("mps2-an521")
62
#define TYPE_MPS3TZ_AN524_MACHINE MACHINE_TYPE_NAME("mps3-an524")
63
+#define TYPE_MPS3TZ_AN547_MACHINE MACHINE_TYPE_NAME("mps3-an547")
64
65
OBJECT_DECLARE_TYPE(MPS2TZMachineState, MPS2TZMachineClass, MPS2TZ_MACHINE)
66
67
@@ -XXX,XX +XXX,XX @@ static const RAMInfo an524_raminfo[] = { {
68
},
69
};
70
71
+static const RAMInfo an547_raminfo[] = { {
72
+ .name = "itcm",
73
+ .base = 0x00000000,
74
+ .size = 512 * KiB,
75
+ .mpc = -1,
76
+ .mrindex = 0,
77
+ }, {
78
+ .name = "sram",
79
+ .base = 0x01000000,
80
+ .size = 2 * MiB,
81
+ .mpc = 0,
82
+ .mrindex = 1,
83
+ }, {
84
+ .name = "dtcm",
85
+ .base = 0x20000000,
86
+ .size = 4 * 128 * KiB,
87
+ .mpc = -1,
88
+ .mrindex = 2,
89
+ }, {
90
+ .name = "sram 2",
91
+ .base = 0x21000000,
92
+ .size = 4 * MiB,
93
+ .mpc = -1,
94
+ .mrindex = 3,
95
+ }, {
96
+ /* We don't model QSPI flash yet; for now expose it as simple ROM */
97
+ .name = "QSPI",
98
+ .base = 0x28000000,
99
+ .size = 8 * MiB,
100
+ .mpc = 1,
101
+ .mrindex = 4,
102
+ .flags = IS_ROM,
103
+ }, {
104
+ .name = "DDR",
105
+ .base = 0x60000000,
106
+ .size = MPS3_DDR_SIZE,
107
+ .mpc = 2,
108
+ .mrindex = -1,
109
+ }, {
110
+ .name = NULL,
111
+ },
112
+};
113
+
114
static const RAMInfo *find_raminfo_for_mpc(MPS2TZMachineState *mms, int mpc)
115
{
116
MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
117
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
118
},
119
};
120
121
+ const PPCInfo an547_ppcs[] = { {
122
+ .name = "apb_ppcexp0",
123
+ .ports = {
124
+ { "ssram-mpc", make_mpc, &mms->mpc[0], 0x57000000, 0x1000 },
125
+ { "qspi-mpc", make_mpc, &mms->mpc[1], 0x57001000, 0x1000 },
126
+ { "ddr-mpc", make_mpc, &mms->mpc[2], 0x57002000, 0x1000 },
127
+ },
128
+ }, {
129
+ .name = "apb_ppcexp1",
130
+ .ports = {
131
+ { "i2c0", make_i2c, &mms->i2c[0], 0x49200000, 0x1000 },
132
+ { "i2c1", make_i2c, &mms->i2c[1], 0x49201000, 0x1000 },
133
+ { "spi0", make_spi, &mms->spi[0], 0x49202000, 0x1000, { 53 } },
134
+ { "spi1", make_spi, &mms->spi[1], 0x49203000, 0x1000, { 54 } },
135
+ { "spi2", make_spi, &mms->spi[2], 0x49204000, 0x1000, { 55 } },
136
+ { "i2c2", make_i2c, &mms->i2c[2], 0x49205000, 0x1000 },
137
+ { "i2c3", make_i2c, &mms->i2c[3], 0x49206000, 0x1000 },
138
+ { /* port 7 reserved */ },
139
+ { "i2c4", make_i2c, &mms->i2c[4], 0x49208000, 0x1000 },
140
+ },
141
+ }, {
142
+ .name = "apb_ppcexp2",
143
+ .ports = {
144
+ { "scc", make_scc, &mms->scc, 0x49300000, 0x1000 },
145
+ { "i2s-audio", make_unimp_dev, &mms->i2s_audio, 0x49301000, 0x1000 },
146
+ { "fpgaio", make_fpgaio, &mms->fpgaio, 0x49302000, 0x1000 },
147
+ { "uart0", make_uart, &mms->uart[0], 0x49303000, 0x1000, { 33, 34, 43 } },
148
+ { "uart1", make_uart, &mms->uart[1], 0x49304000, 0x1000, { 35, 36, 44 } },
149
+ { "uart2", make_uart, &mms->uart[2], 0x49305000, 0x1000, { 37, 38, 45 } },
150
+ { "uart3", make_uart, &mms->uart[3], 0x49306000, 0x1000, { 39, 40, 46 } },
151
+ { "uart4", make_uart, &mms->uart[4], 0x49307000, 0x1000, { 41, 42, 47 } },
152
+ { "uart5", make_uart, &mms->uart[5], 0x49308000, 0x1000, { 125, 126, 127 } },
153
+
154
+ { /* port 9 reserved */ },
155
+ { "clcd", make_unimp_dev, &mms->cldc, 0x4930a000, 0x1000 },
156
+ { "rtc", make_rtc, &mms->rtc, 0x4930b000, 0x1000 },
157
+ },
158
+ }, {
159
+ .name = "ahb_ppcexp0",
160
+ .ports = {
161
+ { "gpio0", make_unimp_dev, &mms->gpio[0], 0x41100000, 0x1000 },
162
+ { "gpio1", make_unimp_dev, &mms->gpio[1], 0x41101000, 0x1000 },
163
+ { "gpio2", make_unimp_dev, &mms->gpio[2], 0x41102000, 0x1000 },
164
+ { "gpio3", make_unimp_dev, &mms->gpio[3], 0x41103000, 0x1000 },
165
+ { "eth-usb", make_eth_usb, NULL, 0x41400000, 0x200000, { 49 } },
166
+ },
167
+ },
168
+ };
169
+
170
switch (mmc->fpga_type) {
171
case FPGA_AN505:
172
case FPGA_AN521:
173
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
174
ppcs = an524_ppcs;
175
num_ppcs = ARRAY_SIZE(an524_ppcs);
176
break;
177
+ case FPGA_AN547:
178
+ ppcs = an547_ppcs;
179
+ num_ppcs = ARRAY_SIZE(an547_ppcs);
180
+ break;
181
default:
182
g_assert_not_reached();
30
g_assert_not_reached();
183
}
31
}
184
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
32
185
33
+ iss_valid = !is_vector && !writeback;
186
create_unimplemented_device("FPGA NS PC", 0x48007000, 0x1000);
187
188
+ if (mmc->fpga_type == FPGA_AN547) {
189
+ create_unimplemented_device("U55 timing adapter 0", 0x48102000, 0x1000);
190
+ create_unimplemented_device("U55 timing adapter 1", 0x48103000, 0x1000);
191
+ }
192
+
34
+
193
create_non_mpc_ram(mms);
35
if (rn == 31) {
194
36
gen_check_sp_alignment(s);
195
armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename,
37
}
196
@@ -XXX,XX +XXX,XX @@ static void mps3tz_an524_class_init(ObjectClass *oc, void *data)
197
mps2tz_set_default_ram_info(mmc);
198
}
199
200
+static void mps3tz_an547_class_init(ObjectClass *oc, void *data)
201
+{
202
+ MachineClass *mc = MACHINE_CLASS(oc);
203
+ MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_CLASS(oc);
204
+
205
+ mc->desc = "ARM MPS3 with AN547 FPGA image for Cortex-M55";
206
+ mc->default_cpus = 1;
207
+ mc->min_cpus = mc->default_cpus;
208
+ mc->max_cpus = mc->default_cpus;
209
+ mmc->fpga_type = FPGA_AN547;
210
+ mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m55");
211
+ mmc->scc_id = 0x41055470;
212
+ mmc->sysclk_frq = 32 * 1000 * 1000; /* 32MHz */
213
+ mmc->apb_periph_frq = 25 * 1000 * 1000; /* 25MHz */
214
+ mmc->oscclk = an524_oscclk; /* same as AN524 */
215
+ mmc->len_oscclk = ARRAY_SIZE(an524_oscclk);
216
+ mmc->fpgaio_num_leds = 10;
217
+ mmc->fpgaio_has_switches = true;
218
+ mmc->fpgaio_has_dbgctrl = true;
219
+ mmc->numirq = 96;
220
+ mmc->uart_overflow_irq = 48;
221
+ mmc->init_svtor = 0x00000000;
222
+ mmc->raminfo = an547_raminfo;
223
+ mmc->armsse_type = TYPE_SSE300;
224
+ mps2tz_set_default_ram_info(mmc);
225
+}
226
+
227
static const TypeInfo mps2tz_info = {
228
.name = TYPE_MPS2TZ_MACHINE,
229
.parent = TYPE_MACHINE,
230
@@ -XXX,XX +XXX,XX @@ static const TypeInfo mps3tz_an524_info = {
231
.class_init = mps3tz_an524_class_init,
232
};
233
234
+static const TypeInfo mps3tz_an547_info = {
235
+ .name = TYPE_MPS3TZ_AN547_MACHINE,
236
+ .parent = TYPE_MPS2TZ_MACHINE,
237
+ .class_init = mps3tz_an547_class_init,
238
+};
239
+
240
static void mps2tz_machine_init(void)
241
{
242
type_register_static(&mps2tz_info);
243
type_register_static(&mps2tz_an505_info);
244
type_register_static(&mps2tz_an521_info);
245
type_register_static(&mps3tz_an524_info);
246
+ type_register_static(&mps3tz_an547_info);
247
}
248
249
type_init(mps2tz_machine_init);
250
--
38
--
251
2.20.1
39
2.25.1
252
253
diff view generated by jsdifflib
Deleted patch
1
Add brief documentation of the new mps3-an547 board.
2
1
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
5
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Message-id: 20210219144617.4782-44-peter.maydell@linaro.org
7
---
8
docs/system/arm/mps2.rst | 6 ++++--
9
1 file changed, 4 insertions(+), 2 deletions(-)
10
11
diff --git a/docs/system/arm/mps2.rst b/docs/system/arm/mps2.rst
12
index XXXXXXX..XXXXXXX 100644
13
--- a/docs/system/arm/mps2.rst
14
+++ b/docs/system/arm/mps2.rst
15
@@ -XXX,XX +XXX,XX @@
16
-Arm MPS2 and MPS3 boards (``mps2-an385``, ``mps2-an386``, ``mps2-an500``, ``mps2-an505``, ``mps2-an511``, ``mps2-an521``, ``mps3-an524``)
17
-=========================================================================================================================================
18
+Arm MPS2 and MPS3 boards (``mps2-an385``, ``mps2-an386``, ``mps2-an500``, ``mps2-an505``, ``mps2-an511``, ``mps2-an521``, ``mps3-an524``, ``mps3-an547``)
19
+=========================================================================================================================================================
20
21
These board models all use Arm M-profile CPUs.
22
23
@@ -XXX,XX +XXX,XX @@ QEMU models the following FPGA images:
24
Dual Cortex-M33 as documented in Arm Application Note AN521
25
``mps3-an524``
26
Dual Cortex-M33 on an MPS3, as documented in Arm Application Note AN524
27
+``mps3-an547``
28
+ Cortex-M55 on an MPS3, as documented in Arm Application Note AN547
29
30
Differences between QEMU and real hardware:
31
32
--
33
2.20.1
34
35
diff view generated by jsdifflib
1
Add a simple qtest to exercise the new system counter device in the
1
From: Andrey Makarov <ph.makarov@gmail.com>
2
SSE-300.
2
3
3
There is nothing in the specs on DMA engine interrupt lines: it should have
4
We'll add tests of the system timer device here too, so this includes
4
been in the "BCM2835 ARM Peripherals" datasheet but the appropriate
5
scaffolding (register definitions, etc) for those.
5
"ARM peripherals interrupt table" (p.113) is nearly empty.
6
6
7
All Raspberry Pi models 1-3 (based on bcm2835) have
8
Linux device tree (arch/arm/boot/dts/bcm2835-common.dtsi +25):
9
10
/* dma channel 11-14 share one irq */
11
12
This information is repeated in the driver code
13
(drivers/dma/bcm2835-dma.c +1344):
14
15
/*
16
* in case of channel >= 11
17
* use the 11th interrupt and that is shared
18
*/
19
20
In this patch channels 0--10 and 11--14 are handled separately.
21
22
Signed-off-by: Andrey Makarov <andrey.makarov@auriga.com>
23
Message-id: 20220716113210.349153-1-andrey.makarov@auriga.com
24
[PMM: fixed checkpatch nits]
25
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
26
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
Message-id: 20210219144617.4782-45-peter.maydell@linaro.org
11
---
27
---
12
tests/qtest/sse-timer-test.c | 117 +++++++++++++++++++++++++++++++++++
28
include/hw/arm/bcm2835_peripherals.h | 2 +
13
MAINTAINERS | 1 +
29
hw/arm/bcm2835_peripherals.c | 26 +++++-
14
tests/qtest/meson.build | 1 +
30
tests/qtest/bcm2835-dma-test.c | 118 +++++++++++++++++++++++++++
15
3 files changed, 119 insertions(+)
31
tests/qtest/meson.build | 3 +-
16
create mode 100644 tests/qtest/sse-timer-test.c
32
4 files changed, 147 insertions(+), 2 deletions(-)
17
33
create mode 100644 tests/qtest/bcm2835-dma-test.c
18
diff --git a/tests/qtest/sse-timer-test.c b/tests/qtest/sse-timer-test.c
34
35
diff --git a/include/hw/arm/bcm2835_peripherals.h b/include/hw/arm/bcm2835_peripherals.h
36
index XXXXXXX..XXXXXXX 100644
37
--- a/include/hw/arm/bcm2835_peripherals.h
38
+++ b/include/hw/arm/bcm2835_peripherals.h
39
@@ -XXX,XX +XXX,XX @@
40
#include "hw/char/bcm2835_aux.h"
41
#include "hw/display/bcm2835_fb.h"
42
#include "hw/dma/bcm2835_dma.h"
43
+#include "hw/or-irq.h"
44
#include "hw/intc/bcm2835_ic.h"
45
#include "hw/misc/bcm2835_property.h"
46
#include "hw/misc/bcm2835_rng.h"
47
@@ -XXX,XX +XXX,XX @@ struct BCM2835PeripheralState {
48
BCM2835AuxState aux;
49
BCM2835FBState fb;
50
BCM2835DMAState dma;
51
+ qemu_or_irq orgated_dma_irq;
52
BCM2835ICState ic;
53
BCM2835PropertyState property;
54
BCM2835RngState rng;
55
diff --git a/hw/arm/bcm2835_peripherals.c b/hw/arm/bcm2835_peripherals.c
56
index XXXXXXX..XXXXXXX 100644
57
--- a/hw/arm/bcm2835_peripherals.c
58
+++ b/hw/arm/bcm2835_peripherals.c
59
@@ -XXX,XX +XXX,XX @@
60
/* Capabilities for SD controller: no DMA, high-speed, default clocks etc. */
61
#define BCM2835_SDHC_CAPAREG 0x52134b4
62
63
+/*
64
+ * According to Linux driver & DTS, dma channels 0--10 have separate IRQ,
65
+ * while channels 11--14 share one IRQ:
66
+ */
67
+#define SEPARATE_DMA_IRQ_MAX 10
68
+#define ORGATED_DMA_IRQ_COUNT 4
69
+
70
static void create_unimp(BCM2835PeripheralState *ps,
71
UnimplementedDeviceState *uds,
72
const char *name, hwaddr ofs, hwaddr size)
73
@@ -XXX,XX +XXX,XX @@ static void bcm2835_peripherals_init(Object *obj)
74
/* DMA Channels */
75
object_initialize_child(obj, "dma", &s->dma, TYPE_BCM2835_DMA);
76
77
+ object_initialize_child(obj, "orgated-dma-irq",
78
+ &s->orgated_dma_irq, TYPE_OR_IRQ);
79
+ object_property_set_int(OBJECT(&s->orgated_dma_irq), "num-lines",
80
+ ORGATED_DMA_IRQ_COUNT, &error_abort);
81
+
82
object_property_add_const_link(OBJECT(&s->dma), "dma-mr",
83
OBJECT(&s->gpu_bus_mr));
84
85
@@ -XXX,XX +XXX,XX @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
86
memory_region_add_subregion(&s->peri_mr, DMA15_OFFSET,
87
sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->dma), 1));
88
89
- for (n = 0; n <= 12; n++) {
90
+ for (n = 0; n <= SEPARATE_DMA_IRQ_MAX; n++) {
91
sysbus_connect_irq(SYS_BUS_DEVICE(&s->dma), n,
92
qdev_get_gpio_in_named(DEVICE(&s->ic),
93
BCM2835_IC_GPU_IRQ,
94
INTERRUPT_DMA0 + n));
95
}
96
+ if (!qdev_realize(DEVICE(&s->orgated_dma_irq), NULL, errp)) {
97
+ return;
98
+ }
99
+ for (n = 0; n < ORGATED_DMA_IRQ_COUNT; n++) {
100
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->dma),
101
+ SEPARATE_DMA_IRQ_MAX + 1 + n,
102
+ qdev_get_gpio_in(DEVICE(&s->orgated_dma_irq), n));
103
+ }
104
+ qdev_connect_gpio_out(DEVICE(&s->orgated_dma_irq), 0,
105
+ qdev_get_gpio_in_named(DEVICE(&s->ic),
106
+ BCM2835_IC_GPU_IRQ,
107
+ INTERRUPT_DMA0 + SEPARATE_DMA_IRQ_MAX + 1));
108
109
/* THERMAL */
110
if (!sysbus_realize(SYS_BUS_DEVICE(&s->thermal), errp)) {
111
diff --git a/tests/qtest/bcm2835-dma-test.c b/tests/qtest/bcm2835-dma-test.c
19
new file mode 100644
112
new file mode 100644
20
index XXXXXXX..XXXXXXX
113
index XXXXXXX..XXXXXXX
21
--- /dev/null
114
--- /dev/null
22
+++ b/tests/qtest/sse-timer-test.c
115
+++ b/tests/qtest/bcm2835-dma-test.c
23
@@ -XXX,XX +XXX,XX @@
116
@@ -XXX,XX +XXX,XX @@
24
+/*
117
+/*
25
+ * QTest testcase for the SSE timer device
118
+ * QTest testcase for BCM283x DMA engine (on Raspberry Pi 3)
119
+ * and its interrupts coming to Interrupt Controller.
26
+ *
120
+ *
27
+ * Copyright (c) 2021 Linaro Limited
121
+ * Copyright (c) 2022 Auriga LLC
28
+ *
122
+ *
29
+ * This program is free software; you can redistribute it and/or modify it
123
+ * SPDX-License-Identifier: GPL-2.0-or-later
30
+ * under the terms of the GNU General Public License as published by the
31
+ * Free Software Foundation; either version 2 of the License, or
32
+ * (at your option) any later version.
33
+ *
34
+ * This program is distributed in the hope that it will be useful, but WITHOUT
35
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
36
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
37
+ * for more details.
38
+ */
124
+ */
39
+
125
+
40
+#include "qemu/osdep.h"
126
+#include "qemu/osdep.h"
41
+#include "libqtest-single.h"
127
+#include "libqtest-single.h"
42
+
128
+
43
+/*
129
+/* Offsets in raspi3b platform: */
44
+ * SSE-123/SSE-300 timer in the mps3-an547 board, where it is driven
130
+#define RASPI3_DMA_BASE 0x3f007000
45
+ * at 32MHz, so 31.25ns per tick.
131
+#define RASPI3_IC_BASE 0x3f00b200
46
+ */
132
+
47
+#define TIMER_BASE 0x48000000
133
+/* Used register/fields definitions */
48
+
134
+
49
+/* PERIPHNSPPC0 register in the SSE-300 Secure Access Configuration block */
135
+/* DMA engine registers: */
50
+#define PERIPHNSPPC0 (0x50080000 + 0x70)
136
+#define BCM2708_DMA_CS 0
51
+
137
+#define BCM2708_DMA_ACTIVE (1 << 0)
52
+/* Base of the System Counter control frame */
138
+#define BCM2708_DMA_INT (1 << 2)
53
+#define COUNTER_BASE 0x58100000
139
+
54
+
140
+#define BCM2708_DMA_ADDR 0x04
55
+/* SSE counter register offsets in the control frame */
141
+
56
+#define CNTCR 0
142
+#define BCM2708_DMA_INT_STATUS 0xfe0
57
+#define CNTSR 0x4
143
+
58
+#define CNTCV_LO 0x8
144
+/* DMA Trasfer Info fields: */
59
+#define CNTCV_HI 0xc
145
+#define BCM2708_DMA_INT_EN (1 << 0)
60
+#define CNTSCR 0x10
146
+#define BCM2708_DMA_D_INC (1 << 4)
61
+
147
+#define BCM2708_DMA_S_INC (1 << 8)
62
+/* SSE timer register offsets */
148
+
63
+#define CNTPCT_LO 0
149
+/* Interrupt controller registers: */
64
+#define CNTPCT_HI 4
150
+#define IRQ_PENDING_BASIC 0x00
65
+#define CNTFRQ 0x10
151
+#define IRQ_GPU_PENDING1_AGGR (1 << 8)
66
+#define CNTP_CVAL_LO 0x20
152
+#define IRQ_PENDING_1 0x04
67
+#define CNTP_CVAL_HI 0x24
153
+#define IRQ_ENABLE_1 0x10
68
+#define CNTP_TVAL 0x28
154
+
69
+#define CNTP_CTL 0x2c
155
+/* Data for the test: */
70
+#define CNTP_AIVAL_LO 0x40
156
+#define SCB_ADDR 256
71
+#define CNTP_AIVAL_HI 0x44
157
+#define S_ADDR 32
72
+#define CNTP_AIVAL_RELOAD 0x48
158
+#define D_ADDR 64
73
+#define CNTP_AIVAL_CTL 0x4c
159
+#define TXFR_LEN 32
74
+
160
+const uint32_t check_data = 0x12345678;
75
+/* 4 ticks in nanoseconds (so we can work in integers) */
161
+
76
+#define FOUR_TICKS 125
162
+static void bcm2835_dma_test_interrupt(int dma_c, int irq_line)
77
+
78
+static void clock_step_ticks(uint64_t ticks)
79
+{
163
+{
80
+ /*
164
+ uint64_t dma_base = RASPI3_DMA_BASE + dma_c * 0x100;
81
+ * Advance the qtest clock by however many nanoseconds we
165
+ int gpu_irq_line = 16 + irq_line;
82
+ * need to move the timer forward the specified number of ticks.
166
+
83
+ * ticks must be a multiple of 4, so we get a whole number of ns.
167
+ /* Check that interrupts are silent by default: */
84
+ */
168
+ writel(RASPI3_IC_BASE + IRQ_ENABLE_1, 1 << gpu_irq_line);
85
+ assert(!(ticks & 3));
169
+ int isr = readl(dma_base + BCM2708_DMA_INT_STATUS);
86
+ clock_step(FOUR_TICKS * (ticks >> 2));
170
+ g_assert_cmpint(isr, ==, 0);
171
+ uint32_t reg0 = readl(dma_base + BCM2708_DMA_CS);
172
+ g_assert_cmpint(reg0, ==, 0);
173
+ uint32_t ic_pending = readl(RASPI3_IC_BASE + IRQ_PENDING_BASIC);
174
+ g_assert_cmpint(ic_pending, ==, 0);
175
+ uint32_t gpu_pending1 = readl(RASPI3_IC_BASE + IRQ_PENDING_1);
176
+ g_assert_cmpint(gpu_pending1, ==, 0);
177
+
178
+ /* Prepare Control Block: */
179
+ writel(SCB_ADDR + 0, BCM2708_DMA_S_INC | BCM2708_DMA_D_INC |
180
+ BCM2708_DMA_INT_EN); /* transfer info */
181
+ writel(SCB_ADDR + 4, S_ADDR); /* source address */
182
+ writel(SCB_ADDR + 8, D_ADDR); /* destination address */
183
+ writel(SCB_ADDR + 12, TXFR_LEN); /* transfer length */
184
+ writel(dma_base + BCM2708_DMA_ADDR, SCB_ADDR);
185
+
186
+ writel(S_ADDR, check_data);
187
+ for (int word = S_ADDR + 4; word < S_ADDR + TXFR_LEN; word += 4) {
188
+ writel(word, ~check_data);
189
+ }
190
+ /* Perform the transfer: */
191
+ writel(dma_base + BCM2708_DMA_CS, BCM2708_DMA_ACTIVE);
192
+
193
+ /* Check that destination == source: */
194
+ uint32_t data = readl(D_ADDR);
195
+ g_assert_cmpint(data, ==, check_data);
196
+ for (int word = D_ADDR + 4; word < D_ADDR + TXFR_LEN; word += 4) {
197
+ data = readl(word);
198
+ g_assert_cmpint(data, ==, ~check_data);
199
+ }
200
+
201
+ /* Check that interrupt status is set both in DMA and IC controllers: */
202
+ isr = readl(RASPI3_DMA_BASE + BCM2708_DMA_INT_STATUS);
203
+ g_assert_cmpint(isr, ==, 1 << dma_c);
204
+
205
+ ic_pending = readl(RASPI3_IC_BASE + IRQ_PENDING_BASIC);
206
+ g_assert_cmpint(ic_pending, ==, IRQ_GPU_PENDING1_AGGR);
207
+
208
+ gpu_pending1 = readl(RASPI3_IC_BASE + IRQ_PENDING_1);
209
+ g_assert_cmpint(gpu_pending1, ==, 1 << gpu_irq_line);
210
+
211
+ /* Clean up, clear interrupt: */
212
+ writel(dma_base + BCM2708_DMA_CS, BCM2708_DMA_INT);
87
+}
213
+}
88
+
214
+
89
+static void reset_counter_and_timer(void)
215
+static void bcm2835_dma_test_interrupts(void)
90
+{
216
+{
91
+ /*
217
+ /* DMA engines 0--10 have separate IRQ lines, 11--14 - only one: */
92
+ * Reset the system counter and the timer between tests. This
218
+ bcm2835_dma_test_interrupt(0, 0);
93
+ * isn't a full reset, but it's sufficient for what the tests check.
219
+ bcm2835_dma_test_interrupt(10, 10);
94
+ */
220
+ bcm2835_dma_test_interrupt(11, 11);
95
+ writel(COUNTER_BASE + CNTCR, 0);
221
+ bcm2835_dma_test_interrupt(14, 11);
96
+ writel(TIMER_BASE + CNTP_CTL, 0);
97
+ writel(TIMER_BASE + CNTP_AIVAL_CTL, 0);
98
+ writel(COUNTER_BASE + CNTCV_LO, 0);
99
+ writel(COUNTER_BASE + CNTCV_HI, 0);
100
+}
101
+
102
+static void test_counter(void)
103
+{
104
+ /* Basic counter functionality test */
105
+
106
+ reset_counter_and_timer();
107
+ /* The counter should start disabled: check that it doesn't move */
108
+ clock_step_ticks(100);
109
+ g_assert_cmpuint(readl(COUNTER_BASE + CNTCV_LO), ==, 0);
110
+ g_assert_cmpuint(readl(COUNTER_BASE + CNTCV_HI), ==, 0);
111
+ /* Now enable it and check that it does count */
112
+ writel(COUNTER_BASE + CNTCR, 1);
113
+ clock_step_ticks(100);
114
+ g_assert_cmpuint(readl(COUNTER_BASE + CNTCV_LO), ==, 100);
115
+ g_assert_cmpuint(readl(COUNTER_BASE + CNTCV_HI), ==, 0);
116
+ /* Check the counter scaling functionality */
117
+ writel(COUNTER_BASE + CNTCR, 0);
118
+ writel(COUNTER_BASE + CNTSCR, 0x00100000); /* 1/16th normal speed */
119
+ writel(COUNTER_BASE + CNTCR, 5); /* EN, SCEN */
120
+ clock_step_ticks(160);
121
+ g_assert_cmpuint(readl(COUNTER_BASE + CNTCV_LO), ==, 110);
122
+ g_assert_cmpuint(readl(COUNTER_BASE + CNTCV_HI), ==, 0);
123
+}
222
+}
124
+
223
+
125
+int main(int argc, char **argv)
224
+int main(int argc, char **argv)
126
+{
225
+{
127
+ int r;
226
+ int ret;
128
+
129
+ g_test_init(&argc, &argv, NULL);
227
+ g_test_init(&argc, &argv, NULL);
130
+
228
+ qtest_add_func("/bcm2835/dma/test_interrupts",
131
+ qtest_start("-machine mps3-an547");
229
+ bcm2835_dma_test_interrupts);
132
+
230
+ qtest_start("-machine raspi3b");
133
+ qtest_add_func("/sse-timer/counter", test_counter);
231
+ ret = g_test_run();
134
+
135
+ r = g_test_run();
136
+
137
+ qtest_end();
232
+ qtest_end();
138
+
233
+ return ret;
139
+ return r;
140
+}
234
+}
141
diff --git a/MAINTAINERS b/MAINTAINERS
142
index XXXXXXX..XXXXXXX 100644
143
--- a/MAINTAINERS
144
+++ b/MAINTAINERS
145
@@ -XXX,XX +XXX,XX @@ F: hw/timer/sse-counter.c
146
F: include/hw/timer/sse-counter.h
147
F: hw/timer/sse-timer.c
148
F: include/hw/timer/sse-timer.h
149
+F: tests/qtest/sse-timer-test.c
150
F: docs/system/arm/mps2.rst
151
152
Musca
153
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
235
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
154
index XXXXXXX..XXXXXXX 100644
236
index XXXXXXX..XXXXXXX 100644
155
--- a/tests/qtest/meson.build
237
--- a/tests/qtest/meson.build
156
+++ b/tests/qtest/meson.build
238
+++ b/tests/qtest/meson.build
157
@@ -XXX,XX +XXX,XX @@ qtests_npcm7xx = \
239
@@ -XXX,XX +XXX,XX @@ qtests_aarch64 = \
158
'npcm7xx_watchdog_timer-test'] + \
240
['arm-cpu-features',
159
(slirp.found() ? ['npcm7xx_emc-test'] : [])
241
'numa-test',
160
qtests_arm = \
242
'boot-serial-test',
161
+ (config_all_devices.has_key('CONFIG_MPS2') ? ['sse-timer-test'] : []) + \
243
- 'migration-test']
162
(config_all_devices.has_key('CONFIG_CMSDK_APB_DUALTIMER') ? ['cmsdk-apb-dualtimer-test'] : []) + \
244
+ 'migration-test',
163
(config_all_devices.has_key('CONFIG_CMSDK_APB_TIMER') ? ['cmsdk-apb-timer-test'] : []) + \
245
+ 'bcm2835-dma-test']
164
(config_all_devices.has_key('CONFIG_CMSDK_APB_WATCHDOG') ? ['cmsdk-apb-watchdog-test'] : []) + \
246
247
qtests_s390x = \
248
(slirp.found() ? ['pxe-test', 'test-netfilter'] : []) + \
165
--
249
--
166
2.20.1
250
2.25.1
167
168
diff view generated by jsdifflib
Deleted patch
1
From: Xuzhou Cheng <xuzhou.cheng@windriver.com>
2
1
3
ZynqMP QSPI supports SPI transfer using DMA mode, but currently this
4
is unimplemented. When QSPI is programmed to use DMA mode, QEMU will
5
crash. This is observed when testing VxWorks 7.
6
7
This adds a Xilinx CSU DMA model and the implementation is based on
8
https://github.com/Xilinx/qemu/blob/master/hw/dma/csu_stream_dma.c.
9
The DST part of the model is verified along with ZynqMP GQSPI model.
10
11
Signed-off-by: Xuzhou Cheng <xuzhou.cheng@windriver.com>
12
Signed-off-by: Bin Meng <bin.meng@windriver.com>
13
Tested-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
14
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
15
Message-id: 20210303135254.3970-2-bmeng.cn@gmail.com
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
---
18
include/hw/dma/xlnx_csu_dma.h | 52 +++
19
hw/dma/xlnx_csu_dma.c | 745 ++++++++++++++++++++++++++++++++++
20
hw/dma/Kconfig | 4 +
21
hw/dma/meson.build | 1 +
22
4 files changed, 802 insertions(+)
23
create mode 100644 include/hw/dma/xlnx_csu_dma.h
24
create mode 100644 hw/dma/xlnx_csu_dma.c
25
26
diff --git a/include/hw/dma/xlnx_csu_dma.h b/include/hw/dma/xlnx_csu_dma.h
27
new file mode 100644
28
index XXXXXXX..XXXXXXX
29
--- /dev/null
30
+++ b/include/hw/dma/xlnx_csu_dma.h
31
@@ -XXX,XX +XXX,XX @@
32
+/*
33
+ * Xilinx Platform CSU Stream DMA emulation
34
+ *
35
+ * This implementation is based on
36
+ * https://github.com/Xilinx/qemu/blob/master/hw/dma/csu_stream_dma.c
37
+ *
38
+ * This program is free software; you can redistribute it and/or
39
+ * modify it under the terms of the GNU General Public License as
40
+ * published by the Free Software Foundation; either version 2 or
41
+ * (at your option) version 3 of the License.
42
+ *
43
+ * This program is distributed in the hope that it will be useful,
44
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
45
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
46
+ * GNU General Public License for more details.
47
+ *
48
+ * You should have received a copy of the GNU General Public License along
49
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
50
+ */
51
+
52
+#ifndef XLNX_CSU_DMA_H
53
+#define XLNX_CSU_DMA_H
54
+
55
+#define TYPE_XLNX_CSU_DMA "xlnx.csu_dma"
56
+
57
+#define XLNX_CSU_DMA_R_MAX (0x2c / 4)
58
+
59
+typedef struct XlnxCSUDMA {
60
+ SysBusDevice busdev;
61
+ MemoryRegion iomem;
62
+ MemTxAttrs attr;
63
+ MemoryRegion *dma_mr;
64
+ AddressSpace *dma_as;
65
+ qemu_irq irq;
66
+ StreamSink *tx_dev; /* Used as generic StreamSink */
67
+ ptimer_state *src_timer;
68
+
69
+ uint16_t width;
70
+ bool is_dst;
71
+ bool r_size_last_word;
72
+
73
+ StreamCanPushNotifyFn notify;
74
+ void *notify_opaque;
75
+
76
+ uint32_t regs[XLNX_CSU_DMA_R_MAX];
77
+ RegisterInfo regs_info[XLNX_CSU_DMA_R_MAX];
78
+} XlnxCSUDMA;
79
+
80
+#define XLNX_CSU_DMA(obj) \
81
+ OBJECT_CHECK(XlnxCSUDMA, (obj), TYPE_XLNX_CSU_DMA)
82
+
83
+#endif
84
diff --git a/hw/dma/xlnx_csu_dma.c b/hw/dma/xlnx_csu_dma.c
85
new file mode 100644
86
index XXXXXXX..XXXXXXX
87
--- /dev/null
88
+++ b/hw/dma/xlnx_csu_dma.c
89
@@ -XXX,XX +XXX,XX @@
90
+/*
91
+ * Xilinx Platform CSU Stream DMA emulation
92
+ *
93
+ * This implementation is based on
94
+ * https://github.com/Xilinx/qemu/blob/master/hw/dma/csu_stream_dma.c
95
+ *
96
+ * This program is free software; you can redistribute it and/or
97
+ * modify it under the terms of the GNU General Public License as
98
+ * published by the Free Software Foundation; either version 2 or
99
+ * (at your option) version 3 of the License.
100
+ *
101
+ * This program is distributed in the hope that it will be useful,
102
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
103
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
104
+ * GNU General Public License for more details.
105
+ *
106
+ * You should have received a copy of the GNU General Public License along
107
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
108
+ */
109
+
110
+#include "qemu/osdep.h"
111
+#include "qemu/log.h"
112
+#include "qapi/error.h"
113
+#include "hw/hw.h"
114
+#include "hw/irq.h"
115
+#include "hw/qdev-properties.h"
116
+#include "hw/sysbus.h"
117
+#include "migration/vmstate.h"
118
+#include "sysemu/dma.h"
119
+#include "hw/ptimer.h"
120
+#include "hw/stream.h"
121
+#include "hw/register.h"
122
+#include "hw/dma/xlnx_csu_dma.h"
123
+
124
+/*
125
+ * Ref: UG1087 (v1.7) February 8, 2019
126
+ * https://www.xilinx.com/html_docs/registers/ug1087/ug1087-zynq-ultrascale-registers.html
127
+ * CSUDMA Module section
128
+ */
129
+REG32(ADDR, 0x0)
130
+ FIELD(ADDR, ADDR, 2, 30) /* wo */
131
+REG32(SIZE, 0x4)
132
+ FIELD(SIZE, SIZE, 2, 27) /* wo */
133
+ FIELD(SIZE, LAST_WORD, 0, 1) /* rw, only exists in SRC */
134
+REG32(STATUS, 0x8)
135
+ FIELD(STATUS, DONE_CNT, 13, 3) /* wtc */
136
+ FIELD(STATUS, FIFO_LEVEL, 5, 8) /* ro */
137
+ FIELD(STATUS, OUTSTANDING, 1, 4) /* ro */
138
+ FIELD(STATUS, BUSY, 0, 1) /* ro */
139
+REG32(CTRL, 0xc)
140
+ FIELD(CTRL, FIFOTHRESH, 25, 7) /* rw, only exists in DST, reset 0x40 */
141
+ FIELD(CTRL, APB_ERR_RESP, 24, 1) /* rw */
142
+ FIELD(CTRL, ENDIANNESS, 23, 1) /* rw */
143
+ FIELD(CTRL, AXI_BRST_TYPE, 22, 1) /* rw */
144
+ FIELD(CTRL, TIMEOUT_VAL, 10, 12) /* rw, reset: 0xFFE */
145
+ FIELD(CTRL, FIFO_THRESH, 2, 8) /* rw, reset: 0x80 */
146
+ FIELD(CTRL, PAUSE_STRM, 1, 1) /* rw */
147
+ FIELD(CTRL, PAUSE_MEM, 0, 1) /* rw */
148
+REG32(CRC, 0x10)
149
+REG32(INT_STATUS, 0x14)
150
+ FIELD(INT_STATUS, FIFO_OVERFLOW, 7, 1) /* wtc */
151
+ FIELD(INT_STATUS, INVALID_APB, 6, 1) /* wtc */
152
+ FIELD(INT_STATUS, THRESH_HIT, 5, 1) /* wtc */
153
+ FIELD(INT_STATUS, TIMEOUT_MEM, 4, 1) /* wtc */
154
+ FIELD(INT_STATUS, TIMEOUT_STRM, 3, 1) /* wtc */
155
+ FIELD(INT_STATUS, AXI_BRESP_ERR, 2, 1) /* wtc, SRC: AXI_RDERR */
156
+ FIELD(INT_STATUS, DONE, 1, 1) /* wtc */
157
+ FIELD(INT_STATUS, MEM_DONE, 0, 1) /* wtc */
158
+REG32(INT_ENABLE, 0x18)
159
+ FIELD(INT_ENABLE, FIFO_OVERFLOW, 7, 1) /* wtc */
160
+ FIELD(INT_ENABLE, INVALID_APB, 6, 1) /* wtc */
161
+ FIELD(INT_ENABLE, THRESH_HIT, 5, 1) /* wtc */
162
+ FIELD(INT_ENABLE, TIMEOUT_MEM, 4, 1) /* wtc */
163
+ FIELD(INT_ENABLE, TIMEOUT_STRM, 3, 1) /* wtc */
164
+ FIELD(INT_ENABLE, AXI_BRESP_ERR, 2, 1) /* wtc, SRC: AXI_RDERR */
165
+ FIELD(INT_ENABLE, DONE, 1, 1) /* wtc */
166
+ FIELD(INT_ENABLE, MEM_DONE, 0, 1) /* wtc */
167
+REG32(INT_DISABLE, 0x1c)
168
+ FIELD(INT_DISABLE, FIFO_OVERFLOW, 7, 1) /* wtc */
169
+ FIELD(INT_DISABLE, INVALID_APB, 6, 1) /* wtc */
170
+ FIELD(INT_DISABLE, THRESH_HIT, 5, 1) /* wtc */
171
+ FIELD(INT_DISABLE, TIMEOUT_MEM, 4, 1) /* wtc */
172
+ FIELD(INT_DISABLE, TIMEOUT_STRM, 3, 1) /* wtc */
173
+ FIELD(INT_DISABLE, AXI_BRESP_ERR, 2, 1) /* wtc, SRC: AXI_RDERR */
174
+ FIELD(INT_DISABLE, DONE, 1, 1) /* wtc */
175
+ FIELD(INT_DISABLE, MEM_DONE, 0, 1) /* wtc */
176
+REG32(INT_MASK, 0x20)
177
+ FIELD(INT_MASK, FIFO_OVERFLOW, 7, 1) /* ro, reset: 0x1 */
178
+ FIELD(INT_MASK, INVALID_APB, 6, 1) /* ro, reset: 0x1 */
179
+ FIELD(INT_MASK, THRESH_HIT, 5, 1) /* ro, reset: 0x1 */
180
+ FIELD(INT_MASK, TIMEOUT_MEM, 4, 1) /* ro, reset: 0x1 */
181
+ FIELD(INT_MASK, TIMEOUT_STRM, 3, 1) /* ro, reset: 0x1 */
182
+ FIELD(INT_MASK, AXI_BRESP_ERR, 2, 1) /* ro, reset: 0x1, SRC: AXI_RDERR */
183
+ FIELD(INT_MASK, DONE, 1, 1) /* ro, reset: 0x1 */
184
+ FIELD(INT_MASK, MEM_DONE, 0, 1) /* ro, reset: 0x1 */
185
+REG32(CTRL2, 0x24)
186
+ FIELD(CTRL2, ARCACHE, 24, 3) /* rw */
187
+ FIELD(CTRL2, ROUTE_BIT, 23, 1) /* rw */
188
+ FIELD(CTRL2, TIMEOUT_EN, 22, 1) /* rw */
189
+ FIELD(CTRL2, TIMEOUT_PRE, 4, 12) /* rw, reset: 0xFFF */
190
+ FIELD(CTRL2, MAX_OUTS_CMDS, 0, 4) /* rw, reset: 0x8 */
191
+REG32(ADDR_MSB, 0x28)
192
+ FIELD(ADDR_MSB, ADDR_MSB, 0, 17) /* wo */
193
+
194
+#define R_CTRL_TIMEOUT_VAL_RESET (0xFFE)
195
+#define R_CTRL_FIFO_THRESH_RESET (0x80)
196
+#define R_CTRL_FIFOTHRESH_RESET (0x40)
197
+
198
+#define R_CTRL2_TIMEOUT_PRE_RESET (0xFFF)
199
+#define R_CTRL2_MAX_OUTS_CMDS_RESET (0x8)
200
+
201
+#define XLNX_CSU_DMA_ERR_DEBUG (0)
202
+#define XLNX_CSU_DMA_INT_R_MASK (0xff)
203
+
204
+/* UG1807: Set the prescaler value for the timeout in clk (~2.5ns) cycles */
205
+#define XLNX_CSU_DMA_TIMER_FREQ (400 * 1000 * 1000)
206
+
207
+static bool xlnx_csu_dma_is_paused(XlnxCSUDMA *s)
208
+{
209
+ bool paused;
210
+
211
+ paused = !!(s->regs[R_CTRL] & R_CTRL_PAUSE_STRM_MASK);
212
+ paused |= !!(s->regs[R_CTRL] & R_CTRL_PAUSE_MEM_MASK);
213
+
214
+ return paused;
215
+}
216
+
217
+static bool xlnx_csu_dma_get_eop(XlnxCSUDMA *s)
218
+{
219
+ return s->r_size_last_word;
220
+}
221
+
222
+static bool xlnx_csu_dma_burst_is_fixed(XlnxCSUDMA *s)
223
+{
224
+ return !!(s->regs[R_CTRL] & R_CTRL_AXI_BRST_TYPE_MASK);
225
+}
226
+
227
+static bool xlnx_csu_dma_timeout_enabled(XlnxCSUDMA *s)
228
+{
229
+ return !!(s->regs[R_CTRL2] & R_CTRL2_TIMEOUT_EN_MASK);
230
+}
231
+
232
+static void xlnx_csu_dma_update_done_cnt(XlnxCSUDMA *s, int a)
233
+{
234
+ int cnt;
235
+
236
+ /* Increase DONE_CNT */
237
+ cnt = ARRAY_FIELD_EX32(s->regs, STATUS, DONE_CNT) + a;
238
+ ARRAY_FIELD_DP32(s->regs, STATUS, DONE_CNT, cnt);
239
+}
240
+
241
+static void xlnx_csu_dma_data_process(XlnxCSUDMA *s, uint8_t *buf, uint32_t len)
242
+{
243
+ uint32_t bswap;
244
+ uint32_t i;
245
+
246
+ bswap = s->regs[R_CTRL] & R_CTRL_ENDIANNESS_MASK;
247
+ if (s->is_dst && !bswap) {
248
+ /* Fast when ENDIANNESS cleared */
249
+ return;
250
+ }
251
+
252
+ for (i = 0; i < len; i += 4) {
253
+ uint8_t *b = &buf[i];
254
+ union {
255
+ uint8_t u8[4];
256
+ uint32_t u32;
257
+ } v = {
258
+ .u8 = { b[0], b[1], b[2], b[3] }
259
+ };
260
+
261
+ if (!s->is_dst) {
262
+ s->regs[R_CRC] += v.u32;
263
+ }
264
+ if (bswap) {
265
+ /*
266
+ * No point using bswap, we need to writeback
267
+ * into a potentially unaligned pointer.
268
+ */
269
+ b[0] = v.u8[3];
270
+ b[1] = v.u8[2];
271
+ b[2] = v.u8[1];
272
+ b[3] = v.u8[0];
273
+ }
274
+ }
275
+}
276
+
277
+static void xlnx_csu_dma_update_irq(XlnxCSUDMA *s)
278
+{
279
+ qemu_set_irq(s->irq, !!(s->regs[R_INT_STATUS] & ~s->regs[R_INT_MASK]));
280
+}
281
+
282
+/* len is in bytes */
283
+static uint32_t xlnx_csu_dma_read(XlnxCSUDMA *s, uint8_t *buf, uint32_t len)
284
+{
285
+ hwaddr addr = (hwaddr)s->regs[R_ADDR_MSB] << 32 | s->regs[R_ADDR];
286
+ MemTxResult result = MEMTX_OK;
287
+
288
+ if (xlnx_csu_dma_burst_is_fixed(s)) {
289
+ uint32_t i;
290
+
291
+ for (i = 0; i < len && (result == MEMTX_OK); i += s->width) {
292
+ uint32_t mlen = MIN(len - i, s->width);
293
+
294
+ result = address_space_rw(s->dma_as, addr, s->attr,
295
+ buf + i, mlen, false);
296
+ }
297
+ } else {
298
+ result = address_space_rw(s->dma_as, addr, s->attr, buf, len, false);
299
+ }
300
+
301
+ if (result == MEMTX_OK) {
302
+ xlnx_csu_dma_data_process(s, buf, len);
303
+ } else {
304
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad address 0x%lx for mem read",
305
+ __func__, addr);
306
+ s->regs[R_INT_STATUS] |= R_INT_STATUS_AXI_BRESP_ERR_MASK;
307
+ xlnx_csu_dma_update_irq(s);
308
+ }
309
+ return len;
310
+}
311
+
312
+/* len is in bytes */
313
+static uint32_t xlnx_csu_dma_write(XlnxCSUDMA *s, uint8_t *buf, uint32_t len)
314
+{
315
+ hwaddr addr = (hwaddr)s->regs[R_ADDR_MSB] << 32 | s->regs[R_ADDR];
316
+ MemTxResult result = MEMTX_OK;
317
+
318
+ xlnx_csu_dma_data_process(s, buf, len);
319
+ if (xlnx_csu_dma_burst_is_fixed(s)) {
320
+ uint32_t i;
321
+
322
+ for (i = 0; i < len && (result == MEMTX_OK); i += s->width) {
323
+ uint32_t mlen = MIN(len - i, s->width);
324
+
325
+ result = address_space_rw(s->dma_as, addr, s->attr,
326
+ buf, mlen, true);
327
+ buf += mlen;
328
+ }
329
+ } else {
330
+ result = address_space_rw(s->dma_as, addr, s->attr, buf, len, true);
331
+ }
332
+
333
+ if (result != MEMTX_OK) {
334
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad address 0x%lx for mem write",
335
+ __func__, addr);
336
+ s->regs[R_INT_STATUS] |= R_INT_STATUS_AXI_BRESP_ERR_MASK;
337
+ xlnx_csu_dma_update_irq(s);
338
+ }
339
+ return len;
340
+}
341
+
342
+static void xlnx_csu_dma_done(XlnxCSUDMA *s)
343
+{
344
+ s->regs[R_STATUS] &= ~R_STATUS_BUSY_MASK;
345
+ s->regs[R_INT_STATUS] |= R_INT_STATUS_DONE_MASK;
346
+
347
+ if (!s->is_dst) {
348
+ s->regs[R_INT_STATUS] |= R_INT_STATUS_MEM_DONE_MASK;
349
+ }
350
+
351
+ xlnx_csu_dma_update_done_cnt(s, 1);
352
+}
353
+
354
+static uint32_t xlnx_csu_dma_advance(XlnxCSUDMA *s, uint32_t len)
355
+{
356
+ uint32_t size = s->regs[R_SIZE];
357
+ hwaddr dst = (hwaddr)s->regs[R_ADDR_MSB] << 32 | s->regs[R_ADDR];
358
+
359
+ assert(len <= size);
360
+
361
+ size -= len;
362
+ s->regs[R_SIZE] = size;
363
+
364
+ if (!xlnx_csu_dma_burst_is_fixed(s)) {
365
+ dst += len;
366
+ s->regs[R_ADDR] = (uint32_t) dst;
367
+ s->regs[R_ADDR_MSB] = dst >> 32;
368
+ }
369
+
370
+ if (size == 0) {
371
+ xlnx_csu_dma_done(s);
372
+ }
373
+
374
+ return size;
375
+}
376
+
377
+static void xlnx_csu_dma_src_notify(void *opaque)
378
+{
379
+ XlnxCSUDMA *s = XLNX_CSU_DMA(opaque);
380
+ unsigned char buf[4 * 1024];
381
+ size_t rlen = 0;
382
+
383
+ ptimer_transaction_begin(s->src_timer);
384
+ /* Stop the backpreassure timer */
385
+ ptimer_stop(s->src_timer);
386
+
387
+ while (s->regs[R_SIZE] && !xlnx_csu_dma_is_paused(s) &&
388
+ stream_can_push(s->tx_dev, xlnx_csu_dma_src_notify, s)) {
389
+ uint32_t plen = MIN(s->regs[R_SIZE], sizeof buf);
390
+ bool eop = false;
391
+
392
+ /* Did we fit it all? */
393
+ if (s->regs[R_SIZE] == plen && xlnx_csu_dma_get_eop(s)) {
394
+ eop = true;
395
+ }
396
+
397
+ /* DMA transfer */
398
+ xlnx_csu_dma_read(s, buf, plen);
399
+ rlen = stream_push(s->tx_dev, buf, plen, eop);
400
+ xlnx_csu_dma_advance(s, rlen);
401
+ }
402
+
403
+ if (xlnx_csu_dma_timeout_enabled(s) && s->regs[R_SIZE] &&
404
+ !stream_can_push(s->tx_dev, xlnx_csu_dma_src_notify, s)) {
405
+ uint32_t timeout = ARRAY_FIELD_EX32(s->regs, CTRL, TIMEOUT_VAL);
406
+ uint32_t div = ARRAY_FIELD_EX32(s->regs, CTRL2, TIMEOUT_PRE) + 1;
407
+ uint32_t freq = XLNX_CSU_DMA_TIMER_FREQ;
408
+
409
+ freq /= div;
410
+ ptimer_set_freq(s->src_timer, freq);
411
+ ptimer_set_count(s->src_timer, timeout);
412
+ ptimer_run(s->src_timer, 1);
413
+ }
414
+
415
+ ptimer_transaction_commit(s->src_timer);
416
+ xlnx_csu_dma_update_irq(s);
417
+}
418
+
419
+static uint64_t addr_pre_write(RegisterInfo *reg, uint64_t val)
420
+{
421
+ /* Address is word aligned */
422
+ return val & R_ADDR_ADDR_MASK;
423
+}
424
+
425
+static uint64_t size_pre_write(RegisterInfo *reg, uint64_t val)
426
+{
427
+ XlnxCSUDMA *s = XLNX_CSU_DMA(reg->opaque);
428
+
429
+ if (s->regs[R_SIZE] != 0) {
430
+ qemu_log_mask(LOG_GUEST_ERROR,
431
+ "%s: Starting DMA while already running.\n", __func__);
432
+ }
433
+
434
+ if (!s->is_dst) {
435
+ s->r_size_last_word = !!(val & R_SIZE_LAST_WORD_MASK);
436
+ }
437
+
438
+ /* Size is word aligned */
439
+ return val & R_SIZE_SIZE_MASK;
440
+}
441
+
442
+static uint64_t size_post_read(RegisterInfo *reg, uint64_t val)
443
+{
444
+ XlnxCSUDMA *s = XLNX_CSU_DMA(reg->opaque);
445
+
446
+ return val | s->r_size_last_word;
447
+}
448
+
449
+static void size_post_write(RegisterInfo *reg, uint64_t val)
450
+{
451
+ XlnxCSUDMA *s = XLNX_CSU_DMA(reg->opaque);
452
+
453
+ s->regs[R_STATUS] |= R_STATUS_BUSY_MASK;
454
+
455
+ /*
456
+ * Note that if SIZE is programmed to 0, and the DMA is started,
457
+ * the interrupts DONE and MEM_DONE will be asserted.
458
+ */
459
+ if (s->regs[R_SIZE] == 0) {
460
+ xlnx_csu_dma_done(s);
461
+ xlnx_csu_dma_update_irq(s);
462
+ return;
463
+ }
464
+
465
+ /* Set SIZE is considered the last step in transfer configuration */
466
+ if (!s->is_dst) {
467
+ xlnx_csu_dma_src_notify(s);
468
+ } else {
469
+ if (s->notify) {
470
+ s->notify(s->notify_opaque);
471
+ }
472
+ }
473
+}
474
+
475
+static uint64_t status_pre_write(RegisterInfo *reg, uint64_t val)
476
+{
477
+ return val & (R_STATUS_DONE_CNT_MASK | R_STATUS_BUSY_MASK);
478
+}
479
+
480
+static void ctrl_post_write(RegisterInfo *reg, uint64_t val)
481
+{
482
+ XlnxCSUDMA *s = XLNX_CSU_DMA(reg->opaque);
483
+
484
+ if (!s->is_dst) {
485
+ if (!xlnx_csu_dma_is_paused(s)) {
486
+ xlnx_csu_dma_src_notify(s);
487
+ }
488
+ } else {
489
+ if (!xlnx_csu_dma_is_paused(s) && s->notify) {
490
+ s->notify(s->notify_opaque);
491
+ }
492
+ }
493
+}
494
+
495
+static uint64_t int_status_pre_write(RegisterInfo *reg, uint64_t val)
496
+{
497
+ XlnxCSUDMA *s = XLNX_CSU_DMA(reg->opaque);
498
+
499
+ /* DMA counter decrements when flag 'DONE' is cleared */
500
+ if ((val & s->regs[R_INT_STATUS] & R_INT_STATUS_DONE_MASK)) {
501
+ xlnx_csu_dma_update_done_cnt(s, -1);
502
+ }
503
+
504
+ return s->regs[R_INT_STATUS] & ~val;
505
+}
506
+
507
+static void int_status_post_write(RegisterInfo *reg, uint64_t val)
508
+{
509
+ XlnxCSUDMA *s = XLNX_CSU_DMA(reg->opaque);
510
+
511
+ xlnx_csu_dma_update_irq(s);
512
+}
513
+
514
+static uint64_t int_enable_pre_write(RegisterInfo *reg, uint64_t val)
515
+{
516
+ XlnxCSUDMA *s = XLNX_CSU_DMA(reg->opaque);
517
+ uint32_t v32 = val;
518
+
519
+ /*
520
+ * R_INT_ENABLE doesn't have its own state.
521
+ * It is used to indirectly modify R_INT_MASK.
522
+ *
523
+ * 1: Enable this interrupt field (the mask bit will be cleared to 0)
524
+ * 0: No effect
525
+ */
526
+ s->regs[R_INT_MASK] &= ~v32;
527
+ return 0;
528
+}
529
+
530
+static void int_enable_post_write(RegisterInfo *reg, uint64_t val)
531
+{
532
+ XlnxCSUDMA *s = XLNX_CSU_DMA(reg->opaque);
533
+
534
+ xlnx_csu_dma_update_irq(s);
535
+}
536
+
537
+static uint64_t int_disable_pre_write(RegisterInfo *reg, uint64_t val)
538
+{
539
+ XlnxCSUDMA *s = XLNX_CSU_DMA(reg->opaque);
540
+ uint32_t v32 = val;
541
+
542
+ /*
543
+ * R_INT_DISABLE doesn't have its own state.
544
+ * It is used to indirectly modify R_INT_MASK.
545
+ *
546
+ * 1: Disable this interrupt field (the mask bit will be set to 1)
547
+ * 0: No effect
548
+ */
549
+ s->regs[R_INT_MASK] |= v32;
550
+ return 0;
551
+}
552
+
553
+static void int_disable_post_write(RegisterInfo *reg, uint64_t val)
554
+{
555
+ XlnxCSUDMA *s = XLNX_CSU_DMA(reg->opaque);
556
+
557
+ xlnx_csu_dma_update_irq(s);
558
+}
559
+
560
+static uint64_t addr_msb_pre_write(RegisterInfo *reg, uint64_t val)
561
+{
562
+ return val & R_ADDR_MSB_ADDR_MSB_MASK;
563
+}
564
+
565
+static const RegisterAccessInfo *xlnx_csu_dma_regs_info[] = {
566
+#define DMACH_REGINFO(NAME, snd) \
567
+ (const RegisterAccessInfo []) { \
568
+ { \
569
+ .name = #NAME "_ADDR", \
570
+ .addr = A_ADDR, \
571
+ .pre_write = addr_pre_write \
572
+ }, { \
573
+ .name = #NAME "_SIZE", \
574
+ .addr = A_SIZE, \
575
+ .pre_write = size_pre_write, \
576
+ .post_write = size_post_write, \
577
+ .post_read = size_post_read \
578
+ }, { \
579
+ .name = #NAME "_STATUS", \
580
+ .addr = A_STATUS, \
581
+ .pre_write = status_pre_write, \
582
+ .w1c = R_STATUS_DONE_CNT_MASK, \
583
+ .ro = (R_STATUS_BUSY_MASK \
584
+ | R_STATUS_FIFO_LEVEL_MASK \
585
+ | R_STATUS_OUTSTANDING_MASK) \
586
+ }, { \
587
+ .name = #NAME "_CTRL", \
588
+ .addr = A_CTRL, \
589
+ .post_write = ctrl_post_write, \
590
+ .reset = ((R_CTRL_TIMEOUT_VAL_RESET << R_CTRL_TIMEOUT_VAL_SHIFT) \
591
+ | (R_CTRL_FIFO_THRESH_RESET << R_CTRL_FIFO_THRESH_SHIFT)\
592
+ | (snd ? 0 : R_CTRL_FIFOTHRESH_RESET \
593
+ << R_CTRL_FIFOTHRESH_SHIFT)) \
594
+ }, { \
595
+ .name = #NAME "_CRC", \
596
+ .addr = A_CRC, \
597
+ }, { \
598
+ .name = #NAME "_INT_STATUS", \
599
+ .addr = A_INT_STATUS, \
600
+ .pre_write = int_status_pre_write, \
601
+ .post_write = int_status_post_write \
602
+ }, { \
603
+ .name = #NAME "_INT_ENABLE", \
604
+ .addr = A_INT_ENABLE, \
605
+ .pre_write = int_enable_pre_write, \
606
+ .post_write = int_enable_post_write \
607
+ }, { \
608
+ .name = #NAME "_INT_DISABLE", \
609
+ .addr = A_INT_DISABLE, \
610
+ .pre_write = int_disable_pre_write, \
611
+ .post_write = int_disable_post_write \
612
+ }, { \
613
+ .name = #NAME "_INT_MASK", \
614
+ .addr = A_INT_MASK, \
615
+ .ro = ~0, \
616
+ .reset = XLNX_CSU_DMA_INT_R_MASK \
617
+ }, { \
618
+ .name = #NAME "_CTRL2", \
619
+ .addr = A_CTRL2, \
620
+ .reset = ((R_CTRL2_TIMEOUT_PRE_RESET \
621
+ << R_CTRL2_TIMEOUT_PRE_SHIFT) \
622
+ | (R_CTRL2_MAX_OUTS_CMDS_RESET \
623
+ << R_CTRL2_MAX_OUTS_CMDS_SHIFT)) \
624
+ }, { \
625
+ .name = #NAME "_ADDR_MSB", \
626
+ .addr = A_ADDR_MSB, \
627
+ .pre_write = addr_msb_pre_write \
628
+ } \
629
+ }
630
+
631
+ DMACH_REGINFO(DMA_SRC, true),
632
+ DMACH_REGINFO(DMA_DST, false)
633
+};
634
+
635
+static const MemoryRegionOps xlnx_csu_dma_ops = {
636
+ .read = register_read_memory,
637
+ .write = register_write_memory,
638
+ .endianness = DEVICE_LITTLE_ENDIAN,
639
+ .valid = {
640
+ .min_access_size = 4,
641
+ .max_access_size = 4,
642
+ }
643
+};
644
+
645
+static void xlnx_csu_dma_src_timeout_hit(void *opaque)
646
+{
647
+ XlnxCSUDMA *s = XLNX_CSU_DMA(opaque);
648
+
649
+ /* Ignore if the timeout is masked */
650
+ if (!xlnx_csu_dma_timeout_enabled(s)) {
651
+ return;
652
+ }
653
+
654
+ s->regs[R_INT_STATUS] |= R_INT_STATUS_TIMEOUT_STRM_MASK;
655
+ xlnx_csu_dma_update_irq(s);
656
+}
657
+
658
+static size_t xlnx_csu_dma_stream_push(StreamSink *obj, uint8_t *buf,
659
+ size_t len, bool eop)
660
+{
661
+ XlnxCSUDMA *s = XLNX_CSU_DMA(obj);
662
+ uint32_t size = s->regs[R_SIZE];
663
+ uint32_t mlen = MIN(size, len) & (~3); /* Size is word aligned */
664
+
665
+ /* Be called when it's DST */
666
+ assert(s->is_dst);
667
+
668
+ if (size == 0 || len <= 0) {
669
+ return 0;
670
+ }
671
+
672
+ if (len && (xlnx_csu_dma_is_paused(s) || mlen == 0)) {
673
+ qemu_log_mask(LOG_GUEST_ERROR,
674
+ "csu-dma: DST channel dropping %zd b of data.\n", len);
675
+ s->regs[R_INT_STATUS] |= R_INT_STATUS_FIFO_OVERFLOW_MASK;
676
+ return len;
677
+ }
678
+
679
+ if (xlnx_csu_dma_write(s, buf, mlen) != mlen) {
680
+ return 0;
681
+ }
682
+
683
+ xlnx_csu_dma_advance(s, mlen);
684
+ xlnx_csu_dma_update_irq(s);
685
+
686
+ return mlen;
687
+}
688
+
689
+static bool xlnx_csu_dma_stream_can_push(StreamSink *obj,
690
+ StreamCanPushNotifyFn notify,
691
+ void *notify_opaque)
692
+{
693
+ XlnxCSUDMA *s = XLNX_CSU_DMA(obj);
694
+
695
+ if (s->regs[R_SIZE] != 0) {
696
+ return true;
697
+ } else {
698
+ s->notify = notify;
699
+ s->notify_opaque = notify_opaque;
700
+ return false;
701
+ }
702
+}
703
+
704
+static void xlnx_csu_dma_reset(DeviceState *dev)
705
+{
706
+ XlnxCSUDMA *s = XLNX_CSU_DMA(dev);
707
+ unsigned int i;
708
+
709
+ for (i = 0; i < ARRAY_SIZE(s->regs_info); ++i) {
710
+ register_reset(&s->regs_info[i]);
711
+ }
712
+}
713
+
714
+static void xlnx_csu_dma_realize(DeviceState *dev, Error **errp)
715
+{
716
+ XlnxCSUDMA *s = XLNX_CSU_DMA(dev);
717
+ RegisterInfoArray *reg_array;
718
+
719
+ reg_array =
720
+ register_init_block32(dev, xlnx_csu_dma_regs_info[!!s->is_dst],
721
+ XLNX_CSU_DMA_R_MAX,
722
+ s->regs_info, s->regs,
723
+ &xlnx_csu_dma_ops,
724
+ XLNX_CSU_DMA_ERR_DEBUG,
725
+ XLNX_CSU_DMA_R_MAX * 4);
726
+ memory_region_add_subregion(&s->iomem,
727
+ 0x0,
728
+ &reg_array->mem);
729
+
730
+ sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->iomem);
731
+ sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->irq);
732
+
733
+ if (!s->is_dst && !s->tx_dev) {
734
+ error_setg(errp, "zynqmp.csu-dma: Stream not connected");
735
+ return;
736
+ }
737
+
738
+ s->src_timer = ptimer_init(xlnx_csu_dma_src_timeout_hit,
739
+ s, PTIMER_POLICY_DEFAULT);
740
+
741
+ if (s->dma_mr) {
742
+ s->dma_as = g_malloc0(sizeof(AddressSpace));
743
+ address_space_init(s->dma_as, s->dma_mr, NULL);
744
+ } else {
745
+ s->dma_as = &address_space_memory;
746
+ }
747
+
748
+ s->attr = MEMTXATTRS_UNSPECIFIED;
749
+
750
+ s->r_size_last_word = 0;
751
+}
752
+
753
+static const VMStateDescription vmstate_xlnx_csu_dma = {
754
+ .name = TYPE_XLNX_CSU_DMA,
755
+ .version_id = 0,
756
+ .minimum_version_id = 0,
757
+ .minimum_version_id_old = 0,
758
+ .fields = (VMStateField[]) {
759
+ VMSTATE_PTIMER(src_timer, XlnxCSUDMA),
760
+ VMSTATE_UINT16(width, XlnxCSUDMA),
761
+ VMSTATE_BOOL(is_dst, XlnxCSUDMA),
762
+ VMSTATE_BOOL(r_size_last_word, XlnxCSUDMA),
763
+ VMSTATE_UINT32_ARRAY(regs, XlnxCSUDMA, XLNX_CSU_DMA_R_MAX),
764
+ VMSTATE_END_OF_LIST(),
765
+ }
766
+};
767
+
768
+static Property xlnx_csu_dma_properties[] = {
769
+ /*
770
+ * Ref PG021, Stream Data Width:
771
+ * Data width in bits of the AXI S2MM AXI4-Stream Data bus.
772
+ * This value must be equal or less than the Memory Map Data Width.
773
+ * Valid values are 8, 16, 32, 64, 128, 512 and 1024.
774
+ * "dma-width" is the byte value of the "Stream Data Width".
775
+ */
776
+ DEFINE_PROP_UINT16("dma-width", XlnxCSUDMA, width, 4),
777
+ /*
778
+ * The CSU DMA is a two-channel, simple DMA, allowing separate control of
779
+ * the SRC (read) channel and DST (write) channel. "is-dst" is used to mark
780
+ * which channel the device is connected to.
781
+ */
782
+ DEFINE_PROP_BOOL("is-dst", XlnxCSUDMA, is_dst, true),
783
+ DEFINE_PROP_END_OF_LIST(),
784
+};
785
+
786
+static void xlnx_csu_dma_class_init(ObjectClass *klass, void *data)
787
+{
788
+ DeviceClass *dc = DEVICE_CLASS(klass);
789
+ StreamSinkClass *ssc = STREAM_SINK_CLASS(klass);
790
+
791
+ dc->reset = xlnx_csu_dma_reset;
792
+ dc->realize = xlnx_csu_dma_realize;
793
+ dc->vmsd = &vmstate_xlnx_csu_dma;
794
+ device_class_set_props(dc, xlnx_csu_dma_properties);
795
+
796
+ ssc->push = xlnx_csu_dma_stream_push;
797
+ ssc->can_push = xlnx_csu_dma_stream_can_push;
798
+}
799
+
800
+static void xlnx_csu_dma_init(Object *obj)
801
+{
802
+ XlnxCSUDMA *s = XLNX_CSU_DMA(obj);
803
+
804
+ memory_region_init(&s->iomem, obj, TYPE_XLNX_CSU_DMA,
805
+ XLNX_CSU_DMA_R_MAX * 4);
806
+
807
+ object_property_add_link(obj, "stream-connected-dma", TYPE_STREAM_SINK,
808
+ (Object **)&s->tx_dev,
809
+ qdev_prop_allow_set_link_before_realize,
810
+ OBJ_PROP_LINK_STRONG);
811
+ object_property_add_link(obj, "dma", TYPE_MEMORY_REGION,
812
+ (Object **)&s->dma_mr,
813
+ qdev_prop_allow_set_link_before_realize,
814
+ OBJ_PROP_LINK_STRONG);
815
+}
816
+
817
+static const TypeInfo xlnx_csu_dma_info = {
818
+ .name = TYPE_XLNX_CSU_DMA,
819
+ .parent = TYPE_SYS_BUS_DEVICE,
820
+ .instance_size = sizeof(XlnxCSUDMA),
821
+ .class_init = xlnx_csu_dma_class_init,
822
+ .instance_init = xlnx_csu_dma_init,
823
+ .interfaces = (InterfaceInfo[]) {
824
+ { TYPE_STREAM_SINK },
825
+ { }
826
+ }
827
+};
828
+
829
+static void xlnx_csu_dma_register_types(void)
830
+{
831
+ type_register_static(&xlnx_csu_dma_info);
832
+}
833
+
834
+type_init(xlnx_csu_dma_register_types)
835
diff --git a/hw/dma/Kconfig b/hw/dma/Kconfig
836
index XXXXXXX..XXXXXXX 100644
837
--- a/hw/dma/Kconfig
838
+++ b/hw/dma/Kconfig
839
@@ -XXX,XX +XXX,XX @@ config STP2000
840
841
config SIFIVE_PDMA
842
bool
843
+
844
+config XLNX_CSU_DMA
845
+ bool
846
+ select REGISTER
847
diff --git a/hw/dma/meson.build b/hw/dma/meson.build
848
index XXXXXXX..XXXXXXX 100644
849
--- a/hw/dma/meson.build
850
+++ b/hw/dma/meson.build
851
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_OMAP', if_true: files('omap_dma.c', 'soc_dma.c'))
852
softmmu_ss.add(when: 'CONFIG_PXA2XX', if_true: files('pxa2xx_dma.c'))
853
softmmu_ss.add(when: 'CONFIG_RASPI', if_true: files('bcm2835_dma.c'))
854
softmmu_ss.add(when: 'CONFIG_SIFIVE_PDMA', if_true: files('sifive_pdma.c'))
855
+softmmu_ss.add(when: 'CONFIG_XLNX_CSU_DMA', if_true: files('xlnx_csu_dma.c'))
856
--
857
2.20.1
858
859
diff view generated by jsdifflib
Deleted patch
1
From: Xuzhou Cheng <xuzhou.cheng@windriver.com>
2
1
3
There are some coding convention warnings in xlnx-zynqmp.c and
4
xlnx-zynqmp.h, as reported by:
5
6
$ ./scripts/checkpatch.pl include/hw/arm/xlnx-zynqmp.h
7
$ ./scripts/checkpatch.pl hw/arm/xlnx-zynqmp.c
8
9
Let's clean them up.
10
11
Signed-off-by: Xuzhou Cheng <xuzhou.cheng@windriver.com>
12
Signed-off-by: Bin Meng <bin.meng@windriver.com>
13
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
14
Message-id: 20210303135254.3970-3-bmeng.cn@gmail.com
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
---
17
include/hw/arm/xlnx-zynqmp.h | 3 ++-
18
hw/arm/xlnx-zynqmp.c | 9 ++++++---
19
2 files changed, 8 insertions(+), 4 deletions(-)
20
21
diff --git a/include/hw/arm/xlnx-zynqmp.h b/include/hw/arm/xlnx-zynqmp.h
22
index XXXXXXX..XXXXXXX 100644
23
--- a/include/hw/arm/xlnx-zynqmp.h
24
+++ b/include/hw/arm/xlnx-zynqmp.h
25
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_SIMPLE_TYPE(XlnxZynqMPState, XLNX_ZYNQMP)
26
27
#define XLNX_ZYNQMP_GIC_REGIONS 6
28
29
-/* ZynqMP maps the ARM GIC regions (GICC, GICD ...) at consecutive 64k offsets
30
+/*
31
+ * ZynqMP maps the ARM GIC regions (GICC, GICD ...) at consecutive 64k offsets
32
* and under-decodes the 64k region. This mirrors the 4k regions to every 4k
33
* aligned address in the 64k region. To implement each GIC region needs a
34
* number of memory region aliases.
35
diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c
36
index XXXXXXX..XXXXXXX 100644
37
--- a/hw/arm/xlnx-zynqmp.c
38
+++ b/hw/arm/xlnx-zynqmp.c
39
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
40
41
ram_size = memory_region_size(s->ddr_ram);
42
43
- /* Create the DDR Memory Regions. User friendly checks should happen at
44
+ /*
45
+ * Create the DDR Memory Regions. User friendly checks should happen at
46
* the board level
47
*/
48
if (ram_size > XLNX_ZYNQMP_MAX_LOW_RAM_SIZE) {
49
- /* The RAM size is above the maximum available for the low DDR.
50
+ /*
51
+ * The RAM size is above the maximum available for the low DDR.
52
* Create the high DDR memory region as well.
53
*/
54
assert(ram_size <= XLNX_ZYNQMP_MAX_RAM_SIZE);
55
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
56
SysBusDevice *sbd = SYS_BUS_DEVICE(&s->sdhci[i]);
57
Object *sdhci = OBJECT(&s->sdhci[i]);
58
59
- /* Compatible with:
60
+ /*
61
+ * Compatible with:
62
* - SD Host Controller Specification Version 3.00
63
* - SDIO Specification Version 3.0
64
* - eMMC Specification Version 4.51
65
--
66
2.20.1
67
68
diff view generated by jsdifflib