1
First arm pullreq of the 2.11 cycle. I know I still have some
1
This is almost all the mps3-an547 series, but there are a few
2
more stuff on my queue to review, but 36 patches is big enough
2
other bits in there too.
3
as it is; I expect I'll do another pull later this week.
4
3
5
thanks
4
thanks
6
-- PMM
5
-- PMM
7
6
8
The following changes since commit 32f0f68bb77289b75a82925f712bb52e16eac3ba:
9
7
10
Merge remote-tracking branch 'remotes/ehabkost/tags/x86-and-machine-pull-request' into staging (2017-09-01 17:28:54 +0100)
8
The following changes since commit 0436c55edf6b357ff56e2a5bf688df8636f83456:
11
9
12
are available in the git repository at:
10
Merge remote-tracking branch 'remotes/bonzini-gitlab/tags/for-upstream' into staging (2021-03-08 13:51:41 +0000)
13
11
14
git://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20170904
12
are available in the Git repository at:
15
13
16
for you to fetch changes up to 1e35c4ce33a94cf78dbf639695cb877ef35920b0:
14
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20210308-1
17
15
18
arm_gicv3_kvm: Fix compile warning (2017-09-04 12:09:32 +0100)
16
for you to fetch changes up to da2140183ac3a04b1ccb861aeac1f2c048c71b66:
17
18
hw/timer/renesas_tmr: Fix use of uninitialized data in read_tcnt() (2021-03-08 17:20:04 +0000)
19
19
20
----------------------------------------------------------------
20
----------------------------------------------------------------
21
target-arm:
21
* Add new mps3-an547 board
22
* collection of M profile cleanups and minor bugfixes
22
* target/arm: Restrict v7A TCG cpus to TCG accel
23
* loader: handle ELF files with overlapping zero-init data
23
* Implement a Xilinx CSU DMA model
24
* virt: allow PMU instantiation with userspace irqchip
24
* hw/timer/renesas_tmr: Fix use of uninitialized data in read_tcnt()
25
* wdt_aspeed: Add support for the reset width register
26
* cpu: Define new cpu_transaction_failed() hook
27
* arm: Support generating CPU exceptions on memory
28
transaction failures (bus faults)
29
* Mark some SoC devices as not user-creatable
30
* arm: Fix aa64 ldp register writeback
31
* arm_gicv3_kvm: Fix compile warning
32
25
33
----------------------------------------------------------------
26
----------------------------------------------------------------
34
Andrew Jeffery (2):
27
Peter Maydell (48):
35
watchdog: wdt_aspeed: Add support for the reset width register
28
clock: Add ClockEvent parameter to callbacks
36
aspeed_soc: Propagate silicon-rev to watchdog
29
clock: Add ClockPreUpdate callback event type
37
30
clock: Add clock_ns_to_ticks() function
38
Andrew Jones (4):
31
hw/timer/npcm7xx_timer: Use new clock_ns_to_ticks()
39
hw/arm/virt: add pmu interrupt state
32
hw/arm/armsse: Introduce SSE subsystem version property
40
target/arm/kvm: pmu: split init and set-irq stages
33
hw/misc/iotkit-sysctl: Remove is_sse200 flag
41
hw/arm/virt: allow pmu instantiation with userspace irqchip
34
hw/misc/iotkit-secctl.c: Implement SSE-300 PID register values
42
target/arm/kvm: pmu: improve error handling
35
hw/misc/iotkit-sysinfo.c: Implement SSE-300 PID register values
43
36
hw/arm/armsse.c: Use correct SYS_CONFIG0 register value for SSE-300
44
Peter Maydell (25):
37
hw/misc/iotkit-sysinfo.c: Implement SYS_CONFIG1 and IIDR
45
target/arm: Use MMUAccessType enum rather than int
38
hw/timer/sse-counter: Model the SSE Subsystem System Counter
46
target/arm: Don't trap WFI/WFE for M profile
39
hw/timer/sse-timer: Model the SSE Subsystem System Timer
47
target/arm: Consolidate PMSA handling in get_phys_addr()
40
hw/misc/iotkit-sysctl: Add SSE-300 cases which match SSE-200 behaviour
48
target/arm: Tighten up Thumb decode where new v8M insns will be
41
hw/misc/iotkit-sysctl: Handle CPU_WAIT, NMI_ENABLE for SSE-300
49
hw/intc/armv7m_nvic.c: Remove out of date comment
42
hw/misc/iotkit-sysctl: Handle INITSVTOR* for SSE-300
50
target/arm: Remove incorrect comment about MPU_CTRL
43
hw/misc/iotkit-sysctl: Implement dummy version of SSE-300 PWRCTRL register
51
target/arm: Fix outdated comment about exception exit
44
hw/misc/iotkit-sysctl: Handle SSE-300 changes to PDCM_PD_*_SENSE registers
52
target/arm: Define and use XPSR bit masks
45
hw/misc/iotkit-sysctl: Implement SSE-200 and SSE-300 PID register values
53
target/arm: Don't store M profile PRIMASK and FAULTMASK in daif
46
hw/arm/Kconfig: Move ARMSSE_CPUID and ARMSSE_MHU stanzas to hw/misc
54
target/arm: Don't use cpsr_write/cpsr_read to transfer M profile XPSR
47
hw/misc/sse-cpu-pwrctrl: Implement SSE-300 CPU<N>_PWRCTRL register block
55
target/arm: Make arm_cpu_dump_state() handle the M-profile XPSR
48
hw/arm/armsse: Use an array for apb_ppc fields in the state structure
56
target/arm: Don't calculate lr in arm_v7m_cpu_do_interrupt() until needed
49
hw/arm/armsse: Add a define for number of IRQs used by the SSE itself
57
target/arm: Create and use new function arm_v7m_is_handler_mode()
50
hw/arm/armsse: Add framework for data-driven device placement
58
armv7m_nvic.h: Move from include/hw/arm to include/hw/intc
51
hw/arm/armsse: Move dual-timer device into data-driven framework
59
nvic: Implement "user accesses BusFault" SCS region behaviour
52
hw/arm/armsse: Move watchdogs into data-driven framework
60
loader: Handle ELF files with overlapping zero-initialized data
53
hw/arm/armsse: Move s32ktimer into data-driven framework
61
loader: Ignore zero-sized ELF segments
54
hw/arm/armsse: Move sysinfo register block into data-driven framework
62
memory.h: Move MemTxResult type to memattrs.h
55
hw/arm/armsse: Move sysctl register block into data-driven framework
63
cpu: Define new cpu_transaction_failed() hook
56
hw/arm/armsse: Move PPUs into data-driven framework
64
cputlb: Support generating CPU exceptions on memory transaction failures
57
hw/arm/armsse: Add missing SSE-200 SYS_PPU
65
boards.h: Define new flag ignore_memory_transaction_failures
58
hw/arm/armsse: Indirect irq_is_common[] through ARMSSEInfo
66
hw/arm: Set ignore_memory_transaction_failures for most ARM boards
59
hw/arm/armsse: Add support for SSE variants with a system counter
67
target/arm: Factor out fault delivery code
60
hw/arm/armsse: Add support for TYPE_SSE_TIMER in ARMSSEDeviceInfo
68
target/arm: Allow deliver_fault() caller to specify EA bit
61
hw/arm/armsse: Support variants with ARMSSE_CPU_PWRCTRL block
69
target/arm: Implement new do_transaction_failed hook
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()
70
76
71
Philippe Mathieu-Daudé (1):
77
Philippe Mathieu-Daudé (1):
72
hw/arm: use defined type name instead of hard-coded string
78
target/arm: Restrict v7A TCG cpus to TCG accel
73
79
74
Pranith Kumar (1):
80
Xuzhou Cheng (5):
75
arm_gicv3_kvm: Fix compile warning
81
hw/dma: Implement a Xilinx CSU DMA model
82
hw/arm: xlnx-zynqmp: Clean up coding convention issues
83
hw/arm: xlnx-zynqmp: Connect a Xilinx CSU DMA module for QSPI
84
hw/ssi: xilinx_spips: Clean up coding convention issues
85
hw/ssi: xilinx_spips: Remove DMA related dead codes from zynqmp_spips
76
86
77
Richard Henderson (1):
87
docs/devel/clocks.rst | 71 ++-
78
target/arm: Fix aa64 ldp register writeback
88
docs/system/arm/mps2.rst | 6 +-
89
include/hw/arm/armsse-version.h | 42 ++
90
include/hw/arm/armsse.h | 40 +-
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
79
158
80
Thomas Huth (2):
81
hw/arm/aspeed_soc: Mark devices as user_creatable = false
82
hw/arm/digic: Mark device with user_creatable = false
83
84
include/exec/memattrs.h | 10 +++
85
include/exec/memory.h | 10 ---
86
include/hw/arm/armv7m.h | 2 +-
87
include/hw/boards.h | 11 +++
88
include/hw/elf_ops.h | 72 +++++++++++++--
89
include/hw/{arm => intc}/armv7m_nvic.h | 0
90
include/hw/watchdog/wdt_aspeed.h | 2 +
91
include/qom/cpu.h | 27 ++++++
92
softmmu_template.h | 4 +-
93
target/arm/cpu.h | 56 +++++++++---
94
target/arm/internals.h | 15 +++-
95
target/arm/kvm_arm.h | 9 +-
96
accel/tcg/cputlb.c | 32 ++++++-
97
hw/arm/armv7m.c | 4 +-
98
hw/arm/aspeed.c | 3 +
99
hw/arm/aspeed_soc.c | 4 +
100
hw/arm/collie.c | 1 +
101
hw/arm/cubieboard.c | 1 +
102
hw/arm/digic.c | 2 +
103
hw/arm/digic_boards.c | 1 +
104
hw/arm/exynos4210.c | 4 +-
105
hw/arm/exynos4_boards.c | 2 +
106
hw/arm/gumstix.c | 2 +
107
hw/arm/highbank.c | 13 ++-
108
hw/arm/imx25_pdk.c | 1 +
109
hw/arm/integratorcp.c | 1 +
110
hw/arm/kzm.c | 1 +
111
hw/arm/mainstone.c | 1 +
112
hw/arm/musicpal.c | 1 +
113
hw/arm/netduino2.c | 1 +
114
hw/arm/nseries.c | 2 +
115
hw/arm/omap_sx1.c | 2 +
116
hw/arm/palm.c | 1 +
117
hw/arm/raspi.c | 1 +
118
hw/arm/realview.c | 10 ++-
119
hw/arm/sabrelite.c | 1 +
120
hw/arm/spitz.c | 4 +
121
hw/arm/stellaris.c | 2 +
122
hw/arm/tosa.c | 1 +
123
hw/arm/versatilepb.c | 2 +
124
hw/arm/vexpress.c | 7 +-
125
hw/arm/virt.c | 12 ++-
126
hw/arm/xilinx_zynq.c | 15 ++--
127
hw/arm/xlnx-ep108.c | 2 +
128
hw/arm/z2.c | 1 +
129
hw/intc/arm_gicv3_kvm.c | 2 +-
130
hw/intc/armv7m_nvic.c | 68 +++++++++-----
131
hw/watchdog/wdt_aspeed.c | 93 ++++++++++++++++---
132
qom/cpu.c | 7 ++
133
target/arm/cpu.c | 8 +-
134
target/arm/helper.c | 124 ++++++++++++-------------
135
target/arm/kvm.c | 6 +-
136
target/arm/kvm32.c | 7 +-
137
target/arm/kvm64.c | 63 +++++++------
138
target/arm/machine.c | 54 ++++++++++-
139
target/arm/op_helper.c | 160 ++++++++++++++++++++++-----------
140
target/arm/translate-a64.c | 29 +++---
141
target/arm/translate.c | 106 ++++++++++++++++------
142
58 files changed, 795 insertions(+), 288 deletions(-)
143
rename include/hw/{arm => intc}/armv7m_nvic.h (100%)
144
diff view generated by jsdifflib
1
Currently we have a rather half-baked setup for allowing CPUs to
1
The Clock framework allows users to specify a callback which is
2
generate exceptions on accesses to invalid memory: the CPU has a
2
called after the clock's period has been updated. Some users need to
3
cpu_unassigned_access() hook which the memory system calls in
3
also have a callback which is called before the clock period is
4
unassigned_mem_write() and unassigned_mem_read() if the current_cpu
4
updated.
5
pointer is non-NULL. This was originally designed before we
6
implemented the MemTxResult type that allows memory operations to
7
report a success or failure code, which is why the hook is called
8
right at the bottom of the memory system. The major problem with
9
this is that it means that the hook can be called even when the
10
access was not actually done by the CPU: for instance if the CPU
11
writes to a DMA engine register which causes the DMA engine to begin
12
a transaction which has been set up by the guest to operate on
13
invalid memory then this will casue the CPU to take an exception
14
incorrectly. Another minor problem is that currently if a device
15
returns a transaction error then this won't turn into a CPU exception
16
at all.
17
5
18
The right way to do this is to have allow the CPU to respond
6
As the first step in adding support for notifying Clock users on
19
to memory system transaction failures at the point where the
7
pre-update events, add an argument to the ClockCallback to specify
20
CPU specific code calls into the memory system.
8
what event is being notified, and add an argument to the various
9
functions for registering a callback to specify which events are
10
of interest to that callback.
21
11
22
Define a new QOM CPU method and utility function
12
Note that the documentation update renders correct the previously
23
cpu_transaction_failed() which is called in these cases.
13
incorrect claim in 'Adding a new clock' that callbacks "will be
24
The functionality here overlaps with the existing
14
explained in a following section".
25
cpu_unassigned_access() because individual target CPUs will
26
need some work to convert them to the new system. When this
27
transition is complete we can remove the old cpu_unassigned_access()
28
code.
29
15
30
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
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>
31
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
20
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
32
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
21
Message-id: 20210219144617.4782-2-peter.maydell@linaro.org
33
---
22
---
34
include/qom/cpu.h | 22 ++++++++++++++++++++++
23
docs/devel/clocks.rst | 52 +++++++++++++++++++++++++++-----
35
1 file changed, 22 insertions(+)
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(-)
36
44
37
diff --git a/include/qom/cpu.h b/include/qom/cpu.h
45
diff --git a/docs/devel/clocks.rst b/docs/devel/clocks.rst
38
index XXXXXXX..XXXXXXX 100644
46
index XXXXXXX..XXXXXXX 100644
39
--- a/include/qom/cpu.h
47
--- a/docs/devel/clocks.rst
40
+++ b/include/qom/cpu.h
48
+++ b/docs/devel/clocks.rst
41
@@ -XXX,XX +XXX,XX @@ struct TranslationBlock;
49
@@ -XXX,XX +XXX,XX @@ Adding clocks to a device must be done during the init method of the Device
42
* @has_work: Callback for checking if there is work to do.
50
instance.
43
* @do_interrupt: Callback for interrupt handling.
51
44
* @do_unassigned_access: Callback for unassigned access handling.
52
To add an input clock to a device, the function ``qdev_init_clock_in()``
45
+ * (this is deprecated: new targets should use do_transaction_failed instead)
53
-must be used. It takes the name, a callback and an opaque parameter
46
* @do_unaligned_access: Callback for unaligned access handling, if
54
-for the callback (this will be explained in a following section).
47
* the target defines #ALIGNED_ONLY.
55
+must be used. It takes the name, a callback, an opaque parameter
48
+ * @do_transaction_failed: Callback for handling failed memory transactions
56
+for the callback and a mask of events when the callback should be
49
+ * (ie bus faults or external aborts; not MMU faults)
57
+called (this will be explained in a following section).
50
* @virtio_is_big_endian: Callback to return %true if a CPU which supports
58
Output is simpler; only the name is required. Typically::
51
* runtime configurable endianness is currently big-endian. Non-configurable
59
52
* CPUs can use the default implementation of this method. This method should
60
- qdev_init_clock_in(DEVICE(dev), "clk_in", clk_in_callback, dev);
53
@@ -XXX,XX +XXX,XX @@ typedef struct CPUClass {
61
+ qdev_init_clock_in(DEVICE(dev), "clk_in", clk_in_callback, dev, ClockUpdate);
54
void (*do_unaligned_access)(CPUState *cpu, vaddr addr,
62
qdev_init_clock_out(DEVICE(dev), "clk_out");
55
MMUAccessType access_type,
63
56
int mmu_idx, uintptr_t retaddr);
64
Both functions return the created Clock pointer, which should be saved in the
57
+ void (*do_transaction_failed)(CPUState *cpu, hwaddr physaddr, vaddr addr,
65
@@ -XXX,XX +XXX,XX @@ output.
58
+ unsigned size, MMUAccessType access_type,
66
* callback for the input clock (see "Callback on input clock
59
+ int mmu_idx, MemTxAttrs attrs,
67
* change" section below for more information).
60
+ MemTxResult response, uintptr_t retaddr);
68
*/
61
bool (*virtio_is_big_endian)(CPUState *cpu);
69
- static void clk_in_callback(void *opaque);
62
int (*memory_rw_debug)(CPUState *cpu, vaddr addr,
70
+ static void clk_in_callback(void *opaque, ClockEvent event);
63
uint8_t *buf, int len, bool is_write);
71
64
@@ -XXX,XX +XXX,XX @@ static inline void cpu_unaligned_access(CPUState *cpu, vaddr addr,
72
/*
65
73
* static array describing clocks:
66
cc->do_unaligned_access(cpu, addr, access_type, mmu_idx, retaddr);
74
@@ -XXX,XX +XXX,XX @@ output.
67
}
75
* the clk_out field of a MyDeviceState structure.
68
+
76
*/
69
+static inline void cpu_transaction_failed(CPUState *cpu, hwaddr physaddr,
77
static const ClockPortInitArray mydev_clocks = {
70
+ vaddr addr, unsigned size,
78
- QDEV_CLOCK_IN(MyDeviceState, clk_in, clk_in_callback),
71
+ MMUAccessType access_type,
79
+ QDEV_CLOCK_IN(MyDeviceState, clk_in, clk_in_callback, ClockUpdate),
72
+ int mmu_idx, MemTxAttrs attrs,
80
QDEV_CLOCK_OUT(MyDeviceState, clk_out),
73
+ MemTxResult response,
81
QDEV_CLOCK_END
74
+ uintptr_t retaddr)
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
276
index XXXXXXX..XXXXXXX 100644
277
--- a/hw/adc/npcm7xx_adc.c
278
+++ b/hw/adc/npcm7xx_adc.c
279
@@ -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
286
for (i = 0; i < NPCM7XX_ADC_NUM_INPUTS; ++i) {
287
object_property_add_uint32_ptr(obj, "adci[*]",
288
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
289
index XXXXXXX..XXXXXXX 100644
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
}
352
}
353
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)
75
+{
420
+{
76
+ CPUClass *cc = CPU_GET_CLASS(cpu);
421
+ /*
77
+
422
+ * Call the Clock's callback for this event, if it has one and
78
+ if (cc->do_transaction_failed) {
423
+ * is interested in this event.
79
+ cc->do_transaction_failed(cpu, physaddr, addr, size, access_type,
424
+ */
80
+ mmu_idx, attrs, response, retaddr);
425
+ if (clk->callback && (clk->callback_events & event)) {
426
+ clk->callback(clk->callback_opaque, event);
81
+ }
427
+ }
82
+}
428
+}
83
#endif
429
+
84
430
static void clock_propagate_period(Clock *clk, bool call_callbacks)
85
#endif /* NEED_CPU_H */
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
86
--
772
--
87
2.7.4
773
2.20.1
88
774
89
775
diff view generated by jsdifflib
New patch
1
Add a new callback event type ClockPreUpdate, which is called on
2
period changes before the period is updated.
1
3
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
New patch
1
Add a clock_ns_to_ticks() function which does the opposite of
2
clock_ticks_to_ns(): given a duration in nanoseconds, it returns the
3
number of clock ticks that would happen in that time. This is useful
4
for devices that have a free running counter register whose value can
5
be calculated when it is read.
1
6
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Luc Michel <luc@lmichel.fr>
9
Reviewed-by: Hao Wu <wuhaotsh@google.com>
10
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
11
Message-id: 20210219144617.4782-4-peter.maydell@linaro.org
12
---
13
docs/devel/clocks.rst | 12 ++++++++++++
14
include/hw/clock.h | 41 +++++++++++++++++++++++++++++++++++++++++
15
2 files changed, 53 insertions(+)
16
17
diff --git a/docs/devel/clocks.rst b/docs/devel/clocks.rst
18
index XXXXXXX..XXXXXXX 100644
19
--- a/docs/devel/clocks.rst
20
+++ b/docs/devel/clocks.rst
21
@@ -XXX,XX +XXX,XX @@ rather than simply passing it to a QEMUTimer function like
22
``timer_mod_ns()`` then you should be careful to avoid overflow
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
}
47
48
+/**
49
+ * clock_ns_to_ticks:
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
+{
70
+ /*
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
+}
88
+
89
/**
90
* clock_is_enabled:
91
* @clk: a clock
92
--
93
2.20.1
94
95
diff view generated by jsdifflib
New patch
1
Use the new clock_ns_to_ticks() function in npcm7xx_timer where
2
appropriate.
1
3
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
New patch
1
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
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
New patch
1
1
Remove the is_sse200 flag in favour of just directly testing the new
2
sse_version field.
3
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
1
Set the MachineClass flag ignore_memory_transaction_failures
1
The versions of the Secure Access Configuration Register Block
2
for almost all ARM boards. This means they retain the legacy
2
and Non-secure Access Configuration Register Block in the SSE-300
3
behaviour that accesses to unimplemented addresses will RAZ/WI
3
are the same as those in the SSE-200, but the CIDR/PIDR ID
4
rather than aborting, when a subsequent commit adds support
4
register values are different.
5
for external aborts.
6
5
7
The exceptions are:
6
Plumb through the sse-version property and use it to select
8
* virt -- we know that guests won't try to prod devices
7
the correct ID register values.
9
that we don't describe in the device tree or ACPI tables
10
* mps2 -- this board was written to use unimplemented-device
11
for all the ranges with devices we don't yet handle
12
13
New boards should not set the flag, but instead be written
14
like the mps2.
15
8
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
For the Xilinx boards:
10
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
18
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20210219144617.4782-8-peter.maydell@linaro.org
19
---
13
---
20
hw/arm/aspeed.c | 3 +++
14
include/hw/misc/iotkit-secctl.h | 2 ++
21
hw/arm/collie.c | 1 +
15
hw/arm/armsse.c | 2 ++
22
hw/arm/cubieboard.c | 1 +
16
hw/misc/iotkit-secctl.c | 50 +++++++++++++++++++++++++++++++--
23
hw/arm/digic_boards.c | 1 +
17
3 files changed, 52 insertions(+), 2 deletions(-)
24
hw/arm/exynos4_boards.c | 2 ++
25
hw/arm/gumstix.c | 2 ++
26
hw/arm/highbank.c | 2 ++
27
hw/arm/imx25_pdk.c | 1 +
28
hw/arm/integratorcp.c | 1 +
29
hw/arm/kzm.c | 1 +
30
hw/arm/mainstone.c | 1 +
31
hw/arm/musicpal.c | 1 +
32
hw/arm/netduino2.c | 1 +
33
hw/arm/nseries.c | 2 ++
34
hw/arm/omap_sx1.c | 2 ++
35
hw/arm/palm.c | 1 +
36
hw/arm/raspi.c | 1 +
37
hw/arm/realview.c | 4 ++++
38
hw/arm/sabrelite.c | 1 +
39
hw/arm/spitz.c | 4 ++++
40
hw/arm/stellaris.c | 2 ++
41
hw/arm/tosa.c | 1 +
42
hw/arm/versatilepb.c | 2 ++
43
hw/arm/vexpress.c | 1 +
44
hw/arm/xilinx_zynq.c | 1 +
45
hw/arm/xlnx-ep108.c | 2 ++
46
hw/arm/z2.c | 1 +
47
27 files changed, 43 insertions(+)
48
18
49
diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
19
diff --git a/include/hw/misc/iotkit-secctl.h b/include/hw/misc/iotkit-secctl.h
50
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
51
--- a/hw/arm/aspeed.c
21
--- a/include/hw/misc/iotkit-secctl.h
52
+++ b/hw/arm/aspeed.c
22
+++ b/include/hw/misc/iotkit-secctl.h
53
@@ -XXX,XX +XXX,XX @@ static void palmetto_bmc_class_init(ObjectClass *oc, void *data)
23
@@ -XXX,XX +XXX,XX @@ struct IoTKitSecCtl {
54
mc->no_floppy = 1;
24
IoTKitSecCtlPPC apb[IOTS_NUM_APB_PPC];
55
mc->no_cdrom = 1;
25
IoTKitSecCtlPPC apbexp[IOTS_NUM_APB_EXP_PPC];
56
mc->no_parallel = 1;
26
IoTKitSecCtlPPC ahbexp[IOTS_NUM_APB_EXP_PPC];
57
+ mc->ignore_memory_transaction_failures = true;
27
+
28
+ uint32_t sse_version;
29
};
30
31
#endif
32
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
33
index XXXXXXX..XXXXXXX 100644
34
--- a/hw/arm/armsse.c
35
+++ b/hw/arm/armsse.c
36
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
37
}
38
39
/* Security controller */
40
+ object_property_set_int(OBJECT(&s->secctl), "sse-version",
41
+ info->sse_version, &error_abort);
42
if (!sysbus_realize(SYS_BUS_DEVICE(&s->secctl), errp)) {
43
return;
44
}
45
diff --git a/hw/misc/iotkit-secctl.c b/hw/misc/iotkit-secctl.c
46
index XXXXXXX..XXXXXXX 100644
47
--- a/hw/misc/iotkit-secctl.c
48
+++ b/hw/misc/iotkit-secctl.c
49
@@ -XXX,XX +XXX,XX @@
50
#include "hw/registerfields.h"
51
#include "hw/irq.h"
52
#include "hw/misc/iotkit-secctl.h"
53
+#include "hw/arm/armsse-version.h"
54
+#include "hw/qdev-properties.h"
55
56
/* Registers in the secure privilege control block */
57
REG32(SECRESPCFG, 0x10)
58
@@ -XXX,XX +XXX,XX @@ static const uint8_t iotkit_secctl_ns_idregs[] = {
59
0x0d, 0xf0, 0x05, 0xb1,
60
};
61
62
+static const uint8_t iotkit_secctl_s_sse300_idregs[] = {
63
+ 0x04, 0x00, 0x00, 0x00,
64
+ 0x52, 0xb8, 0x2b, 0x00,
65
+ 0x0d, 0xf0, 0x05, 0xb1,
66
+};
67
+
68
+static const uint8_t iotkit_secctl_ns_sse300_idregs[] = {
69
+ 0x04, 0x00, 0x00, 0x00,
70
+ 0x53, 0xb8, 0x2b, 0x00,
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);
58
}
112
}
59
113
60
static const TypeInfo palmetto_bmc_type = {
114
+static void iotkit_secctl_realize(DeviceState *dev, Error **errp)
61
@@ -XXX,XX +XXX,XX @@ static void ast2500_evb_class_init(ObjectClass *oc, void *data)
115
+{
62
mc->no_floppy = 1;
116
+ IoTKitSecCtl *s = IOTKIT_SECCTL(dev);
63
mc->no_cdrom = 1;
117
+
64
mc->no_parallel = 1;
118
+ if (!armsse_version_valid(s->sse_version)) {
65
+ mc->ignore_memory_transaction_failures = true;
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
},
129
};
130
131
+static Property iotkit_secctl_props[] = {
132
+ DEFINE_PROP_UINT32("sse-version", IoTKitSecCtl, sse_version, 0),
133
+ DEFINE_PROP_END_OF_LIST()
134
+};
135
+
136
static void iotkit_secctl_class_init(ObjectClass *klass, void *data)
137
{
138
DeviceClass *dc = DEVICE_CLASS(klass);
139
140
dc->vmsd = &iotkit_secctl_vmstate;
141
dc->reset = iotkit_secctl_reset;
142
+ dc->realize = iotkit_secctl_realize;
143
+ device_class_set_props(dc, iotkit_secctl_props);
66
}
144
}
67
145
68
static const TypeInfo ast2500_evb_type = {
146
static const TypeInfo iotkit_secctl_info = {
69
@@ -XXX,XX +XXX,XX @@ static void romulus_bmc_class_init(ObjectClass *oc, void *data)
70
mc->no_floppy = 1;
71
mc->no_cdrom = 1;
72
mc->no_parallel = 1;
73
+ mc->ignore_memory_transaction_failures = true;
74
}
75
76
static const TypeInfo romulus_bmc_type = {
77
diff --git a/hw/arm/collie.c b/hw/arm/collie.c
78
index XXXXXXX..XXXXXXX 100644
79
--- a/hw/arm/collie.c
80
+++ b/hw/arm/collie.c
81
@@ -XXX,XX +XXX,XX @@ static void collie_machine_init(MachineClass *mc)
82
{
83
mc->desc = "Sharp SL-5500 (Collie) PDA (SA-1110)";
84
mc->init = collie_init;
85
+ mc->ignore_memory_transaction_failures = true;
86
}
87
88
DEFINE_MACHINE("collie", collie_machine_init)
89
diff --git a/hw/arm/cubieboard.c b/hw/arm/cubieboard.c
90
index XXXXXXX..XXXXXXX 100644
91
--- a/hw/arm/cubieboard.c
92
+++ b/hw/arm/cubieboard.c
93
@@ -XXX,XX +XXX,XX @@ static void cubieboard_machine_init(MachineClass *mc)
94
mc->init = cubieboard_init;
95
mc->block_default_type = IF_IDE;
96
mc->units_per_default_bus = 1;
97
+ mc->ignore_memory_transaction_failures = true;
98
}
99
100
DEFINE_MACHINE("cubieboard", cubieboard_machine_init)
101
diff --git a/hw/arm/digic_boards.c b/hw/arm/digic_boards.c
102
index XXXXXXX..XXXXXXX 100644
103
--- a/hw/arm/digic_boards.c
104
+++ b/hw/arm/digic_boards.c
105
@@ -XXX,XX +XXX,XX @@ static void canon_a1100_machine_init(MachineClass *mc)
106
{
107
mc->desc = "Canon PowerShot A1100 IS";
108
mc->init = &canon_a1100_init;
109
+ mc->ignore_memory_transaction_failures = true;
110
}
111
112
DEFINE_MACHINE("canon-a1100", canon_a1100_machine_init)
113
diff --git a/hw/arm/exynos4_boards.c b/hw/arm/exynos4_boards.c
114
index XXXXXXX..XXXXXXX 100644
115
--- a/hw/arm/exynos4_boards.c
116
+++ b/hw/arm/exynos4_boards.c
117
@@ -XXX,XX +XXX,XX @@ static void nuri_class_init(ObjectClass *oc, void *data)
118
mc->desc = "Samsung NURI board (Exynos4210)";
119
mc->init = nuri_init;
120
mc->max_cpus = EXYNOS4210_NCPUS;
121
+ mc->ignore_memory_transaction_failures = true;
122
}
123
124
static const TypeInfo nuri_type = {
125
@@ -XXX,XX +XXX,XX @@ static void smdkc210_class_init(ObjectClass *oc, void *data)
126
mc->desc = "Samsung SMDKC210 board (Exynos4210)";
127
mc->init = smdkc210_init;
128
mc->max_cpus = EXYNOS4210_NCPUS;
129
+ mc->ignore_memory_transaction_failures = true;
130
}
131
132
static const TypeInfo smdkc210_type = {
133
diff --git a/hw/arm/gumstix.c b/hw/arm/gumstix.c
134
index XXXXXXX..XXXXXXX 100644
135
--- a/hw/arm/gumstix.c
136
+++ b/hw/arm/gumstix.c
137
@@ -XXX,XX +XXX,XX @@ static void connex_class_init(ObjectClass *oc, void *data)
138
139
mc->desc = "Gumstix Connex (PXA255)";
140
mc->init = connex_init;
141
+ mc->ignore_memory_transaction_failures = true;
142
}
143
144
static const TypeInfo connex_type = {
145
@@ -XXX,XX +XXX,XX @@ static void verdex_class_init(ObjectClass *oc, void *data)
146
147
mc->desc = "Gumstix Verdex (PXA270)";
148
mc->init = verdex_init;
149
+ mc->ignore_memory_transaction_failures = true;
150
}
151
152
static const TypeInfo verdex_type = {
153
diff --git a/hw/arm/highbank.c b/hw/arm/highbank.c
154
index XXXXXXX..XXXXXXX 100644
155
--- a/hw/arm/highbank.c
156
+++ b/hw/arm/highbank.c
157
@@ -XXX,XX +XXX,XX @@ static void highbank_class_init(ObjectClass *oc, void *data)
158
mc->block_default_type = IF_IDE;
159
mc->units_per_default_bus = 1;
160
mc->max_cpus = 4;
161
+ mc->ignore_memory_transaction_failures = true;
162
}
163
164
static const TypeInfo highbank_type = {
165
@@ -XXX,XX +XXX,XX @@ static void midway_class_init(ObjectClass *oc, void *data)
166
mc->block_default_type = IF_IDE;
167
mc->units_per_default_bus = 1;
168
mc->max_cpus = 4;
169
+ mc->ignore_memory_transaction_failures = true;
170
}
171
172
static const TypeInfo midway_type = {
173
diff --git a/hw/arm/imx25_pdk.c b/hw/arm/imx25_pdk.c
174
index XXXXXXX..XXXXXXX 100644
175
--- a/hw/arm/imx25_pdk.c
176
+++ b/hw/arm/imx25_pdk.c
177
@@ -XXX,XX +XXX,XX @@ static void imx25_pdk_machine_init(MachineClass *mc)
178
{
179
mc->desc = "ARM i.MX25 PDK board (ARM926)";
180
mc->init = imx25_pdk_init;
181
+ mc->ignore_memory_transaction_failures = true;
182
}
183
184
DEFINE_MACHINE("imx25-pdk", imx25_pdk_machine_init)
185
diff --git a/hw/arm/integratorcp.c b/hw/arm/integratorcp.c
186
index XXXXXXX..XXXXXXX 100644
187
--- a/hw/arm/integratorcp.c
188
+++ b/hw/arm/integratorcp.c
189
@@ -XXX,XX +XXX,XX @@ static void integratorcp_machine_init(MachineClass *mc)
190
{
191
mc->desc = "ARM Integrator/CP (ARM926EJ-S)";
192
mc->init = integratorcp_init;
193
+ mc->ignore_memory_transaction_failures = true;
194
}
195
196
DEFINE_MACHINE("integratorcp", integratorcp_machine_init)
197
diff --git a/hw/arm/kzm.c b/hw/arm/kzm.c
198
index XXXXXXX..XXXXXXX 100644
199
--- a/hw/arm/kzm.c
200
+++ b/hw/arm/kzm.c
201
@@ -XXX,XX +XXX,XX @@ static void kzm_machine_init(MachineClass *mc)
202
{
203
mc->desc = "ARM KZM Emulation Baseboard (ARM1136)";
204
mc->init = kzm_init;
205
+ mc->ignore_memory_transaction_failures = true;
206
}
207
208
DEFINE_MACHINE("kzm", kzm_machine_init)
209
diff --git a/hw/arm/mainstone.c b/hw/arm/mainstone.c
210
index XXXXXXX..XXXXXXX 100644
211
--- a/hw/arm/mainstone.c
212
+++ b/hw/arm/mainstone.c
213
@@ -XXX,XX +XXX,XX @@ static void mainstone2_machine_init(MachineClass *mc)
214
{
215
mc->desc = "Mainstone II (PXA27x)";
216
mc->init = mainstone_init;
217
+ mc->ignore_memory_transaction_failures = true;
218
}
219
220
DEFINE_MACHINE("mainstone", mainstone2_machine_init)
221
diff --git a/hw/arm/musicpal.c b/hw/arm/musicpal.c
222
index XXXXXXX..XXXXXXX 100644
223
--- a/hw/arm/musicpal.c
224
+++ b/hw/arm/musicpal.c
225
@@ -XXX,XX +XXX,XX @@ static void musicpal_machine_init(MachineClass *mc)
226
{
227
mc->desc = "Marvell 88w8618 / MusicPal (ARM926EJ-S)";
228
mc->init = musicpal_init;
229
+ mc->ignore_memory_transaction_failures = true;
230
}
231
232
DEFINE_MACHINE("musicpal", musicpal_machine_init)
233
diff --git a/hw/arm/netduino2.c b/hw/arm/netduino2.c
234
index XXXXXXX..XXXXXXX 100644
235
--- a/hw/arm/netduino2.c
236
+++ b/hw/arm/netduino2.c
237
@@ -XXX,XX +XXX,XX @@ static void netduino2_machine_init(MachineClass *mc)
238
{
239
mc->desc = "Netduino 2 Machine";
240
mc->init = netduino2_init;
241
+ mc->ignore_memory_transaction_failures = true;
242
}
243
244
DEFINE_MACHINE("netduino2", netduino2_machine_init)
245
diff --git a/hw/arm/nseries.c b/hw/arm/nseries.c
246
index XXXXXXX..XXXXXXX 100644
247
--- a/hw/arm/nseries.c
248
+++ b/hw/arm/nseries.c
249
@@ -XXX,XX +XXX,XX @@ static void n800_class_init(ObjectClass *oc, void *data)
250
mc->desc = "Nokia N800 tablet aka. RX-34 (OMAP2420)";
251
mc->init = n800_init;
252
mc->default_boot_order = "";
253
+ mc->ignore_memory_transaction_failures = true;
254
}
255
256
static const TypeInfo n800_type = {
257
@@ -XXX,XX +XXX,XX @@ static void n810_class_init(ObjectClass *oc, void *data)
258
mc->desc = "Nokia N810 tablet aka. RX-44 (OMAP2420)";
259
mc->init = n810_init;
260
mc->default_boot_order = "";
261
+ mc->ignore_memory_transaction_failures = true;
262
}
263
264
static const TypeInfo n810_type = {
265
diff --git a/hw/arm/omap_sx1.c b/hw/arm/omap_sx1.c
266
index XXXXXXX..XXXXXXX 100644
267
--- a/hw/arm/omap_sx1.c
268
+++ b/hw/arm/omap_sx1.c
269
@@ -XXX,XX +XXX,XX @@ static void sx1_machine_v2_class_init(ObjectClass *oc, void *data)
270
271
mc->desc = "Siemens SX1 (OMAP310) V2";
272
mc->init = sx1_init_v2;
273
+ mc->ignore_memory_transaction_failures = true;
274
}
275
276
static const TypeInfo sx1_machine_v2_type = {
277
@@ -XXX,XX +XXX,XX @@ static void sx1_machine_v1_class_init(ObjectClass *oc, void *data)
278
279
mc->desc = "Siemens SX1 (OMAP310) V1";
280
mc->init = sx1_init_v1;
281
+ mc->ignore_memory_transaction_failures = true;
282
}
283
284
static const TypeInfo sx1_machine_v1_type = {
285
diff --git a/hw/arm/palm.c b/hw/arm/palm.c
286
index XXXXXXX..XXXXXXX 100644
287
--- a/hw/arm/palm.c
288
+++ b/hw/arm/palm.c
289
@@ -XXX,XX +XXX,XX @@ static void palmte_machine_init(MachineClass *mc)
290
{
291
mc->desc = "Palm Tungsten|E aka. Cheetah PDA (OMAP310)";
292
mc->init = palmte_init;
293
+ mc->ignore_memory_transaction_failures = true;
294
}
295
296
DEFINE_MACHINE("cheetah", palmte_machine_init)
297
diff --git a/hw/arm/raspi.c b/hw/arm/raspi.c
298
index XXXXXXX..XXXXXXX 100644
299
--- a/hw/arm/raspi.c
300
+++ b/hw/arm/raspi.c
301
@@ -XXX,XX +XXX,XX @@ static void raspi2_machine_init(MachineClass *mc)
302
mc->no_cdrom = 1;
303
mc->max_cpus = BCM2836_NCPUS;
304
mc->default_ram_size = 1024 * 1024 * 1024;
305
+ mc->ignore_memory_transaction_failures = true;
306
};
307
DEFINE_MACHINE("raspi2", raspi2_machine_init)
308
diff --git a/hw/arm/realview.c b/hw/arm/realview.c
309
index XXXXXXX..XXXXXXX 100644
310
--- a/hw/arm/realview.c
311
+++ b/hw/arm/realview.c
312
@@ -XXX,XX +XXX,XX @@ static void realview_eb_class_init(ObjectClass *oc, void *data)
313
mc->desc = "ARM RealView Emulation Baseboard (ARM926EJ-S)";
314
mc->init = realview_eb_init;
315
mc->block_default_type = IF_SCSI;
316
+ mc->ignore_memory_transaction_failures = true;
317
}
318
319
static const TypeInfo realview_eb_type = {
320
@@ -XXX,XX +XXX,XX @@ static void realview_eb_mpcore_class_init(ObjectClass *oc, void *data)
321
mc->init = realview_eb_mpcore_init;
322
mc->block_default_type = IF_SCSI;
323
mc->max_cpus = 4;
324
+ mc->ignore_memory_transaction_failures = true;
325
}
326
327
static const TypeInfo realview_eb_mpcore_type = {
328
@@ -XXX,XX +XXX,XX @@ static void realview_pb_a8_class_init(ObjectClass *oc, void *data)
329
330
mc->desc = "ARM RealView Platform Baseboard for Cortex-A8";
331
mc->init = realview_pb_a8_init;
332
+ mc->ignore_memory_transaction_failures = true;
333
}
334
335
static const TypeInfo realview_pb_a8_type = {
336
@@ -XXX,XX +XXX,XX @@ static void realview_pbx_a9_class_init(ObjectClass *oc, void *data)
337
mc->desc = "ARM RealView Platform Baseboard Explore for Cortex-A9";
338
mc->init = realview_pbx_a9_init;
339
mc->max_cpus = 4;
340
+ mc->ignore_memory_transaction_failures = true;
341
}
342
343
static const TypeInfo realview_pbx_a9_type = {
344
diff --git a/hw/arm/sabrelite.c b/hw/arm/sabrelite.c
345
index XXXXXXX..XXXXXXX 100644
346
--- a/hw/arm/sabrelite.c
347
+++ b/hw/arm/sabrelite.c
348
@@ -XXX,XX +XXX,XX @@ static void sabrelite_machine_init(MachineClass *mc)
349
mc->desc = "Freescale i.MX6 Quad SABRE Lite Board (Cortex A9)";
350
mc->init = sabrelite_init;
351
mc->max_cpus = FSL_IMX6_NUM_CPUS;
352
+ mc->ignore_memory_transaction_failures = true;
353
}
354
355
DEFINE_MACHINE("sabrelite", sabrelite_machine_init)
356
diff --git a/hw/arm/spitz.c b/hw/arm/spitz.c
357
index XXXXXXX..XXXXXXX 100644
358
--- a/hw/arm/spitz.c
359
+++ b/hw/arm/spitz.c
360
@@ -XXX,XX +XXX,XX @@ static void akitapda_class_init(ObjectClass *oc, void *data)
361
362
mc->desc = "Sharp SL-C1000 (Akita) PDA (PXA270)";
363
mc->init = akita_init;
364
+ mc->ignore_memory_transaction_failures = true;
365
}
366
367
static const TypeInfo akitapda_type = {
368
@@ -XXX,XX +XXX,XX @@ static void spitzpda_class_init(ObjectClass *oc, void *data)
369
mc->desc = "Sharp SL-C3000 (Spitz) PDA (PXA270)";
370
mc->init = spitz_init;
371
mc->block_default_type = IF_IDE;
372
+ mc->ignore_memory_transaction_failures = true;
373
}
374
375
static const TypeInfo spitzpda_type = {
376
@@ -XXX,XX +XXX,XX @@ static void borzoipda_class_init(ObjectClass *oc, void *data)
377
mc->desc = "Sharp SL-C3100 (Borzoi) PDA (PXA270)";
378
mc->init = borzoi_init;
379
mc->block_default_type = IF_IDE;
380
+ mc->ignore_memory_transaction_failures = true;
381
}
382
383
static const TypeInfo borzoipda_type = {
384
@@ -XXX,XX +XXX,XX @@ static void terrierpda_class_init(ObjectClass *oc, void *data)
385
mc->desc = "Sharp SL-C3200 (Terrier) PDA (PXA270)";
386
mc->init = terrier_init;
387
mc->block_default_type = IF_IDE;
388
+ mc->ignore_memory_transaction_failures = true;
389
}
390
391
static const TypeInfo terrierpda_type = {
392
diff --git a/hw/arm/stellaris.c b/hw/arm/stellaris.c
393
index XXXXXXX..XXXXXXX 100644
394
--- a/hw/arm/stellaris.c
395
+++ b/hw/arm/stellaris.c
396
@@ -XXX,XX +XXX,XX @@ static void lm3s811evb_class_init(ObjectClass *oc, void *data)
397
398
mc->desc = "Stellaris LM3S811EVB";
399
mc->init = lm3s811evb_init;
400
+ mc->ignore_memory_transaction_failures = true;
401
}
402
403
static const TypeInfo lm3s811evb_type = {
404
@@ -XXX,XX +XXX,XX @@ static void lm3s6965evb_class_init(ObjectClass *oc, void *data)
405
406
mc->desc = "Stellaris LM3S6965EVB";
407
mc->init = lm3s6965evb_init;
408
+ mc->ignore_memory_transaction_failures = true;
409
}
410
411
static const TypeInfo lm3s6965evb_type = {
412
diff --git a/hw/arm/tosa.c b/hw/arm/tosa.c
413
index XXXXXXX..XXXXXXX 100644
414
--- a/hw/arm/tosa.c
415
+++ b/hw/arm/tosa.c
416
@@ -XXX,XX +XXX,XX @@ static void tosapda_machine_init(MachineClass *mc)
417
mc->desc = "Sharp SL-6000 (Tosa) PDA (PXA255)";
418
mc->init = tosa_init;
419
mc->block_default_type = IF_IDE;
420
+ mc->ignore_memory_transaction_failures = true;
421
}
422
423
DEFINE_MACHINE("tosa", tosapda_machine_init)
424
diff --git a/hw/arm/versatilepb.c b/hw/arm/versatilepb.c
425
index XXXXXXX..XXXXXXX 100644
426
--- a/hw/arm/versatilepb.c
427
+++ b/hw/arm/versatilepb.c
428
@@ -XXX,XX +XXX,XX @@ static void versatilepb_class_init(ObjectClass *oc, void *data)
429
mc->desc = "ARM Versatile/PB (ARM926EJ-S)";
430
mc->init = vpb_init;
431
mc->block_default_type = IF_SCSI;
432
+ mc->ignore_memory_transaction_failures = true;
433
}
434
435
static const TypeInfo versatilepb_type = {
436
@@ -XXX,XX +XXX,XX @@ static void versatileab_class_init(ObjectClass *oc, void *data)
437
mc->desc = "ARM Versatile/AB (ARM926EJ-S)";
438
mc->init = vab_init;
439
mc->block_default_type = IF_SCSI;
440
+ mc->ignore_memory_transaction_failures = true;
441
}
442
443
static const TypeInfo versatileab_type = {
444
diff --git a/hw/arm/vexpress.c b/hw/arm/vexpress.c
445
index XXXXXXX..XXXXXXX 100644
446
--- a/hw/arm/vexpress.c
447
+++ b/hw/arm/vexpress.c
448
@@ -XXX,XX +XXX,XX @@ static void vexpress_class_init(ObjectClass *oc, void *data)
449
mc->desc = "ARM Versatile Express";
450
mc->init = vexpress_common_init;
451
mc->max_cpus = 4;
452
+ mc->ignore_memory_transaction_failures = true;
453
}
454
455
static void vexpress_a9_class_init(ObjectClass *oc, void *data)
456
diff --git a/hw/arm/xilinx_zynq.c b/hw/arm/xilinx_zynq.c
457
index XXXXXXX..XXXXXXX 100644
458
--- a/hw/arm/xilinx_zynq.c
459
+++ b/hw/arm/xilinx_zynq.c
460
@@ -XXX,XX +XXX,XX @@ static void zynq_machine_init(MachineClass *mc)
461
mc->init = zynq_init;
462
mc->max_cpus = 1;
463
mc->no_sdcard = 1;
464
+ mc->ignore_memory_transaction_failures = true;
465
}
466
467
DEFINE_MACHINE("xilinx-zynq-a9", zynq_machine_init)
468
diff --git a/hw/arm/xlnx-ep108.c b/hw/arm/xlnx-ep108.c
469
index XXXXXXX..XXXXXXX 100644
470
--- a/hw/arm/xlnx-ep108.c
471
+++ b/hw/arm/xlnx-ep108.c
472
@@ -XXX,XX +XXX,XX @@ static void xlnx_ep108_machine_init(MachineClass *mc)
473
mc->init = xlnx_ep108_init;
474
mc->block_default_type = IF_IDE;
475
mc->units_per_default_bus = 1;
476
+ mc->ignore_memory_transaction_failures = true;
477
}
478
479
DEFINE_MACHINE("xlnx-ep108", xlnx_ep108_machine_init)
480
@@ -XXX,XX +XXX,XX @@ static void xlnx_zcu102_machine_init(MachineClass *mc)
481
mc->init = xlnx_ep108_init;
482
mc->block_default_type = IF_IDE;
483
mc->units_per_default_bus = 1;
484
+ mc->ignore_memory_transaction_failures = true;
485
}
486
487
DEFINE_MACHINE("xlnx-zcu102", xlnx_zcu102_machine_init)
488
diff --git a/hw/arm/z2.c b/hw/arm/z2.c
489
index XXXXXXX..XXXXXXX 100644
490
--- a/hw/arm/z2.c
491
+++ b/hw/arm/z2.c
492
@@ -XXX,XX +XXX,XX @@ static void z2_machine_init(MachineClass *mc)
493
{
494
mc->desc = "Zipit Z2 (PXA27x)";
495
mc->init = z2_init;
496
+ mc->ignore_memory_transaction_failures = true;
497
}
498
499
DEFINE_MACHINE("z2", z2_machine_init)
500
--
147
--
501
2.7.4
148
2.20.1
502
149
503
150
diff view generated by jsdifflib
1
The ARMv7M architecture specifies that most of the addresses in the
1
The version of the SYSINFO Register Block in the SSE-300 has
2
PPB region (which includes the NVIC, systick and system registers)
2
different CIDR/PIDR register values to the SSE-200; pass in
3
are not accessible to unprivileged accesses, which should
3
the sse-version property and use it to select the correct
4
BusFault with a few exceptions:
4
ID register values.
5
* the STIR is configurably user-accessible
6
* the ITM (which we don't implement at all) is always
7
user-accessible
8
9
Implement this by switching the register access functions
10
to the _with_attrs scheme that lets us distinguish user
11
mode accesses.
12
13
This allows us to pull the handling of the CCR.USERSETMPEND
14
flag up to the level where we can make it generate a BusFault
15
as it should for non-permitted accesses.
16
17
Note that until the core ARM CPU code implements turning
18
MEMTX_ERROR into a BusFault the registers will continue to
19
act as RAZ/WI to user accesses.
20
5
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
22
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
7
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
23
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
24
Message-id: 1501692241-23310-16-git-send-email-peter.maydell@linaro.org
9
Message-id: 20210219144617.4782-9-peter.maydell@linaro.org
25
---
10
---
26
hw/intc/armv7m_nvic.c | 58 ++++++++++++++++++++++++++++++++++++---------------
11
include/hw/misc/iotkit-sysinfo.h | 1 +
27
1 file changed, 41 insertions(+), 17 deletions(-)
12
hw/arm/armsse.c | 2 ++
13
hw/misc/iotkit-sysinfo.c | 29 +++++++++++++++++++++++++++--
14
3 files changed, 30 insertions(+), 2 deletions(-)
28
15
29
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
16
diff --git a/include/hw/misc/iotkit-sysinfo.h b/include/hw/misc/iotkit-sysinfo.h
30
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
31
--- a/hw/intc/armv7m_nvic.c
18
--- a/include/hw/misc/iotkit-sysinfo.h
32
+++ b/hw/intc/armv7m_nvic.c
19
+++ b/include/hw/misc/iotkit-sysinfo.h
33
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value)
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;
34
}
35
}
35
case 0xf00: /* Software Triggered Interrupt Register */
36
+ object_property_set_int(OBJECT(&s->sysinfo), "sse-version",
36
{
37
+ info->sse_version, &error_abort);
37
- /* user mode can only write to STIR if CCR.USERSETMPEND permits it */
38
if (!sysbus_realize(SYS_BUS_DEVICE(&s->sysinfo), errp)) {
38
int excnum = (value & 0x1ff) + NVIC_FIRST_IRQ;
39
return;
39
- if (excnum < s->num_irq &&
40
}
40
- (arm_current_el(&cpu->env) ||
41
diff --git a/hw/misc/iotkit-sysinfo.c b/hw/misc/iotkit-sysinfo.c
41
- (cpu->env.v7m.ccr & R_V7M_CCR_USERSETMPEND_MASK))) {
42
index XXXXXXX..XXXXXXX 100644
42
+ if (excnum < s->num_irq) {
43
--- a/hw/misc/iotkit-sysinfo.c
43
armv7m_nvic_set_pending(s, excnum);
44
+++ b/hw/misc/iotkit-sysinfo.c
44
}
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;
45
break;
68
break;
46
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value)
69
case A_PID4 ... A_CID3:
47
}
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);
48
}
92
}
49
93
50
-static uint64_t nvic_sysreg_read(void *opaque, hwaddr addr,
94
+static void iotkit_sysinfo_realize(DeviceState *dev, Error **errp)
51
- unsigned size)
52
+static bool nvic_user_access_ok(NVICState *s, hwaddr offset)
53
+{
95
+{
54
+ /* Return true if unprivileged access to this register is permitted. */
96
+ IoTKitSysInfo *s = IOTKIT_SYSINFO(dev);
55
+ switch (offset) {
97
+
56
+ case 0xf00: /* STIR: accessible only if CCR.USERSETMPEND permits */
98
+ if (!armsse_version_valid(s->sse_version)) {
57
+ return s->cpu->env.v7m.ccr & R_V7M_CCR_USERSETMPEND_MASK;
99
+ error_setg(errp, "invalid sse-version value %d", s->sse_version);
58
+ default:
100
+ return;
59
+ /* All other user accesses cause a BusFault unconditionally */
60
+ return false;
61
+ }
101
+ }
62
+}
102
+}
63
+
103
+
64
+static MemTxResult nvic_sysreg_read(void *opaque, hwaddr addr,
104
static void iotkit_sysinfo_class_init(ObjectClass *klass, void *data)
65
+ uint64_t *data, unsigned size,
66
+ MemTxAttrs attrs)
67
{
105
{
68
NVICState *s = (NVICState *)opaque;
106
DeviceClass *dc = DEVICE_CLASS(klass);
69
uint32_t offset = addr;
107
@@ -XXX,XX +XXX,XX @@ static void iotkit_sysinfo_class_init(ObjectClass *klass, void *data)
70
unsigned i, startvec, end;
108
* This device has no guest-modifiable state and so it
71
uint32_t val;
109
* does not need a reset function or VMState.
72
110
*/
73
+ if (attrs.user && !nvic_user_access_ok(s, addr)) {
111
-
74
+ /* Generate BusFault for unprivileged accesses */
112
+ dc->realize = iotkit_sysinfo_realize;
75
+ return MEMTX_ERROR;
113
device_class_set_props(dc, iotkit_sysinfo_props);
76
+ }
77
+
78
switch (offset) {
79
/* reads of set and clear both return the status */
80
case 0x100 ... 0x13f: /* NVIC Set enable */
81
@@ -XXX,XX +XXX,XX @@ static uint64_t nvic_sysreg_read(void *opaque, hwaddr addr,
82
}
83
84
trace_nvic_sysreg_read(addr, val, size);
85
- return val;
86
+ *data = val;
87
+ return MEMTX_OK;
88
}
114
}
89
115
90
-static void nvic_sysreg_write(void *opaque, hwaddr addr,
91
- uint64_t value, unsigned size)
92
+static MemTxResult nvic_sysreg_write(void *opaque, hwaddr addr,
93
+ uint64_t value, unsigned size,
94
+ MemTxAttrs attrs)
95
{
96
NVICState *s = (NVICState *)opaque;
97
uint32_t offset = addr;
98
@@ -XXX,XX +XXX,XX @@ static void nvic_sysreg_write(void *opaque, hwaddr addr,
99
100
trace_nvic_sysreg_write(addr, value, size);
101
102
+ if (attrs.user && !nvic_user_access_ok(s, addr)) {
103
+ /* Generate BusFault for unprivileged accesses */
104
+ return MEMTX_ERROR;
105
+ }
106
+
107
switch (offset) {
108
case 0x100 ... 0x13f: /* NVIC Set enable */
109
offset += 0x80;
110
@@ -XXX,XX +XXX,XX @@ static void nvic_sysreg_write(void *opaque, hwaddr addr,
111
}
112
}
113
nvic_irq_update(s);
114
- return;
115
+ return MEMTX_OK;
116
case 0x200 ... 0x23f: /* NVIC Set pend */
117
/* the special logic in armv7m_nvic_set_pending()
118
* is not needed since IRQs are never escalated
119
@@ -XXX,XX +XXX,XX @@ static void nvic_sysreg_write(void *opaque, hwaddr addr,
120
}
121
}
122
nvic_irq_update(s);
123
- return;
124
+ return MEMTX_OK;
125
case 0x300 ... 0x33f: /* NVIC Active */
126
- return; /* R/O */
127
+ return MEMTX_OK; /* R/O */
128
case 0x400 ... 0x5ef: /* NVIC Priority */
129
startvec = 8 * (offset - 0x400) + NVIC_FIRST_IRQ; /* vector # */
130
131
@@ -XXX,XX +XXX,XX @@ static void nvic_sysreg_write(void *opaque, hwaddr addr,
132
set_prio(s, startvec + i, (value >> (i * 8)) & 0xff);
133
}
134
nvic_irq_update(s);
135
- return;
136
+ return MEMTX_OK;
137
case 0xd18 ... 0xd23: /* System Handler Priority. */
138
for (i = 0; i < size; i++) {
139
unsigned hdlidx = (offset - 0xd14) + i;
140
set_prio(s, hdlidx, (value >> (i * 8)) & 0xff);
141
}
142
nvic_irq_update(s);
143
- return;
144
+ return MEMTX_OK;
145
}
146
if (size == 4) {
147
nvic_writel(s, offset, value);
148
- return;
149
+ return MEMTX_OK;
150
}
151
qemu_log_mask(LOG_GUEST_ERROR,
152
"NVIC: Bad write of size %d at offset 0x%x\n", size, offset);
153
+ /* This is UNPREDICTABLE; treat as RAZ/WI */
154
+ return MEMTX_OK;
155
}
156
157
static const MemoryRegionOps nvic_sysreg_ops = {
158
- .read = nvic_sysreg_read,
159
- .write = nvic_sysreg_write,
160
+ .read_with_attrs = nvic_sysreg_read,
161
+ .write_with_attrs = nvic_sysreg_write,
162
.endianness = DEVICE_NATIVE_ENDIAN,
163
};
164
165
--
116
--
166
2.7.4
117
2.20.1
167
118
168
119
diff view generated by jsdifflib
New 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.
1
3
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
New patch
1
For SSE-300, the SYSINFO register block has two new registers:
1
2
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
New patch
1
The SSE-300 includes a counter module; implement a model of it.
1
2
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
1
For embedded systems, notably ARM, one common use of ELF
1
The SSE-300 includes some timers which are a different kind to
2
file segments is that the 'physical addresses' represent load addresses
2
those in the SSE-200. Model them.
3
and the 'virtual addresses' execution addresses, such that
4
the load addresses are packed into ROM or flash, and the
5
relocation and zero-initialization of data is done at runtime.
6
This means that the 'memsz' in the segment header represents
7
the runtime size of the segment, but the size that needs to
8
be loaded is only the 'filesz'. In particular, paddr+memsz
9
may overlap with the next segment to be loaded, as in this
10
example:
11
3
12
0x70000001 off 0x00007f68 vaddr 0x00008150 paddr 0x00008150 align 2**2
4
These timers are documented in the SSE-123 Example Subsystem
13
filesz 0x00000008 memsz 0x00000008 flags r--
5
Technical Reference Manual:
14
LOAD off 0x000000f4 vaddr 0x00000000 paddr 0x00000000 align 2**2
6
https://developer.arm.com/documentation/101370/latest/
15
filesz 0x00000124 memsz 0x00000124 flags r--
16
LOAD off 0x00000218 vaddr 0x00000400 paddr 0x00000400 align 2**3
17
filesz 0x00007d58 memsz 0x00007d58 flags r-x
18
LOAD off 0x00007f70 vaddr 0x20000140 paddr 0x00008158 align 2**3
19
filesz 0x00000a80 memsz 0x000022f8 flags rw-
20
LOAD off 0x000089f0 vaddr 0x20002438 paddr 0x00008bd8 align 2**0
21
filesz 0x00000000 memsz 0x00004000 flags rw-
22
LOAD off 0x000089f0 vaddr 0x20000000 paddr 0x20000000 align 2**0
23
filesz 0x00000000 memsz 0x00000140 flags rw-
24
25
where the segment at paddr 0x8158 has a memsz of 0x2258 and
26
would overlap with the segment at paddr 0x8bd8 if QEMU's loader
27
tried to honour it. (At runtime the segments will not overlap
28
since their vaddrs are more widely spaced than their paddrs.)
29
30
Currently if you try to load an ELF file like this with QEMU then
31
it will fail with an error "rom: requested regions overlap",
32
because we create a ROM image for each segment using the memsz
33
as the size.
34
35
Support ELF files using this scheme, by truncating the
36
zero-initialized part of the segment if it would overlap another
37
segment. This will retain the existing loader behaviour for
38
all ELF files we currently accept, and also accept ELF files
39
which only need 'filesz' bytes to be loaded.
40
7
41
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
42
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
43
Message-id: 1502116754-18867-2-git-send-email-peter.maydell@linaro.org
11
Message-id: 20210219144617.4782-13-peter.maydell@linaro.org
44
---
12
---
45
include/hw/elf_ops.h | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
13
include/hw/timer/sse-timer.h | 53 ++++
46
1 file changed, 48 insertions(+)
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
47
23
48
diff --git a/include/hw/elf_ops.h b/include/hw/elf_ops.h
24
diff --git a/include/hw/timer/sse-timer.h b/include/hw/timer/sse-timer.h
49
index XXXXXXX..XXXXXXX 100644
25
new file mode 100644
50
--- a/include/hw/elf_ops.h
26
index XXXXXXX..XXXXXXX
51
+++ b/include/hw/elf_ops.h
27
--- /dev/null
52
@@ -XXX,XX +XXX,XX @@ static int glue(load_elf, SZ)(const char *name, int fd,
28
+++ b/include/hw/timer/sse-timer.h
53
goto fail;
29
@@ -XXX,XX +XXX,XX @@
54
}
30
+/*
55
}
31
+ * Arm SSE Subsystem System Timer
56
+
32
+ *
57
+ /* The ELF spec is somewhat vague about the purpose of the
33
+ * Copyright (c) 2020 Linaro Limited
58
+ * physical address field. One common use in the embedded world
34
+ * Written by Peter Maydell
59
+ * is that physical address field specifies the load address
35
+ *
60
+ * and the virtual address field specifies the execution address.
36
+ * This program is free software; you can redistribute it and/or modify
61
+ * Segments are packed into ROM or flash, and the relocation
37
+ * it under the terms of the GNU General Public License version 2 or
62
+ * and zero-initialization of data is done at runtime. This
38
+ * (at your option) any later version.
63
+ * means that the memsz header represents the runtime size of the
39
+ */
64
+ * segment, but the filesz represents the loadtime size. If
40
+
65
+ * we try to honour the memsz value for an ELF file like this
41
+/*
66
+ * we will end up with overlapping segments (which the
42
+ * This is a model of the "System timer" which is documented in
67
+ * loader.c code will later reject).
43
+ * the Arm SSE-123 Example Subsystem Technical Reference Manual:
68
+ * We support ELF files using this scheme by by checking whether
44
+ * https://developer.arm.com/documentation/101370/latest/
69
+ * paddr + memsz for this segment would overlap with any other
45
+ *
70
+ * segment. If so, then we assume it's using this scheme and
46
+ * QEMU interface:
71
+ * truncate the loaded segment to the filesz size.
47
+ * + QOM property "counter": link property to be set to the
72
+ * If the segment considered as being memsz size doesn't overlap
48
+ * TYPE_SSE_COUNTER timestamp counter device this timer runs off
73
+ * then we use memsz for the segment length, to handle ELF files
49
+ * + sysbus MMIO region 0: the register bank
74
+ * which assume that the loader will do the zero-initialization.
50
+ * + sysbus IRQ 0: timer interrupt
75
+ */
51
+ */
76
+ if (mem_size > file_size) {
52
+
77
+ /* If this segment's zero-init portion overlaps another
53
+#ifndef SSE_TIMER_H
78
+ * segment's data or zero-init portion, then truncate this one.
54
+#define SSE_TIMER_H
79
+ * Invalid ELF files where the segments overlap even when
55
+
80
+ * only file_size bytes are loaded will be rejected by
56
+#include "hw/sysbus.h"
81
+ * the ROM overlap check in loader.c, so we don't try to
57
+#include "qom/object.h"
82
+ * explicitly detect those here.
58
+#include "hw/timer/sse-counter.h"
83
+ */
59
+
84
+ int j;
60
+#define TYPE_SSE_TIMER "sse-timer"
85
+ elf_word zero_start = ph->p_paddr + file_size;
61
+OBJECT_DECLARE_SIMPLE_TYPE(SSETimer, SSE_TIMER)
86
+ elf_word zero_end = ph->p_paddr + mem_size;
62
+
87
+
63
+struct SSETimer {
88
+ for (j = 0; j < ehdr.e_phnum; j++) {
64
+ /*< private >*/
89
+ struct elf_phdr *jph = &phdr[j];
65
+ SysBusDevice parent_obj;
90
+
66
+
91
+ if (i != j && jph->p_type == PT_LOAD) {
67
+ /*< public >*/
92
+ elf_word other_start = jph->p_paddr;
68
+ MemoryRegion iomem;
93
+ elf_word other_end = jph->p_paddr + jph->p_memsz;
69
+ qemu_irq irq;
94
+
70
+ SSECounter *counter;
95
+ if (!(other_start >= zero_end ||
71
+ QEMUTimer timer;
96
+ zero_start >= other_end)) {
72
+ Notifier counter_notifier;
97
+ mem_size = file_size;
73
+
98
+ break;
74
+ uint32_t cntfrq;
99
+ }
75
+ uint32_t cntp_ctl;
100
+ }
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);
101
+ }
402
+ }
102
+ }
403
+ }
103
+
404
+ }
104
/* address_offset is hack for kernel images that are
405
+ sse_update_irq(s);
105
linked at the wrong physical address. */
406
+ break;
106
if (translate_fn) {
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"
107
--
622
--
108
2.7.4
623
2.20.1
109
624
110
625
diff view generated by jsdifflib
New 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:
1
7
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
1
From: Thomas Huth <thuth@redhat.com>
1
In the SSE-300 the CPU_WAIT and NMI_ENABLE registers have
2
moved offsets, so they are now where the SSE-200's WICCTRL
3
and EWCTRL were. The SSE-300 does not have WICCTLR or EWCTRL
4
at all, and the old offsets are reserved:
2
5
3
QEMU currently shows some unexpected behavior when the user trys to
6
Offset SSE-200 SSE-300
4
do a "device_add digic" on an unrelated ARM machine like integratorcp
7
-----------------------------------
5
in "-nographic" mode (the device_add command does not immediately
8
0x118 CPUWAIT reserved
6
return to the monitor prompt), and trying to "device_del" the device
9
0x118 NMI_ENABLE reserved
7
later results in a "qemu/qdev-monitor.c:872:qdev_unplug: assertion
10
0x120 WICCTRL CPUWAIT
8
failed: (hotplug_ctrl)" error condition.
11
0x124 EWCTRL NMI_ENABLE
9
Looking at the realize function of the device, it uses serial_hds
10
directly and this means that the device can not be added a second
11
time, so let's simply mark it with "user_creatable = false" now.
12
12
13
Signed-off-by: Thomas Huth <thuth@redhat.com>
13
Handle this reshuffle, and the fact that SSE-300 has only
14
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
one CPU and so only one active bit in CPUWAIT.
15
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
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
16
---
20
---
17
hw/arm/digic.c | 2 ++
21
hw/misc/iotkit-sysctl.c | 88 +++++++++++++++++++++++++++++++++++------
18
1 file changed, 2 insertions(+)
22
1 file changed, 76 insertions(+), 12 deletions(-)
19
23
20
diff --git a/hw/arm/digic.c b/hw/arm/digic.c
24
diff --git a/hw/misc/iotkit-sysctl.c b/hw/misc/iotkit-sysctl.c
21
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
22
--- a/hw/arm/digic.c
26
--- a/hw/misc/iotkit-sysctl.c
23
+++ b/hw/arm/digic.c
27
+++ b/hw/misc/iotkit-sysctl.c
24
@@ -XXX,XX +XXX,XX @@ static void digic_class_init(ObjectClass *oc, void *data)
28
@@ -XXX,XX +XXX,XX @@ static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
25
DeviceClass *dc = DEVICE_CLASS(oc);
29
}
26
30
break;
27
dc->realize = digic_realize;
31
case A_CPUWAIT:
28
+ /* Reason: Uses serial_hds in the realize function --> not usable twice */
32
- r = s->cpuwait;
29
+ dc->user_creatable = false;
33
+ switch (s->sse_version) {
34
+ case ARMSSE_IOTKIT:
35
+ case ARMSSE_SSE200:
36
+ r = s->cpuwait;
37
+ break;
38
+ case ARMSSE_SSE300:
39
+ /* In SSE300 this is reserved (for INITSVTOR2) */
40
+ goto bad_offset;
41
+ default:
42
+ g_assert_not_reached();
43
+ }
44
break;
45
case A_NMI_ENABLE:
46
switch (s->sse_version) {
47
@@ -XXX,XX +XXX,XX @@ static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
48
case ARMSSE_SSE200:
49
r = s->nmi_enable;
50
break;
51
+ case ARMSSE_SSE300:
52
+ /* In SSE300 this is reserved (for INITSVTOR3) */
53
+ goto bad_offset;
54
default:
55
g_assert_not_reached();
56
}
57
break;
58
case A_WICCTRL:
59
- r = s->wicctrl;
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;
30
}
88
}
31
89
32
static const TypeInfo digic_type_info = {
90
+static void cpuwait_write(IoTKitSysCtl *s, uint32_t value)
91
+{
92
+ int num_cpus = (s->sse_version == ARMSSE_SSE300) ? 1 : 2;
93
+ int i;
94
+
95
+ for (i = 0; i < num_cpus; i++) {
96
+ uint32_t mask = 1 << i;
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
{
108
@@ -XXX,XX +XXX,XX @@ static void iotkit_sysctl_write(void *opaque, hwaddr offset,
109
set_init_vtor(0, s->initsvtor0);
110
break;
111
case A_CPUWAIT:
112
- if ((s->cpuwait & 1) && !(value & 1)) {
113
- /* Powering up CPU 0 */
114
- arm_set_cpu_on_and_reset(0);
115
+ switch (s->sse_version) {
116
+ case ARMSSE_IOTKIT:
117
+ case ARMSSE_SSE200:
118
+ cpuwait_write(s, value);
119
+ break;
120
+ case ARMSSE_SSE300:
121
+ /* In SSE300 this is reserved (for INITSVTOR2) */
122
+ goto bad_offset;
123
+ default:
124
+ g_assert_not_reached();
125
}
126
- if ((s->cpuwait & 2) && !(value & 2)) {
127
- /* Powering up CPU 1 */
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
}
33
--
173
--
34
2.7.4
174
2.20.1
35
175
36
176
diff view generated by jsdifflib
New 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.
1
5
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
1
We currently store the M profile CPU register state PRIMASK and
1
The SSE-300 has a new PWRCTRL register at offset 0x1fc (previously
2
FAULTMASK in the daif field of the CPU state in its I and F
2
reserved). This register controls accessibility of some registers
3
bits. This is a legacy from the original implementation, which
3
in the Power Policy Units (PPUs). Since QEMU doesn't implement
4
tried to share the cpu_exec_interrupt code between A profile
4
the PPUs, we don't need to implement any real behaviour for this
5
and M profile. We've since separated out the two cases because
5
register, so we just handle the UNLOCK bit which controls whether
6
they are significantly different, so now there is no common
6
writes to the register itself are permitted and otherwise make it
7
code between M and A profile which looks at env->daif: all the
7
be reads-as-written.
8
uses are either in A-only or M-only code paths. Sharing the state
9
fields now is just confusing, and will make things awkward
10
when we implement v8M, where the PRIMASK and FAULTMASK
11
registers are banked between security states.
12
13
Switch M profile over to using v7m.faultmask and v7m.primask
14
fields for these registers.
15
8
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
17
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
18
Message-id: 1501692241-23310-10-git-send-email-peter.maydell@linaro.org
12
Message-id: 20210219144617.4782-17-peter.maydell@linaro.org
19
---
13
---
20
target/arm/cpu.h | 4 +++-
14
include/hw/misc/iotkit-sysctl.h | 1 +
21
hw/intc/armv7m_nvic.c | 4 ++--
15
hw/misc/iotkit-sysctl.c | 52 +++++++++++++++++++++++++++++++++
22
target/arm/cpu.c | 5 -----
16
2 files changed, 53 insertions(+)
23
target/arm/helper.c | 18 +++++-------------
24
target/arm/machine.c | 33 +++++++++++++++++++++++++++++++++
25
5 files changed, 43 insertions(+), 21 deletions(-)
26
17
27
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
18
diff --git a/include/hw/misc/iotkit-sysctl.h b/include/hw/misc/iotkit-sysctl.h
28
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
29
--- a/target/arm/cpu.h
20
--- a/include/hw/misc/iotkit-sysctl.h
30
+++ b/target/arm/cpu.h
21
+++ b/include/hw/misc/iotkit-sysctl.h
31
@@ -XXX,XX +XXX,XX @@ typedef struct CPUARMState {
22
@@ -XXX,XX +XXX,XX @@ struct IoTKitSysCtl {
32
uint32_t bfar; /* BusFault Address */
23
uint32_t initsvtor1;
33
unsigned mpu_ctrl; /* MPU_CTRL */
24
uint32_t nmi_enable;
34
int exception;
25
uint32_t ewctrl;
35
+ uint32_t primask;
26
+ uint32_t pwrctrl;
36
+ uint32_t faultmask;
27
uint32_t pdcm_pd_sys_sense;
37
} v7m;
28
uint32_t pdcm_pd_sram0_sense;
38
29
uint32_t pdcm_pd_sram1_sense;
39
/* Information associated with an exception about to be taken:
30
diff --git a/hw/misc/iotkit-sysctl.c b/hw/misc/iotkit-sysctl.c
40
@@ -XXX,XX +XXX,XX @@ static inline int cpu_mmu_index(CPUARMState *env, bool ifetch)
41
* we're in a HardFault or NMI handler.
42
*/
43
if ((env->v7m.exception > 0 && env->v7m.exception <= 3)
44
- || env->daif & PSTATE_F) {
45
+ || env->v7m.faultmask) {
46
return arm_to_core_mmu_idx(ARMMMUIdx_MNegPri);
47
}
48
49
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
50
index XXXXXXX..XXXXXXX 100644
31
index XXXXXXX..XXXXXXX 100644
51
--- a/hw/intc/armv7m_nvic.c
32
--- a/hw/misc/iotkit-sysctl.c
52
+++ b/hw/intc/armv7m_nvic.c
33
+++ b/hw/misc/iotkit-sysctl.c
53
@@ -XXX,XX +XXX,XX @@ static inline int nvic_exec_prio(NVICState *s)
34
@@ -XXX,XX +XXX,XX @@ REG32(CPUWAIT, 0x118)
54
CPUARMState *env = &s->cpu->env;
35
REG32(NMI_ENABLE, 0x11c) /* BUSWAIT in IoTKit */
55
int running;
36
REG32(WICCTRL, 0x120)
56
37
REG32(EWCTRL, 0x124)
57
- if (env->daif & PSTATE_F) { /* FAULTMASK */
38
+REG32(PWRCTRL, 0x1fc)
58
+ if (env->v7m.faultmask) {
39
+ FIELD(PWRCTRL, PPU_ACCESS_UNLOCK, 0, 1)
59
running = -1;
40
+ FIELD(PWRCTRL, PPU_ACCESS_FILTER, 1, 1)
60
- } else if (env->daif & PSTATE_I) { /* PRIMASK */
41
REG32(PDCM_PD_SYS_SENSE, 0x200)
61
+ } else if (env->v7m.primask) {
42
REG32(PDCM_PD_SRAM0_SENSE, 0x20c)
62
running = 0;
43
REG32(PDCM_PD_SRAM1_SENSE, 0x210)
63
} else if (env->v7m.basepri > 0) {
44
@@ -XXX,XX +XXX,XX @@ static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
64
running = env->v7m.basepri & nvic_gprio_mask(s);
45
g_assert_not_reached();
65
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
66
index XXXXXXX..XXXXXXX 100644
67
--- a/target/arm/cpu.c
68
+++ b/target/arm/cpu.c
69
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_reset(CPUState *s)
70
uint32_t initial_pc; /* Loaded from 0x4 */
71
uint8_t *rom;
72
73
- /* For M profile we store FAULTMASK and PRIMASK in the
74
- * PSTATE F and I bits; these are both clear at reset.
75
- */
76
- env->daif &= ~(PSTATE_I | PSTATE_F);
77
-
78
/* The reset value of this bit is IMPDEF, but ARM recommends
79
* that it resets to 1, so QEMU always does that rather than making
80
* it dependent on CPU model.
81
diff --git a/target/arm/helper.c b/target/arm/helper.c
82
index XXXXXXX..XXXXXXX 100644
83
--- a/target/arm/helper.c
84
+++ b/target/arm/helper.c
85
@@ -XXX,XX +XXX,XX @@ static void do_v7m_exception_exit(ARMCPU *cpu)
86
87
if (env->v7m.exception != ARMV7M_EXCP_NMI) {
88
/* Auto-clear FAULTMASK on return from other than NMI */
89
- env->daif &= ~PSTATE_F;
90
+ env->v7m.faultmask = 0;
91
}
92
93
switch (armv7m_nvic_complete_irq(env->nvic, env->v7m.exception)) {
94
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(v7m_mrs)(CPUARMState *env, uint32_t reg)
95
return (env->v7m.control & R_V7M_CONTROL_SPSEL_MASK) ?
96
env->regs[13] : env->v7m.other_sp;
97
case 16: /* PRIMASK */
98
- return (env->daif & PSTATE_I) != 0;
99
+ return env->v7m.primask;
100
case 17: /* BASEPRI */
101
case 18: /* BASEPRI_MAX */
102
return env->v7m.basepri;
103
case 19: /* FAULTMASK */
104
- return (env->daif & PSTATE_F) != 0;
105
+ return env->v7m.faultmask;
106
default:
107
qemu_log_mask(LOG_GUEST_ERROR, "Attempt to read unknown special"
108
" register %d\n", reg);
109
@@ -XXX,XX +XXX,XX @@ void HELPER(v7m_msr)(CPUARMState *env, uint32_t maskreg, uint32_t val)
110
}
46
}
111
break;
47
break;
112
case 16: /* PRIMASK */
48
+ case A_PWRCTRL:
113
- if (val & 1) {
49
+ switch (s->sse_version) {
114
- env->daif |= PSTATE_I;
50
+ case ARMSSE_IOTKIT:
115
- } else {
51
+ case ARMSSE_SSE200:
116
- env->daif &= ~PSTATE_I;
52
+ goto bad_offset;
117
- }
53
+ case ARMSSE_SSE300:
118
+ env->v7m.primask = val & 1;
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
}
119
break;
66
break;
120
case 17: /* BASEPRI */
67
+ case A_PWRCTRL:
121
env->v7m.basepri = val & 0xff;
68
+ switch (s->sse_version) {
122
@@ -XXX,XX +XXX,XX @@ void HELPER(v7m_msr)(CPUARMState *env, uint32_t maskreg, uint32_t val)
69
+ case ARMSSE_IOTKIT:
123
env->v7m.basepri = val;
70
+ case ARMSSE_SSE200:
124
break;
71
+ goto bad_offset;
125
case 19: /* FAULTMASK */
72
+ case ARMSSE_SSE300:
126
- if (val & 1) {
73
+ if (!(s->pwrctrl & R_PWRCTRL_PPU_ACCESS_UNLOCK_MASK)) {
127
- env->daif |= PSTATE_F;
74
+ qemu_log_mask(LOG_GUEST_ERROR,
128
- } else {
75
+ "IoTKit PWRCTRL write when register locked\n");
129
- env->daif &= ~PSTATE_F;
76
+ break;
130
- }
77
+ }
131
+ env->v7m.faultmask = val & 1;
78
+ s->pwrctrl = value;
132
break;
79
+ break;
133
case 20: /* CONTROL */
80
+ default:
134
/* Writing to the SPSEL bit only has an effect if we are in
81
+ g_assert_not_reached();
135
diff --git a/target/arm/machine.c b/target/arm/machine.c
82
+ }
136
index XXXXXXX..XXXXXXX 100644
83
+ break;
137
--- a/target/arm/machine.c
84
case A_PDCM_PD_SYS_SENSE:
138
+++ b/target/arm/machine.c
85
switch (s->sse_version) {
139
@@ -XXX,XX +XXX,XX @@ static bool m_needed(void *opaque)
86
case ARMSSE_IOTKIT:
140
return arm_feature(env, ARM_FEATURE_M);
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
}
141
}
97
}
142
98
143
+static const VMStateDescription vmstate_m_faultmask_primask = {
99
+static bool sse300_needed(void *opaque)
144
+ .name = "cpu/m/faultmask-primask",
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",
145
+ .version_id = 1,
108
+ .version_id = 1,
146
+ .minimum_version_id = 1,
109
+ .minimum_version_id = 1,
110
+ .needed = sse300_needed,
147
+ .fields = (VMStateField[]) {
111
+ .fields = (VMStateField[]) {
148
+ VMSTATE_UINT32(env.v7m.faultmask, ARMCPU),
112
+ VMSTATE_UINT32(pwrctrl, IoTKitSysCtl),
149
+ VMSTATE_UINT32(env.v7m.primask, ARMCPU),
150
+ VMSTATE_END_OF_LIST()
113
+ VMSTATE_END_OF_LIST()
151
+ }
114
+ }
152
+};
115
+};
153
+
116
+
154
static const VMStateDescription vmstate_m = {
117
static bool sse200_needed(void *opaque)
155
.name = "cpu/m",
118
{
156
.version_id = 4,
119
IoTKitSysCtl *s = IOTKIT_SYSCTL(opaque);
157
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_m = {
120
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription iotkit_sysctl_vmstate = {
158
VMSTATE_UINT32(env.v7m.mpu_ctrl, ARMCPU),
121
},
159
VMSTATE_INT32(env.v7m.exception, ARMCPU),
122
.subsections = (const VMStateDescription*[]) {
160
VMSTATE_END_OF_LIST()
123
&iotkit_sysctl_sse200_vmstate,
161
+ },
124
+ &iotkit_sysctl_sse300_vmstate,
162
+ .subsections = (const VMStateDescription*[]) {
125
NULL
163
+ &vmstate_m_faultmask_primask,
164
+ NULL
165
}
126
}
166
};
127
};
167
168
@@ -XXX,XX +XXX,XX @@ static int get_cpsr(QEMUFile *f, void *opaque, size_t size,
169
CPUARMState *env = &cpu->env;
170
uint32_t val = qemu_get_be32(f);
171
172
+ if (arm_feature(env, ARM_FEATURE_M)) {
173
+ /* If the I or F bits are set then this is a migration from
174
+ * an old QEMU which still stored the M profile FAULTMASK
175
+ * and PRIMASK in env->daif. Set v7m.faultmask and v7m.primask
176
+ * accordingly, and then clear the bits so they don't confuse
177
+ * cpsr_write(). For a new QEMU, the bits here will always be
178
+ * clear, and the data is transferred using the
179
+ * vmstate_m_faultmask_primask subsection.
180
+ */
181
+ if (val & CPSR_F) {
182
+ env->v7m.faultmask = 1;
183
+ }
184
+ if (val & CPSR_I) {
185
+ env->v7m.primask = 1;
186
+ }
187
+ val &= ~(CPSR_F | CPSR_I);
188
+ }
189
+
190
env->aarch64 = ((val & PSTATE_nRW) == 0);
191
192
if (is_a64(env)) {
193
--
128
--
194
2.7.4
129
2.20.1
195
130
196
131
diff view generated by jsdifflib
New patch
1
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
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
1
For external aborts, we will want to be able to specify the EA
1
The SSE-200 and SSE-300 have different PID register values from the
2
(external abort type) bit in the syndrome field. Allow callers of
2
IoTKit for the sysctl register block. We incorrectly implemented the
3
deliver_fault() to do that by adding a field to ARMMMUFaultInfo which
3
SSE-200 with the same PID values as IoTKit. Fix the SSE-200 bug and
4
we use when constructing the syndrome values.
4
report these register values for SSE-300.
5
5
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
9
Message-id: 20210219144617.4782-19-peter.maydell@linaro.org
9
---
10
---
10
target/arm/internals.h | 2 ++
11
hw/misc/iotkit-sysctl.c | 21 +++++++++++++++++++--
11
target/arm/op_helper.c | 10 +++++-----
12
1 file changed, 19 insertions(+), 2 deletions(-)
12
2 files changed, 7 insertions(+), 5 deletions(-)
13
13
14
diff --git a/target/arm/internals.h b/target/arm/internals.h
14
diff --git a/hw/misc/iotkit-sysctl.c b/hw/misc/iotkit-sysctl.c
15
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/internals.h
16
--- a/hw/misc/iotkit-sysctl.c
17
+++ b/target/arm/internals.h
17
+++ b/hw/misc/iotkit-sysctl.c
18
@@ -XXX,XX +XXX,XX @@ void arm_handle_psci_call(ARMCPU *cpu);
18
@@ -XXX,XX +XXX,XX @@ REG32(CID2, 0xff8)
19
* @s2addr: Address that caused a fault at stage 2
19
REG32(CID3, 0xffc)
20
* @stage2: True if we faulted at stage 2
20
21
* @s1ptw: True if we faulted at stage 2 while doing a stage 1 page-table walk
21
/* PID/CID values */
22
+ * @ea: True if we should set the EA (external abort type) bit in syndrome
22
-static const int sysctl_id[] = {
23
*/
23
+static const int iotkit_sysctl_id[] = {
24
typedef struct ARMMMUFaultInfo ARMMMUFaultInfo;
24
0x04, 0x00, 0x00, 0x00, /* PID4..PID7 */
25
struct ARMMMUFaultInfo {
25
0x54, 0xb8, 0x0b, 0x00, /* PID0..PID3 */
26
target_ulong s2addr;
26
0x0d, 0xf0, 0x05, 0xb1, /* CID0..CID3 */
27
bool stage2;
28
bool s1ptw;
29
+ bool ea;
30
};
27
};
31
28
32
/* Do a page table walk and add page to TLB if possible */
29
+/* Also used by the SSE300 */
33
diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c
30
+static const int sse200_sysctl_id[] = {
34
index XXXXXXX..XXXXXXX 100644
31
+ 0x04, 0x00, 0x00, 0x00, /* PID4..PID7 */
35
--- a/target/arm/op_helper.c
32
+ 0x54, 0xb8, 0x1b, 0x00, /* PID0..PID3 */
36
+++ b/target/arm/op_helper.c
33
+ 0x0d, 0xf0, 0x05, 0xb1, /* CID0..CID3 */
37
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(neon_tbl)(CPUARMState *env, uint32_t ireg, uint32_t def,
34
+};
38
35
+
39
static inline uint32_t merge_syn_data_abort(uint32_t template_syn,
36
/*
40
unsigned int target_el,
37
* Set the initial secure vector table offset address for the core.
41
- bool same_el,
38
* This will take effect when the CPU next resets.
42
+ bool same_el, bool ea,
39
@@ -XXX,XX +XXX,XX @@ static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
43
bool s1ptw, bool is_write,
40
}
44
int fsc)
41
break;
45
{
42
case A_PID4 ... A_CID3:
46
@@ -XXX,XX +XXX,XX @@ static inline uint32_t merge_syn_data_abort(uint32_t template_syn,
43
- r = sysctl_id[(offset - A_PID4) / 4];
47
*/
44
+ switch (s->sse_version) {
48
if (!(template_syn & ARM_EL_ISV) || target_el != 2 || s1ptw) {
45
+ case ARMSSE_IOTKIT:
49
syn = syn_data_abort_no_iss(same_el,
46
+ r = iotkit_sysctl_id[(offset - A_PID4) / 4];
50
- 0, 0, s1ptw, is_write, fsc);
47
+ break;
51
+ ea, 0, s1ptw, is_write, fsc);
48
+ case ARMSSE_SSE200:
52
} else {
49
+ case ARMSSE_SSE300:
53
/* Fields: IL, ISV, SAS, SSE, SRT, SF and AR come from the template
50
+ r = sse200_sysctl_id[(offset - A_PID4) / 4];
54
* syndrome created at translation time.
51
+ break;
55
@@ -XXX,XX +XXX,XX @@ static inline uint32_t merge_syn_data_abort(uint32_t template_syn,
52
+ default:
56
*/
53
+ g_assert_not_reached();
57
syn = syn_data_abort_with_iss(same_el,
54
+ }
58
0, 0, 0, 0, 0,
55
break;
59
- 0, 0, s1ptw, is_write, fsc,
56
case A_SECDBGSET:
60
+ ea, 0, s1ptw, is_write, fsc,
57
case A_SECDBGCLR:
61
false);
62
/* Merge the runtime syndrome with the template syndrome. */
63
syn |= template_syn;
64
@@ -XXX,XX +XXX,XX @@ static void deliver_fault(ARMCPU *cpu, vaddr addr, MMUAccessType access_type,
65
}
66
67
if (access_type == MMU_INST_FETCH) {
68
- syn = syn_insn_abort(same_el, 0, fi->s1ptw, fsc);
69
+ syn = syn_insn_abort(same_el, fi->ea, fi->s1ptw, fsc);
70
exc = EXCP_PREFETCH_ABORT;
71
} else {
72
syn = merge_syn_data_abort(env->exception.syndrome, target_el,
73
- same_el, fi->s1ptw,
74
+ same_el, fi->ea, fi->s1ptw,
75
access_type == MMU_DATA_STORE,
76
fsc);
77
if (access_type == MMU_DATA_STORE
78
--
58
--
79
2.7.4
59
2.20.1
80
60
81
61
diff view generated by jsdifflib
New 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.
1
4
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
New patch
1
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
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
1
Currently get_phys_addr() has PMSAv7 handling before the
1
Convert the apb_ppc0 and apb_ppc1 fields in the ARMSSE state struct
2
"is translation disabled?" check, and then PMSAv5 after it.
2
to use an array instead of two separate fields. We already had one
3
Tidy this up by making the PMSAv5 code handle the "MPU disabled"
3
place in the code that wanted to be able to refer to the PPC by
4
case itself, so that we have all the PMSA code in one place.
4
index, and we're about to add more code like that.
5
This will make adding the PMSAv8 code slightly cleaner, and
6
also means that pre-v7 PMSA cores benefit from the MPU lookup
7
logging that the PMSAv7 codepath had.
8
5
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
7
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
11
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
13
Message-id: 1501692241-23310-4-git-send-email-peter.maydell@linaro.org
10
Message-id: 20210219144617.4782-22-peter.maydell@linaro.org
14
---
11
---
15
target/arm/helper.c | 38 ++++++++++++++++++++++----------------
12
include/hw/arm/armsse.h | 6 +++---
16
1 file changed, 22 insertions(+), 16 deletions(-)
13
hw/arm/armsse.c | 32 ++++++++++++++++++--------------
14
2 files changed, 21 insertions(+), 17 deletions(-)
17
15
18
diff --git a/target/arm/helper.c b/target/arm/helper.c
16
diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
19
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
20
--- a/target/arm/helper.c
18
--- a/include/hw/arm/armsse.h
21
+++ b/target/arm/helper.c
19
+++ b/include/hw/arm/armsse.h
22
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_pmsav5(CPUARMState *env, uint32_t address,
20
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_TYPE(ARMSSE, ARMSSEClass,
23
uint32_t base;
21
/* We have an IRQ splitter and an OR gate input for each external PPC
24
bool is_user = regime_is_user(env, mmu_idx);
22
* and the 2 internal PPCs
25
23
*/
26
+ if (regime_translation_disabled(env, mmu_idx)) {
24
+#define NUM_INTERNAL_PPCS 2
27
+ /* MPU disabled. */
25
#define NUM_EXTERNAL_PPCS (IOTS_NUM_AHB_EXP_PPC + IOTS_NUM_APB_EXP_PPC)
28
+ *phys_ptr = address;
26
-#define NUM_PPCS (NUM_EXTERNAL_PPCS + 2)
29
+ *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
27
+#define NUM_PPCS (NUM_EXTERNAL_PPCS + NUM_INTERNAL_PPCS)
30
+ return false;
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);
31
+ }
55
+ }
32
+
56
+
33
*phys_ptr = address;
57
for (i = 0; i < info->sram_banks; i++) {
34
for (n = 7; n >= 0; n--) {
58
char *name = g_strdup_printf("mpc%d", i);
35
base = env->cp15.c6_region[n];
59
object_initialize_child(obj, name, &s->mpc[i], TYPE_TZ_MPC);
36
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr(CPUARMState *env, target_ulong address,
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)
37
}
97
}
38
}
98
}
39
99
40
- /* pmsav7 has special handling for when MPU is disabled so call it before
100
- if (!sysbus_realize(SYS_BUS_DEVICE(&s->apb_ppc0), errp)) {
41
- * the common MMU/MPU disabled check below.
101
+ if (!sysbus_realize(SYS_BUS_DEVICE(&s->apb_ppc[0]), errp)) {
42
- */
102
return;
43
- if (arm_feature(env, ARM_FEATURE_PMSA) &&
44
- arm_feature(env, ARM_FEATURE_V7)) {
45
+ if (arm_feature(env, ARM_FEATURE_PMSA)) {
46
bool ret;
47
*page_size = TARGET_PAGE_SIZE;
48
- ret = get_phys_addr_pmsav7(env, address, access_type, mmu_idx,
49
- phys_ptr, prot, fsr);
50
- qemu_log_mask(CPU_LOG_MMU, "PMSAv7 MPU lookup for %s at 0x%08" PRIx32
51
+
52
+ if (arm_feature(env, ARM_FEATURE_V7)) {
53
+ /* PMSAv7 */
54
+ ret = get_phys_addr_pmsav7(env, address, access_type, mmu_idx,
55
+ phys_ptr, prot, fsr);
56
+ } else {
57
+ /* Pre-v7 MPU */
58
+ ret = get_phys_addr_pmsav5(env, address, access_type, mmu_idx,
59
+ phys_ptr, prot, fsr);
60
+ }
61
+ qemu_log_mask(CPU_LOG_MMU, "PMSA MPU lookup for %s at 0x%08" PRIx32
62
" mmu_idx %u -> %s (prot %c%c%c)\n",
63
access_type == MMU_DATA_LOAD ? "reading" :
64
(access_type == MMU_DATA_STORE ? "writing" : "execute"),
65
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr(CPUARMState *env, target_ulong address,
66
return ret;
67
}
103
}
68
104
69
+ /* Definitely a real MMU, not an MPU */
105
- sbd_apb_ppc0 = SYS_BUS_DEVICE(&s->apb_ppc0);
70
+
106
- dev_apb_ppc0 = DEVICE(&s->apb_ppc0);
71
if (regime_translation_disabled(env, mmu_idx)) {
107
+ sbd_apb_ppc0 = SYS_BUS_DEVICE(&s->apb_ppc[0]);
72
- /* MMU/MPU disabled. */
108
+ dev_apb_ppc0 = DEVICE(&s->apb_ppc[0]);
73
+ /* MMU disabled. */
109
74
*phys_ptr = address;
110
mr = sysbus_mmio_get_region(sbd_apb_ppc0, 0);
75
*prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
111
memory_region_add_subregion(&s->container, 0x40000000, mr);
76
*page_size = TARGET_PAGE_SIZE;
112
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
77
return 0;
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;
78
}
123
}
79
124
- mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->apb_ppc1), 0);
80
- if (arm_feature(env, ARM_FEATURE_PMSA)) {
125
+ mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->apb_ppc[1]), 0);
81
- /* Pre-v7 MPU */
126
memory_region_add_subregion(&s->container, 0x4002f000, mr);
82
- *page_size = TARGET_PAGE_SIZE;
127
83
- return get_phys_addr_pmsav5(env, address, access_type, mmu_idx,
128
- dev_apb_ppc1 = DEVICE(&s->apb_ppc1);
84
- phys_ptr, prot, fsr);
129
+ dev_apb_ppc1 = DEVICE(&s->apb_ppc[1]);
85
- }
130
qdev_connect_gpio_out_named(dev_secctl, "apb_ppc1_nonsec", 0,
86
-
131
qdev_get_gpio_in_named(dev_apb_ppc1,
87
if (regime_using_lpae_format(env, mmu_idx)) {
132
"cfg_nonsec", 0));
88
return get_phys_addr_lpae(env, address, access_type, mmu_idx, phys_ptr,
133
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
89
attrs, prot, page_size, fsr, fi);
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));
90
--
142
--
91
2.7.4
143
2.20.1
92
144
93
145
diff view generated by jsdifflib
New 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.
1
5
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
New patch
1
1
The SSE-300 is mostly the same as the SSE-200, but it has moved some
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
6
This commit adds the framework for this data-driven device placement,
7
and makes the CMSDK APB timer devices use it. Subsequent commits
8
will convert the other devices which differ between SSE-200 and
9
SSE-300.
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-24-peter.maydell@linaro.org
15
---
16
include/hw/arm/armsse.h | 3 +-
17
hw/arm/armsse.c | 147 +++++++++++++++++++++++++++++++++-------
18
2 files changed, 125 insertions(+), 25 deletions(-)
19
20
diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
21
index XXXXXXX..XXXXXXX 100644
22
--- a/include/hw/arm/armsse.h
23
+++ b/include/hw/arm/armsse.h
24
@@ -XXX,XX +XXX,XX @@ struct ARMSSE {
25
IoTKitSecCtl secctl;
26
TZPPC apb_ppc[NUM_INTERNAL_PPCS];
27
TZMPC mpc[IOTS_NUM_MPC];
28
- CMSDKAPBTimer timer0;
29
- CMSDKAPBTimer timer1;
30
+ CMSDKAPBTimer timer[2];
31
CMSDKAPBTimer s32ktimer;
32
qemu_or_irq ppc_irq_orgate;
33
SplitIRQ sec_resp_splitter;
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 @@
39
#include "hw/irq.h"
40
#include "hw/qdev-clock.h"
41
42
+/*
43
+ * The SSE-300 puts some devices in different places to the
44
+ * SSE-200 (and original IoTKit). We use an array of these structs
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
+ */
49
+
50
+#define NO_IRQ -1
51
+#define NO_PPC -1
52
+
53
+typedef struct ARMSSEDeviceInfo {
54
+ const char *name; /* name to use for the QOM object; NULL terminates list */
55
+ const char *type; /* QOM type name */
56
+ unsigned int index; /* Which of the N devices of this type is this ? */
57
+ hwaddr addr;
58
+ int ppc; /* Index of APB PPC this device is wired up to, or NO_PPC */
59
+ int ppc_port; /* Port number of this device on the PPC */
60
+ int irq; /* NO_IRQ, or 0..NUM_SSE_IRQS-1 */
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
}
131
}
132
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
--
272
2.20.1
273
274
diff view generated by jsdifflib
1
Define a new MachineClass field ignore_memory_transaction_failures.
1
Move the CMSDK dualtimer device handling into the data-driven
2
If this is flag is true then the CPU will ignore memory transaction
2
device placement framework.
3
failures which should cause the CPU to take an exception due to an
4
access to an unassigned physical address; the transaction will
5
instead return zero (for a read) or be ignored (for a write). This
6
should be set only by legacy board models which rely on the old
7
RAZ/WI behaviour for handling devices that QEMU does not yet model.
8
New board models should instead use "unimplemented-device" for all
9
memory ranges where the guest will attempt to probe for a device that
10
QEMU doesn't implement and a stub device is required.
11
12
We need this for ARM boards, where we're about to implement support for
13
generating external aborts on memory transaction failures. Too many
14
of our legacy board models rely on the RAZ/WI behaviour and we
15
would break currently working guests when their "probe for device"
16
code provoked an external abort rather than a RAZ.
17
3
18
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>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20210219144617.4782-25-peter.maydell@linaro.org
19
---
8
---
20
include/hw/boards.h | 11 +++++++++++
9
hw/arm/armsse.c | 35 +++++++++++++++++++++--------------
21
include/qom/cpu.h | 7 ++++++-
10
1 file changed, 21 insertions(+), 14 deletions(-)
22
qom/cpu.c | 7 +++++++
23
3 files changed, 24 insertions(+), 1 deletion(-)
24
11
25
diff --git a/include/hw/boards.h b/include/hw/boards.h
12
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
26
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
27
--- a/include/hw/boards.h
14
--- a/hw/arm/armsse.c
28
+++ b/include/hw/boards.h
15
+++ b/hw/arm/armsse.c
29
@@ -XXX,XX +XXX,XX @@ typedef struct {
16
@@ -XXX,XX +XXX,XX @@ static const ARMSSEDeviceInfo sse200_devices[] = {
30
* size than the target architecture's minimum. (Attempting to create
17
.ppc_port = 1,
31
* such a CPU will fail.) Note that changing this is a migration
18
.irq = 4,
32
* compatibility break for the machine.
19
},
33
+ * @ignore_memory_transaction_failures:
20
+ {
34
+ * If this is flag is true then the CPU will ignore memory transaction
21
+ .name = "dualtimer",
35
+ * failures which should cause the CPU to take an exception due to an
22
+ .type = TYPE_CMSDK_APB_DUALTIMER,
36
+ * access to an unassigned physical address; the transaction will instead
23
+ .index = 0,
37
+ * return zero (for a read) or be ignored (for a write). This should be
24
+ .addr = 0x40002000,
38
+ * set only by legacy board models which rely on the old RAZ/WI behaviour
25
+ .ppc = 0,
39
+ * for handling devices that QEMU does not yet model. New board models
26
+ .ppc_port = 2,
40
+ * should instead use "unimplemented-device" for all memory ranges where
27
+ .irq = 5,
41
+ * the guest will attempt to probe for a device that QEMU doesn't
28
+ },
42
+ * implement and a stub device is required.
29
{
43
*/
30
.name = NULL,
44
struct MachineClass {
31
}
45
/*< private >*/
32
@@ -XXX,XX +XXX,XX @@ static void armsse_init(Object *obj)
46
@@ -XXX,XX +XXX,XX @@ struct MachineClass {
33
object_initialize_child(obj, devinfo->name,
47
bool rom_file_has_mr;
34
&s->timer[devinfo->index],
48
int minimum_page_bits;
35
TYPE_CMSDK_APB_TIMER);
49
bool has_hotpluggable_cpus;
36
+ } else if (!strcmp(devinfo->type, TYPE_CMSDK_APB_DUALTIMER)) {
50
+ bool ignore_memory_transaction_failures;
37
+ assert(devinfo->index == 0);
51
int numa_mem_align_shift;
38
+ object_initialize_child(obj, devinfo->name, &s->dualtimer,
52
void (*numa_auto_assign_ram)(MachineClass *mc, NodeInfo *nodes,
39
+ TYPE_CMSDK_APB_DUALTIMER);
53
int nb_nodes, ram_addr_t size);
40
} else {
54
diff --git a/include/qom/cpu.h b/include/qom/cpu.h
41
g_assert_not_reached();
55
index XXXXXXX..XXXXXXX 100644
42
}
56
--- a/include/qom/cpu.h
43
@@ -XXX,XX +XXX,XX @@ static void armsse_init(Object *obj)
57
+++ b/include/qom/cpu.h
44
}
58
@@ -XXX,XX +XXX,XX @@ struct qemu_work_item;
45
object_initialize_child(obj, "s32ktimer", &s->s32ktimer,
59
* @trace_dstate_delayed: Delayed changes to trace_dstate (includes all changes
46
TYPE_CMSDK_APB_TIMER);
60
* to @trace_dstate).
47
- object_initialize_child(obj, "dualtimer", &s->dualtimer,
61
* @trace_dstate: Dynamic tracing state of events for this vCPU (bitmask).
48
- TYPE_CMSDK_APB_DUALTIMER);
62
+ * @ignore_memory_transaction_failures: Cached copy of the MachineState
49
object_initialize_child(obj, "s32kwatchdog", &s->s32kwatchdog,
63
+ * flag of the same name: allows the board to suppress calling of the
50
TYPE_CMSDK_APB_WATCHDOG);
64
+ * CPU do_transaction_failed hook function.
51
object_initialize_child(obj, "nswatchdog", &s->nswatchdog,
65
*
52
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
66
* State of one CPU core or thread.
53
return;
67
*/
54
}
68
@@ -XXX,XX +XXX,XX @@ struct CPUState {
55
mr = sysbus_mmio_get_region(sbd, 0);
69
*/
56
+ } else if (!strcmp(devinfo->type, TYPE_CMSDK_APB_DUALTIMER)) {
70
bool throttle_thread_scheduled;
57
+ sbd = SYS_BUS_DEVICE(&s->dualtimer);
71
72
+ bool ignore_memory_transaction_failures;
73
+
58
+
74
/* Note that this is accessed at the start of every TB via a negative
59
+ qdev_connect_clock_in(DEVICE(sbd), "TIMCLK", s->mainclk);
75
offset from AREG0. Leave this field at the end so as to make the
60
+ if (!sysbus_realize(sbd, errp)) {
76
(absolute value) offset as small as possible. This reduces code
61
+ return;
77
@@ -XXX,XX +XXX,XX @@ static inline void cpu_transaction_failed(CPUState *cpu, hwaddr physaddr,
62
+ }
78
{
63
+ mr = sysbus_mmio_get_region(sbd, 0);
79
CPUClass *cc = CPU_GET_CLASS(cpu);
64
} else {
80
65
g_assert_not_reached();
81
- if (cc->do_transaction_failed) {
66
}
82
+ if (!cpu->ignore_memory_transaction_failures && cc->do_transaction_failed) {
67
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
83
cc->do_transaction_failed(cpu, physaddr, addr, size, access_type,
68
}
84
mmu_idx, attrs, response, retaddr);
85
}
69
}
86
diff --git a/qom/cpu.c b/qom/cpu.c
70
87
index XXXXXXX..XXXXXXX 100644
71
- qdev_connect_clock_in(DEVICE(&s->dualtimer), "TIMCLK", s->mainclk);
88
--- a/qom/cpu.c
72
- if (!sysbus_realize(SYS_BUS_DEVICE(&s->dualtimer), errp)) {
89
+++ b/qom/cpu.c
73
- return;
90
@@ -XXX,XX +XXX,XX @@
74
- }
91
#include "exec/cpu-common.h"
75
- sysbus_connect_irq(SYS_BUS_DEVICE(&s->dualtimer), 0,
92
#include "qemu/error-report.h"
76
- armsse_get_common_irq_in(s, 5));
93
#include "sysemu/sysemu.h"
77
- mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->dualtimer), 0);
94
+#include "hw/boards.h"
78
- object_property_set_link(OBJECT(&s->apb_ppc[0]), "port[2]", OBJECT(mr),
95
#include "hw/qdev-properties.h"
79
- &error_abort);
96
#include "trace-root.h"
80
-
97
81
if (info->has_mhus) {
98
@@ -XXX,XX +XXX,XX @@ static void cpu_common_parse_features(const char *typename, char *features,
82
/*
99
static void cpu_common_realizefn(DeviceState *dev, Error **errp)
83
* An SSE-200 with only one CPU should have only one MHU created,
100
{
84
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
101
CPUState *cpu = CPU(dev);
85
sbd_apb_ppc0 = SYS_BUS_DEVICE(&s->apb_ppc[0]);
102
+ Object *machine = qdev_get_machine();
86
dev_apb_ppc0 = DEVICE(&s->apb_ppc[0]);
103
+ ObjectClass *oc = object_get_class(machine);
87
104
+ MachineClass *mc = MACHINE_CLASS(oc);
88
- mr = sysbus_mmio_get_region(sbd_apb_ppc0, 2);
105
+
89
- memory_region_add_subregion(&s->container, 0x40002000, mr);
106
+ cpu->ignore_memory_transaction_failures =
90
if (info->has_mhus) {
107
+ mc->ignore_memory_transaction_failures;
91
mr = sysbus_mmio_get_region(sbd_apb_ppc0, 3);
108
92
memory_region_add_subregion(&s->container, 0x40003000, mr);
109
if (dev->hotplugged) {
110
cpu_synchronize_post_init(cpu);
111
--
93
--
112
2.7.4
94
2.20.1
113
95
114
96
diff view generated by jsdifflib
New patch
1
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
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
1
From: Andrew Jeffery <andrew@aj.id.au>
1
Move the CMSDK timer that uses the S32K slow clock into the data-driven
2
device placement framework.
2
3
3
This is required to configure differences in behaviour between the
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
AST2400 and AST2500 watchdog IPs.
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(-)
5
12
6
Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
13
diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
7
Reviewed-by: Cédric Le Goater <clg@kaod.org>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
hw/arm/aspeed_soc.c | 2 ++
12
1 file changed, 2 insertions(+)
13
14
diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c
15
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/arm/aspeed_soc.c
15
--- a/include/hw/arm/armsse.h
17
+++ b/hw/arm/aspeed_soc.c
16
+++ b/include/hw/arm/armsse.h
18
@@ -XXX,XX +XXX,XX @@ static void aspeed_soc_init(Object *obj)
17
@@ -XXX,XX +XXX,XX @@ struct ARMSSE {
19
object_initialize(&s->wdt[i], sizeof(s->wdt[i]), TYPE_ASPEED_WDT);
18
IoTKitSecCtl secctl;
20
object_property_add_child(obj, "wdt[*]", OBJECT(&s->wdt[i]), NULL);
19
TZPPC apb_ppc[NUM_INTERNAL_PPCS];
21
qdev_set_parent_bus(DEVICE(&s->wdt[i]), sysbus_get_default());
20
TZMPC mpc[IOTS_NUM_MPC];
22
+ qdev_prop_set_uint32(DEVICE(&s->wdt[i]), "silicon-rev",
21
- CMSDKAPBTimer timer[2];
23
+ sc->info->silicon_rev);
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);
24
}
50
}
25
51
26
object_initialize(&s->ftgmac100, sizeof(s->ftgmac100), TYPE_FTGMAC100);
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,
27
--
93
--
28
2.7.4
94
2.20.1
29
95
30
96
diff view generated by jsdifflib
1
From: Andrew Jones <drjones@redhat.com>
1
Move the sysinfo register block into the data-driven framework.
2
2
3
Move the in-kernel-irqchip test to only guard the set-irq
3
While we are moving the code for configuring this device around,
4
stage, not the init stage of the PMU. Also add the PMU to
4
regularize on using &error_abortw when setting the integer
5
the KVM device irq line synchronization to enable its use.
5
properties: they are all simple DEFINE_PROP_UINT32 properties so the
6
setting can never fail.
6
7
7
Signed-off-by: Andrew Jones <drjones@redhat.com>
8
Reviewed-by: Christoffer Dall <cdall@linaro.org>
9
Message-id: 1500471597-2517-4-git-send-email-drjones@redhat.com
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
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
---
12
---
13
hw/arm/virt.c | 3 ++-
13
hw/arm/armsse.c | 47 ++++++++++++++++++++++++++++-------------------
14
target/arm/kvm.c | 6 +++++-
14
1 file changed, 28 insertions(+), 19 deletions(-)
15
target/arm/kvm64.c | 3 +--
16
3 files changed, 8 insertions(+), 4 deletions(-)
17
15
18
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
16
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
19
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
20
--- a/hw/arm/virt.c
18
--- a/hw/arm/armsse.c
21
+++ b/hw/arm/virt.c
19
+++ b/hw/arm/armsse.c
22
@@ -XXX,XX +XXX,XX @@ static void fdt_add_pmu_nodes(const VirtMachineState *vms)
20
@@ -XXX,XX +XXX,XX @@ static const ARMSSEDeviceInfo sse200_devices[] = {
23
return;
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();
24
}
45
}
25
if (kvm_enabled()) {
46
@@ -XXX,XX +XXX,XX @@ static void armsse_init(Object *obj)
26
- if (!kvm_arm_pmu_set_irq(cpu, PPI(VIRTUAL_PMU_IRQ))) {
47
27
+ if (kvm_irqchip_in_kernel() &&
48
object_initialize_child(obj, "armsse-sysctl", &s->sysctl,
28
+ !kvm_arm_pmu_set_irq(cpu, PPI(VIRTUAL_PMU_IRQ))) {
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)
29
return;
56
return;
30
}
57
}
31
if (!kvm_arm_pmu_init(cpu)) {
58
mr = sysbus_mmio_get_region(sbd, 0);
32
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
59
+ } else if (!strcmp(devinfo->type, TYPE_IOTKIT_SYSINFO)) {
33
index XXXXXXX..XXXXXXX 100644
60
+ sbd = SYS_BUS_DEVICE(&s->sysinfo);
34
--- a/target/arm/kvm.c
61
+
35
+++ b/target/arm/kvm.c
62
+ object_property_set_int(OBJECT(&s->sysinfo), "SYS_VERSION",
36
@@ -XXX,XX +XXX,XX @@ MemTxAttrs kvm_arch_post_run(CPUState *cs, struct kvm_run *run)
63
+ info->sys_version, &error_abort);
37
switched_level &= ~KVM_ARM_DEV_EL1_PTIMER;
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();
38
}
77
}
39
78
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
40
- /* XXX PMU IRQ is missing */
79
memory_region_add_subregion(&s->container, devinfo->addr, mr);
41
+ if (switched_level & KVM_ARM_DEV_PMU) {
42
+ qemu_set_irq(cpu->pmu_interrupt,
43
+ !!(run->s.regs.device_irq_level & KVM_ARM_DEV_PMU));
44
+ switched_level &= ~KVM_ARM_DEV_PMU;
45
+ }
46
47
if (switched_level) {
48
qemu_log_mask(LOG_UNIMP, "%s: unhandled in-kernel device IRQ %x\n",
49
diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
50
index XXXXXXX..XXXXXXX 100644
51
--- a/target/arm/kvm64.c
52
+++ b/target/arm/kvm64.c
53
@@ -XXX,XX +XXX,XX @@ int kvm_arch_init_vcpu(CPUState *cs)
54
if (!arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) {
55
cpu->kvm_init_features[0] |= 1 << KVM_ARM_VCPU_EL1_32BIT;
56
}
80
}
57
- if (!kvm_irqchip_in_kernel() ||
81
58
- !kvm_check_extension(cs->kvm_state, KVM_CAP_ARM_PMU_V3)) {
82
- if (!object_property_set_int(OBJECT(&s->sysinfo), "SYS_VERSION",
59
+ if (!kvm_check_extension(cs->kvm_state, KVM_CAP_ARM_PMU_V3)) {
83
- info->sys_version, errp)) {
60
cpu->has_pmu = false;
84
- return;
61
}
85
- }
62
if (cpu->has_pmu) {
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);
63
--
102
--
64
2.7.4
103
2.20.1
65
104
66
105
diff view generated by jsdifflib
1
For M profile the XPSR is a similar but not identical format to the
1
Move the sysctl register block into the data-driven device placement
2
A profile CPSR/SPSR. (For instance the Thumb bit is in a different
2
framework.
3
place.) For guest accesses we make the M profile code go through
4
xpsr_read() and xpsr_write() which handle the different layout.
5
However for migration we use cpsr_read() and cpsr_write() to
6
marshal state into and out of the migration data stream. This
7
is pretty confusing and works more by luck than anything else.
8
Make M profile migration use xpsr_read() and xpsr_write() instead.
9
10
The most complicated part of this is handling the possibility
11
that the migration source is an older QEMU which hands us a
12
CPSR format value; helpfully we can always tell the two apart.
13
3
14
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>
15
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
16
Message-id: 1501692241-23310-11-git-send-email-peter.maydell@linaro.org
7
Message-id: 20210219144617.4782-29-peter.maydell@linaro.org
17
---
8
---
18
target/arm/machine.c | 49 ++++++++++++++++++++++++++++++++++---------------
9
hw/arm/armsse.c | 44 ++++++++++++++++++++++++++++----------------
19
1 file changed, 34 insertions(+), 15 deletions(-)
10
1 file changed, 28 insertions(+), 16 deletions(-)
20
11
21
diff --git a/target/arm/machine.c b/target/arm/machine.c
12
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
22
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
23
--- a/target/arm/machine.c
14
--- a/hw/arm/armsse.c
24
+++ b/target/arm/machine.c
15
+++ b/hw/arm/armsse.c
25
@@ -XXX,XX +XXX,XX @@ static int get_cpsr(QEMUFile *f, void *opaque, size_t size,
16
@@ -XXX,XX +XXX,XX @@ static const ARMSSEDeviceInfo sse200_devices[] = {
26
uint32_t val = qemu_get_be32(f);
17
.ppc = NO_PPC,
27
18
.irq = NO_IRQ,
28
if (arm_feature(env, ARM_FEATURE_M)) {
19
},
29
- /* If the I or F bits are set then this is a migration from
20
+ {
30
- * an old QEMU which still stored the M profile FAULTMASK
21
+ .name = "armsse-sysctl",
31
- * and PRIMASK in env->daif. Set v7m.faultmask and v7m.primask
22
+ .type = TYPE_IOTKIT_SYSCTL,
32
- * accordingly, and then clear the bits so they don't confuse
23
+ .index = 0,
33
- * cpsr_write(). For a new QEMU, the bits here will always be
24
+ .addr = 0x50021000,
34
- * clear, and the data is transferred using the
25
+ .ppc = NO_PPC,
35
- * vmstate_m_faultmask_primask subsection.
26
+ .irq = NO_IRQ,
36
- */
27
+ },
37
- if (val & CPSR_F) {
28
{
38
- env->v7m.faultmask = 1;
29
.name = NULL,
39
- }
30
}
40
- if (val & CPSR_I) {
31
@@ -XXX,XX +XXX,XX @@ static void armsse_init(Object *obj)
41
- env->v7m.primask = 1;
32
assert(devinfo->index == 0);
42
+ if (val & XPSR_EXCP) {
33
object_initialize_child(obj, devinfo->name, &s->sysinfo,
43
+ /* This is a CPSR format value from an older QEMU. (We can tell
34
TYPE_IOTKIT_SYSINFO);
44
+ * because values transferred in XPSR format always have zero
35
+ } else if (!strcmp(devinfo->type, TYPE_IOTKIT_SYSCTL)) {
45
+ * for the EXCP field, and CPSR format will always have bit 4
36
+ assert(devinfo->index == 0);
46
+ * set in CPSR_M.) Rearrange it into XPSR format. The significant
37
+ object_initialize_child(obj, devinfo->name, &s->sysctl,
47
+ * differences are that the T bit is not in the same place, the
38
+ TYPE_IOTKIT_SYSCTL);
48
+ * primask/faultmask info may be in the CPSR I and F bits, and
39
} else {
49
+ * we do not want the mode bits.
40
g_assert_not_reached();
50
+ */
41
}
51
+ uint32_t newval = val;
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);
52
+
58
+
53
+ newval &= (CPSR_NZCV | CPSR_Q | CPSR_IT | CPSR_GE);
59
+ object_property_set_int(OBJECT(&s->sysctl), "sse-version",
54
+ if (val & CPSR_T) {
60
+ info->sse_version, &error_abort);
55
+ newval |= XPSR_T;
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;
56
+ }
69
+ }
57
+ /* If the I or F bits are set then this is a migration from
70
+ mr = sysbus_mmio_get_region(sbd, 0);
58
+ * an old QEMU which still stored the M profile FAULTMASK
71
} else {
59
+ * and PRIMASK in env->daif. For a new QEMU, the data is
72
g_assert_not_reached();
60
+ * transferred using the vmstate_m_faultmask_primask subsection.
61
+ */
62
+ if (val & CPSR_F) {
63
+ env->v7m.faultmask = 1;
64
+ }
65
+ if (val & CPSR_I) {
66
+ env->v7m.primask = 1;
67
+ }
68
+ val = newval;
69
}
73
}
70
- val &= ~(CPSR_F | CPSR_I);
74
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
71
+ /* Ignore the low bits, they are handled by vmstate_m. */
75
memory_region_add_subregion(&s->container, devinfo->addr, mr);
72
+ xpsr_write(env, val, ~XPSR_EXCP);
73
+ return 0;
74
}
76
}
75
77
76
env->aarch64 = ((val & PSTATE_nRW) == 0);
78
- /* System control registers */
77
@@ -XXX,XX +XXX,XX @@ static int put_cpsr(QEMUFile *f, void *opaque, size_t size,
79
- object_property_set_int(OBJECT(&s->sysctl), "sse-version",
78
CPUARMState *env = &cpu->env;
80
- info->sse_version, &error_abort);
79
uint32_t val;
81
- object_property_set_int(OBJECT(&s->sysctl), "CPUWAIT_RST",
80
82
- info->cpuwait_rst, &error_abort);
81
- if (is_a64(env)) {
83
- object_property_set_int(OBJECT(&s->sysctl), "INITSVTOR0_RST",
82
+ if (arm_feature(env, ARM_FEATURE_M)) {
84
- s->init_svtor, &error_abort);
83
+ /* The low 9 bits are v7m.exception, which is handled by vmstate_m. */
85
- object_property_set_int(OBJECT(&s->sysctl), "INITSVTOR1_RST",
84
+ val = xpsr_read(env) & ~XPSR_EXCP;
86
- s->init_svtor, &error_abort);
85
+ } else if (is_a64(env)) {
87
- if (!sysbus_realize(SYS_BUS_DEVICE(&s->sysctl), errp)) {
86
val = pstate_read(env);
88
- return;
87
} else {
89
- }
88
val = cpsr_read(env);
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++) {
89
--
95
--
90
2.7.4
96
2.20.1
91
97
92
98
diff view generated by jsdifflib
1
We currently have some similar code in tlb_fill() and in
1
Move the PPUs into the data-driven device placement framework.
2
arm_cpu_do_unaligned_access() for delivering a data abort or prefetch
2
We don't implement them, so they are just TYPE_UNIMPLEMENTED stubs.
3
abort. We're also going to want to do the same thing to handle
3
4
external aborts. Factor out the common code into a new function
4
Because the SSE-200 and the IotKit diverge here (the IoTKit does
5
deliver_fault().
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.
6
7
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Acked-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
11
Message-id: 20210219144617.4782-30-peter.maydell@linaro.org
10
---
12
---
11
target/arm/op_helper.c | 110 +++++++++++++++++++++++++------------------------
13
include/hw/arm/armsse.h | 10 +-
12
1 file changed, 57 insertions(+), 53 deletions(-)
14
hw/arm/armsse.c | 222 +++++++++++++++++++++++++++++-----------
13
15
2 files changed, 165 insertions(+), 67 deletions(-)
14
diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c
16
17
diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
15
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/op_helper.c
19
--- a/include/hw/arm/armsse.h
17
+++ b/target/arm/op_helper.c
20
+++ b/include/hw/arm/armsse.h
18
@@ -XXX,XX +XXX,XX @@ static inline uint32_t merge_syn_data_abort(uint32_t template_syn,
21
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_TYPE(ARMSSE, ARMSSEClass,
19
return syn;
22
20
}
23
#define SSE_MAX_CPUS 2
21
24
22
+static void deliver_fault(ARMCPU *cpu, vaddr addr, MMUAccessType access_type,
25
-/* These define what each PPU in the ppu[] index is for */
23
+ uint32_t fsr, uint32_t fsc, ARMMMUFaultInfo *fi)
26
-#define CPU0CORE_PPU 0
24
+{
27
-#define CPU1CORE_PPU 1
25
+ CPUARMState *env = &cpu->env;
28
-#define DBG_PPU 2
26
+ int target_el;
29
-#define RAM0_PPU 3
27
+ bool same_el;
30
-#define RAM1_PPU 4
28
+ uint32_t syn, exc;
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
+};
29
+
224
+
30
+ target_el = exception_target_el(env);
225
static const ARMSSEInfo armsse_variants[] = {
31
+ if (fi->stage2) {
226
{
32
+ target_el = 2;
227
.name = TYPE_IOTKIT,
33
+ env->cp15.hpfar_el2 = extract64(fi->s2addr, 12, 47) << 4;
228
@@ -XXX,XX +XXX,XX @@ static const ARMSSEInfo armsse_variants[] = {
34
+ }
229
.iidr = 0,
35
+ same_el = (arm_current_el(env) == target_el);
230
.cpuwait_rst = 0,
36
+
231
.has_mhus = false,
37
+ if (fsc == 0x3f) {
232
- .has_ppus = false,
38
+ /* Caller doesn't have a long-format fault status code. This
233
.has_cachectrl = false,
39
+ * should only happen if this fault will never actually be reported
234
.has_cpusecctrl = false,
40
+ * to an EL that uses a syndrome register. Check that here.
235
.has_cpuid = false,
41
+ * 0x3f is a (currently) reserved FSC code, in case the constructed
236
.props = iotkit_properties,
42
+ * syndrome does leak into the guest somehow.
237
- .devinfo = sse200_devices,
43
+ */
238
+ .devinfo = iotkit_devices,
44
+ assert(target_el != 2 && !arm_el_is_aa64(env, target_el));
239
},
45
+ }
240
{
46
+
241
.name = TYPE_SSE200,
47
+ if (access_type == MMU_INST_FETCH) {
242
@@ -XXX,XX +XXX,XX @@ static const ARMSSEInfo armsse_variants[] = {
48
+ syn = syn_insn_abort(same_el, 0, fi->s1ptw, fsc);
243
.iidr = 0,
49
+ exc = EXCP_PREFETCH_ABORT;
244
.cpuwait_rst = 2,
50
+ } else {
245
.has_mhus = true,
51
+ syn = merge_syn_data_abort(env->exception.syndrome, target_el,
246
- .has_ppus = true,
52
+ same_el, fi->s1ptw,
247
.has_cachectrl = true,
53
+ access_type == MMU_DATA_STORE,
248
.has_cpusecctrl = true,
54
+ fsc);
249
.has_cpuid = true,
55
+ if (access_type == MMU_DATA_STORE
250
@@ -XXX,XX +XXX,XX @@ static void armsse_init(Object *obj)
56
+ && arm_feature(env, ARM_FEATURE_V6)) {
251
assert(devinfo->index == 0);
57
+ fsr |= (1 << 11);
252
object_initialize_child(obj, devinfo->name, &s->sysctl,
58
+ }
253
TYPE_IOTKIT_SYSCTL);
59
+ exc = EXCP_DATA_ABORT;
254
+ } else if (!strcmp(devinfo->type, TYPE_UNIMPLEMENTED_DEVICE)) {
60
+ }
255
+ assert(devinfo->index < ARRAY_SIZE(s->unimp));
61
+
256
+ object_initialize_child(obj, devinfo->name,
62
+ env->exception.vaddress = addr;
257
+ &s->unimp[devinfo->index],
63
+ env->exception.fsr = fsr;
258
+ TYPE_UNIMPLEMENTED_DEVICE);
64
+ raise_exception(env, exc, syn, target_el);
259
} else {
65
+}
260
g_assert_not_reached();
66
+
67
/* try to fill the TLB and return an exception if error. If retaddr is
68
* NULL, it means that the function was called in C code (i.e. not
69
* from generated code or from helper.c)
70
@@ -XXX,XX +XXX,XX @@ void tlb_fill(CPUState *cs, target_ulong addr, MMUAccessType access_type,
71
ret = arm_tlb_fill(cs, addr, access_type, mmu_idx, &fsr, &fi);
72
if (unlikely(ret)) {
73
ARMCPU *cpu = ARM_CPU(cs);
74
- CPUARMState *env = &cpu->env;
75
- uint32_t syn, exc, fsc;
76
- unsigned int target_el;
77
- bool same_el;
78
+ uint32_t fsc;
79
80
if (retaddr) {
81
/* now we have a real cpu fault */
82
cpu_restore_state(cs, retaddr);
83
}
261
}
84
262
@@ -XXX,XX +XXX,XX @@ static void armsse_init(Object *obj)
85
- target_el = exception_target_el(env);
263
object_initialize_child(obj, "mhu0", &s->mhu[0], TYPE_ARMSSE_MHU);
86
- if (fi.stage2) {
264
object_initialize_child(obj, "mhu1", &s->mhu[1], TYPE_ARMSSE_MHU);
87
- target_el = 2;
265
}
88
- env->cp15.hpfar_el2 = extract64(fi.s2addr, 12, 47) << 4;
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);
89
- }
274
- }
90
- same_el = arm_current_el(env) == target_el;
275
- object_initialize_child(obj, "DBG_PPU", &s->ppu[DBG_PPU],
91
-
276
- TYPE_UNIMPLEMENTED_DEVICE);
92
if (fsr & (1 << 9)) {
277
- for (i = 0; i < info->sram_banks; i++) {
93
/* LPAE format fault status register : bottom 6 bits are
278
- char *name = g_strdup_printf("RAM%d_PPU", i);
94
* status code in the same form as needed for syndrome
279
- int ppuidx = RAM0_PPU + i;
95
@@ -XXX,XX +XXX,XX @@ void tlb_fill(CPUState *cs, target_ulong addr, MMUAccessType access_type,
280
-
96
fsc = extract32(fsr, 0, 6);
281
- object_initialize_child(obj, name, &s->ppu[ppuidx],
97
} else {
282
- TYPE_UNIMPLEMENTED_DEVICE);
98
/* Short format FSR : this fault will never actually be reported
283
- g_free(name);
99
- * to an EL that uses a syndrome register. Check that here,
100
- * and use a (currently) reserved FSR code in case the constructed
101
- * syndrome does leak into the guest somehow.
102
+ * to an EL that uses a syndrome register. Use a (currently)
103
+ * reserved FSR code in case the constructed syndrome does leak
104
+ * into the guest somehow. deliver_fault will assert that
105
+ * we don't target an EL using the syndrome.
106
*/
107
- assert(target_el != 2 && !arm_el_is_aa64(env, target_el));
108
fsc = 0x3f;
109
}
110
111
- /* For insn and data aborts we assume there is no instruction syndrome
112
- * information; this is always true for exceptions reported to EL1.
113
- */
114
- if (access_type == MMU_INST_FETCH) {
115
- syn = syn_insn_abort(same_el, 0, fi.s1ptw, fsc);
116
- exc = EXCP_PREFETCH_ABORT;
117
- } else {
118
- syn = merge_syn_data_abort(env->exception.syndrome, target_el,
119
- same_el, fi.s1ptw,
120
- access_type == MMU_DATA_STORE, fsc);
121
- if (access_type == MMU_DATA_STORE
122
- && arm_feature(env, ARM_FEATURE_V6)) {
123
- fsr |= (1 << 11);
124
- }
125
- exc = EXCP_DATA_ABORT;
126
- }
284
- }
127
-
285
- }
128
- env->exception.vaddress = addr;
286
if (info->has_cachectrl) {
129
- env->exception.fsr = fsr;
287
for (i = 0; i < info->num_cpus; i++) {
130
- raise_exception(env, exc, syn, target_el);
288
char *name = g_strdup_printf("cachectrl%d", i);
131
+ deliver_fault(cpu, addr, access_type, fsr, fsc, &fi);
289
@@ -XXX,XX +XXX,XX @@ static qemu_irq armsse_get_common_irq_in(ARMSSE *s, int irqno)
132
}
290
}
133
}
291
}
134
292
135
@@ -XXX,XX +XXX,XX @@ void arm_cpu_do_unaligned_access(CPUState *cs, vaddr vaddr,
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)
136
{
305
{
137
ARMCPU *cpu = ARM_CPU(cs);
306
ARMSSE *s = ARM_SSE(dev);
138
CPUARMState *env = &cpu->env;
307
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
139
- int target_el;
308
return;
140
- bool same_el;
309
}
141
- uint32_t syn;
310
mr = sysbus_mmio_get_region(sbd, 0);
142
+ uint32_t fsr, fsc;
311
+ } else if (!strcmp(devinfo->type, TYPE_UNIMPLEMENTED_DEVICE)) {
143
+ ARMMMUFaultInfo fi = {};
312
+ sbd = SYS_BUS_DEVICE(&s->unimp[devinfo->index]);
144
ARMMMUIdx arm_mmu_idx = core_to_arm_mmu_idx(env, mmu_idx);
313
+
145
314
+ qdev_prop_set_string(DEVICE(sbd), "name", devinfo->name);
146
if (retaddr) {
315
+ qdev_prop_set_uint64(DEVICE(sbd), "size", devinfo->size);
147
@@ -XXX,XX +XXX,XX @@ void arm_cpu_do_unaligned_access(CPUState *cs, vaddr vaddr,
316
+ if (!sysbus_realize(sbd, errp)) {
148
cpu_restore_state(cs, retaddr);
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);
149
}
325
}
150
326
151
- target_el = exception_target_el(env);
327
- if (info->has_ppus) {
152
- same_el = (arm_current_el(env) == target_el);
328
- /* CPUnCORE_PPU for each CPU */
153
-
329
- for (i = 0; i < info->num_cpus; i++) {
154
- env->exception.vaddress = vaddr;
330
- char *name = g_strdup_printf("CPU%dCORE_PPU", i);
155
-
331
-
156
/* the DFSR for an alignment fault depends on whether we're using
332
- map_ppu(s, CPU0CORE_PPU + i, name, 0x50023000 + i * 0x2000);
157
* the LPAE long descriptor format, or the short descriptor format
333
- /*
158
*/
334
- * We don't support CPU debug so don't create the
159
if (arm_s1_regime_using_lpae_format(env, arm_mmu_idx)) {
335
- * CPU0DEBUG_PPU at 0x50024000 and 0x50026000.
160
- env->exception.fsr = (1 << 9) | 0x21;
336
- */
161
+ fsr = (1 << 9) | 0x21;
337
- g_free(name);
162
} else {
338
- }
163
- env->exception.fsr = 0x1;
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
- }
164
- }
347
- }
165
-
348
-
166
- if (access_type == MMU_DATA_STORE && arm_feature(env, ARM_FEATURE_V6)) {
349
for (i = 0; i < ARRAY_SIZE(s->ppc_irq_splitter); i++) {
167
- env->exception.fsr |= (1 << 11);
350
Object *splitter = OBJECT(&s->ppc_irq_splitter[i]);
168
+ fsr = 0x1;
351
169
}
170
+ fsc = 0x21;
171
172
- syn = merge_syn_data_abort(env->exception.syndrome, target_el,
173
- same_el, 0, access_type == MMU_DATA_STORE,
174
- 0x21);
175
- raise_exception(env, EXCP_DATA_ABORT, syn, target_el);
176
+ deliver_fault(cpu, vaddr, access_type, fsr, fsc, &fi);
177
}
178
179
#endif /* !defined(CONFIG_USER_ONLY) */
180
--
352
--
181
2.7.4
353
2.20.1
182
354
183
355
diff view generated by jsdifflib
1
Call the new cpu_transaction_failed() hook at the places where
1
We forgot to implement a TYPE_UNIMPLEMENTED_DEVICE stub
2
CPU generated code interacts with the memory system:
2
for the SYS_PPU in the SSE-200, which is at 0x50022000.
3
io_readx()
4
io_writex()
5
get_page_addr_code()
6
7
Any access from C code (eg via cpu_physical_memory_rw(),
8
address_space_rw(), ld/st_*_phys()) will *not* trigger CPU exceptions
9
via cpu_transaction_failed(). Handling for transactions failures for
10
this kind of call should be done by using a function which returns a
11
MemTxResult and treating the failure case appropriately in the
12
calling code.
13
14
In an ideal world we would not generate CPU exceptions for
15
instruction fetch failures in get_page_addr_code() but instead wait
16
until the code translation process tried a load and it failed;
17
however that change would require too great a restructuring and
18
redesign to attempt at this point.
19
3
20
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
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
22
---
8
---
23
softmmu_template.h | 4 ++--
9
include/hw/arm/armsse.h | 2 +-
24
accel/tcg/cputlb.c | 32 ++++++++++++++++++++++++++++++--
10
hw/arm/armsse.c | 9 +++++++++
25
2 files changed, 32 insertions(+), 4 deletions(-)
11
2 files changed, 10 insertions(+), 1 deletion(-)
26
12
27
diff --git a/softmmu_template.h b/softmmu_template.h
13
diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
28
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
29
--- a/softmmu_template.h
15
--- a/include/hw/arm/armsse.h
30
+++ b/softmmu_template.h
16
+++ b/include/hw/arm/armsse.h
31
@@ -XXX,XX +XXX,XX @@ static inline DATA_TYPE glue(io_read, SUFFIX)(CPUArchState *env,
17
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_TYPE(ARMSSE, ARMSSEClass,
32
uintptr_t retaddr)
18
33
{
19
#define SSE_MAX_CPUS 2
34
CPUIOTLBEntry *iotlbentry = &env->iotlb[mmu_idx][index];
20
35
- return io_readx(env, iotlbentry, addr, retaddr, DATA_SIZE);
21
-#define NUM_PPUS 7
36
+ return io_readx(env, iotlbentry, mmu_idx, addr, retaddr, DATA_SIZE);
22
+#define NUM_PPUS 8
37
}
23
38
#endif
24
/* Number of CPU IRQs used by the SSE itself */
39
25
#define NUM_SSE_IRQS 32
40
@@ -XXX,XX +XXX,XX @@ static inline void glue(io_write, SUFFIX)(CPUArchState *env,
26
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
41
uintptr_t retaddr)
42
{
43
CPUIOTLBEntry *iotlbentry = &env->iotlb[mmu_idx][index];
44
- return io_writex(env, iotlbentry, val, addr, retaddr, DATA_SIZE);
45
+ return io_writex(env, iotlbentry, mmu_idx, val, addr, retaddr, DATA_SIZE);
46
}
47
48
void helper_le_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
49
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
50
index XXXXXXX..XXXXXXX 100644
27
index XXXXXXX..XXXXXXX 100644
51
--- a/accel/tcg/cputlb.c
28
--- a/hw/arm/armsse.c
52
+++ b/accel/tcg/cputlb.c
29
+++ b/hw/arm/armsse.c
53
@@ -XXX,XX +XXX,XX @@ static inline ram_addr_t qemu_ram_addr_from_host_nofail(void *ptr)
30
@@ -XXX,XX +XXX,XX @@ static const ARMSSEDeviceInfo sse200_devices[] = {
54
}
31
.ppc = NO_PPC,
55
32
.irq = NO_IRQ,
56
static uint64_t io_readx(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
33
},
57
+ int mmu_idx,
34
+ {
58
target_ulong addr, uintptr_t retaddr, int size)
35
+ .name = "SYS_PPU",
59
{
36
+ .type = TYPE_UNIMPLEMENTED_DEVICE,
60
CPUState *cpu = ENV_GET_CPU(env);
37
+ .index = 7,
61
@@ -XXX,XX +XXX,XX @@ static uint64_t io_readx(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
38
+ .addr = 0x50022000,
62
MemoryRegion *mr = iotlb_to_region(cpu, physaddr, iotlbentry->attrs);
39
+ .size = 0x1000,
63
uint64_t val;
40
+ .ppc = NO_PPC,
64
bool locked = false;
41
+ .irq = NO_IRQ,
65
+ MemTxResult r;
42
+ },
66
43
{
67
physaddr = (physaddr & TARGET_PAGE_MASK) + addr;
44
.name = NULL,
68
cpu->mem_io_pc = retaddr;
69
@@ -XXX,XX +XXX,XX @@ static uint64_t io_readx(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
70
qemu_mutex_lock_iothread();
71
locked = true;
72
}
45
}
73
- memory_region_dispatch_read(mr, physaddr, &val, size, iotlbentry->attrs);
74
+ r = memory_region_dispatch_read(mr, physaddr,
75
+ &val, size, iotlbentry->attrs);
76
+ if (r != MEMTX_OK) {
77
+ cpu_transaction_failed(cpu, physaddr, addr, size, MMU_DATA_LOAD,
78
+ mmu_idx, iotlbentry->attrs, r, retaddr);
79
+ }
80
if (locked) {
81
qemu_mutex_unlock_iothread();
82
}
83
@@ -XXX,XX +XXX,XX @@ static uint64_t io_readx(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
84
}
85
86
static void io_writex(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
87
+ int mmu_idx,
88
uint64_t val, target_ulong addr,
89
uintptr_t retaddr, int size)
90
{
91
@@ -XXX,XX +XXX,XX @@ static void io_writex(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
92
hwaddr physaddr = iotlbentry->addr;
93
MemoryRegion *mr = iotlb_to_region(cpu, physaddr, iotlbentry->attrs);
94
bool locked = false;
95
+ MemTxResult r;
96
97
physaddr = (physaddr & TARGET_PAGE_MASK) + addr;
98
if (mr != &io_mem_rom && mr != &io_mem_notdirty && !cpu->can_do_io) {
99
@@ -XXX,XX +XXX,XX @@ static void io_writex(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
100
qemu_mutex_lock_iothread();
101
locked = true;
102
}
103
- memory_region_dispatch_write(mr, physaddr, val, size, iotlbentry->attrs);
104
+ r = memory_region_dispatch_write(mr, physaddr,
105
+ val, size, iotlbentry->attrs);
106
+ if (r != MEMTX_OK) {
107
+ cpu_transaction_failed(cpu, physaddr, addr, size, MMU_DATA_STORE,
108
+ mmu_idx, iotlbentry->attrs, r, retaddr);
109
+ }
110
if (locked) {
111
qemu_mutex_unlock_iothread();
112
}
113
@@ -XXX,XX +XXX,XX @@ tb_page_addr_t get_page_addr_code(CPUArchState *env, target_ulong addr)
114
MemoryRegion *mr;
115
CPUState *cpu = ENV_GET_CPU(env);
116
CPUIOTLBEntry *iotlbentry;
117
+ hwaddr physaddr;
118
119
index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
120
mmu_idx = cpu_mmu_index(env, true);
121
@@ -XXX,XX +XXX,XX @@ tb_page_addr_t get_page_addr_code(CPUArchState *env, target_ulong addr)
122
}
123
qemu_mutex_unlock_iothread();
124
125
+ /* Give the new-style cpu_transaction_failed() hook first chance
126
+ * to handle this.
127
+ * This is not the ideal place to detect and generate CPU
128
+ * exceptions for instruction fetch failure (for instance
129
+ * we don't know the length of the access that the CPU would
130
+ * use, and it would be better to go ahead and try the access
131
+ * and use the MemTXResult it produced). However it is the
132
+ * simplest place we have currently available for the check.
133
+ */
134
+ physaddr = (iotlbentry->addr & TARGET_PAGE_MASK) + addr;
135
+ cpu_transaction_failed(cpu, physaddr, addr, 0, MMU_INST_FETCH, mmu_idx,
136
+ iotlbentry->attrs, MEMTX_DECODE_ERROR, 0);
137
+
138
cpu_unassigned_access(cpu, addr, false, true, 0, 4);
139
/* The CPU's unassigned access hook might have longjumped out
140
* with an exception. If it didn't (or there was no hook) then
141
--
46
--
142
2.7.4
47
2.20.1
143
48
144
49
diff view generated by jsdifflib
1
Move the MemTxResult type to memattrs.h. We're going to want to
1
The SSE-300 has a slightly different set of shared-per-CPU interrupts,
2
use it in cpu/qom.h, which doesn't want to include all of
2
allow the irq_is_common[] array to be different per SSE variant.
3
memory.h. In practice MemTxResult and MemTxAttrs are pretty
4
closely linked since both are used for the new-style
5
read_with_attrs and write_with_attrs callbacks, so memattrs.h
6
is a reasonable home for this rather than creating a whole
7
new header file for it.
8
3
9
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>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
8
Message-id: 20210219144617.4782-32-peter.maydell@linaro.org
12
Reviewed-by: Alistair Francis <alistair.francis@xilinx.com>
13
---
9
---
14
include/exec/memattrs.h | 10 ++++++++++
10
hw/arm/armsse.c | 39 +++++++++++++++++++++------------------
15
include/exec/memory.h | 10 ----------
11
1 file changed, 21 insertions(+), 18 deletions(-)
16
2 files changed, 10 insertions(+), 10 deletions(-)
17
12
18
diff --git a/include/exec/memattrs.h b/include/exec/memattrs.h
13
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
19
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
20
--- a/include/exec/memattrs.h
15
--- a/hw/arm/armsse.c
21
+++ b/include/exec/memattrs.h
16
+++ b/hw/arm/armsse.c
22
@@ -XXX,XX +XXX,XX @@ typedef struct MemTxAttrs {
17
@@ -XXX,XX +XXX,XX @@ struct ARMSSEInfo {
23
*/
18
bool has_cpuid;
24
#define MEMTXATTRS_UNSPECIFIED ((MemTxAttrs) { .unspecified = 1 })
19
Property *props;
25
20
const ARMSSEDeviceInfo *devinfo;
26
+/* New-style MMIO accessors can indicate that the transaction failed.
21
+ const bool *irq_is_common;
27
+ * A zero (MEMTX_OK) response means success; anything else is a failure
22
};
28
+ * of some kind. The memory subsystem will bitwise-OR together results
23
29
+ * if it is synthesizing an operation from multiple smaller accesses.
24
static Property iotkit_properties[] = {
30
+ */
25
@@ -XXX,XX +XXX,XX @@ static const ARMSSEDeviceInfo sse200_devices[] = {
31
+#define MEMTX_OK 0
26
}
32
+#define MEMTX_ERROR (1U << 0) /* device returned an error */
27
};
33
+#define MEMTX_DECODE_ERROR (1U << 1) /* nothing at that address */
28
34
+typedef uint32_t MemTxResult;
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
+};
35
+
43
+
36
#endif
44
static const ARMSSEInfo armsse_variants[] = {
37
diff --git a/include/exec/memory.h b/include/exec/memory.h
45
{
38
index XXXXXXX..XXXXXXX 100644
46
.name = TYPE_IOTKIT,
39
--- a/include/exec/memory.h
47
@@ -XXX,XX +XXX,XX @@ static const ARMSSEInfo armsse_variants[] = {
40
+++ b/include/exec/memory.h
48
.has_cpuid = false,
41
@@ -XXX,XX +XXX,XX @@ static inline void iommu_notifier_init(IOMMUNotifier *n, IOMMUNotify fn,
49
.props = iotkit_properties,
42
n->end = end;
50
.devinfo = iotkit_devices,
43
}
51
+ .irq_is_common = sse200_irq_is_common,
44
52
},
45
-/* New-style MMIO accessors can indicate that the transaction failed.
53
{
46
- * A zero (MEMTX_OK) response means success; anything else is a failure
54
.name = TYPE_SSE200,
47
- * of some kind. The memory subsystem will bitwise-OR together results
55
@@ -XXX,XX +XXX,XX @@ static const ARMSSEInfo armsse_variants[] = {
48
- * if it is synthesizing an operation from multiple smaller accesses.
56
.has_cpuid = true,
49
- */
57
.props = armsse_properties,
50
-#define MEMTX_OK 0
58
.devinfo = sse200_devices,
51
-#define MEMTX_ERROR (1U << 0) /* device returned an error */
59
+ .irq_is_common = sse200_irq_is_common,
52
-#define MEMTX_DECODE_ERROR (1U << 1) /* nothing at that address */
60
},
53
-typedef uint32_t MemTxResult;
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
-};
54
-
81
-
55
/*
82
/*
56
* Memory region callbacks
83
* Create an alias region in @container of @size bytes starting at @base
57
*/
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;
58
--
112
--
59
2.7.4
113
2.20.1
60
114
61
115
diff view generated by jsdifflib
1
Move the code in arm_v7m_cpu_do_interrupt() that calculates the
1
The SSE-300 has a system counter device; add support for SSE
2
magic LR value down to when we're actually going to use it.
2
variants having this device.
3
Having the calculation and use so far apart makes the code
3
4
a little harder to understand than it needs to be.
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.
5
8
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 1501692241-23310-13-git-send-email-peter.maydell@linaro.org
12
Message-id: 20210219144617.4782-33-peter.maydell@linaro.org
11
---
13
---
12
target/arm/helper.c | 15 ++++++++-------
14
include/hw/arm/armsse.h | 3 +++
13
1 file changed, 8 insertions(+), 7 deletions(-)
15
hw/arm/armsse.c | 27 +++++++++++++++++++++++++++
16
2 files changed, 30 insertions(+)
14
17
15
diff --git a/target/arm/helper.c b/target/arm/helper.c
18
diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
16
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/helper.c
20
--- a/include/hw/arm/armsse.h
18
+++ b/target/arm/helper.c
21
+++ b/include/hw/arm/armsse.h
19
@@ -XXX,XX +XXX,XX @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
22
@@ -XXX,XX +XXX,XX @@
20
23
#include "hw/misc/tz-mpc.h"
21
arm_log_exception(cs->exception_index);
24
#include "hw/timer/cmsdk-apb-timer.h"
22
25
#include "hw/timer/cmsdk-apb-dualtimer.h"
23
- lr = 0xfffffff1;
26
+#include "hw/timer/sse-counter.h"
24
- if (env->v7m.control & R_V7M_CONTROL_SPSEL_MASK) {
27
#include "hw/watchdog/cmsdk-apb-watchdog.h"
25
- lr |= 4;
28
#include "hw/misc/iotkit-sysctl.h"
26
- }
29
#include "hw/misc/iotkit-sysinfo.h"
27
- if (env->v7m.exception == 0)
30
@@ -XXX,XX +XXX,XX @@ struct ARMSSE {
28
- lr |= 8;
31
29
-
32
CMSDKAPBWatchdog cmsdk_watchdog[3];
30
/* For exceptions we just mark as pending on the NVIC, and let that
33
31
handle it. */
34
+ SSECounter sse_counter;
32
switch (cs->exception_index) {
35
+
33
@@ -XXX,XX +XXX,XX @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
36
IoTKitSysCtl sysctl;
34
return; /* Never happens. Keep compiler happy. */
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
}
35
}
70
}
36
71
+ if (info->has_sse_counter) {
37
+ lr = 0xfffffff1;
72
+ object_initialize_child(obj, "sse-counter", &s->sse_counter,
38
+ if (env->v7m.control & R_V7M_CONTROL_SPSEL_MASK) {
73
+ TYPE_SSE_COUNTER);
39
+ lr |= 4;
40
+ }
41
+ if (env->v7m.exception == 0) {
42
+ lr |= 8;
43
+ }
74
+ }
44
+
75
+
45
v7m_push_stack(cpu);
76
object_initialize_child(obj, "nmi-orgate", &s->nmi_orgate, TYPE_OR_IRQ);
46
v7m_exception_taken(cpu, lr);
77
object_initialize_child(obj, "ppc-irq-orgate", &s->ppc_irq_orgate,
47
qemu_log_mask(CPU_LOG_INT, "... as %d\n", env->v7m.exception);
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
48
--
105
--
49
2.7.4
106
2.20.1
50
107
51
108
diff view generated by jsdifflib
1
Remove the comment that claims that some MPU_CTRL bits are stored
1
The SSE-300 has four timers of type TYPE_SSE_TIMER; add support in
2
in sctlr_el[1]. This has never been true since MPU_CTRL was added
2
the code for having these in an ARMSSEDeviceInfo array.
3
in commit 29c483a50607 -- the comment is a leftover from
4
Michael Davidsaver's original implementation, which I modified
5
not to use sctlr_el[1]; I forgot to delete the comment then.
6
3
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
5
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 1501692241-23310-7-git-send-email-peter.maydell@linaro.org
8
Message-id: 20210219144617.4782-34-peter.maydell@linaro.org
11
---
9
---
12
target/arm/cpu.h | 2 +-
10
include/hw/arm/armsse.h | 2 ++
13
1 file changed, 1 insertion(+), 1 deletion(-)
11
hw/arm/armsse.c | 15 +++++++++++++++
12
2 files changed, 17 insertions(+)
14
13
15
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
14
diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
16
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/cpu.h
16
--- a/include/hw/arm/armsse.h
18
+++ b/target/arm/cpu.h
17
+++ b/include/hw/arm/armsse.h
19
@@ -XXX,XX +XXX,XX @@ typedef struct CPUARMState {
18
@@ -XXX,XX +XXX,XX @@
20
uint32_t dfsr; /* Debug Fault Status Register */
19
#include "hw/timer/cmsdk-apb-timer.h"
21
uint32_t mmfar; /* MemManage Fault Address */
20
#include "hw/timer/cmsdk-apb-dualtimer.h"
22
uint32_t bfar; /* BusFault Address */
21
#include "hw/timer/sse-counter.h"
23
- unsigned mpu_ctrl; /* MPU_CTRL (some bits kept in sctlr_el[1]) */
22
+#include "hw/timer/sse-timer.h"
24
+ unsigned mpu_ctrl; /* MPU_CTRL */
23
#include "hw/watchdog/cmsdk-apb-watchdog.h"
25
int exception;
24
#include "hw/misc/iotkit-sysctl.h"
26
} v7m;
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]);
27
66
28
--
67
--
29
2.7.4
68
2.20.1
30
69
31
70
diff view generated by jsdifflib
1
Make the arm_cpu_dump_state() debug logging handle the M-profile XPSR
1
Support SSE variants like the SSE-300 with an ARMSSE_CPU_PWRCTRL register
2
rather than assuming it's an A-profile CPSR. On M profile the PSR
2
block. Because this block is per-CPU and does not clash with any of the
3
line of a register dump will now look like this:
3
SSE-200 devices, we handle it with a has_cpu_pwrctrl flag like the
4
4
existing has_cachectrl, has_cpusectrl and has_cpuid, rather than
5
XPSR=41000000 -Z-- T priv-thread
5
trying to add per-CPU-device support to the devinfo array handling code.
6
6
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
8
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 1501692241-23310-12-git-send-email-peter.maydell@linaro.org
10
Message-id: 20210219144617.4782-35-peter.maydell@linaro.org
11
---
11
---
12
target/arm/translate.c | 58 ++++++++++++++++++++++++++++++++++----------------
12
include/hw/arm/armsse.h | 3 +++
13
1 file changed, 40 insertions(+), 18 deletions(-)
13
hw/arm/armsse.c | 26 ++++++++++++++++++++++++++
14
2 files changed, 29 insertions(+)
14
15
15
diff --git a/target/arm/translate.c b/target/arm/translate.c
16
diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
16
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/translate.c
18
--- a/include/hw/arm/armsse.h
18
+++ b/target/arm/translate.c
19
+++ b/include/hw/arm/armsse.h
19
@@ -XXX,XX +XXX,XX @@ void arm_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
20
@@ -XXX,XX +XXX,XX @@
20
ARMCPU *cpu = ARM_CPU(cs);
21
#include "hw/misc/iotkit-sysinfo.h"
21
CPUARMState *env = &cpu->env;
22
#include "hw/misc/armsse-cpuid.h"
22
int i;
23
#include "hw/misc/armsse-mhu.h"
23
- uint32_t psr;
24
+#include "hw/misc/armsse-cpu-pwrctrl.h"
24
- const char *ns_status;
25
#include "hw/misc/unimp.h"
25
26
#include "hw/or-irq.h"
26
if (is_a64(env)) {
27
#include "hw/clock.h"
27
aarch64_cpu_dump_state(cs, f, cpu_fprintf, flags);
28
@@ -XXX,XX +XXX,XX @@ struct ARMSSE {
28
@@ -XXX,XX +XXX,XX @@ void arm_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
29
29
else
30
ARMSSECPUID cpuid[SSE_MAX_CPUS];
30
cpu_fprintf(f, " ");
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
}
31
}
68
}
32
- psr = cpsr_read(env);
69
+ if (info->has_cpu_pwrctrl) {
33
70
+ for (i = 0; i < info->num_cpus; i++) {
34
- if (arm_feature(env, ARM_FEATURE_EL3) &&
71
+ char *name = g_strdup_printf("cpu_pwrctrl%d", i);
35
- (psr & CPSR_M) != ARM_CPU_MODE_MON) {
36
- ns_status = env->cp15.scr_el3 & SCR_NS ? "NS " : "S ";
37
+ if (arm_feature(env, ARM_FEATURE_M)) {
38
+ uint32_t xpsr = xpsr_read(env);
39
+ const char *mode;
40
+
72
+
41
+ if (xpsr & XPSR_EXCP) {
73
+ object_initialize_child(obj, name, &s->cpu_pwrctrl[i],
42
+ mode = "handler";
74
+ TYPE_ARMSSE_CPU_PWRCTRL);
43
+ } else {
75
+ g_free(name);
44
+ if (env->v7m.control & R_V7M_CONTROL_NPRIV_MASK) {
76
+ }
45
+ mode = "unpriv-thread";
77
+ }
46
+ } else {
78
if (info->has_sse_counter) {
47
+ mode = "priv-thread";
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;
48
+ }
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);
49
+ }
104
+ }
50
+
51
+ cpu_fprintf(f, "XPSR=%08x %c%c%c%c %c %s\n",
52
+ xpsr,
53
+ xpsr & XPSR_N ? 'N' : '-',
54
+ xpsr & XPSR_Z ? 'Z' : '-',
55
+ xpsr & XPSR_C ? 'C' : '-',
56
+ xpsr & XPSR_V ? 'V' : '-',
57
+ xpsr & XPSR_T ? 'T' : 'A',
58
+ mode);
59
} else {
60
- ns_status = "";
61
- }
62
-
63
- cpu_fprintf(f, "PSR=%08x %c%c%c%c %c %s%s%d\n",
64
- psr,
65
- psr & (1 << 31) ? 'N' : '-',
66
- psr & (1 << 30) ? 'Z' : '-',
67
- psr & (1 << 29) ? 'C' : '-',
68
- psr & (1 << 28) ? 'V' : '-',
69
- psr & CPSR_T ? 'T' : 'A',
70
- ns_status,
71
- cpu_mode_names[psr & 0xf], (psr & 0x10) ? 32 : 26);
72
+ uint32_t psr = cpsr_read(env);
73
+ const char *ns_status = "";
74
+
75
+ if (arm_feature(env, ARM_FEATURE_EL3) &&
76
+ (psr & CPSR_M) != ARM_CPU_MODE_MON) {
77
+ ns_status = env->cp15.scr_el3 & SCR_NS ? "NS " : "S ";
78
+ }
79
+
80
+ cpu_fprintf(f, "PSR=%08x %c%c%c%c %c %s%s%d\n",
81
+ psr,
82
+ psr & CPSR_N ? 'N' : '-',
83
+ psr & CPSR_Z ? 'Z' : '-',
84
+ psr & CPSR_C ? 'C' : '-',
85
+ psr & CPSR_V ? 'V' : '-',
86
+ psr & CPSR_T ? 'T' : 'A',
87
+ ns_status,
88
+ cpu_mode_names[psr & 0xf], (psr & 0x10) ? 32 : 26);
89
+ }
105
+ }
90
106
91
if (flags & CPU_DUMP_FPU) {
107
if (!sysbus_realize(SYS_BUS_DEVICE(&s->apb_ppc[1]), errp)) {
92
int numvfpregs = 0;
108
return;
93
--
109
--
94
2.7.4
110
2.20.1
95
111
96
112
diff view generated by jsdifflib
New patch
1
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
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
1
Some ELF files have program headers that specify segments that
1
The AN547 puts the combined UART overflow IRQ at 48, not 47 like the
2
are of zero size. Ignore them, rather than trying to create
2
other images. Make this setting board-specific.
3
zero-length ROM blobs for them, because the zero-length blob
4
can falsely trigger the overlapping-ROM-blobs check.
5
3
6
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>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Tested-by: Hua Yanghao <huayanghao@gmail.com>
8
Message-id: 20210219144617.4782-37-peter.maydell@linaro.org
10
Message-id: 1502116754-18867-3-git-send-email-peter.maydell@linaro.org
11
---
9
---
12
include/hw/elf_ops.h | 24 +++++++++++++++++-------
10
hw/arm/mps2-tz.c | 6 +++++-
13
1 file changed, 17 insertions(+), 7 deletions(-)
11
1 file changed, 5 insertions(+), 1 deletion(-)
14
12
15
diff --git a/include/hw/elf_ops.h b/include/hw/elf_ops.h
13
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
16
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
17
--- a/include/hw/elf_ops.h
15
--- a/hw/arm/mps2-tz.c
18
+++ b/include/hw/elf_ops.h
16
+++ b/hw/arm/mps2-tz.c
19
@@ -XXX,XX +XXX,XX @@ static int glue(load_elf, SZ)(const char *name, int fd,
17
@@ -XXX,XX +XXX,XX @@ struct MPS2TZMachineClass {
20
*pentry = ehdr.e_entry - ph->p_vaddr + ph->p_paddr;
18
uint32_t fpgaio_num_leds; /* Number of LEDs in FPGAIO LED0 register */
21
}
19
bool fpgaio_has_switches; /* Does FPGAIO have SWITCH register? */
22
20
int numirq; /* Number of external interrupts */
23
- if (load_rom) {
21
+ int uart_overflow_irq; /* number of the combined UART overflow IRQ */
24
- snprintf(label, sizeof(label), "phdr #%d: %s", i, name);
22
const RAMInfo *raminfo;
25
-
23
const char *armsse_type;
26
- /* rom_add_elf_program() seize the ownership of 'data' */
24
};
27
- rom_add_elf_program(label, data, file_size, mem_size, addr, as);
25
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
28
- } else {
26
&error_fatal);
29
- cpu_physical_memory_write(addr, data, file_size);
27
qdev_realize(DEVICE(&mms->uart_irq_orgate), NULL, &error_fatal);
30
+ if (mem_size == 0) {
28
qdev_connect_gpio_out(DEVICE(&mms->uart_irq_orgate), 0,
31
+ /* Some ELF files really do have segments of zero size;
29
- get_sse_irq_in(mms, 47));
32
+ * just ignore them rather than trying to create empty
30
+ get_sse_irq_in(mms, mmc->uart_overflow_irq));
33
+ * ROM blobs, because the zero-length blob can falsely
31
34
+ * trigger the overlapping-ROM-blobs check.
32
/* Most of the devices in the FPGA are behind Peripheral Protection
35
+ */
33
* Controllers. The required order for initializing things is:
36
g_free(data);
34
@@ -XXX,XX +XXX,XX @@ static void mps2tz_an505_class_init(ObjectClass *oc, void *data)
37
+ } else {
35
mmc->fpgaio_num_leds = 2;
38
+ if (load_rom) {
36
mmc->fpgaio_has_switches = false;
39
+ snprintf(label, sizeof(label), "phdr #%d: %s", i, name);
37
mmc->numirq = 92;
40
+
38
+ mmc->uart_overflow_irq = 47;
41
+ /* rom_add_elf_program() seize the ownership of 'data' */
39
mmc->raminfo = an505_raminfo;
42
+ rom_add_elf_program(label, data, file_size, mem_size,
40
mmc->armsse_type = TYPE_IOTKIT;
43
+ addr, as);
41
mps2tz_set_default_ram_info(mmc);
44
+ } else {
42
@@ -XXX,XX +XXX,XX @@ static void mps2tz_an521_class_init(ObjectClass *oc, void *data)
45
+ cpu_physical_memory_write(addr, data, file_size);
43
mmc->fpgaio_num_leds = 2;
46
+ g_free(data);
44
mmc->fpgaio_has_switches = false;
47
+ }
45
mmc->numirq = 92;
48
}
46
+ mmc->uart_overflow_irq = 47;
49
47
mmc->raminfo = an505_raminfo; /* AN521 is the same as AN505 here */
50
total_size += mem_size;
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);
51
--
58
--
52
2.7.4
59
2.20.1
53
60
54
61
diff view generated by jsdifflib
1
The M profile XPSR is almost the same format as the A profile CPSR,
1
We've already broken migration compatibility for all the MPS
2
but not quite. Define some XPSR_* macros and use them where we
2
boards, so we might as well take advantage of this to simplify
3
definitely dealing with an XPSR rather than reusing the CPSR ones.
3
the vmstate for the FPGAIO device by folding the counters
4
subsection into the main vmstate description.
4
5
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
7
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 1501692241-23310-9-git-send-email-peter.maydell@linaro.org
9
Message-id: 20210219144617.4782-38-peter.maydell@linaro.org
9
---
10
---
10
target/arm/cpu.h | 38 ++++++++++++++++++++++++++++----------
11
hw/misc/mps2-fpgaio.c | 30 +++++-------------------------
11
target/arm/helper.c | 15 ++++++++-------
12
1 file changed, 5 insertions(+), 25 deletions(-)
12
2 files changed, 36 insertions(+), 17 deletions(-)
13
13
14
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
14
diff --git a/hw/misc/mps2-fpgaio.c b/hw/misc/mps2-fpgaio.c
15
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/cpu.h
16
--- a/hw/misc/mps2-fpgaio.c
17
+++ b/target/arm/cpu.h
17
+++ b/hw/misc/mps2-fpgaio.c
18
@@ -XXX,XX +XXX,XX @@ void pmccntr_sync(CPUARMState *env);
18
@@ -XXX,XX +XXX,XX @@ static void mps2_fpgaio_realize(DeviceState *dev, Error **errp)
19
/* Mask of bits which may be set by exception return copying them from SPSR */
20
#define CPSR_ERET_MASK (~CPSR_RESERVED)
21
22
+/* Bit definitions for M profile XPSR. Most are the same as CPSR. */
23
+#define XPSR_EXCP 0x1ffU
24
+#define XPSR_SPREALIGN (1U << 9) /* Only set in exception stack frames */
25
+#define XPSR_IT_2_7 CPSR_IT_2_7
26
+#define XPSR_GE CPSR_GE
27
+#define XPSR_SFPA (1U << 20) /* Only set in exception stack frames */
28
+#define XPSR_T (1U << 24) /* Not the same as CPSR_T ! */
29
+#define XPSR_IT_0_1 CPSR_IT_0_1
30
+#define XPSR_Q CPSR_Q
31
+#define XPSR_V CPSR_V
32
+#define XPSR_C CPSR_C
33
+#define XPSR_Z CPSR_Z
34
+#define XPSR_N CPSR_N
35
+#define XPSR_NZCV CPSR_NZCV
36
+#define XPSR_IT CPSR_IT
37
+
38
#define TTBCR_N (7U << 0) /* TTBCR.EAE==0 */
39
#define TTBCR_T0SZ (7U << 0) /* TTBCR.EAE==1 */
40
#define TTBCR_PD0 (1U << 4)
41
@@ -XXX,XX +XXX,XX @@ static inline uint32_t xpsr_read(CPUARMState *env)
42
/* Set the xPSR. Note that some bits of mask must be all-set or all-clear. */
43
static inline void xpsr_write(CPUARMState *env, uint32_t val, uint32_t mask)
44
{
45
- if (mask & CPSR_NZCV) {
46
- env->ZF = (~val) & CPSR_Z;
47
+ if (mask & XPSR_NZCV) {
48
+ env->ZF = (~val) & XPSR_Z;
49
env->NF = val;
50
env->CF = (val >> 29) & 1;
51
env->VF = (val << 3) & 0x80000000;
52
}
53
- if (mask & CPSR_Q)
54
- env->QF = ((val & CPSR_Q) != 0);
55
- if (mask & (1 << 24))
56
- env->thumb = ((val & (1 << 24)) != 0);
57
- if (mask & CPSR_IT_0_1) {
58
+ if (mask & XPSR_Q) {
59
+ env->QF = ((val & XPSR_Q) != 0);
60
+ }
61
+ if (mask & XPSR_T) {
62
+ env->thumb = ((val & XPSR_T) != 0);
63
+ }
64
+ if (mask & XPSR_IT_0_1) {
65
env->condexec_bits &= ~3;
66
env->condexec_bits |= (val >> 25) & 3;
67
}
68
- if (mask & CPSR_IT_2_7) {
69
+ if (mask & XPSR_IT_2_7) {
70
env->condexec_bits &= 3;
71
env->condexec_bits |= (val >> 8) & 0xfc;
72
}
73
- if (mask & 0x1ff) {
74
- env->v7m.exception = val & 0x1ff;
75
+ if (mask & XPSR_EXCP) {
76
+ env->v7m.exception = val & XPSR_EXCP;
77
}
19
}
78
}
20
}
79
21
80
diff --git a/target/arm/helper.c b/target/arm/helper.c
22
-static bool mps2_fpgaio_counters_needed(void *opaque)
81
index XXXXXXX..XXXXXXX 100644
23
-{
82
--- a/target/arm/helper.c
24
- /* Currently vmstate.c insists all subsections have a 'needed' function */
83
+++ b/target/arm/helper.c
25
- return true;
84
@@ -XXX,XX +XXX,XX @@ static void v7m_push_stack(ARMCPU *cpu)
26
-}
85
/* Align stack pointer if the guest wants that */
27
-
86
if ((env->regs[13] & 4) && (env->v7m.ccr & R_V7M_CCR_STKALIGN_MASK)) {
28
-static const VMStateDescription mps2_fpgaio_counters_vmstate = {
87
env->regs[13] -= 4;
29
- .name = "mps2-fpgaio/counters",
88
- xpsr |= 0x200;
30
+static const VMStateDescription mps2_fpgaio_vmstate = {
89
+ xpsr |= XPSR_SPREALIGN;
31
+ .name = "mps2-fpgaio",
90
}
32
.version_id = 2,
91
/* Switch to the handler mode. */
33
.minimum_version_id = 2,
92
v7m_push(env, xpsr);
34
- .needed = mps2_fpgaio_counters_needed,
93
@@ -XXX,XX +XXX,XX @@ static void do_v7m_exception_exit(ARMCPU *cpu)
35
.fields = (VMStateField[]) {
94
env->regs[15] &= ~1U;
36
+ VMSTATE_UINT32(led0, MPS2FPGAIO),
95
}
37
+ VMSTATE_UINT32(prescale, MPS2FPGAIO),
96
xpsr = v7m_pop(env);
38
+ VMSTATE_UINT32(misc, MPS2FPGAIO),
97
- xpsr_write(env, xpsr, 0xfffffdff);
39
VMSTATE_INT64(clk1hz_tick_offset, MPS2FPGAIO),
98
+ xpsr_write(env, xpsr, ~XPSR_SPREALIGN);
40
VMSTATE_INT64(clk100hz_tick_offset, MPS2FPGAIO),
99
/* Undo stack alignment. */
41
VMSTATE_UINT32(counter, MPS2FPGAIO),
100
- if (xpsr & 0x200)
42
VMSTATE_UINT32(pscntr, MPS2FPGAIO),
101
+ if (xpsr & XPSR_SPREALIGN) {
43
VMSTATE_INT64(pscntr_sync_ticks, MPS2FPGAIO),
102
env->regs[13] |= 4;
44
VMSTATE_END_OF_LIST()
103
+ }
45
- }
104
46
-};
105
/* The restored xPSR exception field will be zero if we're
47
-
106
* resuming in Thread mode. If that doesn't match what the
48
-static const VMStateDescription mps2_fpgaio_vmstate = {
107
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(v7m_mrs)(CPUARMState *env, uint32_t reg)
49
- .name = "mps2-fpgaio",
108
case 0 ... 7: /* xPSR sub-fields */
50
- .version_id = 1,
109
mask = 0;
51
- .minimum_version_id = 1,
110
if ((reg & 1) && el) {
52
- .fields = (VMStateField[]) {
111
- mask |= 0x000001ff; /* IPSR (unpriv. reads as zero) */
53
- VMSTATE_UINT32(led0, MPS2FPGAIO),
112
+ mask |= XPSR_EXCP; /* IPSR (unpriv. reads as zero) */
54
- VMSTATE_UINT32(prescale, MPS2FPGAIO),
113
}
55
- VMSTATE_UINT32(misc, MPS2FPGAIO),
114
if (!(reg & 4)) {
56
- VMSTATE_END_OF_LIST()
115
- mask |= 0xf8000000; /* APSR */
57
},
116
+ mask |= XPSR_NZCV | XPSR_Q; /* APSR */
58
- .subsections = (const VMStateDescription*[]) {
117
}
59
- &mps2_fpgaio_counters_vmstate,
118
/* EPSR reads as zero */
60
- NULL
119
return xpsr_read(env) & mask;
61
- }
120
@@ -XXX,XX +XXX,XX @@ void HELPER(v7m_msr)(CPUARMState *env, uint32_t maskreg, uint32_t val)
62
};
121
uint32_t apsrmask = 0;
63
122
64
static Property mps2_fpgaio_properties[] = {
123
if (mask & 8) {
124
- apsrmask |= 0xf8000000; /* APSR NZCVQ */
125
+ apsrmask |= XPSR_NZCV | XPSR_Q;
126
}
127
if ((mask & 4) && arm_feature(env, ARM_FEATURE_THUMB_DSP)) {
128
- apsrmask |= 0x000f0000; /* APSR GE[3:0] */
129
+ apsrmask |= XPSR_GE;
130
}
131
xpsr_write(env, val, apsrmask);
132
}
133
--
65
--
134
2.7.4
66
2.20.1
135
67
136
68
diff view generated by jsdifflib
1
In the ARM get_phys_addr() code, switch to using the MMUAccessType
1
For the AN547 image, the FPGAIO block has an extra DBGCTRL register,
2
enum and its MMU_* values rather than int and literal 0/1/2.
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
8
Implement the register, with a property defining whether it is
9
present, and allow mps2-tz boards to specify that it is present.
3
10
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
12
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
13
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 1501692241-23310-2-git-send-email-peter.maydell@linaro.org
15
Message-id: 20210219144617.4782-39-peter.maydell@linaro.org
9
---
16
---
10
target/arm/internals.h | 3 ++-
17
include/hw/misc/mps2-fpgaio.h | 2 ++
11
target/arm/helper.c | 30 +++++++++++++++---------------
18
hw/arm/mps2-tz.c | 5 +++++
12
2 files changed, 17 insertions(+), 16 deletions(-)
19
hw/misc/mps2-fpgaio.c | 22 ++++++++++++++++++++--
20
3 files changed, 27 insertions(+), 2 deletions(-)
13
21
14
diff --git a/target/arm/internals.h b/target/arm/internals.h
22
diff --git a/include/hw/misc/mps2-fpgaio.h b/include/hw/misc/mps2-fpgaio.h
15
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/internals.h
24
--- a/include/hw/misc/mps2-fpgaio.h
17
+++ b/target/arm/internals.h
25
+++ b/include/hw/misc/mps2-fpgaio.h
18
@@ -XXX,XX +XXX,XX @@ struct ARMMMUFaultInfo {
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(),
19
};
153
};
20
154
21
/* Do a page table walk and add page to TLB if possible */
22
-bool arm_tlb_fill(CPUState *cpu, vaddr address, int rw, int mmu_idx,
23
+bool arm_tlb_fill(CPUState *cpu, vaddr address,
24
+ MMUAccessType access_type, int mmu_idx,
25
uint32_t *fsr, ARMMMUFaultInfo *fi);
26
27
/* Return true if the stage 1 translation regime is using LPAE format page
28
diff --git a/target/arm/helper.c b/target/arm/helper.c
29
index XXXXXXX..XXXXXXX 100644
30
--- a/target/arm/helper.c
31
+++ b/target/arm/helper.c
32
@@ -XXX,XX +XXX,XX @@
33
34
#ifndef CONFIG_USER_ONLY
35
static bool get_phys_addr(CPUARMState *env, target_ulong address,
36
- int access_type, ARMMMUIdx mmu_idx,
37
+ MMUAccessType access_type, ARMMMUIdx mmu_idx,
38
hwaddr *phys_ptr, MemTxAttrs *attrs, int *prot,
39
target_ulong *page_size, uint32_t *fsr,
40
ARMMMUFaultInfo *fi);
41
42
static bool get_phys_addr_lpae(CPUARMState *env, target_ulong address,
43
- int access_type, ARMMMUIdx mmu_idx,
44
+ MMUAccessType access_type, ARMMMUIdx mmu_idx,
45
hwaddr *phys_ptr, MemTxAttrs *txattrs, int *prot,
46
target_ulong *page_size_ptr, uint32_t *fsr,
47
ARMMMUFaultInfo *fi);
48
@@ -XXX,XX +XXX,XX @@ static CPAccessResult ats_access(CPUARMState *env, const ARMCPRegInfo *ri,
49
}
50
51
static uint64_t do_ats_write(CPUARMState *env, uint64_t value,
52
- int access_type, ARMMMUIdx mmu_idx)
53
+ MMUAccessType access_type, ARMMMUIdx mmu_idx)
54
{
55
hwaddr phys_addr;
56
target_ulong page_size;
57
@@ -XXX,XX +XXX,XX @@ static uint64_t do_ats_write(CPUARMState *env, uint64_t value,
58
59
static void ats_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
60
{
61
- int access_type = ri->opc2 & 1;
62
+ MMUAccessType access_type = ri->opc2 & 1 ? MMU_DATA_STORE : MMU_DATA_LOAD;
63
uint64_t par64;
64
ARMMMUIdx mmu_idx;
65
int el = arm_current_el(env);
66
@@ -XXX,XX +XXX,XX @@ static void ats_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
67
static void ats1h_write(CPUARMState *env, const ARMCPRegInfo *ri,
68
uint64_t value)
69
{
70
- int access_type = ri->opc2 & 1;
71
+ MMUAccessType access_type = ri->opc2 & 1 ? MMU_DATA_STORE : MMU_DATA_LOAD;
72
uint64_t par64;
73
74
par64 = do_ats_write(env, value, access_type, ARMMMUIdx_S2NS);
75
@@ -XXX,XX +XXX,XX @@ static CPAccessResult at_s1e2_access(CPUARMState *env, const ARMCPRegInfo *ri,
76
static void ats_write64(CPUARMState *env, const ARMCPRegInfo *ri,
77
uint64_t value)
78
{
79
- int access_type = ri->opc2 & 1;
80
+ MMUAccessType access_type = ri->opc2 & 1 ? MMU_DATA_STORE : MMU_DATA_LOAD;
81
ARMMMUIdx mmu_idx;
82
int secure = arm_is_secure_below_el3(env);
83
84
@@ -XXX,XX +XXX,XX @@ static uint64_t arm_ldq_ptw(CPUState *cs, hwaddr addr, bool is_secure,
85
}
86
87
static bool get_phys_addr_v5(CPUARMState *env, uint32_t address,
88
- int access_type, ARMMMUIdx mmu_idx,
89
+ MMUAccessType access_type, ARMMMUIdx mmu_idx,
90
hwaddr *phys_ptr, int *prot,
91
target_ulong *page_size, uint32_t *fsr,
92
ARMMMUFaultInfo *fi)
93
@@ -XXX,XX +XXX,XX @@ do_fault:
94
}
95
96
static bool get_phys_addr_v6(CPUARMState *env, uint32_t address,
97
- int access_type, ARMMMUIdx mmu_idx,
98
+ MMUAccessType access_type, ARMMMUIdx mmu_idx,
99
hwaddr *phys_ptr, MemTxAttrs *attrs, int *prot,
100
target_ulong *page_size, uint32_t *fsr,
101
ARMMMUFaultInfo *fi)
102
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_v6(CPUARMState *env, uint32_t address,
103
if (pxn && !regime_is_user(env, mmu_idx)) {
104
xn = 1;
105
}
106
- if (xn && access_type == 2)
107
+ if (xn && access_type == MMU_INST_FETCH)
108
goto do_fault;
109
110
if (arm_feature(env, ARM_FEATURE_V6K) &&
111
@@ -XXX,XX +XXX,XX @@ static bool check_s2_mmu_setup(ARMCPU *cpu, bool is_aa64, int level,
112
}
113
114
static bool get_phys_addr_lpae(CPUARMState *env, target_ulong address,
115
- int access_type, ARMMMUIdx mmu_idx,
116
+ MMUAccessType access_type, ARMMMUIdx mmu_idx,
117
hwaddr *phys_ptr, MemTxAttrs *txattrs, int *prot,
118
target_ulong *page_size_ptr, uint32_t *fsr,
119
ARMMMUFaultInfo *fi)
120
@@ -XXX,XX +XXX,XX @@ static inline bool m_is_system_region(CPUARMState *env, uint32_t address)
121
}
122
123
static bool get_phys_addr_pmsav7(CPUARMState *env, uint32_t address,
124
- int access_type, ARMMMUIdx mmu_idx,
125
+ MMUAccessType access_type, ARMMMUIdx mmu_idx,
126
hwaddr *phys_ptr, int *prot, uint32_t *fsr)
127
{
128
ARMCPU *cpu = arm_env_get_cpu(env);
129
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_pmsav7(CPUARMState *env, uint32_t address,
130
}
131
132
static bool get_phys_addr_pmsav5(CPUARMState *env, uint32_t address,
133
- int access_type, ARMMMUIdx mmu_idx,
134
+ MMUAccessType access_type, ARMMMUIdx mmu_idx,
135
hwaddr *phys_ptr, int *prot, uint32_t *fsr)
136
{
137
int n;
138
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_pmsav5(CPUARMState *env, uint32_t address,
139
return true;
140
}
141
142
- if (access_type == 2) {
143
+ if (access_type == MMU_INST_FETCH) {
144
mask = env->cp15.pmsav5_insn_ap;
145
} else {
146
mask = env->cp15.pmsav5_data_ap;
147
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_pmsav5(CPUARMState *env, uint32_t address,
148
* @fsr: set to the DFSR/IFSR value on failure
149
*/
150
static bool get_phys_addr(CPUARMState *env, target_ulong address,
151
- int access_type, ARMMMUIdx mmu_idx,
152
+ MMUAccessType access_type, ARMMMUIdx mmu_idx,
153
hwaddr *phys_ptr, MemTxAttrs *attrs, int *prot,
154
target_ulong *page_size, uint32_t *fsr,
155
ARMMMUFaultInfo *fi)
156
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr(CPUARMState *env, target_ulong address,
157
* fsr with ARM DFSR/IFSR fault register format value on failure.
158
*/
159
bool arm_tlb_fill(CPUState *cs, vaddr address,
160
- int access_type, int mmu_idx, uint32_t *fsr,
161
+ MMUAccessType access_type, int mmu_idx, uint32_t *fsr,
162
ARMMMUFaultInfo *fi)
163
{
164
ARMCPU *cpu = ARM_CPU(cs);
165
--
155
--
166
2.7.4
156
2.20.1
167
157
168
158
diff view generated by jsdifflib
1
When we switched our handling of exception exit to detect
1
Implement the minor changes required to the SCC block for AN547 images:
2
the magic addresses at translate time rather than via
2
* CFG2 and CFG5 exist (like AN524)
3
a do_unassigned_access hook, we forgot to update a
3
* CFG3 is reserved (like AN524)
4
comment; correct the omission.
4
* CFG0 bit 1 is CPU_WAIT; we don't implement it, but note this
5
in the TODO comment
5
6
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
8
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 1501692241-23310-8-git-send-email-peter.maydell@linaro.org
10
Message-id: 20210219144617.4782-40-peter.maydell@linaro.org
10
---
11
---
11
target/arm/helper.c | 2 +-
12
hw/misc/mps2-scc.c | 15 +++++++++------
12
1 file changed, 1 insertion(+), 1 deletion(-)
13
1 file changed, 9 insertions(+), 6 deletions(-)
13
14
14
diff --git a/target/arm/helper.c b/target/arm/helper.c
15
diff --git a/hw/misc/mps2-scc.c b/hw/misc/mps2-scc.c
15
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/helper.c
17
--- a/hw/misc/mps2-scc.c
17
+++ b/target/arm/helper.c
18
+++ b/hw/misc/mps2-scc.c
18
@@ -XXX,XX +XXX,XX @@ static void do_v7m_exception_exit(ARMCPU *cpu)
19
@@ -XXX,XX +XXX,XX @@ static uint64_t mps2_scc_read(void *opaque, hwaddr offset, unsigned size)
19
bool rettobase = false;
20
r = s->cfg1;
20
21
break;
21
/* We can only get here from an EXCP_EXCEPTION_EXIT, and
22
case A_CFG2:
22
- * arm_v7m_do_unassigned_access() enforces the architectural rule
23
- if (scc_partno(s) != 0x524) {
23
+ * gen_bx_excret() enforces the architectural rule
24
+ if (scc_partno(s) != 0x524 && scc_partno(s) != 0x547) {
24
* that jumps to magic addresses don't have magic behaviour unless
25
/* CFG2 reserved on other boards */
25
* we're in Handler mode (compare pseudocode BXWritePC()).
26
goto bad_offset;
26
*/
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
}
27
--
75
--
28
2.7.4
76
2.20.1
29
77
30
78
diff view generated by jsdifflib
1
Remove an out of date comment which says there's only one
1
The AN547 runs the APB peripherals outside the SSE-300 on a different
2
item in the NVIC container region -- we put systick into its
2
and slightly slower clock than it runs the SSE-300 with. Support
3
own device object a while back and so now there are two
3
making the APB peripheral clock frequency board-specific. (For our
4
things in the container.
4
implementation only the UARTs actually take a clock.)
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: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
7
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 1501692241-23310-6-git-send-email-peter.maydell@linaro.org
10
Message-id: 20210219144617.4782-41-peter.maydell@linaro.org
10
---
11
---
11
hw/intc/armv7m_nvic.c | 4 ----
12
hw/arm/mps2-tz.c | 6 +++++-
12
1 file changed, 4 deletions(-)
13
1 file changed, 5 insertions(+), 1 deletion(-)
13
14
14
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
15
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
15
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/intc/armv7m_nvic.c
17
--- a/hw/arm/mps2-tz.c
17
+++ b/hw/intc/armv7m_nvic.c
18
+++ b/hw/arm/mps2-tz.c
18
@@ -XXX,XX +XXX,XX @@ static void armv7m_nvic_realize(DeviceState *dev, Error **errp)
19
@@ -XXX,XX +XXX,XX @@ struct MPS2TZMachineClass {
19
* 0xd00..0xd3c - SCS registers
20
MPS2TZFPGAType fpga_type;
20
* 0xd40..0xeff - Reserved or Not implemented
21
uint32_t scc_id;
21
* 0xf00 - STIR
22
uint32_t sysclk_frq; /* Main SYSCLK frequency in Hz */
22
- *
23
+ uint32_t apb_periph_frq; /* APB peripheral frequency in Hz */
23
- * At the moment there is only one thing in the container region,
24
uint32_t len_oscclk;
24
- * but we leave it in place to allow us to pull systick out into
25
const uint32_t *oscclk;
25
- * its own device object later.
26
uint32_t fpgaio_num_leds; /* Number of LEDs in FPGAIO LED0 register */
26
*/
27
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_uart(MPS2TZMachineState *mms, void *opaque,
27
memory_region_init(&s->container, OBJECT(s), "nvic", 0x1000);
28
28
/* The system register region goes at the bottom of the priority
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;
29
--
60
--
30
2.7.4
61
2.20.1
31
62
32
63
diff view generated by jsdifflib
1
M profile cores can never trap on WFI or WFE instructions. Check for
1
The AN547 configures the SSE-300 with a different initsvtor0
2
M profile in check_wfx_trap() to ensure this.
2
setting from its default; make this a board-specific setting.
3
4
The existing code will do the right thing for v7M cores because
5
the hcr_el2 and scr_el3 registers will be all-zeroes and so we
6
won't attempt to trap, but when we start setting ARM_FEATURE_V8
7
for v8M cores the v8A handling of SCTLR.nTWE and .nTWI will not
8
give the right results.
9
3
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
5
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
13
Message-id: 1501692241-23310-3-git-send-email-peter.maydell@linaro.org
8
Message-id: 20210219144617.4782-42-peter.maydell@linaro.org
14
---
9
---
15
target/arm/op_helper.c | 5 +++++
10
hw/arm/mps2-tz.c | 5 +++++
16
1 file changed, 5 insertions(+)
11
1 file changed, 5 insertions(+)
17
12
18
diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c
13
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
19
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
20
--- a/target/arm/op_helper.c
15
--- a/hw/arm/mps2-tz.c
21
+++ b/target/arm/op_helper.c
16
+++ b/hw/arm/mps2-tz.c
22
@@ -XXX,XX +XXX,XX @@ static inline int check_wfx_trap(CPUARMState *env, bool is_wfe)
17
@@ -XXX,XX +XXX,XX @@ struct MPS2TZMachineClass {
23
int cur_el = arm_current_el(env);
18
bool fpgaio_has_dbgctrl; /* Does FPGAIO have DBGCTRL register? */
24
uint64_t mask;
19
int numirq; /* Number of external interrupts */
25
20
int uart_overflow_irq; /* number of the combined UART overflow IRQ */
26
+ if (arm_feature(env, ARM_FEATURE_M)) {
21
+ uint32_t init_svtor; /* init-svtor setting for SSE */
27
+ /* M profile cores can never trap WFI/WFE. */
22
const RAMInfo *raminfo;
28
+ return 0;
23
const char *armsse_type;
29
+ }
24
};
30
+
25
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
31
/* If we are currently in EL0 then we need to check if SCTLR is set up for
26
object_property_set_link(OBJECT(&mms->iotkit), "memory",
32
* WFx instructions being trapped to EL1. These trap bits don't exist in v7.
27
OBJECT(system_memory), &error_abort);
33
*/
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);
34
--
57
--
35
2.7.4
58
2.20.1
36
59
37
60
diff view generated by jsdifflib
New patch
1
1
Add support for the mps3-an547 board; this is an SSE-300 based
2
FPGA image that runs on the MPS3.
3
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-43-peter.maydell@linaro.org
8
---
9
hw/arm/mps2-tz.c | 146 ++++++++++++++++++++++++++++++++++++++++++++++-
10
1 file changed, 144 insertions(+), 2 deletions(-)
11
12
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/arm/mps2-tz.c
15
+++ b/hw/arm/mps2-tz.c
16
@@ -XXX,XX +XXX,XX @@
17
* "mps2-an505" -- Cortex-M33 as documented in ARM Application Note AN505
18
* "mps2-an521" -- Dual Cortex-M33 as documented in Application Note AN521
19
* "mps2-an524" -- Dual Cortex-M33 as documented in Application Note AN524
20
+ * "mps2-an547" -- Single Cortex-M55 as documented in Application Note AN547
21
*
22
* Links to the TRM for the board itself and to the various Application
23
* Notes which document the FPGA images can be found here:
24
@@ -XXX,XX +XXX,XX @@
25
* https://developer.arm.com/documentation/dai0521/latest/
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();
183
}
184
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
185
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
+
193
create_non_mpc_ram(mms);
194
195
armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename,
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
--
251
2.20.1
252
253
diff view generated by jsdifflib
1
Tighten up the T32 decoder in the places where new v8M instructions
1
Add brief documentation of the new mps3-an547 board.
2
will be:
3
* TT/TTT/TTA/TTAT are in what was nominally LDREX/STREX r15, ...
4
which is UNPREDICTABLE:
5
make the UNPREDICTABLE behaviour be to UNDEF
6
* BXNS/BLXNS are distinguished from BX/BLX via the low 3 bits,
7
which in previous architectural versions are SBZ:
8
enforce the SBZ via UNDEF rather than ignoring it, and move
9
the "ARCH(5)" UNDEF case up so we don't leak a TCG temporary
10
* SG is in the encoding which would be LDRD/STRD with rn = r15;
11
this is UNPREDICTABLE and we currently UNDEF:
12
move this check further up the code so that we don't leak
13
TCG temporaries in the UNDEF case and have a better place
14
to put the SG decode.
15
16
This means that if a v8M binary is accidentally run on v7M
17
or if a test case hits something that we haven't implemented
18
yet the behaviour will be obvious (UNDEF) rather than obscure
19
(plough on treating it as a different instruction).
20
21
In the process, add some comments about the instruction patterns
22
at these points in the decode. Our Thumb and ARM decoders are
23
very difficult to understand currently, but gradually adding
24
comments like this should help to clarify what exactly has
25
been decoded when.
26
2
27
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
28
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
4
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
29
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
30
Message-id: 1501692241-23310-5-git-send-email-peter.maydell@linaro.org
6
Message-id: 20210219144617.4782-44-peter.maydell@linaro.org
31
---
7
---
32
target/arm/translate.c | 48 +++++++++++++++++++++++++++++++++++++++---------
8
docs/system/arm/mps2.rst | 6 ++++--
33
1 file changed, 39 insertions(+), 9 deletions(-)
9
1 file changed, 4 insertions(+), 2 deletions(-)
34
10
35
diff --git a/target/arm/translate.c b/target/arm/translate.c
11
diff --git a/docs/system/arm/mps2.rst b/docs/system/arm/mps2.rst
36
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
37
--- a/target/arm/translate.c
13
--- a/docs/system/arm/mps2.rst
38
+++ b/target/arm/translate.c
14
+++ b/docs/system/arm/mps2.rst
39
@@ -XXX,XX +XXX,XX @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
15
@@ -XXX,XX +XXX,XX @@
40
abort();
16
-Arm MPS2 and MPS3 boards (``mps2-an385``, ``mps2-an386``, ``mps2-an500``, ``mps2-an505``, ``mps2-an511``, ``mps2-an521``, ``mps3-an524``)
41
case 4:
17
-=========================================================================================================================================
42
if (insn & (1 << 22)) {
18
+Arm MPS2 and MPS3 boards (``mps2-an385``, ``mps2-an386``, ``mps2-an500``, ``mps2-an505``, ``mps2-an511``, ``mps2-an521``, ``mps3-an524``, ``mps3-an547``)
43
- /* Other load/store, table branch. */
19
+=========================================================================================================================================================
44
+ /* 0b1110_100x_x1xx_xxxx_xxxx_xxxx_xxxx_xxxx
20
45
+ * - load/store doubleword, load/store exclusive, ldacq/strel,
21
These board models all use Arm M-profile CPUs.
46
+ * table branch.
22
47
+ */
23
@@ -XXX,XX +XXX,XX @@ QEMU models the following FPGA images:
48
if (insn & 0x01200000) {
24
Dual Cortex-M33 as documented in Arm Application Note AN521
49
- /* Load/store doubleword. */
25
``mps3-an524``
50
+ /* 0b1110_1000_x11x_xxxx_xxxx_xxxx_xxxx_xxxx
26
Dual Cortex-M33 on an MPS3, as documented in Arm Application Note AN524
51
+ * - load/store dual (post-indexed)
27
+``mps3-an547``
52
+ * 0b1111_1001_x10x_xxxx_xxxx_xxxx_xxxx_xxxx
28
+ Cortex-M55 on an MPS3, as documented in Arm Application Note AN547
53
+ * - load/store dual (literal and immediate)
29
54
+ * 0b1111_1001_x11x_xxxx_xxxx_xxxx_xxxx_xxxx
30
Differences between QEMU and real hardware:
55
+ * - load/store dual (pre-indexed)
56
+ */
57
if (rn == 15) {
58
+ if (insn & (1 << 21)) {
59
+ /* UNPREDICTABLE */
60
+ goto illegal_op;
61
+ }
62
addr = tcg_temp_new_i32();
63
tcg_gen_movi_i32(addr, s->pc & ~3);
64
} else {
65
@@ -XXX,XX +XXX,XX @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
66
}
67
if (insn & (1 << 21)) {
68
/* Base writeback. */
69
- if (rn == 15)
70
- goto illegal_op;
71
tcg_gen_addi_i32(addr, addr, offset - 4);
72
store_reg(s, rn, addr);
73
} else {
74
tcg_temp_free_i32(addr);
75
}
76
} else if ((insn & (1 << 23)) == 0) {
77
- /* Load/store exclusive word. */
78
+ /* 0b1110_1000_010x_xxxx_xxxx_xxxx_xxxx_xxxx
79
+ * - load/store exclusive word
80
+ */
81
+ if (rs == 15) {
82
+ goto illegal_op;
83
+ }
84
addr = tcg_temp_local_new_i32();
85
load_reg_var(s, addr, rn);
86
tcg_gen_addi_i32(addr, addr, (insn & 0xff) << 2);
87
@@ -XXX,XX +XXX,XX @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
88
break;
89
}
90
if (insn & (1 << 10)) {
91
- /* data processing extended or blx */
92
+ /* 0b0100_01xx_xxxx_xxxx
93
+ * - data processing extended, branch and exchange
94
+ */
95
rd = (insn & 7) | ((insn >> 4) & 8);
96
rm = (insn >> 3) & 0xf;
97
op = (insn >> 8) & 3;
98
@@ -XXX,XX +XXX,XX @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
99
tmp = load_reg(s, rm);
100
store_reg(s, rd, tmp);
101
break;
102
- case 3:/* branch [and link] exchange thumb register */
103
- tmp = load_reg(s, rm);
104
- if (insn & (1 << 7)) {
105
+ case 3:
106
+ {
107
+ /* 0b0100_0111_xxxx_xxxx
108
+ * - branch [and link] exchange thumb register
109
+ */
110
+ bool link = insn & (1 << 7);
111
+
112
+ if (insn & 7) {
113
+ goto undef;
114
+ }
115
+ if (link) {
116
ARCH(5);
117
+ }
118
+ tmp = load_reg(s, rm);
119
+ if (link) {
120
val = (uint32_t)s->pc | 1;
121
tmp2 = tcg_temp_new_i32();
122
tcg_gen_movi_i32(tmp2, val);
123
@@ -XXX,XX +XXX,XX @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
124
}
125
break;
126
}
127
+ }
128
break;
129
}
130
31
131
--
32
--
132
2.7.4
33
2.20.1
133
34
134
35
diff view generated by jsdifflib
1
From: Andrew Jones <drjones@redhat.com>
1
Add a simple qtest to exercise the new system counter device in the
2
SSE-300.
2
3
3
When adding a PMU with a userspace irqchip we skip the set-irq
4
We'll add tests of the system timer device here too, so this includes
4
stage of device creation. Split the 'create' function into two
5
scaffolding (register definitions, etc) for those.
5
functions 'init' and 'set-irq' so they may be called separately.
6
6
7
Signed-off-by: Andrew Jones <drjones@redhat.com>
8
Reviewed-by: Christoffer Dall <cdall@linaro.org>
9
Message-id: 1500471597-2517-3-git-send-email-drjones@redhat.com
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
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
---
11
---
12
target/arm/kvm_arm.h | 10 ++++++++--
12
tests/qtest/sse-timer-test.c | 117 +++++++++++++++++++++++++++++++++++
13
hw/arm/virt.c | 11 +++++++++--
13
MAINTAINERS | 1 +
14
target/arm/kvm32.c | 8 +++++++-
14
tests/qtest/meson.build | 1 +
15
target/arm/kvm64.c | 52 +++++++++++++++++++++++++---------------------------
15
3 files changed, 119 insertions(+)
16
4 files changed, 49 insertions(+), 32 deletions(-)
16
create mode 100644 tests/qtest/sse-timer-test.c
17
17
18
diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h
18
diff --git a/tests/qtest/sse-timer-test.c b/tests/qtest/sse-timer-test.c
19
index XXXXXXX..XXXXXXX 100644
19
new file mode 100644
20
--- a/target/arm/kvm_arm.h
20
index XXXXXXX..XXXXXXX
21
+++ b/target/arm/kvm_arm.h
21
--- /dev/null
22
@@ -XXX,XX +XXX,XX @@ int kvm_arm_sync_mpstate_to_qemu(ARMCPU *cpu);
22
+++ b/tests/qtest/sse-timer-test.c
23
23
@@ -XXX,XX +XXX,XX @@
24
int kvm_arm_vgic_probe(void);
24
+/*
25
25
+ * QTest testcase for the SSE timer device
26
-int kvm_arm_pmu_create(CPUState *cs, int irq);
26
+ *
27
+int kvm_arm_pmu_set_irq(CPUState *cs, int irq);
27
+ * Copyright (c) 2021 Linaro Limited
28
+int kvm_arm_pmu_init(CPUState *cs);
28
+ *
29
29
+ * This program is free software; you can redistribute it and/or modify it
30
#else
30
+ * under the terms of the GNU General Public License as published by the
31
31
+ * Free Software Foundation; either version 2 of the License, or
32
@@ -XXX,XX +XXX,XX @@ static inline int kvm_arm_vgic_probe(void)
32
+ * (at your option) any later version.
33
return 0;
33
+ *
34
}
34
+ * This program is distributed in the hope that it will be useful, but WITHOUT
35
35
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
36
-static inline int kvm_arm_pmu_create(CPUState *cs, int irq)
36
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
37
+static inline int kvm_arm_pmu_set_irq(CPUState *cs, int irq)
37
+ * for more details.
38
+ */
39
+
40
+#include "qemu/osdep.h"
41
+#include "libqtest-single.h"
42
+
43
+/*
44
+ * SSE-123/SSE-300 timer in the mps3-an547 board, where it is driven
45
+ * at 32MHz, so 31.25ns per tick.
46
+ */
47
+#define TIMER_BASE 0x48000000
48
+
49
+/* PERIPHNSPPC0 register in the SSE-300 Secure Access Configuration block */
50
+#define PERIPHNSPPC0 (0x50080000 + 0x70)
51
+
52
+/* Base of the System Counter control frame */
53
+#define COUNTER_BASE 0x58100000
54
+
55
+/* SSE counter register offsets in the control frame */
56
+#define CNTCR 0
57
+#define CNTSR 0x4
58
+#define CNTCV_LO 0x8
59
+#define CNTCV_HI 0xc
60
+#define CNTSCR 0x10
61
+
62
+/* SSE timer register offsets */
63
+#define CNTPCT_LO 0
64
+#define CNTPCT_HI 4
65
+#define CNTFRQ 0x10
66
+#define CNTP_CVAL_LO 0x20
67
+#define CNTP_CVAL_HI 0x24
68
+#define CNTP_TVAL 0x28
69
+#define CNTP_CTL 0x2c
70
+#define CNTP_AIVAL_LO 0x40
71
+#define CNTP_AIVAL_HI 0x44
72
+#define CNTP_AIVAL_RELOAD 0x48
73
+#define CNTP_AIVAL_CTL 0x4c
74
+
75
+/* 4 ticks in nanoseconds (so we can work in integers) */
76
+#define FOUR_TICKS 125
77
+
78
+static void clock_step_ticks(uint64_t ticks)
38
+{
79
+{
39
+ return 0;
80
+ /*
81
+ * Advance the qtest clock by however many nanoseconds we
82
+ * need to move the timer forward the specified number of ticks.
83
+ * ticks must be a multiple of 4, so we get a whole number of ns.
84
+ */
85
+ assert(!(ticks & 3));
86
+ clock_step(FOUR_TICKS * (ticks >> 2));
40
+}
87
+}
41
+
88
+
42
+static inline int kvm_arm_pmu_init(CPUState *cs)
89
+static void reset_counter_and_timer(void)
43
{
44
return 0;
45
}
46
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
47
index XXXXXXX..XXXXXXX 100644
48
--- a/hw/arm/virt.c
49
+++ b/hw/arm/virt.c
50
@@ -XXX,XX +XXX,XX @@ static void fdt_add_pmu_nodes(const VirtMachineState *vms)
51
52
CPU_FOREACH(cpu) {
53
armcpu = ARM_CPU(cpu);
54
- if (!arm_feature(&armcpu->env, ARM_FEATURE_PMU) ||
55
- (kvm_enabled() && !kvm_arm_pmu_create(cpu, PPI(VIRTUAL_PMU_IRQ)))) {
56
+ if (!arm_feature(&armcpu->env, ARM_FEATURE_PMU)) {
57
return;
58
}
59
+ if (kvm_enabled()) {
60
+ if (!kvm_arm_pmu_set_irq(cpu, PPI(VIRTUAL_PMU_IRQ))) {
61
+ return;
62
+ }
63
+ if (!kvm_arm_pmu_init(cpu)) {
64
+ return;
65
+ }
66
+ }
67
}
68
69
if (vms->gic_version == 2) {
70
diff --git a/target/arm/kvm32.c b/target/arm/kvm32.c
71
index XXXXXXX..XXXXXXX 100644
72
--- a/target/arm/kvm32.c
73
+++ b/target/arm/kvm32.c
74
@@ -XXX,XX +XXX,XX @@ bool kvm_arm_hw_debug_active(CPUState *cs)
75
return false;
76
}
77
78
-int kvm_arm_pmu_create(CPUState *cs, int irq)
79
+int kvm_arm_pmu_set_irq(CPUState *cs, int irq)
80
+{
90
+{
81
+ qemu_log_mask(LOG_UNIMP, "%s: not implemented\n", __func__);
91
+ /*
82
+ return 0;
92
+ * Reset the system counter and the timer between tests. This
93
+ * isn't a full reset, but it's sufficient for what the tests check.
94
+ */
95
+ writel(COUNTER_BASE + CNTCR, 0);
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);
83
+}
100
+}
84
+
101
+
85
+int kvm_arm_pmu_init(CPUState *cs)
102
+static void test_counter(void)
86
{
87
qemu_log_mask(LOG_UNIMP, "%s: not implemented\n", __func__);
88
return 0;
89
diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
90
index XXXXXXX..XXXXXXX 100644
91
--- a/target/arm/kvm64.c
92
+++ b/target/arm/kvm64.c
93
@@ -XXX,XX +XXX,XX @@ static CPUWatchpoint *find_hw_watchpoint(CPUState *cpu, target_ulong addr)
94
return NULL;
95
}
96
97
-static bool kvm_arm_pmu_support_ctrl(CPUState *cs, struct kvm_device_attr *attr)
98
-{
99
- return kvm_vcpu_ioctl(cs, KVM_HAS_DEVICE_ATTR, attr) == 0;
100
-}
101
-
102
-int kvm_arm_pmu_create(CPUState *cs, int irq)
103
+static bool kvm_arm_pmu_set_attr(CPUState *cs, struct kvm_device_attr *attr)
104
{
105
int err;
106
107
- struct kvm_device_attr attr = {
108
- .group = KVM_ARM_VCPU_PMU_V3_CTRL,
109
- .addr = (intptr_t)&irq,
110
- .attr = KVM_ARM_VCPU_PMU_V3_IRQ,
111
- .flags = 0,
112
- };
113
-
114
- if (!kvm_arm_pmu_support_ctrl(cs, &attr)) {
115
- return 0;
116
+ err = kvm_vcpu_ioctl(cs, KVM_HAS_DEVICE_ATTR, attr);
117
+ if (err != 0) {
118
+ return false;
119
}
120
121
- err = kvm_vcpu_ioctl(cs, KVM_SET_DEVICE_ATTR, &attr);
122
+ err = kvm_vcpu_ioctl(cs, KVM_SET_DEVICE_ATTR, attr);
123
if (err < 0) {
124
fprintf(stderr, "KVM_SET_DEVICE_ATTR failed: %s\n",
125
strerror(-err));
126
abort();
127
}
128
129
- attr.group = KVM_ARM_VCPU_PMU_V3_CTRL;
130
- attr.attr = KVM_ARM_VCPU_PMU_V3_INIT;
131
- attr.addr = 0;
132
- attr.flags = 0;
133
+ return true;
134
+}
135
136
- err = kvm_vcpu_ioctl(cs, KVM_SET_DEVICE_ATTR, &attr);
137
- if (err < 0) {
138
- fprintf(stderr, "KVM_SET_DEVICE_ATTR failed: %s\n",
139
- strerror(-err));
140
- abort();
141
- }
142
+int kvm_arm_pmu_init(CPUState *cs)
143
+{
103
+{
144
+ struct kvm_device_attr attr = {
104
+ /* Basic counter functionality test */
145
+ .group = KVM_ARM_VCPU_PMU_V3_CTRL,
146
+ .attr = KVM_ARM_VCPU_PMU_V3_INIT,
147
+ };
148
+
105
+
149
+ return kvm_arm_pmu_set_attr(cs, &attr);
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);
150
+}
123
+}
151
+
124
+
152
+int kvm_arm_pmu_set_irq(CPUState *cs, int irq)
125
+int main(int argc, char **argv)
153
+{
126
+{
154
+ struct kvm_device_attr attr = {
127
+ int r;
155
+ .group = KVM_ARM_VCPU_PMU_V3_CTRL,
128
+
156
+ .addr = (intptr_t)&irq,
129
+ g_test_init(&argc, &argv, NULL);
157
+ .attr = KVM_ARM_VCPU_PMU_V3_IRQ,
130
+
158
+ };
131
+ qtest_start("-machine mps3-an547");
159
132
+
160
- return 1;
133
+ qtest_add_func("/sse-timer/counter", test_counter);
161
+ return kvm_arm_pmu_set_attr(cs, &attr);
134
+
162
}
135
+ r = g_test_run();
163
136
+
164
static inline void set_feature(uint64_t *features, int feature)
137
+ qtest_end();
138
+
139
+ return r;
140
+}
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
154
index XXXXXXX..XXXXXXX 100644
155
--- a/tests/qtest/meson.build
156
+++ b/tests/qtest/meson.build
157
@@ -XXX,XX +XXX,XX @@ qtests_npcm7xx = \
158
'npcm7xx_watchdog_timer-test'] + \
159
(slirp.found() ? ['npcm7xx_emc-test'] : [])
160
qtests_arm = \
161
+ (config_all_devices.has_key('CONFIG_MPS2') ? ['sse-timer-test'] : []) + \
162
(config_all_devices.has_key('CONFIG_CMSDK_APB_DUALTIMER') ? ['cmsdk-apb-dualtimer-test'] : []) + \
163
(config_all_devices.has_key('CONFIG_CMSDK_APB_TIMER') ? ['cmsdk-apb-timer-test'] : []) + \
164
(config_all_devices.has_key('CONFIG_CMSDK_APB_WATCHDOG') ? ['cmsdk-apb-watchdog-test'] : []) + \
165
--
165
--
166
2.7.4
166
2.20.1
167
167
168
168
diff view generated by jsdifflib
1
Add a utility function for testing whether the CPU is in Handler
1
Add a test which tests various parts of the functionality of the
2
mode; this is just a check whether v7m.exception is non-zero, but
2
SSE system timer.
3
we do it in several places and it makes the code a bit easier
4
to read to not have to mentally figure out what the test is testing.
5
3
6
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>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 1501692241-23310-14-git-send-email-peter.maydell@linaro.org
11
---
7
---
12
target/arm/cpu.h | 10 ++++++++--
8
tests/qtest/sse-timer-test.c | 91 ++++++++++++++++++++++++++++++++++++
13
target/arm/helper.c | 8 ++++----
9
1 file changed, 91 insertions(+)
14
2 files changed, 12 insertions(+), 6 deletions(-)
15
10
16
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
11
diff --git a/tests/qtest/sse-timer-test.c b/tests/qtest/sse-timer-test.c
17
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/cpu.h
13
--- a/tests/qtest/sse-timer-test.c
19
+++ b/target/arm/cpu.h
14
+++ b/tests/qtest/sse-timer-test.c
20
@@ -XXX,XX +XXX,XX @@ static inline int arm_highest_el(CPUARMState *env)
15
@@ -XXX,XX +XXX,XX @@ static void test_counter(void)
21
return 1;
16
g_assert_cmpuint(readl(COUNTER_BASE + CNTCV_HI), ==, 0);
22
}
17
}
23
18
24
+/* Return true if a v7M CPU is in Handler mode */
19
+static void test_timer(void)
25
+static inline bool arm_v7m_is_handler_mode(CPUARMState *env)
26
+{
20
+{
27
+ return env->v7m.exception != 0;
21
+ /* Basic timer functionality test */
22
+
23
+ reset_counter_and_timer();
24
+ /*
25
+ * The timer is behind a Peripheral Protection Controller, and
26
+ * qtest accesses are always non-secure (no memory attributes),
27
+ * so we must program the PPC to accept NS transactions. TIMER0
28
+ * is on port 0 of PPC0, controlled by bit 0 of this register.
29
+ */
30
+ writel(PERIPHNSPPC0, 1);
31
+ /* We must enable the System Counter or the timer won't run. */
32
+ writel(COUNTER_BASE + CNTCR, 1);
33
+
34
+ /* Timer starts disabled and with a counter of 0 */
35
+ g_assert_cmpuint(readl(TIMER_BASE + CNTP_CTL), ==, 0);
36
+ g_assert_cmpuint(readl(TIMER_BASE + CNTPCT_LO), ==, 0);
37
+ g_assert_cmpuint(readl(TIMER_BASE + CNTPCT_HI), ==, 0);
38
+
39
+ /* Turn it on */
40
+ writel(TIMER_BASE + CNTP_CTL, 1);
41
+
42
+ /* Is the timer ticking? */
43
+ clock_step_ticks(100);
44
+ g_assert_cmpuint(readl(TIMER_BASE + CNTPCT_LO), ==, 100);
45
+ g_assert_cmpuint(readl(TIMER_BASE + CNTPCT_HI), ==, 0);
46
+
47
+ /* Set the CompareValue to 4000 ticks */
48
+ writel(TIMER_BASE + CNTP_CVAL_LO, 4000);
49
+ writel(TIMER_BASE + CNTP_CVAL_HI, 0);
50
+
51
+ /* Check TVAL view of the counter */
52
+ g_assert_cmpuint(readl(TIMER_BASE + CNTP_TVAL), ==, 3900);
53
+
54
+ /* Advance to the CompareValue mark and check ISTATUS is set */
55
+ clock_step_ticks(3900);
56
+ g_assert_cmpuint(readl(TIMER_BASE + CNTP_TVAL), ==, 0);
57
+ g_assert_cmpuint(readl(TIMER_BASE + CNTP_CTL), ==, 5);
58
+
59
+ /* Now exercise the auto-reload part of the timer */
60
+ writel(TIMER_BASE + CNTP_AIVAL_RELOAD, 200);
61
+ writel(TIMER_BASE + CNTP_AIVAL_CTL, 1);
62
+
63
+ /* Check AIVAL was reloaded and that ISTATUS is now clear */
64
+ g_assert_cmpuint(readl(TIMER_BASE + CNTP_AIVAL_LO), ==, 4200);
65
+ g_assert_cmpuint(readl(TIMER_BASE + CNTP_AIVAL_HI), ==, 0);
66
+ g_assert_cmpuint(readl(TIMER_BASE + CNTP_CTL), ==, 1);
67
+
68
+ /*
69
+ * Check that when we advance forward to the reload time the interrupt
70
+ * fires and the value reloads
71
+ */
72
+ clock_step_ticks(100);
73
+ g_assert_cmpuint(readl(TIMER_BASE + CNTP_CTL), ==, 1);
74
+ clock_step_ticks(100);
75
+ g_assert_cmpuint(readl(TIMER_BASE + CNTP_CTL), ==, 5);
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);
28
+}
107
+}
29
+
108
+
30
/* Return the current Exception Level (as per ARMv8; note that this differs
109
int main(int argc, char **argv)
31
* from the ARMv7 Privilege Level).
32
*/
33
static inline int arm_current_el(CPUARMState *env)
34
{
110
{
35
if (arm_feature(env, ARM_FEATURE_M)) {
111
int r;
36
- return !((env->v7m.exception == 0) && (env->v7m.control & 1));
112
@@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv)
37
+ return arm_v7m_is_handler_mode(env) || !(env->v7m.control & 1);
113
qtest_start("-machine mps3-an547");
38
}
114
39
115
qtest_add_func("/sse-timer/counter", test_counter);
40
if (is_a64(env)) {
116
+ qtest_add_func("/sse-timer/timer", test_timer);
41
@@ -XXX,XX +XXX,XX @@ static inline void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
117
42
}
118
r = g_test_run();
43
*flags |= fp_exception_el(env) << ARM_TBFLAG_FPEXC_EL_SHIFT;
119
44
45
- if (env->v7m.exception != 0) {
46
+ if (arm_v7m_is_handler_mode(env)) {
47
*flags |= ARM_TBFLAG_HANDLER_MASK;
48
}
49
50
diff --git a/target/arm/helper.c b/target/arm/helper.c
51
index XXXXXXX..XXXXXXX 100644
52
--- a/target/arm/helper.c
53
+++ b/target/arm/helper.c
54
@@ -XXX,XX +XXX,XX @@ static void do_v7m_exception_exit(ARMCPU *cpu)
55
* that jumps to magic addresses don't have magic behaviour unless
56
* we're in Handler mode (compare pseudocode BXWritePC()).
57
*/
58
- assert(env->v7m.exception != 0);
59
+ assert(arm_v7m_is_handler_mode(env));
60
61
/* In the spec pseudocode ExceptionReturn() is called directly
62
* from BXWritePC() and gets the full target PC value including
63
@@ -XXX,XX +XXX,XX @@ static void do_v7m_exception_exit(ARMCPU *cpu)
64
* resuming in Thread mode. If that doesn't match what the
65
* exception return type specified then this is a UsageFault.
66
*/
67
- if (return_to_handler == (env->v7m.exception == 0)) {
68
+ if (return_to_handler != arm_v7m_is_handler_mode(env)) {
69
/* Take an INVPC UsageFault by pushing the stack again. */
70
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE);
71
env->v7m.cfsr |= R_V7M_CFSR_INVPC_MASK;
72
@@ -XXX,XX +XXX,XX @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
73
if (env->v7m.control & R_V7M_CONTROL_SPSEL_MASK) {
74
lr |= 4;
75
}
76
- if (env->v7m.exception == 0) {
77
+ if (!arm_v7m_is_handler_mode(env)) {
78
lr |= 8;
79
}
80
81
@@ -XXX,XX +XXX,XX @@ void HELPER(v7m_msr)(CPUARMState *env, uint32_t maskreg, uint32_t val)
82
* switch_v7m_sp() deals with updating the SPSEL bit in
83
* env->v7m.control, so we only need update the others.
84
*/
85
- if (env->v7m.exception == 0) {
86
+ if (!arm_v7m_is_handler_mode(env)) {
87
switch_v7m_sp(env, (val & R_V7M_CONTROL_SPSEL_MASK) != 0);
88
}
89
env->v7m.control &= ~R_V7M_CONTROL_NPRIV_MASK;
90
--
120
--
91
2.7.4
121
2.20.1
92
122
93
123
diff view generated by jsdifflib
1
Implement the new do_transaction_failed hook for ARM, which should
1
Test that when we change the scaling of the system counter that the
2
cause the CPU to take a prefetch abort or data abort.
2
system timer responds appropriately.
3
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
---
7
---
8
target/arm/internals.h | 10 ++++++++++
8
tests/qtest/sse-timer-test.c | 32 ++++++++++++++++++++++++++++++++
9
target/arm/cpu.c | 1 +
9
1 file changed, 32 insertions(+)
10
target/arm/op_helper.c | 43 +++++++++++++++++++++++++++++++++++++++++++
11
3 files changed, 54 insertions(+)
12
10
13
diff --git a/target/arm/internals.h b/target/arm/internals.h
11
diff --git a/tests/qtest/sse-timer-test.c b/tests/qtest/sse-timer-test.c
14
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/internals.h
13
--- a/tests/qtest/sse-timer-test.c
16
+++ b/target/arm/internals.h
14
+++ b/tests/qtest/sse-timer-test.c
17
@@ -XXX,XX +XXX,XX @@ void arm_cpu_do_unaligned_access(CPUState *cs, vaddr vaddr,
15
@@ -XXX,XX +XXX,XX @@ static void test_timer(void)
18
MMUAccessType access_type,
16
g_assert_cmpuint(readl(TIMER_BASE + CNTP_AIVAL_HI), ==, 0x42);
19
int mmu_idx, uintptr_t retaddr);
20
21
+/* arm_cpu_do_transaction_failed: handle a memory system error response
22
+ * (eg "no device/memory present at address") by raising an external abort
23
+ * exception
24
+ */
25
+void arm_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr,
26
+ vaddr addr, unsigned size,
27
+ MMUAccessType access_type,
28
+ int mmu_idx, MemTxAttrs attrs,
29
+ MemTxResult response, uintptr_t retaddr);
30
+
31
/* Call the EL change hook if one has been registered */
32
static inline void arm_call_el_change_hook(ARMCPU *cpu)
33
{
34
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
35
index XXXXXXX..XXXXXXX 100644
36
--- a/target/arm/cpu.c
37
+++ b/target/arm/cpu.c
38
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_class_init(ObjectClass *oc, void *data)
39
#else
40
cc->do_interrupt = arm_cpu_do_interrupt;
41
cc->do_unaligned_access = arm_cpu_do_unaligned_access;
42
+ cc->do_transaction_failed = arm_cpu_do_transaction_failed;
43
cc->get_phys_page_attrs_debug = arm_cpu_get_phys_page_attrs_debug;
44
cc->asidx_from_attrs = arm_asidx_from_attrs;
45
cc->vmsd = &vmstate_arm_cpu;
46
diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c
47
index XXXXXXX..XXXXXXX 100644
48
--- a/target/arm/op_helper.c
49
+++ b/target/arm/op_helper.c
50
@@ -XXX,XX +XXX,XX @@ void arm_cpu_do_unaligned_access(CPUState *cs, vaddr vaddr,
51
deliver_fault(cpu, vaddr, access_type, fsr, fsc, &fi);
52
}
17
}
53
18
54
+/* arm_cpu_do_transaction_failed: handle a memory system error response
19
+static void test_timer_scale_change(void)
55
+ * (eg "no device/memory present at address") by raising an external abort
56
+ * exception
57
+ */
58
+void arm_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr,
59
+ vaddr addr, unsigned size,
60
+ MMUAccessType access_type,
61
+ int mmu_idx, MemTxAttrs attrs,
62
+ MemTxResult response, uintptr_t retaddr)
63
+{
20
+{
64
+ ARMCPU *cpu = ARM_CPU(cs);
21
+ /*
65
+ CPUARMState *env = &cpu->env;
22
+ * Test that the timer responds correctly to counter
66
+ uint32_t fsr, fsc;
23
+ * scaling changes while it has an active timer.
67
+ ARMMMUFaultInfo fi = {};
68
+ ARMMMUIdx arm_mmu_idx = core_to_arm_mmu_idx(env, mmu_idx);
69
+
70
+ if (retaddr) {
71
+ /* now we have a real cpu fault */
72
+ cpu_restore_state(cs, retaddr);
73
+ }
74
+
75
+ /* The EA bit in syndromes and fault status registers is an
76
+ * IMPDEF classification of external aborts. ARM implementations
77
+ * usually use this to indicate AXI bus Decode error (0) or
78
+ * Slave error (1); in QEMU we follow that.
79
+ */
24
+ */
80
+ fi.ea = (response != MEMTX_DECODE_ERROR);
25
+ reset_counter_and_timer();
81
+
26
+ /* Give ourselves access to the timer, and enable the counter and timer */
82
+ /* The fault status register format depends on whether we're using
27
+ writel(PERIPHNSPPC0, 1);
83
+ * the LPAE long descriptor format, or the short descriptor format.
28
+ writel(COUNTER_BASE + CNTCR, 1);
84
+ */
29
+ writel(TIMER_BASE + CNTP_CTL, 1);
85
+ if (arm_s1_regime_using_lpae_format(env, arm_mmu_idx)) {
30
+ /* Set the CompareValue to 4000 ticks */
86
+ /* long descriptor form, STATUS 0b010000: synchronous ext abort */
31
+ writel(TIMER_BASE + CNTP_CVAL_LO, 4000);
87
+ fsr = (fi.ea << 12) | (1 << 9) | 0x10;
32
+ writel(TIMER_BASE + CNTP_CVAL_HI, 0);
88
+ } else {
33
+ /* Advance halfway and check ISTATUS is not set */
89
+ /* short descriptor form, FSR 0b01000 : synchronous ext abort */
34
+ clock_step_ticks(2000);
90
+ fsr = (fi.ea << 12) | 0x8;
35
+ g_assert_cmpuint(readl(TIMER_BASE + CNTP_CTL), ==, 1);
91
+ }
36
+ /* Reprogram the counter to run at 1/16th speed */
92
+ fsc = 0x10;
37
+ writel(COUNTER_BASE + CNTCR, 0);
93
+
38
+ writel(COUNTER_BASE + CNTSCR, 0x00100000); /* 1/16th normal speed */
94
+ deliver_fault(cpu, addr, access_type, fsr, fsc, &fi);
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);
95
+}
48
+}
96
+
49
+
97
#endif /* !defined(CONFIG_USER_ONLY) */
50
int main(int argc, char **argv)
98
51
{
99
uint32_t HELPER(add_setq)(CPUARMState *env, uint32_t a, uint32_t b)
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
100
--
61
--
101
2.7.4
62
2.20.1
102
63
103
64
diff view generated by jsdifflib
1
From: Andrew Jones <drjones@redhat.com>
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
2
3
Mimicking gicv3-maintenance-interrupt, add the PMU's interrupt to
3
KVM requires the target cpu to be at least ARMv8 architecture
4
CPU state.
4
(support on ARMv7 has been dropped in commit 82bf7ae84ce:
5
"target/arm: Remove KVM support for 32-bit Arm hosts").
5
6
6
Signed-off-by: Andrew Jones <drjones@redhat.com>
7
A KVM-only build won't be able to run TCG cpus, move the
8
v7A CPU definitions to cpu_tcg.c.
9
10
Reported-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Message-id: 1500471597-2517-2-git-send-email-drjones@redhat.com
12
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
13
Message-id: 20210306151801.2388182-1-f4bug@amsat.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
15
---
11
target/arm/cpu.h | 2 ++
16
target/arm/cpu.c | 335 -------------------------------------------
12
hw/arm/virt.c | 3 +++
17
target/arm/cpu_tcg.c | 318 ++++++++++++++++++++++++++++++++++++++++
13
target/arm/cpu.c | 2 ++
18
2 files changed, 318 insertions(+), 335 deletions(-)
14
3 files changed, 7 insertions(+)
15
19
16
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
17
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/cpu.h
19
+++ b/target/arm/cpu.h
20
@@ -XXX,XX +XXX,XX @@ struct ARMCPU {
21
qemu_irq gt_timer_outputs[NUM_GTIMERS];
22
/* GPIO output for GICv3 maintenance interrupt signal */
23
qemu_irq gicv3_maintenance_interrupt;
24
+ /* GPIO output for the PMU interrupt */
25
+ qemu_irq pmu_interrupt;
26
27
/* MemoryRegion to use for secure physical accesses */
28
MemoryRegion *secure_memory;
29
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
30
index XXXXXXX..XXXXXXX 100644
31
--- a/hw/arm/virt.c
32
+++ b/hw/arm/virt.c
33
@@ -XXX,XX +XXX,XX @@ static void create_gic(VirtMachineState *vms, qemu_irq *pic)
34
qdev_connect_gpio_out_named(cpudev, "gicv3-maintenance-interrupt", 0,
35
qdev_get_gpio_in(gicdev, ppibase
36
+ ARCH_GICV3_MAINT_IRQ));
37
+ qdev_connect_gpio_out_named(cpudev, "pmu-interrupt", 0,
38
+ qdev_get_gpio_in(gicdev, ppibase
39
+ + VIRTUAL_PMU_IRQ));
40
41
sysbus_connect_irq(gicbusdev, i, qdev_get_gpio_in(cpudev, ARM_CPU_IRQ));
42
sysbus_connect_irq(gicbusdev, i + smp_cpus,
43
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
20
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
44
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
45
--- a/target/arm/cpu.c
22
--- a/target/arm/cpu.c
46
+++ b/target/arm/cpu.c
23
+++ b/target/arm/cpu.c
47
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_initfn(Object *obj)
24
@@ -XXX,XX +XXX,XX @@ static ObjectClass *arm_cpu_class_by_name(const char *cpu_model)
48
25
return oc;
49
qdev_init_gpio_out_named(DEVICE(cpu), &cpu->gicv3_maintenance_interrupt,
26
}
50
"gicv3-maintenance-interrupt", 1);
27
51
+ qdev_init_gpio_out_named(DEVICE(cpu), &cpu->pmu_interrupt,
28
-/* CPU models. These are not needed for the AArch64 linux-user build. */
52
+ "pmu-interrupt", 1);
29
-#if !defined(CONFIG_USER_ONLY) || !defined(TARGET_AARCH64)
30
-
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);
53
#endif
366
#endif
54
367
-
55
/* DTB consumers generally don't in fact care what the 'compatible'
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
+
404
+static void cortex_a8_initfn(Object *obj)
405
+{
406
+ ARMCPU *cpu = ARM_CPU(obj);
407
+
408
+ cpu->dtb_compatible = "arm,cortex-a8";
409
+ set_feature(&cpu->env, ARM_FEATURE_V7);
410
+ set_feature(&cpu->env, ARM_FEATURE_NEON);
411
+ set_feature(&cpu->env, ARM_FEATURE_THUMB2EE);
412
+ set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS);
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
+}
441
+
442
+static const ARMCPRegInfo cortexa9_cp_reginfo[] = {
443
+ /*
444
+ * power_control should be set to maximum latency. Again,
445
+ * default to 0 and set by private hook
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
{
628
ARMCPU *cpu = ARM_CPU(obj);
629
@@ -XXX,XX +XXX,XX @@ static void arm_v7m_class_init(ObjectClass *oc, void *data)
630
cc->gdb_core_xml_file = "arm-m-profile.xml";
631
}
632
633
+#ifndef TARGET_AARCH64
634
+/*
635
+ * -cpu max: a CPU with as many features enabled as our emulation supports.
636
+ * The version of '-cpu max' for qemu-system-aarch64 is defined in cpu64.c;
637
+ * this only needs to handle 32 bits, and need not care about KVM.
638
+ */
639
+static void arm_max_initfn(Object *obj)
640
+{
641
+ ARMCPU *cpu = ARM_CPU(obj);
642
+
643
+ cortex_a15_initfn(obj);
644
+
645
+ /* old-style VFP short-vector support */
646
+ cpu->isar.mvfr0 = FIELD_DP32(cpu->isar.mvfr0, MVFR0, FPSHVEC, 1);
647
+
648
+#ifdef CONFIG_USER_ONLY
649
+ /*
650
+ * We don't set these in system emulation mode for the moment,
651
+ * since we don't correctly set (all of) the ID registers to
652
+ * advertise them.
653
+ */
654
+ set_feature(&cpu->env, ARM_FEATURE_V8);
655
+ {
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
+ }
704
+#endif /* CONFIG_USER_ONLY */
705
+}
706
+#endif /* !TARGET_AARCH64 */
707
+
708
static const ARMCPUInfo arm_tcg_cpus[] = {
709
{ .name = "arm926", .initfn = arm926_initfn },
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 = {
56
--
735
--
57
2.7.4
736
2.20.1
58
737
59
738
diff view generated by jsdifflib
1
From: Andrew Jeffery <andrew@aj.id.au>
1
From: Xuzhou Cheng <xuzhou.cheng@windriver.com>
2
2
3
The reset width register controls how the pulse on the SoC's WDTRST{1,2}
3
ZynqMP QSPI supports SPI transfer using DMA mode, but currently this
4
pins behaves. A pulse is emitted if the external reset bit is set in
4
is unimplemented. When QSPI is programmed to use DMA mode, QEMU will
5
WDT_CTRL. On the AST2500 WDT_RESET_WIDTH can consume magic bit patterns
5
crash. This is observed when testing VxWorks 7.
6
to configure push-pull/open-drain and active-high/active-low
7
behaviours and thus needs some special handling in the write path.
8
6
9
As some of the capabilities depend on the SoC version a silicon-rev
7
This adds a Xilinx CSU DMA model and the implementation is based on
10
property is introduced, which is used to guard version-specific
8
https://github.com/Xilinx/qemu/blob/master/hw/dma/csu_stream_dma.c.
11
behaviour.
9
The DST part of the model is verified along with ZynqMP GQSPI model.
12
10
13
Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
11
Signed-off-by: Xuzhou Cheng <xuzhou.cheng@windriver.com>
14
Reviewed-by: Cédric Le Goater <clg@kaod.org>
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
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
---
17
---
17
include/hw/watchdog/wdt_aspeed.h | 2 +
18
include/hw/dma/xlnx_csu_dma.h | 52 +++
18
hw/watchdog/wdt_aspeed.c | 93 +++++++++++++++++++++++++++++++++++-----
19
hw/dma/xlnx_csu_dma.c | 745 ++++++++++++++++++++++++++++++++++
19
2 files changed, 84 insertions(+), 11 deletions(-)
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
20
25
21
diff --git a/include/hw/watchdog/wdt_aspeed.h b/include/hw/watchdog/wdt_aspeed.h
26
diff --git a/include/hw/dma/xlnx_csu_dma.h b/include/hw/dma/xlnx_csu_dma.h
22
index XXXXXXX..XXXXXXX 100644
27
new file mode 100644
23
--- a/include/hw/watchdog/wdt_aspeed.h
28
index XXXXXXX..XXXXXXX
24
+++ b/include/hw/watchdog/wdt_aspeed.h
29
--- /dev/null
25
@@ -XXX,XX +XXX,XX @@ typedef struct AspeedWDTState {
30
+++ b/include/hw/dma/xlnx_csu_dma.h
26
uint32_t regs[ASPEED_WDT_REGS_MAX];
27
28
uint32_t pclk_freq;
29
+ uint32_t silicon_rev;
30
+ uint32_t ext_pulse_width_mask;
31
} AspeedWDTState;
32
33
#endif /* ASPEED_WDT_H */
34
diff --git a/hw/watchdog/wdt_aspeed.c b/hw/watchdog/wdt_aspeed.c
35
index XXXXXXX..XXXXXXX 100644
36
--- a/hw/watchdog/wdt_aspeed.c
37
+++ b/hw/watchdog/wdt_aspeed.c
38
@@ -XXX,XX +XXX,XX @@
31
@@ -XXX,XX +XXX,XX @@
39
*/
32
+/*
40
33
+ * Xilinx Platform CSU Stream DMA emulation
41
#include "qemu/osdep.h"
34
+ *
42
+
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"
43
+#include "qapi/error.h"
112
+#include "qapi/error.h"
44
#include "qemu/log.h"
113
+#include "hw/hw.h"
45
+#include "qemu/timer.h"
114
+#include "hw/irq.h"
46
#include "sysemu/watchdog.h"
115
+#include "hw/qdev-properties.h"
47
+#include "hw/misc/aspeed_scu.h"
116
+#include "hw/sysbus.h"
48
#include "hw/sysbus.h"
117
+#include "migration/vmstate.h"
49
-#include "qemu/timer.h"
118
+#include "sysemu/dma.h"
50
#include "hw/watchdog/wdt_aspeed.h"
119
+#include "hw/ptimer.h"
51
120
+#include "hw/stream.h"
52
-#define WDT_STATUS (0x00 / 4)
121
+#include "hw/register.h"
53
-#define WDT_RELOAD_VALUE (0x04 / 4)
122
+#include "hw/dma/xlnx_csu_dma.h"
54
-#define WDT_RESTART (0x08 / 4)
123
+
55
-#define WDT_CTRL (0x0C / 4)
124
+/*
56
+#define WDT_STATUS (0x00 / 4)
125
+ * Ref: UG1087 (v1.7) February 8, 2019
57
+#define WDT_RELOAD_VALUE (0x04 / 4)
126
+ * https://www.xilinx.com/html_docs/registers/ug1087/ug1087-zynq-ultrascale-registers.html
58
+#define WDT_RESTART (0x08 / 4)
127
+ * CSUDMA Module section
59
+#define WDT_CTRL (0x0C / 4)
128
+ */
60
#define WDT_CTRL_RESET_MODE_SOC (0x00 << 5)
129
+REG32(ADDR, 0x0)
61
#define WDT_CTRL_RESET_MODE_FULL_CHIP (0x01 << 5)
130
+ FIELD(ADDR, ADDR, 2, 30) /* wo */
62
#define WDT_CTRL_1MHZ_CLK BIT(4)
131
+REG32(SIZE, 0x4)
63
@@ -XXX,XX +XXX,XX @@
132
+ FIELD(SIZE, SIZE, 2, 27) /* wo */
64
#define WDT_CTRL_WDT_INTR BIT(2)
133
+ FIELD(SIZE, LAST_WORD, 0, 1) /* rw, only exists in SRC */
65
#define WDT_CTRL_RESET_SYSTEM BIT(1)
134
+REG32(STATUS, 0x8)
66
#define WDT_CTRL_ENABLE BIT(0)
135
+ FIELD(STATUS, DONE_CNT, 13, 3) /* wtc */
67
+#define WDT_RESET_WIDTH (0x18 / 4)
136
+ FIELD(STATUS, FIFO_LEVEL, 5, 8) /* ro */
68
+#define WDT_RESET_WIDTH_ACTIVE_HIGH BIT(31)
137
+ FIELD(STATUS, OUTSTANDING, 1, 4) /* ro */
69
+#define WDT_POLARITY_MASK (0xFF << 24)
138
+ FIELD(STATUS, BUSY, 0, 1) /* ro */
70
+#define WDT_ACTIVE_HIGH_MAGIC (0xA5 << 24)
139
+REG32(CTRL, 0xc)
71
+#define WDT_ACTIVE_LOW_MAGIC (0x5A << 24)
140
+ FIELD(CTRL, FIFOTHRESH, 25, 7) /* rw, only exists in DST, reset 0x40 */
72
+#define WDT_RESET_WIDTH_PUSH_PULL BIT(30)
141
+ FIELD(CTRL, APB_ERR_RESP, 24, 1) /* rw */
73
+#define WDT_DRIVE_TYPE_MASK (0xFF << 24)
142
+ FIELD(CTRL, ENDIANNESS, 23, 1) /* rw */
74
+#define WDT_PUSH_PULL_MAGIC (0xA8 << 24)
143
+ FIELD(CTRL, AXI_BRST_TYPE, 22, 1) /* rw */
75
+#define WDT_OPEN_DRAIN_MAGIC (0x8A << 24)
144
+ FIELD(CTRL, TIMEOUT_VAL, 10, 12) /* rw, reset: 0xFFE */
76
145
+ FIELD(CTRL, FIFO_THRESH, 2, 8) /* rw, reset: 0x80 */
77
-#define WDT_TIMEOUT_STATUS (0x10 / 4)
146
+ FIELD(CTRL, PAUSE_STRM, 1, 1) /* rw */
78
-#define WDT_TIMEOUT_CLEAR (0x14 / 4)
147
+ FIELD(CTRL, PAUSE_MEM, 0, 1) /* rw */
79
-#define WDT_RESET_WDITH (0x18 / 4)
148
+REG32(CRC, 0x10)
80
+#define WDT_TIMEOUT_STATUS (0x10 / 4)
149
+REG32(INT_STATUS, 0x14)
81
+#define WDT_TIMEOUT_CLEAR (0x14 / 4)
150
+ FIELD(INT_STATUS, FIFO_OVERFLOW, 7, 1) /* wtc */
82
151
+ FIELD(INT_STATUS, INVALID_APB, 6, 1) /* wtc */
83
-#define WDT_RESTART_MAGIC 0x4755
152
+ FIELD(INT_STATUS, THRESH_HIT, 5, 1) /* wtc */
84
+#define WDT_RESTART_MAGIC 0x4755
153
+ FIELD(INT_STATUS, TIMEOUT_MEM, 4, 1) /* wtc */
85
154
+ FIELD(INT_STATUS, TIMEOUT_STRM, 3, 1) /* wtc */
86
static bool aspeed_wdt_is_enabled(const AspeedWDTState *s)
155
+ FIELD(INT_STATUS, AXI_BRESP_ERR, 2, 1) /* wtc, SRC: AXI_RDERR */
87
{
156
+ FIELD(INT_STATUS, DONE, 1, 1) /* wtc */
88
return s->regs[WDT_CTRL] & WDT_CTRL_ENABLE;
157
+ FIELD(INT_STATUS, MEM_DONE, 0, 1) /* wtc */
89
}
158
+REG32(INT_ENABLE, 0x18)
90
159
+ FIELD(INT_ENABLE, FIFO_OVERFLOW, 7, 1) /* wtc */
91
+static bool is_ast2500(const AspeedWDTState *s)
160
+ FIELD(INT_ENABLE, INVALID_APB, 6, 1) /* wtc */
92
+{
161
+ FIELD(INT_ENABLE, THRESH_HIT, 5, 1) /* wtc */
93
+ switch (s->silicon_rev) {
162
+ FIELD(INT_ENABLE, TIMEOUT_MEM, 4, 1) /* wtc */
94
+ case AST2500_A0_SILICON_REV:
163
+ FIELD(INT_ENABLE, TIMEOUT_STRM, 3, 1) /* wtc */
95
+ case AST2500_A1_SILICON_REV:
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) {
96
+ return true;
696
+ return true;
97
+ case AST2400_A0_SILICON_REV:
697
+ } else {
98
+ case AST2400_A1_SILICON_REV:
698
+ s->notify = notify;
99
+ default:
699
+ s->notify_opaque = notify_opaque;
100
+ break;
700
+ return false;
101
+ }
701
+ }
102
+
702
+}
103
+ return false;
703
+
104
+}
704
+static void xlnx_csu_dma_reset(DeviceState *dev)
105
+
705
+{
106
static uint64_t aspeed_wdt_read(void *opaque, hwaddr offset, unsigned size)
706
+ XlnxCSUDMA *s = XLNX_CSU_DMA(dev);
107
{
707
+ unsigned int i;
108
AspeedWDTState *s = ASPEED_WDT(opaque);
708
+
109
@@ -XXX,XX +XXX,XX @@ static uint64_t aspeed_wdt_read(void *opaque, hwaddr offset, unsigned size)
709
+ for (i = 0; i < ARRAY_SIZE(s->regs_info); ++i) {
110
return 0;
710
+ register_reset(&s->regs_info[i]);
111
case WDT_CTRL:
711
+ }
112
return s->regs[WDT_CTRL];
712
+}
113
+ case WDT_RESET_WIDTH:
713
+
114
+ return s->regs[WDT_RESET_WIDTH];
714
+static void xlnx_csu_dma_realize(DeviceState *dev, Error **errp)
115
case WDT_TIMEOUT_STATUS:
715
+{
116
case WDT_TIMEOUT_CLEAR:
716
+ XlnxCSUDMA *s = XLNX_CSU_DMA(dev);
117
- case WDT_RESET_WDITH:
717
+ RegisterInfoArray *reg_array;
118
qemu_log_mask(LOG_UNIMP,
718
+
119
"%s: uninmplemented read at offset 0x%" HWADDR_PRIx "\n",
719
+ reg_array =
120
__func__, offset);
720
+ register_init_block32(dev, xlnx_csu_dma_regs_info[!!s->is_dst],
121
@@ -XXX,XX +XXX,XX @@ static void aspeed_wdt_write(void *opaque, hwaddr offset, uint64_t data,
721
+ XLNX_CSU_DMA_R_MAX,
122
timer_del(s->timer);
722
+ s->regs_info, s->regs,
123
}
723
+ &xlnx_csu_dma_ops,
124
break;
724
+ XLNX_CSU_DMA_ERR_DEBUG,
125
+ case WDT_RESET_WIDTH:
725
+ XLNX_CSU_DMA_R_MAX * 4);
126
+ {
726
+ memory_region_add_subregion(&s->iomem,
127
+ uint32_t property = data & WDT_POLARITY_MASK;
727
+ 0x0,
128
+
728
+ &reg_array->mem);
129
+ if (property && is_ast2500(s)) {
729
+
130
+ if (property == WDT_ACTIVE_HIGH_MAGIC) {
730
+ sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->iomem);
131
+ s->regs[WDT_RESET_WIDTH] |= WDT_RESET_WIDTH_ACTIVE_HIGH;
731
+ sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->irq);
132
+ } else if (property == WDT_ACTIVE_LOW_MAGIC) {
732
+
133
+ s->regs[WDT_RESET_WIDTH] &= ~WDT_RESET_WIDTH_ACTIVE_HIGH;
733
+ if (!s->is_dst && !s->tx_dev) {
134
+ } else if (property == WDT_PUSH_PULL_MAGIC) {
734
+ error_setg(errp, "zynqmp.csu-dma: Stream not connected");
135
+ s->regs[WDT_RESET_WIDTH] |= WDT_RESET_WIDTH_PUSH_PULL;
136
+ } else if (property == WDT_OPEN_DRAIN_MAGIC) {
137
+ s->regs[WDT_RESET_WIDTH] &= ~WDT_RESET_WIDTH_PUSH_PULL;
138
+ }
139
+ }
140
+ s->regs[WDT_RESET_WIDTH] &= ~s->ext_pulse_width_mask;
141
+ s->regs[WDT_RESET_WIDTH] |= data & s->ext_pulse_width_mask;
142
+ break;
143
+ }
144
case WDT_TIMEOUT_STATUS:
145
case WDT_TIMEOUT_CLEAR:
146
- case WDT_RESET_WDITH:
147
qemu_log_mask(LOG_UNIMP,
148
"%s: uninmplemented write at offset 0x%" HWADDR_PRIx "\n",
149
__func__, offset);
150
@@ -XXX,XX +XXX,XX @@ static void aspeed_wdt_reset(DeviceState *dev)
151
s->regs[WDT_RELOAD_VALUE] = 0x03EF1480;
152
s->regs[WDT_RESTART] = 0;
153
s->regs[WDT_CTRL] = 0;
154
+ s->regs[WDT_RESET_WIDTH] = 0xFF;
155
156
timer_del(s->timer);
157
}
158
@@ -XXX,XX +XXX,XX @@ static void aspeed_wdt_realize(DeviceState *dev, Error **errp)
159
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
160
AspeedWDTState *s = ASPEED_WDT(dev);
161
162
+ if (!is_supported_silicon_rev(s->silicon_rev)) {
163
+ error_setg(errp, "Unknown silicon revision: 0x%" PRIx32,
164
+ s->silicon_rev);
165
+ return;
735
+ return;
166
+ }
736
+ }
167
+
737
+
168
+ switch (s->silicon_rev) {
738
+ s->src_timer = ptimer_init(xlnx_csu_dma_src_timeout_hit,
169
+ case AST2400_A0_SILICON_REV:
739
+ s, PTIMER_POLICY_DEFAULT);
170
+ case AST2400_A1_SILICON_REV:
740
+
171
+ s->ext_pulse_width_mask = 0xff;
741
+ if (s->dma_mr) {
172
+ break;
742
+ s->dma_as = g_malloc0(sizeof(AddressSpace));
173
+ case AST2500_A0_SILICON_REV:
743
+ address_space_init(s->dma_as, s->dma_mr, NULL);
174
+ case AST2500_A1_SILICON_REV:
744
+ } else {
175
+ s->ext_pulse_width_mask = 0xfffff;
745
+ s->dma_as = &address_space_memory;
176
+ break;
746
+ }
177
+ default:
747
+
178
+ g_assert_not_reached();
748
+ s->attr = MEMTXATTRS_UNSPECIFIED;
179
+ }
749
+
180
+
750
+ s->r_size_last_word = 0;
181
s->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, aspeed_wdt_timer_expired, dev);
751
+}
182
752
+
183
/* FIXME: This setting should be derived from the SCU hw strapping
753
+static const VMStateDescription vmstate_xlnx_csu_dma = {
184
@@ -XXX,XX +XXX,XX @@ static void aspeed_wdt_realize(DeviceState *dev, Error **errp)
754
+ .name = TYPE_XLNX_CSU_DMA,
185
sysbus_init_mmio(sbd, &s->iomem);
755
+ .version_id = 0,
186
}
756
+ .minimum_version_id = 0,
187
757
+ .minimum_version_id_old = 0,
188
+static Property aspeed_wdt_properties[] = {
758
+ .fields = (VMStateField[]) {
189
+ DEFINE_PROP_UINT32("silicon-rev", AspeedWDTState, silicon_rev, 0),
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),
190
+ DEFINE_PROP_END_OF_LIST(),
783
+ DEFINE_PROP_END_OF_LIST(),
191
+};
784
+};
192
+
785
+
193
static void aspeed_wdt_class_init(ObjectClass *klass, void *data)
786
+static void xlnx_csu_dma_class_init(ObjectClass *klass, void *data)
194
{
787
+{
195
DeviceClass *dc = DEVICE_CLASS(klass);
788
+ DeviceClass *dc = DEVICE_CLASS(klass);
196
@@ -XXX,XX +XXX,XX @@ static void aspeed_wdt_class_init(ObjectClass *klass, void *data)
789
+ StreamSinkClass *ssc = STREAM_SINK_CLASS(klass);
197
dc->reset = aspeed_wdt_reset;
790
+
198
set_bit(DEVICE_CATEGORY_MISC, dc->categories);
791
+ dc->reset = xlnx_csu_dma_reset;
199
dc->vmsd = &vmstate_aspeed_wdt;
792
+ dc->realize = xlnx_csu_dma_realize;
200
+ dc->props = aspeed_wdt_properties;
793
+ dc->vmsd = &vmstate_xlnx_csu_dma;
201
}
794
+ device_class_set_props(dc, xlnx_csu_dma_properties);
202
795
+
203
static const TypeInfo aspeed_wdt_info = {
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'))
204
--
856
--
205
2.7.4
857
2.20.1
206
858
207
859
diff view generated by jsdifflib
1
From: Pranith Kumar <bobby.prani@gmail.com>
1
From: Xuzhou Cheng <xuzhou.cheng@windriver.com>
2
2
3
Fix the following warning:
3
There are some coding convention warnings in xlnx-zynqmp.c and
4
xlnx-zynqmp.h, as reported by:
4
5
5
/home/pranith/qemu/hw/intc/arm_gicv3_kvm.c:296:17: warning: logical not is only applied to the left hand side of this bitwise operator [-Wlogical-not-parentheses]
6
$ ./scripts/checkpatch.pl include/hw/arm/xlnx-zynqmp.h
6
if (!c->gicr_ctlr & GICR_CTLR_ENABLE_LPIS) {
7
$ ./scripts/checkpatch.pl hw/arm/xlnx-zynqmp.c
7
^ ~
8
/home/pranith/qemu/hw/intc/arm_gicv3_kvm.c:296:17: note: add parentheses after the '!' to evaluate the bitwise operator first
9
if (!c->gicr_ctlr & GICR_CTLR_ENABLE_LPIS) {
10
^
11
/home/pranith/qemu/hw/intc/arm_gicv3_kvm.c:296:17: note: add parentheses around left hand side expression to silence this warning
12
if (!c->gicr_ctlr & GICR_CTLR_ENABLE_LPIS) {
13
^
14
8
15
This logic error meant we were not setting the PTZ
9
Let's clean them up.
16
bit when we should -- luckily as the comment suggests
17
this wouldn't have had any effects beyond making GIC
18
initialization take a little longer.
19
10
20
Signed-off-by: Pranith Kumar <bobby.prani@gmail.com>
11
Signed-off-by: Xuzhou Cheng <xuzhou.cheng@windriver.com>
21
Message-id: 20170829173226.7625-1-bobby.prani@gmail.com
12
Signed-off-by: Bin Meng <bin.meng@windriver.com>
22
Cc: qemu-stable@nongnu.org
13
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
23
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
Message-id: 20210303135254.3970-3-bmeng.cn@gmail.com
24
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
25
---
16
---
26
hw/intc/arm_gicv3_kvm.c | 2 +-
17
include/hw/arm/xlnx-zynqmp.h | 3 ++-
27
1 file changed, 1 insertion(+), 1 deletion(-)
18
hw/arm/xlnx-zynqmp.c | 9 ++++++---
19
2 files changed, 8 insertions(+), 4 deletions(-)
28
20
29
diff --git a/hw/intc/arm_gicv3_kvm.c b/hw/intc/arm_gicv3_kvm.c
21
diff --git a/include/hw/arm/xlnx-zynqmp.h b/include/hw/arm/xlnx-zynqmp.h
30
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
31
--- a/hw/intc/arm_gicv3_kvm.c
23
--- a/include/hw/arm/xlnx-zynqmp.h
32
+++ b/hw/intc/arm_gicv3_kvm.c
24
+++ b/include/hw/arm/xlnx-zynqmp.h
33
@@ -XXX,XX +XXX,XX @@ static void kvm_arm_gicv3_put(GICv3State *s)
25
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_SIMPLE_TYPE(XlnxZynqMPState, XLNX_ZYNQMP)
34
kvm_gicr_access(s, GICR_PROPBASER + 4, ncpu, &regh, true);
26
35
27
#define XLNX_ZYNQMP_GIC_REGIONS 6
36
reg64 = c->gicr_pendbaser;
28
37
- if (!c->gicr_ctlr & GICR_CTLR_ENABLE_LPIS) {
29
-/* ZynqMP maps the ARM GIC regions (GICC, GICD ...) at consecutive 64k offsets
38
+ if (!(c->gicr_ctlr & GICR_CTLR_ENABLE_LPIS)) {
30
+/*
39
/* Setting PTZ is advised if LPIs are disabled, to reduce
31
+ * ZynqMP maps the ARM GIC regions (GICC, GICD ...) at consecutive 64k offsets
40
* GIC initialization time.
32
* and under-decodes the 64k region. This mirrors the 4k regions to every 4k
41
*/
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
42
--
65
--
43
2.7.4
66
2.20.1
44
67
45
68
diff view generated by jsdifflib
1
From: Thomas Huth <thuth@redhat.com>
1
From: Xuzhou Cheng <xuzhou.cheng@windriver.com>
2
2
3
QEMU currently aborts if the user is accidentially trying to
3
Add a Xilinx CSU DMA module to ZynqMP SoC, and connent the stream
4
do something like this:
4
link of GQSPI to CSU DMA.
5
5
6
$ aarch64-softmmu/qemu-system-aarch64 -S -M integratorcp -nographic
6
Signed-off-by: Xuzhou Cheng <xuzhou.cheng@windriver.com>
7
QEMU 2.9.93 monitor - type 'help' for more information
7
Signed-off-by: Bin Meng <bin.meng@windriver.com>
8
(qemu) device_add ast2400
8
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
9
Unexpected error in error_set_from_qdev_prop_error()
9
Message-id: 20210303135254.3970-4-bmeng.cn@gmail.com
10
at hw/core/qdev-properties.c:1032:
11
Aborted (core dumped)
12
13
The ast2400 SoC devices are clearly not creatable by the user since
14
they are using the serial_hds and nd_table arrays directly in their
15
realize function, so mark them with user_creatable = false.
16
17
Signed-off-by: Thomas Huth <thuth@redhat.com>
18
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
19
Reviewed-by: Cédric Le Goater <clg@kaod.org>
20
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
---
11
---
22
hw/arm/aspeed_soc.c | 2 ++
12
include/hw/arm/xlnx-zynqmp.h | 2 ++
23
1 file changed, 2 insertions(+)
13
hw/arm/xlnx-zynqmp.c | 12 ++++++++++++
14
hw/arm/Kconfig | 1 +
15
3 files changed, 15 insertions(+)
24
16
25
diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c
17
diff --git a/include/hw/arm/xlnx-zynqmp.h b/include/hw/arm/xlnx-zynqmp.h
26
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
27
--- a/hw/arm/aspeed_soc.c
19
--- a/include/hw/arm/xlnx-zynqmp.h
28
+++ b/hw/arm/aspeed_soc.c
20
+++ b/include/hw/arm/xlnx-zynqmp.h
29
@@ -XXX,XX +XXX,XX @@ static void aspeed_soc_class_init(ObjectClass *oc, void *data)
21
@@ -XXX,XX +XXX,XX @@
30
22
#include "target/arm/cpu.h"
31
sc->info = (AspeedSoCInfo *) data;
23
#include "qom/object.h"
32
dc->realize = aspeed_soc_realize;
24
#include "net/can_emu.h"
33
+ /* Reason: Uses serial_hds and nd_table in realize() directly */
25
+#include "hw/dma/xlnx_csu_dma.h"
34
+ dc->user_creatable = false;
26
27
#define TYPE_XLNX_ZYNQMP "xlnx,zynqmp"
28
OBJECT_DECLARE_SIMPLE_TYPE(XlnxZynqMPState, XLNX_ZYNQMP)
29
@@ -XXX,XX +XXX,XX @@ struct XlnxZynqMPState {
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);
35
}
55
}
36
56
37
static const TypeInfo aspeed_soc_type_info = {
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
38
--
86
--
39
2.7.4
87
2.20.1
40
88
41
89
diff view generated by jsdifflib
1
From: Andrew Jones <drjones@redhat.com>
1
From: Xuzhou Cheng <xuzhou.cheng@windriver.com>
2
2
3
If a KVM PMU init or set-irq attr call fails we just silently stop
3
There are some coding convention warnings in xilinx_spips.c,
4
the PMU DT node generation. The only way they could fail, though,
4
as reported by:
5
is if the attr's respective KVM has-attr call fails. But that should
6
never happen if KVM advertises the PMU capability, because both
7
attrs have been available since the capability was introduced. Let's
8
just abort if this should-never-happen stuff does happen, because,
9
if it does, then something is obviously horribly wrong.
10
5
11
Signed-off-by: Andrew Jones <drjones@redhat.com>
6
$ ./scripts/checkpatch.pl hw/ssi/xilinx_spips.c
12
Reviewed-by: Christoffer Dall <cdall@linaro.org>
7
13
Message-id: 1500471597-2517-5-git-send-email-drjones@redhat.com
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>
14
Reviewed-by: Peter Maydell <peter.maydell@linaro.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
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
---
17
---
17
target/arm/kvm_arm.h | 15 ++++-----------
18
hw/ssi/xilinx_spips.c | 23 ++++++++++++++---------
18
hw/arm/virt.c | 9 +++------
19
1 file changed, 14 insertions(+), 9 deletions(-)
19
target/arm/kvm32.c | 3 +--
20
target/arm/kvm64.c | 28 ++++++++++++++++++++--------
21
4 files changed, 28 insertions(+), 27 deletions(-)
22
20
23
diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h
21
diff --git a/hw/ssi/xilinx_spips.c b/hw/ssi/xilinx_spips.c
24
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
25
--- a/target/arm/kvm_arm.h
23
--- a/hw/ssi/xilinx_spips.c
26
+++ b/target/arm/kvm_arm.h
24
+++ b/hw/ssi/xilinx_spips.c
27
@@ -XXX,XX +XXX,XX @@ int kvm_arm_sync_mpstate_to_qemu(ARMCPU *cpu);
25
@@ -XXX,XX +XXX,XX @@
28
26
FIELD(GQSPI_FIFO_CTRL, GENERIC_FIFO_RESET, 0, 1)
29
int kvm_arm_vgic_probe(void);
27
#define R_GQSPI_GFIFO_THRESH (0x150 / 4)
30
28
#define R_GQSPI_DATA_STS (0x15c / 4)
31
-int kvm_arm_pmu_set_irq(CPUState *cs, int irq);
29
-/* We use the snapshot register to hold the core state for the currently
32
-int kvm_arm_pmu_init(CPUState *cs);
30
+/*
33
+void kvm_arm_pmu_set_irq(CPUState *cs, int irq);
31
+ * We use the snapshot register to hold the core state for the currently
34
+void kvm_arm_pmu_init(CPUState *cs);
32
* or most recently executed command. So the generic fifo format is defined
35
33
* for the snapshot register
36
#else
34
*/
37
35
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_qspips_reset(DeviceState *d)
38
@@ -XXX,XX +XXX,XX @@ static inline int kvm_arm_vgic_probe(void)
36
xlnx_zynqmp_qspips_update_ixr(s);
39
return 0;
40
}
37
}
41
38
42
-static inline int kvm_arm_pmu_set_irq(CPUState *cs, int irq)
39
-/* N way (num) in place bit striper. Lay out row wise bits (MSB to LSB)
43
-{
40
+/*
44
- return 0;
41
+ * N way (num) in place bit striper. Lay out row wise bits (MSB to LSB)
45
-}
42
* column wise (from element 0 to N-1). num is the length of x, and dir
46
-
43
* reverses the direction of the transform. Best illustrated by example:
47
-static inline int kvm_arm_pmu_init(CPUState *cs)
44
* Each digit in the below array is a single bit (num == 3):
48
-{
45
@@ -XXX,XX +XXX,XX @@ static void xilinx_spips_flush_txfifo(XilinxSPIPS *s)
49
- return 0;
46
tx_rx[i] = tx;
50
-}
47
}
51
+static inline void kvm_arm_pmu_set_irq(CPUState *cs, int irq) {}
48
} else {
52
+static inline void kvm_arm_pmu_init(CPUState *cs) {}
49
- /* Extract a dummy byte and generate dummy cycles according to the
53
50
- * link state */
54
#endif
51
+ /*
55
52
+ * Extract a dummy byte and generate dummy cycles according to the
56
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
53
+ * link state
57
index XXXXXXX..XXXXXXX 100644
54
+ */
58
--- a/hw/arm/virt.c
55
tx = fifo8_pop(&s->tx_fifo);
59
+++ b/hw/arm/virt.c
56
dummy_cycles = 8 / s->link_state;
60
@@ -XXX,XX +XXX,XX @@ static void fdt_add_pmu_nodes(const VirtMachineState *vms)
61
return;
62
}
57
}
63
if (kvm_enabled()) {
58
@@ -XXX,XX +XXX,XX @@ static void xilinx_spips_flush_txfifo(XilinxSPIPS *s)
64
- if (kvm_irqchip_in_kernel() &&
65
- !kvm_arm_pmu_set_irq(cpu, PPI(VIRTUAL_PMU_IRQ))) {
66
- return;
67
- }
68
- if (!kvm_arm_pmu_init(cpu)) {
69
- return;
70
+ if (kvm_irqchip_in_kernel()) {
71
+ kvm_arm_pmu_set_irq(cpu, PPI(VIRTUAL_PMU_IRQ));
72
}
59
}
73
+ kvm_arm_pmu_init(cpu);
60
break;
74
}
61
case (SNOOP_ADDR):
75
}
62
- /* Address has been transmitted, transmit dummy cycles now if
76
63
- * needed */
77
diff --git a/target/arm/kvm32.c b/target/arm/kvm32.c
64
+ /*
78
index XXXXXXX..XXXXXXX 100644
65
+ * Address has been transmitted, transmit dummy cycles now if needed
79
--- a/target/arm/kvm32.c
66
+ */
80
+++ b/target/arm/kvm32.c
67
if (s->cmd_dummies < 0) {
81
@@ -XXX,XX +XXX,XX @@ bool kvm_arm_hw_debug_active(CPUState *cs)
68
s->snoop_state = SNOOP_NONE;
82
return false;
69
} else {
70
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_qspips_notify(void *opaque)
83
}
71
}
84
72
85
-int kvm_arm_pmu_set_irq(CPUState *cs, int irq)
73
static uint64_t xilinx_spips_read(void *opaque, hwaddr addr,
86
+void kvm_arm_pmu_set_irq(CPUState *cs, int irq)
74
- unsigned size)
75
+ unsigned size)
87
{
76
{
88
qemu_log_mask(LOG_UNIMP, "%s: not implemented\n", __func__);
77
XilinxSPIPS *s = opaque;
89
- return 0;
78
uint32_t mask = ~0;
79
@@ -XXX,XX +XXX,XX @@ static uint64_t xlnx_zynqmp_qspips_read(void *opaque,
90
}
80
}
91
81
92
int kvm_arm_pmu_init(CPUState *cs)
82
static void xilinx_spips_write(void *opaque, hwaddr addr,
93
diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
83
- uint64_t value, unsigned size)
94
index XXXXXXX..XXXXXXX 100644
84
+ uint64_t value, unsigned size)
95
--- a/target/arm/kvm64.c
85
{
96
+++ b/target/arm/kvm64.c
86
int mask = ~0;
97
@@ -XXX,XX +XXX,XX @@ static bool kvm_arm_pmu_set_attr(CPUState *cs, struct kvm_device_attr *attr)
87
XilinxSPIPS *s = opaque;
98
88
@@ -XXX,XX +XXX,XX @@ static void xilinx_qspips_write(void *opaque, hwaddr addr,
99
err = kvm_vcpu_ioctl(cs, KVM_HAS_DEVICE_ATTR, attr);
100
if (err != 0) {
101
+ error_report("PMU: KVM_HAS_DEVICE_ATTR: %s", strerror(-err));
102
return false;
103
}
104
105
err = kvm_vcpu_ioctl(cs, KVM_SET_DEVICE_ATTR, attr);
106
- if (err < 0) {
107
- fprintf(stderr, "KVM_SET_DEVICE_ATTR failed: %s\n",
108
- strerror(-err));
109
- abort();
110
+ if (err != 0) {
111
+ error_report("PMU: KVM_SET_DEVICE_ATTR: %s", strerror(-err));
112
+ return false;
113
}
114
115
return true;
116
}
89
}
117
90
118
-int kvm_arm_pmu_init(CPUState *cs)
91
static void xlnx_zynqmp_qspips_write(void *opaque, hwaddr addr,
119
+void kvm_arm_pmu_init(CPUState *cs)
92
- uint64_t value, unsigned size)
93
+ uint64_t value, unsigned size)
120
{
94
{
121
struct kvm_device_attr attr = {
95
XlnxZynqMPQSPIPS *s = XLNX_ZYNQMP_QSPIPS(opaque);
122
.group = KVM_ARM_VCPU_PMU_V3_CTRL,
96
uint32_t reg = addr / 4;
123
.attr = KVM_ARM_VCPU_PMU_V3_INIT,
124
};
125
126
- return kvm_arm_pmu_set_attr(cs, &attr);
127
+ if (!ARM_CPU(cs)->has_pmu) {
128
+ return;
129
+ }
130
+ if (!kvm_arm_pmu_set_attr(cs, &attr)) {
131
+ error_report("failed to init PMU");
132
+ abort();
133
+ }
134
}
135
136
-int kvm_arm_pmu_set_irq(CPUState *cs, int irq)
137
+void kvm_arm_pmu_set_irq(CPUState *cs, int irq)
138
{
139
struct kvm_device_attr attr = {
140
.group = KVM_ARM_VCPU_PMU_V3_CTRL,
141
@@ -XXX,XX +XXX,XX @@ int kvm_arm_pmu_set_irq(CPUState *cs, int irq)
142
.attr = KVM_ARM_VCPU_PMU_V3_IRQ,
143
};
144
145
- return kvm_arm_pmu_set_attr(cs, &attr);
146
+ if (!ARM_CPU(cs)->has_pmu) {
147
+ return;
148
+ }
149
+ if (!kvm_arm_pmu_set_attr(cs, &attr)) {
150
+ error_report("failed to set irq for PMU");
151
+ abort();
152
+ }
153
}
154
155
static inline void set_feature(uint64_t *features, int feature)
156
--
97
--
157
2.7.4
98
2.20.1
158
99
159
100
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
From: Xuzhou Cheng <xuzhou.cheng@windriver.com>
2
2
3
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
3
Now that the Xilinx CSU DMA model is implemented, the existing
4
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
DMA related dead codes in the ZynqMP QSPI are useless and should
5
be removed. The maximum register number is also updated to only
6
include the QSPI registers.
7
8
Signed-off-by: Xuzhou Cheng <xuzhou.cheng@windriver.com>
9
Signed-off-by: Bin Meng <bin.meng@windriver.com>
10
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
11
Message-id: 20210303135254.3970-6-bmeng.cn@gmail.com
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
---
13
---
7
hw/arm/armv7m.c | 4 ++--
14
include/hw/ssi/xilinx_spips.h | 2 +-
8
hw/arm/exynos4210.c | 4 ++--
15
hw/ssi/xilinx_spips.c | 10 ----------
9
hw/arm/highbank.c | 11 +++++++----
16
2 files changed, 1 insertion(+), 11 deletions(-)
10
hw/arm/realview.c | 6 ++++--
11
hw/arm/vexpress.c | 6 ++++--
12
hw/arm/xilinx_zynq.c | 14 ++++++++------
13
6 files changed, 27 insertions(+), 18 deletions(-)
14
17
15
diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c
18
diff --git a/include/hw/ssi/xilinx_spips.h b/include/hw/ssi/xilinx_spips.h
16
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/arm/armv7m.c
20
--- a/include/hw/ssi/xilinx_spips.h
18
+++ b/hw/arm/armv7m.c
21
+++ b/include/hw/ssi/xilinx_spips.h
19
@@ -XXX,XX +XXX,XX @@ static void armv7m_instance_init(Object *obj)
22
@@ -XXX,XX +XXX,XX @@
20
&error_abort);
23
typedef struct XilinxSPIPS XilinxSPIPS;
21
memory_region_init(&s->container, obj, "armv7m-container", UINT64_MAX);
24
22
25
#define XLNX_SPIPS_R_MAX (0x100 / 4)
23
- object_initialize(&s->nvic, sizeof(s->nvic), "armv7m_nvic");
26
-#define XLNX_ZYNQMP_SPIPS_R_MAX (0x830 / 4)
24
+ object_initialize(&s->nvic, sizeof(s->nvic), TYPE_NVIC);
27
+#define XLNX_ZYNQMP_SPIPS_R_MAX (0x200 / 4)
25
qdev_set_parent_bus(DEVICE(&s->nvic), sysbus_get_default());
28
26
object_property_add_alias(obj, "num-irq",
29
/* Bite off 4k chunks at a time */
27
OBJECT(&s->nvic), "num-irq", &error_abort);
30
#define LQSPI_CACHE_SIZE 1024
28
@@ -XXX,XX +XXX,XX @@ DeviceState *armv7m_init(MemoryRegion *system_memory, int mem_size, int num_irq,
31
diff --git a/hw/ssi/xilinx_spips.c b/hw/ssi/xilinx_spips.c
29
cpu_model = "cortex-m3";
30
}
31
32
- armv7m = qdev_create(NULL, "armv7m");
33
+ armv7m = qdev_create(NULL, TYPE_ARMV7M);
34
qdev_prop_set_uint32(armv7m, "num-irq", num_irq);
35
qdev_prop_set_string(armv7m, "cpu-model", cpu_model);
36
object_property_set_link(OBJECT(armv7m), OBJECT(get_system_memory()),
37
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
38
index XXXXXXX..XXXXXXX 100644
32
index XXXXXXX..XXXXXXX 100644
39
--- a/hw/arm/exynos4210.c
33
--- a/hw/ssi/xilinx_spips.c
40
+++ b/hw/arm/exynos4210.c
34
+++ b/hw/ssi/xilinx_spips.c
41
@@ -XXX,XX +XXX,XX @@
35
@@ -XXX,XX +XXX,XX @@
42
#include "hw/arm/arm.h"
36
#define R_GQSPI_MOD_ID (0x1fc / 4)
43
#include "hw/loader.h"
37
#define R_GQSPI_MOD_ID_RESET (0x10a0000)
44
#include "hw/arm/exynos4210.h"
38
45
-#include "hw/sd/sd.h"
39
-#define R_QSPIDMA_DST_CTRL (0x80c / 4)
46
+#include "hw/sd/sdhci.h"
40
-#define R_QSPIDMA_DST_CTRL_RESET (0x803ffa00)
47
#include "hw/usb/hcd-ehci.h"
41
-#define R_QSPIDMA_DST_I_MASK (0x820 / 4)
48
42
-#define R_QSPIDMA_DST_I_MASK_RESET (0xfe)
49
#define EXYNOS4210_CHIPID_ADDR 0x10000000
43
-#define R_QSPIDMA_DST_CTRL2 (0x824 / 4)
50
@@ -XXX,XX +XXX,XX @@ Exynos4210State *exynos4210_init(MemoryRegion *system_mem)
44
-#define R_QSPIDMA_DST_CTRL2_RESET (0x081bfff8)
51
BlockBackend *blk;
45
-
52
DriveInfo *di;
46
/* size of TXRX FIFOs */
53
47
#define RXFF_A (128)
54
- dev = qdev_create(NULL, "generic-sdhci");
48
#define TXFF_A (128)
55
+ dev = qdev_create(NULL, TYPE_SYSBUS_SDHCI);
49
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_qspips_reset(DeviceState *d)
56
qdev_prop_set_uint32(dev, "capareg", EXYNOS4210_SDHCI_CAPABILITIES);
50
s->regs[R_GQSPI_GPIO] = 1;
57
qdev_init_nofail(dev);
51
s->regs[R_GQSPI_LPBK_DLY_ADJ] = R_GQSPI_LPBK_DLY_ADJ_RESET;
58
52
s->regs[R_GQSPI_MOD_ID] = R_GQSPI_MOD_ID_RESET;
59
diff --git a/hw/arm/highbank.c b/hw/arm/highbank.c
53
- s->regs[R_QSPIDMA_DST_CTRL] = R_QSPIDMA_DST_CTRL_RESET;
60
index XXXXXXX..XXXXXXX 100644
54
- s->regs[R_QSPIDMA_DST_I_MASK] = R_QSPIDMA_DST_I_MASK_RESET;
61
--- a/hw/arm/highbank.c
55
- s->regs[R_QSPIDMA_DST_CTRL2] = R_QSPIDMA_DST_CTRL2_RESET;
62
+++ b/hw/arm/highbank.c
56
s->man_start_com_g = false;
63
@@ -XXX,XX +XXX,XX @@
57
s->gqspi_irqline = 0;
64
#include "exec/address-spaces.h"
58
xlnx_zynqmp_qspips_update_ixr(s);
65
#include "qemu/error-report.h"
66
#include "hw/char/pl011.h"
67
+#include "hw/ide/ahci.h"
68
+#include "hw/cpu/a9mpcore.h"
69
+#include "hw/cpu/a15mpcore.h"
70
71
#define SMP_BOOT_ADDR 0x100
72
#define SMP_BOOT_REG 0x40
73
@@ -XXX,XX +XXX,XX @@ static void calxeda_init(MachineState *machine, enum cxmachines machine_id)
74
busdev = SYS_BUS_DEVICE(dev);
75
sysbus_mmio_map(busdev, 0, 0xfff12000);
76
77
- dev = qdev_create(NULL, "a9mpcore_priv");
78
+ dev = qdev_create(NULL, TYPE_A9MPCORE_PRIV);
79
break;
80
case CALXEDA_MIDWAY:
81
- dev = qdev_create(NULL, "a15mpcore_priv");
82
+ dev = qdev_create(NULL, TYPE_A15MPCORE_PRIV);
83
break;
84
}
85
qdev_prop_set_uint32(dev, "num-cpu", smp_cpus);
86
@@ -XXX,XX +XXX,XX @@ static void calxeda_init(MachineState *machine, enum cxmachines machine_id)
87
sysbus_connect_irq(busdev, 0, pic[18]);
88
pl011_create(0xfff36000, pic[20], serial_hds[0]);
89
90
- dev = qdev_create(NULL, "highbank-regs");
91
+ dev = qdev_create(NULL, TYPE_HIGHBANK_REGISTERS);
92
qdev_init_nofail(dev);
93
busdev = SYS_BUS_DEVICE(dev);
94
sysbus_mmio_map(busdev, 0, 0xfff3c000);
95
@@ -XXX,XX +XXX,XX @@ static void calxeda_init(MachineState *machine, enum cxmachines machine_id)
96
sysbus_create_simple("pl031", 0xfff35000, pic[19]);
97
sysbus_create_simple("pl022", 0xfff39000, pic[23]);
98
99
- sysbus_create_simple("sysbus-ahci", 0xffe08000, pic[83]);
100
+ sysbus_create_simple(TYPE_SYSBUS_AHCI, 0xffe08000, pic[83]);
101
102
if (nd_table[0].used) {
103
qemu_check_nic_model(&nd_table[0], "xgmac");
104
diff --git a/hw/arm/realview.c b/hw/arm/realview.c
105
index XXXXXXX..XXXXXXX 100644
106
--- a/hw/arm/realview.c
107
+++ b/hw/arm/realview.c
108
@@ -XXX,XX +XXX,XX @@
109
#include "exec/address-spaces.h"
110
#include "qemu/error-report.h"
111
#include "hw/char/pl011.h"
112
+#include "hw/cpu/a9mpcore.h"
113
+#include "hw/intc/realview_gic.h"
114
115
#define SMP_BOOT_ADDR 0xe0000000
116
#define SMP_BOOTREG_ADDR 0x10000030
117
@@ -XXX,XX +XXX,XX @@ static void realview_init(MachineState *machine,
118
sysbus_mmio_map(SYS_BUS_DEVICE(sysctl), 0, 0x10000000);
119
120
if (is_mpcore) {
121
- dev = qdev_create(NULL, is_pb ? "a9mpcore_priv": "realview_mpcore");
122
+ dev = qdev_create(NULL, is_pb ? TYPE_A9MPCORE_PRIV : "realview_mpcore");
123
qdev_prop_set_uint32(dev, "num-cpu", smp_cpus);
124
qdev_init_nofail(dev);
125
busdev = SYS_BUS_DEVICE(dev);
126
@@ -XXX,XX +XXX,XX @@ static void realview_init(MachineState *machine,
127
} else {
128
uint32_t gic_addr = is_pb ? 0x1e000000 : 0x10040000;
129
/* For now just create the nIRQ GIC, and ignore the others. */
130
- dev = sysbus_create_simple("realview_gic", gic_addr, cpu_irq[0]);
131
+ dev = sysbus_create_simple(TYPE_REALVIEW_GIC, gic_addr, cpu_irq[0]);
132
}
133
for (n = 0; n < 64; n++) {
134
pic[n] = qdev_get_gpio_in(dev, n);
135
diff --git a/hw/arm/vexpress.c b/hw/arm/vexpress.c
136
index XXXXXXX..XXXXXXX 100644
137
--- a/hw/arm/vexpress.c
138
+++ b/hw/arm/vexpress.c
139
@@ -XXX,XX +XXX,XX @@
140
#include "qemu/error-report.h"
141
#include <libfdt.h>
142
#include "hw/char/pl011.h"
143
+#include "hw/cpu/a9mpcore.h"
144
+#include "hw/cpu/a15mpcore.h"
145
146
#define VEXPRESS_BOARD_ID 0x8e0
147
#define VEXPRESS_FLASH_SIZE (64 * 1024 * 1024)
148
@@ -XXX,XX +XXX,XX @@ static void a9_daughterboard_init(const VexpressMachineState *vms,
149
memory_region_add_subregion(sysmem, 0x60000000, ram);
150
151
/* 0x1e000000 A9MPCore (SCU) private memory region */
152
- init_cpus(cpu_model, "a9mpcore_priv", 0x1e000000, pic, vms->secure);
153
+ init_cpus(cpu_model, TYPE_A9MPCORE_PRIV, 0x1e000000, pic, vms->secure);
154
155
/* Daughterboard peripherals : 0x10020000 .. 0x20000000 */
156
157
@@ -XXX,XX +XXX,XX @@ static void a15_daughterboard_init(const VexpressMachineState *vms,
158
memory_region_add_subregion(sysmem, 0x80000000, ram);
159
160
/* 0x2c000000 A15MPCore private memory region (GIC) */
161
- init_cpus(cpu_model, "a15mpcore_priv", 0x2c000000, pic, vms->secure);
162
+ init_cpus(cpu_model, TYPE_A15MPCORE_PRIV, 0x2c000000, pic, vms->secure);
163
164
/* A15 daughterboard peripherals: */
165
166
diff --git a/hw/arm/xilinx_zynq.c b/hw/arm/xilinx_zynq.c
167
index XXXXXXX..XXXXXXX 100644
168
--- a/hw/arm/xilinx_zynq.c
169
+++ b/hw/arm/xilinx_zynq.c
170
@@ -XXX,XX +XXX,XX @@
171
#include "hw/misc/zynq-xadc.h"
172
#include "hw/ssi/ssi.h"
173
#include "qemu/error-report.h"
174
-#include "hw/sd/sd.h"
175
+#include "hw/sd/sdhci.h"
176
#include "hw/char/cadence_uart.h"
177
+#include "hw/net/cadence_gem.h"
178
+#include "hw/cpu/a9mpcore.h"
179
180
#define NUM_SPI_FLASHES 4
181
#define NUM_QSPI_FLASHES 2
182
@@ -XXX,XX +XXX,XX @@ static void gem_init(NICInfo *nd, uint32_t base, qemu_irq irq)
183
DeviceState *dev;
184
SysBusDevice *s;
185
186
- dev = qdev_create(NULL, "cadence_gem");
187
+ dev = qdev_create(NULL, TYPE_CADENCE_GEM);
188
if (nd->used) {
189
- qemu_check_nic_model(nd, "cadence_gem");
190
+ qemu_check_nic_model(nd, TYPE_CADENCE_GEM);
191
qdev_set_nic_properties(dev, nd);
192
}
193
qdev_init_nofail(dev);
194
@@ -XXX,XX +XXX,XX @@ static void zynq_init(MachineState *machine)
195
qdev_init_nofail(dev);
196
sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0xF8000000);
197
198
- dev = qdev_create(NULL, "a9mpcore_priv");
199
+ dev = qdev_create(NULL, TYPE_A9MPCORE_PRIV);
200
qdev_prop_set_uint32(dev, "num-cpu", 1);
201
qdev_init_nofail(dev);
202
busdev = SYS_BUS_DEVICE(dev);
203
@@ -XXX,XX +XXX,XX @@ static void zynq_init(MachineState *machine)
204
gem_init(&nd_table[0], 0xE000B000, pic[54-IRQ_OFFSET]);
205
gem_init(&nd_table[1], 0xE000C000, pic[77-IRQ_OFFSET]);
206
207
- dev = qdev_create(NULL, "generic-sdhci");
208
+ dev = qdev_create(NULL, TYPE_SYSBUS_SDHCI);
209
qdev_init_nofail(dev);
210
sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0xE0100000);
211
sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[56-IRQ_OFFSET]);
212
@@ -XXX,XX +XXX,XX @@ static void zynq_init(MachineState *machine)
213
qdev_prop_set_drive(carddev, "drive", blk, &error_fatal);
214
object_property_set_bool(OBJECT(carddev), true, "realized", &error_fatal);
215
216
- dev = qdev_create(NULL, "generic-sdhci");
217
+ dev = qdev_create(NULL, TYPE_SYSBUS_SDHCI);
218
qdev_init_nofail(dev);
219
sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0xE0101000);
220
sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[79-IRQ_OFFSET]);
221
--
59
--
222
2.7.4
60
2.20.1
223
61
224
62
diff view generated by jsdifflib
1
The armv7m_nvic.h header file was accidentally placed in
1
The #defines INTERNAL and CASCADING represent different possible
2
include/hw/arm; move it to include/hw/intc to match where
2
values for the TCCR.CSS register field; prefix them with CSS_ to make
3
its corresponding .c file lives.
3
this more obvious, before we add more defines to represent the
4
other possible values of the field in the next commit.
4
5
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
8
Message-id: 20210219223241.16344-2-peter.maydell@linaro.org
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 1501692241-23310-15-git-send-email-peter.maydell@linaro.org
10
---
9
---
11
include/hw/arm/armv7m.h | 2 +-
10
hw/timer/renesas_tmr.c | 16 ++++++++--------
12
include/hw/{arm => intc}/armv7m_nvic.h | 0
11
1 file changed, 8 insertions(+), 8 deletions(-)
13
hw/intc/armv7m_nvic.c | 2 +-
14
3 files changed, 2 insertions(+), 2 deletions(-)
15
rename include/hw/{arm => intc}/armv7m_nvic.h (100%)
16
12
17
diff --git a/include/hw/arm/armv7m.h b/include/hw/arm/armv7m.h
13
diff --git a/hw/timer/renesas_tmr.c b/hw/timer/renesas_tmr.c
18
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
19
--- a/include/hw/arm/armv7m.h
15
--- a/hw/timer/renesas_tmr.c
20
+++ b/include/hw/arm/armv7m.h
16
+++ b/hw/timer/renesas_tmr.c
21
@@ -XXX,XX +XXX,XX @@
17
@@ -XXX,XX +XXX,XX @@ REG8(TCCR, 10)
22
#define HW_ARM_ARMV7M_H
18
FIELD(TCCR, CSS, 3, 2)
23
19
FIELD(TCCR, TMRIS, 7, 1)
24
#include "hw/sysbus.h"
20
25
-#include "hw/arm/armv7m_nvic.h"
21
-#define INTERNAL 0x01
26
+#include "hw/intc/armv7m_nvic.h"
22
-#define CASCADING 0x03
27
23
+#define CSS_INTERNAL 0x01
28
#define TYPE_BITBAND "ARM,bitband-memory"
24
+#define CSS_CASCADING 0x03
29
#define BITBAND(obj) OBJECT_CHECK(BitBandState, (obj), TYPE_BITBAND)
25
#define CCLR_A 0x01
30
diff --git a/include/hw/arm/armv7m_nvic.h b/include/hw/intc/armv7m_nvic.h
26
#define CCLR_B 0x02
31
similarity index 100%
27
32
rename from include/hw/arm/armv7m_nvic.h
28
@@ -XXX,XX +XXX,XX @@ static void update_events(RTMRState *tmr, int ch)
33
rename to include/hw/intc/armv7m_nvic.h
29
/* event not happened */
34
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
30
return ;
35
index XXXXXXX..XXXXXXX 100644
31
}
36
--- a/hw/intc/armv7m_nvic.c
32
- if (FIELD_EX8(tmr->tccr[0], TCCR, CSS) == CASCADING) {
37
+++ b/hw/intc/armv7m_nvic.c
33
+ if (FIELD_EX8(tmr->tccr[0], TCCR, CSS) == CSS_CASCADING) {
38
@@ -XXX,XX +XXX,XX @@
34
/* cascading mode */
39
#include "hw/sysbus.h"
35
if (ch == 1) {
40
#include "qemu/timer.h"
36
tmr->next[ch] = none;
41
#include "hw/arm/arm.h"
37
@@ -XXX,XX +XXX,XX @@ static uint16_t read_tcnt(RTMRState *tmr, unsigned size, int ch)
42
-#include "hw/arm/armv7m_nvic.h"
38
if (delta > 0) {
43
+#include "hw/intc/armv7m_nvic.h"
39
tmr->tick = now;
44
#include "target/arm/cpu.h"
40
45
#include "exec/exec-all.h"
41
- if (FIELD_EX8(tmr->tccr[1], TCCR, CSS) == INTERNAL) {
46
#include "qemu/log.h"
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],
47
--
78
--
48
2.7.4
79
2.20.1
49
80
50
81
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
The read_tcnt() function calculates the TCNT register values for the
2
two channels of the timer module; it sets these up in the local
3
tcnt[] array, and eventually returns either one or both of them,
4
depending on whether the access is 8 or 16 bits. However, not all of
5
the code paths through this function set both elements of this array:
6
if the guest has programmed the TCCR.CSS register fields to values
7
which are either documented as not to be used or which QEMU does not
8
implement, then the function will return uninitialized data. (This
9
was spotted by Coverity.)
2
10
3
For "ldp x0, x1, [x0]", if the second load is on a second page and
11
Add the missing CSS cases to this code, so that we return a
4
the second page is unmapped, the exception would be raised with x0
12
consistent value instead of uninitialized data, and so the code
5
already modified. This means the instruction couldn't be restarted.
13
structure indicates what's happening.
6
14
7
Cc: qemu-arm@nongnu.org
15
Fixes: CID 1429976
8
Cc: qemu-stable@nongnu.org
9
Reported-by: Andrew <andrew@fubar.geek.nz>
10
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20170825224833.4463-1-richard.henderson@linaro.org
12
Fixes: https://bugs.launchpad.net/qemu/+bug/1713066
13
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
14
[PMM: tweaked comment format]
15
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
18
Message-id: 20210219223241.16344-3-peter.maydell@linaro.org
17
---
19
---
18
target/arm/translate-a64.c | 29 +++++++++++++++++------------
20
hw/timer/renesas_tmr.c | 19 +++++++++++++++----
19
1 file changed, 17 insertions(+), 12 deletions(-)
21
1 file changed, 15 insertions(+), 4 deletions(-)
20
22
21
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
23
diff --git a/hw/timer/renesas_tmr.c b/hw/timer/renesas_tmr.c
22
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
23
--- a/target/arm/translate-a64.c
25
--- a/hw/timer/renesas_tmr.c
24
+++ b/target/arm/translate-a64.c
26
+++ b/hw/timer/renesas_tmr.c
25
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_pair(DisasContext *s, uint32_t insn)
27
@@ -XXX,XX +XXX,XX @@ REG8(TCCR, 10)
26
} else {
28
FIELD(TCCR, CSS, 3, 2)
27
do_fp_st(s, rt, tcg_addr, size);
29
FIELD(TCCR, TMRIS, 7, 1)
30
31
+#define CSS_EXTERNAL 0x00
32
#define CSS_INTERNAL 0x01
33
+#define CSS_INVALID 0x02
34
#define CSS_CASCADING 0x03
35
#define CCLR_A 0x01
36
#define CCLR_B 0x02
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) == CSS_INTERNAL) {
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
}
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;
28
}
56
}
29
- } else {
57
switch (FIELD_EX8(tmr->tccr[0], TCCR, CSS)) {
30
- TCGv_i64 tcg_rt = cpu_reg(s, rt);
58
case CSS_INTERNAL:
31
- if (is_load) {
59
@@ -XXX,XX +XXX,XX @@ static uint16_t read_tcnt(RTMRState *tmr, unsigned size, int ch)
32
- do_gpr_ld(s, tcg_rt, tcg_addr, size, is_signed, false,
60
tcnt[0] = tmr->tcnt[0] + elapsed;
33
- false, 0, false, false);
61
break;
34
- } else {
62
case CSS_CASCADING:
35
- do_gpr_st(s, tcg_rt, tcg_addr, size,
63
- if (ovf > 0) {
36
- false, 0, false, false);
64
- tcnt[0] = tmr->tcnt[0] + ovf;
37
- }
65
- }
38
- }
66
+ tcnt[0] = tmr->tcnt[0] + ovf;
39
- tcg_gen_addi_i64(tcg_addr, tcg_addr, 1 << size);
67
+ break;
40
- if (is_vector) {
68
+ case CSS_INVALID: /* guest error to have set this */
41
+ tcg_gen_addi_i64(tcg_addr, tcg_addr, 1 << size);
69
+ case CSS_EXTERNAL: /* QEMU doesn't implement this */
42
if (is_load) {
70
+ tcnt[0] = tmr->tcnt[0];
43
do_fp_ld(s, rt2, tcg_addr, size);
71
break;
44
} else {
45
do_fp_st(s, rt2, tcg_addr, size);
46
}
72
}
47
} else {
73
} else {
48
+ TCGv_i64 tcg_rt = cpu_reg(s, rt);
49
TCGv_i64 tcg_rt2 = cpu_reg(s, rt2);
50
+
51
if (is_load) {
52
+ TCGv_i64 tmp = tcg_temp_new_i64();
53
+
54
+ /* Do not modify tcg_rt before recognizing any exception
55
+ * from the second load.
56
+ */
57
+ do_gpr_ld(s, tmp, tcg_addr, size, is_signed, false,
58
+ false, 0, false, false);
59
+ tcg_gen_addi_i64(tcg_addr, tcg_addr, 1 << size);
60
do_gpr_ld(s, tcg_rt2, tcg_addr, size, is_signed, false,
61
false, 0, false, false);
62
+
63
+ tcg_gen_mov_i64(tcg_rt, tmp);
64
+ tcg_temp_free_i64(tmp);
65
} else {
66
+ do_gpr_st(s, tcg_rt, tcg_addr, size,
67
+ false, 0, false, false);
68
+ tcg_gen_addi_i64(tcg_addr, tcg_addr, 1 << size);
69
do_gpr_st(s, tcg_rt2, tcg_addr, size,
70
false, 0, false, false);
71
}
72
--
74
--
73
2.7.4
75
2.20.1
74
76
75
77
diff view generated by jsdifflib