1
target-arm queue: Eric's SMMUv3 patchset, and an array
1
First pullreq for 6.0: mostly my v8.1M work, plus some other
2
of minor bugfixes and improvements from various others.
2
bits and pieces. (I still have a lot of stuff in my to-review
3
folder, which I may or may not get to before the Christmas break...)
3
4
4
thanks
5
thanks
5
-- PMM
6
-- PMM
6
7
7
The following changes since commit c8b7e627b4269a3bc3ae41d9f420547a47e6d9b9:
8
The following changes since commit 5e7b204dbfae9a562fc73684986f936b97f63877:
8
9
9
Merge remote-tracking branch 'remotes/ericb/tags/pull-nbd-2018-05-04' into staging (2018-05-04 14:42:46 +0100)
10
Merge remote-tracking branch 'remotes/mst/tags/for_upstream' into staging (2020-12-09 20:08:54 +0000)
10
11
11
are available in the Git repository at:
12
are available in the Git repository at:
12
13
13
git://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20180504
14
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20201210
14
15
15
for you to fetch changes up to 5680740c92993e9b3f3e011f2a2c394070e33f56:
16
for you to fetch changes up to 71f916be1c7e9ede0e37d9cabc781b5a9e8638ff:
16
17
17
hw/arm/virt: Introduce the iommu option (2018-05-04 18:05:52 +0100)
18
hw/arm/armv7m: Correct typo in QOM object name (2020-12-10 11:44:56 +0000)
18
19
19
----------------------------------------------------------------
20
----------------------------------------------------------------
20
target-arm queue:
21
target-arm queue:
21
* Emulate the SMMUv3 (IOMMU); one will be created in the 'virt' board
22
* hw/arm/smmuv3: Fix up L1STD_SPAN decoding
22
if the commandline includes "-machine iommu=smmuv3"
23
* xlnx-zynqmp: Support Xilinx ZynqMP CAN controllers
23
* target/arm: Implement v8M VLLDM and VLSTM
24
* sbsa-ref: allow to use Cortex-A53/57/72 cpus
24
* hw/arm: Don't fail qtest due to missing SD card in -nodefaults mode
25
* Various minor code cleanups
25
* Some fixes to silence Coverity false-positives
26
* hw/intc/armv7m_nvic: Make all of system PPB range be RAZWI/BusFault
26
* arm: boot: set boot_info starting from first_cpu
27
* Implement more pieces of ARMv8.1M support
27
(fixes a technical bug not visible in practice)
28
* hw/net/smc91c111: Convert away from old_mmio
29
* hw/usb/tusb6010: Convert away from old_mmio
30
* hw/char/cmsdk-apb-uart.c: Accept more input after character read
31
* target/arm: Make MPUIR write-ignored on OMAP, StrongARM
32
* hw/arm/virt: Add linux,pci-domain property
33
28
34
----------------------------------------------------------------
29
----------------------------------------------------------------
35
Eric Auger (11):
30
Alex Chen (4):
36
hw/arm/smmu-common: smmu base device and datatypes
31
i.MX25: Fix bad printf format specifiers
37
hw/arm/smmu-common: IOMMU memory region and address space setup
32
i.MX31: Fix bad printf format specifiers
38
hw/arm/smmu-common: VMSAv8-64 page table walk
33
i.MX6: Fix bad printf format specifiers
39
hw/arm/smmuv3: Wired IRQ and GERROR helpers
34
i.MX6ul: Fix bad printf format specifiers
40
hw/arm/smmuv3: Queue helpers
41
hw/arm/smmuv3: Implement MMIO write operations
42
hw/arm/smmuv3: Event queue recording helper
43
hw/arm/smmuv3: Implement translate callback
44
hw/arm/smmuv3: Abort on vfio or vhost case
45
target/arm/kvm: Translate the MSI doorbell in kvm_arch_fixup_msi_route
46
hw/arm/virt: Introduce the iommu option
47
35
48
Igor Mammedov (1):
36
Havard Skinnemoen (1):
49
arm: boot: set boot_info starting from first_cpu
37
tests/qtest/npcm7xx_rng-test: dump random data on failure
50
38
51
Jan Kiszka (1):
39
Kunkun Jiang (1):
52
hw/arm/virt: Add linux,pci-domain property
40
hw/arm/smmuv3: Fix up L1STD_SPAN decoding
53
41
54
Mathew Maidment (1):
42
Marcin Juszkiewicz (1):
55
target/arm: Correct MPUIR privilege level in register_cp_regs_for_features() conditional case
43
sbsa-ref: allow to use Cortex-A53/57/72 cpus
56
44
57
Patrick Oppenlander (1):
45
Peter Maydell (25):
58
hw/char/cmsdk-apb-uart.c: Accept more input after character read
46
hw/intc/armv7m_nvic: Make all of system PPB range be RAZWI/BusFault
47
target/arm: Implement v8.1M PXN extension
48
target/arm: Don't clobber ID_PFR1.Security on M-profile cores
49
target/arm: Implement VSCCLRM insn
50
target/arm: Implement CLRM instruction
51
target/arm: Enforce M-profile VMRS/VMSR register restrictions
52
target/arm: Refactor M-profile VMSR/VMRS handling
53
target/arm: Move general-use constant expanders up in translate.c
54
target/arm: Implement VLDR/VSTR system register
55
target/arm: Implement M-profile FPSCR_nzcvqc
56
target/arm: Use new FPCR_NZCV_MASK constant
57
target/arm: Factor out preserve-fp-state from full_vfp_access_check()
58
target/arm: Implement FPCXT_S fp system register
59
hw/intc/armv7m_nvic: Update FPDSCR masking for v8.1M
60
target/arm: For v8.1M, always clear R0-R3, R12, APSR, EPSR on exception entry
61
target/arm: In v8.1M, don't set HFSR.FORCED on vector table fetch failures
62
target/arm: Implement v8.1M REVIDR register
63
target/arm: Implement new v8.1M NOCP check for exception return
64
target/arm: Implement new v8.1M VLLDM and VLSTM encodings
65
hw/intc/armv7m_nvic: Support v8.1M CCR.TRD bit
66
target/arm: Implement CCR_S.TRD behaviour for SG insns
67
hw/intc/armv7m_nvic: Fix "return from inactive handler" check
68
target/arm: Implement M-profile "minimal RAS implementation"
69
hw/intc/armv7m_nvic: Implement read/write for RAS register block
70
hw/arm/armv7m: Correct typo in QOM object name
59
71
60
Peter Maydell (3):
72
Vikram Garhwal (4):
61
hw/usb/tusb6010: Convert away from old_mmio
73
hw/net/can: Introduce Xilinx ZynqMP CAN controller
62
hw/net/smc91c111: Convert away from old_mmio
74
xlnx-zynqmp: Connect Xilinx ZynqMP CAN controllers
63
target/arm: Implement v8M VLLDM and VLSTM
75
tests/qtest: Introduce tests for Xilinx ZynqMP CAN controller
76
MAINTAINERS: Add maintainer entry for Xilinx ZynqMP CAN controller
64
77
65
Prem Mallappa (3):
78
meson.build | 1 +
66
hw/arm/smmuv3: Skeleton
79
hw/arm/smmuv3-internal.h | 2 +-
67
hw/arm/virt: Add SMMUv3 to the virt board
80
hw/net/can/trace.h | 1 +
68
hw/arm/virt-acpi-build: Add smmuv3 node in IORT table
81
include/hw/arm/xlnx-zynqmp.h | 8 +
82
include/hw/intc/armv7m_nvic.h | 2 +
83
include/hw/net/xlnx-zynqmp-can.h | 78 +++
84
target/arm/cpu.h | 46 ++
85
target/arm/m-nocp.decode | 10 +-
86
target/arm/t32.decode | 10 +-
87
target/arm/vfp.decode | 14 +
88
hw/arm/armv7m.c | 4 +-
89
hw/arm/sbsa-ref.c | 23 +-
90
hw/arm/xlnx-zcu102.c | 20 +
91
hw/arm/xlnx-zynqmp.c | 34 ++
92
hw/intc/armv7m_nvic.c | 246 ++++++--
93
hw/misc/imx25_ccm.c | 12 +-
94
hw/misc/imx31_ccm.c | 14 +-
95
hw/misc/imx6_ccm.c | 20 +-
96
hw/misc/imx6_src.c | 2 +-
97
hw/misc/imx6ul_ccm.c | 4 +-
98
hw/misc/imx_ccm.c | 4 +-
99
hw/net/can/xlnx-zynqmp-can.c | 1161 ++++++++++++++++++++++++++++++++++++++
100
target/arm/cpu.c | 5 +-
101
target/arm/helper.c | 7 +-
102
target/arm/m_helper.c | 130 ++++-
103
target/arm/translate.c | 105 +++-
104
tests/qtest/npcm7xx_rng-test.c | 12 +
105
tests/qtest/xlnx-can-test.c | 360 ++++++++++++
106
MAINTAINERS | 8 +
107
hw/Kconfig | 1 +
108
hw/net/can/meson.build | 1 +
109
hw/net/can/trace-events | 9 +
110
target/arm/translate-vfp.c.inc | 511 ++++++++++++++++-
111
tests/qtest/meson.build | 1 +
112
34 files changed, 2713 insertions(+), 153 deletions(-)
113
create mode 100644 hw/net/can/trace.h
114
create mode 100644 include/hw/net/xlnx-zynqmp-can.h
115
create mode 100644 hw/net/can/xlnx-zynqmp-can.c
116
create mode 100644 tests/qtest/xlnx-can-test.c
117
create mode 100644 hw/net/can/trace-events
69
118
70
Richard Henderson (2):
71
target/arm: Tidy conditions in handle_vec_simd_shri
72
target/arm: Tidy condition in disas_simd_two_reg_misc
73
74
Thomas Huth (1):
75
hw/arm: Don't fail qtest due to missing SD card in -nodefaults mode
76
77
hw/arm/Makefile.objs | 1 +
78
hw/arm/smmu-internal.h | 99 +++
79
hw/arm/smmuv3-internal.h | 621 ++++++++++++++++++
80
include/hw/acpi/acpi-defs.h | 15 +
81
include/hw/arm/smmu-common.h | 145 +++++
82
include/hw/arm/smmuv3.h | 87 +++
83
include/hw/arm/virt.h | 10 +
84
hw/arm/boot.c | 2 +-
85
hw/arm/omap1.c | 8 +-
86
hw/arm/omap2.c | 8 +-
87
hw/arm/pxa2xx.c | 15 +-
88
hw/arm/smmu-common.c | 372 +++++++++++
89
hw/arm/smmuv3.c | 1191 +++++++++++++++++++++++++++++++++++
90
hw/arm/virt-acpi-build.c | 55 +-
91
hw/arm/virt.c | 101 ++-
92
hw/char/cmsdk-apb-uart.c | 1 +
93
hw/net/smc91c111.c | 54 +-
94
hw/usb/tusb6010.c | 40 +-
95
target/arm/helper.c | 2 +-
96
target/arm/kvm.c | 38 +-
97
target/arm/translate-a64.c | 12 +-
98
target/arm/translate.c | 17 +-
99
default-configs/aarch64-softmmu.mak | 1 +
100
hw/arm/trace-events | 37 ++
101
target/arm/trace-events | 3 +
102
25 files changed, 2868 insertions(+), 67 deletions(-)
103
create mode 100644 hw/arm/smmu-internal.h
104
create mode 100644 hw/arm/smmuv3-internal.h
105
create mode 100644 include/hw/arm/smmu-common.h
106
create mode 100644 include/hw/arm/smmuv3.h
107
create mode 100644 hw/arm/smmu-common.c
108
create mode 100644 hw/arm/smmuv3.c
109
diff view generated by jsdifflib
1
From: Eric Auger <eric.auger@redhat.com>
1
From: Kunkun Jiang <jiangkunkun@huawei.com>
2
2
3
Now we have relevant helpers for queue and irq
3
Accroding to the SMMUv3 spec, the SPAN field of Level1 Stream Table
4
management, let's implement MMIO write operations.
4
Descriptor is 5 bits([4:0]).
5
5
6
Signed-off-by: Eric Auger <eric.auger@redhat.com>
6
Fixes: 9bde7f0674f(hw/arm/smmuv3: Implement translate callback)
7
Signed-off-by: Prem Mallappa <prem.mallappa@broadcom.com>
7
Signed-off-by: Kunkun Jiang <jiangkunkun@huawei.com>
8
Message-id: 20201124023711.1184-1-jiangkunkun@huawei.com
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Message-id: 1524665762-31355-8-git-send-email-eric.auger@redhat.com
10
Acked-by: Eric Auger <eric.auger@redhat.com>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
---
12
hw/arm/smmuv3-internal.h | 8 +-
13
hw/arm/smmuv3-internal.h | 2 +-
13
hw/arm/smmuv3.c | 170 +++++++++++++++++++++++++++++++++++++--
14
1 file changed, 1 insertion(+), 1 deletion(-)
14
hw/arm/trace-events | 6 ++
15
3 files changed, 174 insertions(+), 10 deletions(-)
16
15
17
diff --git a/hw/arm/smmuv3-internal.h b/hw/arm/smmuv3-internal.h
16
diff --git a/hw/arm/smmuv3-internal.h b/hw/arm/smmuv3-internal.h
18
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/arm/smmuv3-internal.h
18
--- a/hw/arm/smmuv3-internal.h
20
+++ b/hw/arm/smmuv3-internal.h
19
+++ b/hw/arm/smmuv3-internal.h
21
@@ -XXX,XX +XXX,XX @@ REG32(CR0, 0x20)
20
@@ -XXX,XX +XXX,XX @@ static inline uint64_t l1std_l2ptr(STEDesc *desc)
22
FIELD(CR0, EVENTQEN, 2, 1)
21
return hi << 32 | lo;
23
FIELD(CR0, CMDQEN, 3, 1)
24
25
+#define SMMU_CR0_RESERVED 0xFFFFFC20
26
+
27
REG32(CR0ACK, 0x24)
28
REG32(CR1, 0x28)
29
REG32(CR2, 0x2c)
30
@@ -XXX,XX +XXX,XX @@ static inline bool smmuv3_gerror_irq_enabled(SMMUv3State *s)
31
return FIELD_EX32(s->irq_ctrl, IRQ_CTRL, GERROR_IRQEN);
32
}
22
}
33
23
34
-/* public until callers get introduced */
24
-#define L1STD_SPAN(stm) (extract32((stm)->word[0], 0, 4))
35
-void smmuv3_trigger_irq(SMMUv3State *s, SMMUIrq irq, uint32_t gerror_mask);
25
+#define L1STD_SPAN(stm) (extract32((stm)->word[0], 0, 5))
36
-void smmuv3_write_gerrorn(SMMUv3State *s, uint32_t gerrorn);
37
-
38
/* Queue Handling */
39
40
#define Q_BASE(q) ((q)->base & SMMU_BASE_ADDR_MASK)
41
@@ -XXX,XX +XXX,XX @@ enum { /* Command completion notification */
42
addr; \
43
})
44
45
-int smmuv3_cmdq_consume(SMMUv3State *s);
46
+#define SMMU_FEATURE_2LVL_STE (1 << 0)
47
26
48
#endif
27
#endif
49
diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c
50
index XXXXXXX..XXXXXXX 100644
51
--- a/hw/arm/smmuv3.c
52
+++ b/hw/arm/smmuv3.c
53
@@ -XXX,XX +XXX,XX @@
54
* @irq: irq type
55
* @gerror_mask: mask of gerrors to toggle (relevant if @irq is GERROR)
56
*/
57
-void smmuv3_trigger_irq(SMMUv3State *s, SMMUIrq irq, uint32_t gerror_mask)
58
+static void smmuv3_trigger_irq(SMMUv3State *s, SMMUIrq irq,
59
+ uint32_t gerror_mask)
60
{
61
62
bool pulse = false;
63
@@ -XXX,XX +XXX,XX @@ void smmuv3_trigger_irq(SMMUv3State *s, SMMUIrq irq, uint32_t gerror_mask)
64
}
65
}
66
67
-void smmuv3_write_gerrorn(SMMUv3State *s, uint32_t new_gerrorn)
68
+static void smmuv3_write_gerrorn(SMMUv3State *s, uint32_t new_gerrorn)
69
{
70
uint32_t pending = s->gerror ^ s->gerrorn;
71
uint32_t toggled = s->gerrorn ^ new_gerrorn;
72
@@ -XXX,XX +XXX,XX @@ static void smmuv3_init_regs(SMMUv3State *s)
73
s->sid_split = 0;
74
}
75
76
-int smmuv3_cmdq_consume(SMMUv3State *s)
77
+static int smmuv3_cmdq_consume(SMMUv3State *s)
78
{
79
SMMUCmdError cmd_error = SMMU_CERROR_NONE;
80
SMMUQueue *q = &s->cmdq;
81
@@ -XXX,XX +XXX,XX @@ int smmuv3_cmdq_consume(SMMUv3State *s)
82
return 0;
83
}
84
85
+static MemTxResult smmu_writell(SMMUv3State *s, hwaddr offset,
86
+ uint64_t data, MemTxAttrs attrs)
87
+{
88
+ switch (offset) {
89
+ case A_GERROR_IRQ_CFG0:
90
+ s->gerror_irq_cfg0 = data;
91
+ return MEMTX_OK;
92
+ case A_STRTAB_BASE:
93
+ s->strtab_base = data;
94
+ return MEMTX_OK;
95
+ case A_CMDQ_BASE:
96
+ s->cmdq.base = data;
97
+ s->cmdq.log2size = extract64(s->cmdq.base, 0, 5);
98
+ if (s->cmdq.log2size > SMMU_CMDQS) {
99
+ s->cmdq.log2size = SMMU_CMDQS;
100
+ }
101
+ return MEMTX_OK;
102
+ case A_EVENTQ_BASE:
103
+ s->eventq.base = data;
104
+ s->eventq.log2size = extract64(s->eventq.base, 0, 5);
105
+ if (s->eventq.log2size > SMMU_EVENTQS) {
106
+ s->eventq.log2size = SMMU_EVENTQS;
107
+ }
108
+ return MEMTX_OK;
109
+ case A_EVENTQ_IRQ_CFG0:
110
+ s->eventq_irq_cfg0 = data;
111
+ return MEMTX_OK;
112
+ default:
113
+ qemu_log_mask(LOG_UNIMP,
114
+ "%s Unexpected 64-bit access to 0x%"PRIx64" (WI)\n",
115
+ __func__, offset);
116
+ return MEMTX_OK;
117
+ }
118
+}
119
+
120
+static MemTxResult smmu_writel(SMMUv3State *s, hwaddr offset,
121
+ uint64_t data, MemTxAttrs attrs)
122
+{
123
+ switch (offset) {
124
+ case A_CR0:
125
+ s->cr[0] = data;
126
+ s->cr0ack = data & ~SMMU_CR0_RESERVED;
127
+ /* in case the command queue has been enabled */
128
+ smmuv3_cmdq_consume(s);
129
+ return MEMTX_OK;
130
+ case A_CR1:
131
+ s->cr[1] = data;
132
+ return MEMTX_OK;
133
+ case A_CR2:
134
+ s->cr[2] = data;
135
+ return MEMTX_OK;
136
+ case A_IRQ_CTRL:
137
+ s->irq_ctrl = data;
138
+ return MEMTX_OK;
139
+ case A_GERRORN:
140
+ smmuv3_write_gerrorn(s, data);
141
+ /*
142
+ * By acknowledging the CMDQ_ERR, SW may notify cmds can
143
+ * be processed again
144
+ */
145
+ smmuv3_cmdq_consume(s);
146
+ return MEMTX_OK;
147
+ case A_GERROR_IRQ_CFG0: /* 64b */
148
+ s->gerror_irq_cfg0 = deposit64(s->gerror_irq_cfg0, 0, 32, data);
149
+ return MEMTX_OK;
150
+ case A_GERROR_IRQ_CFG0 + 4:
151
+ s->gerror_irq_cfg0 = deposit64(s->gerror_irq_cfg0, 32, 32, data);
152
+ return MEMTX_OK;
153
+ case A_GERROR_IRQ_CFG1:
154
+ s->gerror_irq_cfg1 = data;
155
+ return MEMTX_OK;
156
+ case A_GERROR_IRQ_CFG2:
157
+ s->gerror_irq_cfg2 = data;
158
+ return MEMTX_OK;
159
+ case A_STRTAB_BASE: /* 64b */
160
+ s->strtab_base = deposit64(s->strtab_base, 0, 32, data);
161
+ return MEMTX_OK;
162
+ case A_STRTAB_BASE + 4:
163
+ s->strtab_base = deposit64(s->strtab_base, 32, 32, data);
164
+ return MEMTX_OK;
165
+ case A_STRTAB_BASE_CFG:
166
+ s->strtab_base_cfg = data;
167
+ if (FIELD_EX32(data, STRTAB_BASE_CFG, FMT) == 1) {
168
+ s->sid_split = FIELD_EX32(data, STRTAB_BASE_CFG, SPLIT);
169
+ s->features |= SMMU_FEATURE_2LVL_STE;
170
+ }
171
+ return MEMTX_OK;
172
+ case A_CMDQ_BASE: /* 64b */
173
+ s->cmdq.base = deposit64(s->cmdq.base, 0, 32, data);
174
+ s->cmdq.log2size = extract64(s->cmdq.base, 0, 5);
175
+ if (s->cmdq.log2size > SMMU_CMDQS) {
176
+ s->cmdq.log2size = SMMU_CMDQS;
177
+ }
178
+ return MEMTX_OK;
179
+ case A_CMDQ_BASE + 4: /* 64b */
180
+ s->cmdq.base = deposit64(s->cmdq.base, 32, 32, data);
181
+ return MEMTX_OK;
182
+ case A_CMDQ_PROD:
183
+ s->cmdq.prod = data;
184
+ smmuv3_cmdq_consume(s);
185
+ return MEMTX_OK;
186
+ case A_CMDQ_CONS:
187
+ s->cmdq.cons = data;
188
+ return MEMTX_OK;
189
+ case A_EVENTQ_BASE: /* 64b */
190
+ s->eventq.base = deposit64(s->eventq.base, 0, 32, data);
191
+ s->eventq.log2size = extract64(s->eventq.base, 0, 5);
192
+ if (s->eventq.log2size > SMMU_EVENTQS) {
193
+ s->eventq.log2size = SMMU_EVENTQS;
194
+ }
195
+ return MEMTX_OK;
196
+ case A_EVENTQ_BASE + 4:
197
+ s->eventq.base = deposit64(s->eventq.base, 32, 32, data);
198
+ return MEMTX_OK;
199
+ case A_EVENTQ_PROD:
200
+ s->eventq.prod = data;
201
+ return MEMTX_OK;
202
+ case A_EVENTQ_CONS:
203
+ s->eventq.cons = data;
204
+ return MEMTX_OK;
205
+ case A_EVENTQ_IRQ_CFG0: /* 64b */
206
+ s->eventq_irq_cfg0 = deposit64(s->eventq_irq_cfg0, 0, 32, data);
207
+ return MEMTX_OK;
208
+ case A_EVENTQ_IRQ_CFG0 + 4:
209
+ s->eventq_irq_cfg0 = deposit64(s->eventq_irq_cfg0, 32, 32, data);
210
+ return MEMTX_OK;
211
+ case A_EVENTQ_IRQ_CFG1:
212
+ s->eventq_irq_cfg1 = data;
213
+ return MEMTX_OK;
214
+ case A_EVENTQ_IRQ_CFG2:
215
+ s->eventq_irq_cfg2 = data;
216
+ return MEMTX_OK;
217
+ default:
218
+ qemu_log_mask(LOG_UNIMP,
219
+ "%s Unexpected 32-bit access to 0x%"PRIx64" (WI)\n",
220
+ __func__, offset);
221
+ return MEMTX_OK;
222
+ }
223
+}
224
+
225
static MemTxResult smmu_write_mmio(void *opaque, hwaddr offset, uint64_t data,
226
unsigned size, MemTxAttrs attrs)
227
{
228
- /* not yet implemented */
229
- return MEMTX_ERROR;
230
+ SMMUState *sys = opaque;
231
+ SMMUv3State *s = ARM_SMMUV3(sys);
232
+ MemTxResult r;
233
+
234
+ /* CONSTRAINED UNPREDICTABLE choice to have page0/1 be exact aliases */
235
+ offset &= ~0x10000;
236
+
237
+ switch (size) {
238
+ case 8:
239
+ r = smmu_writell(s, offset, data, attrs);
240
+ break;
241
+ case 4:
242
+ r = smmu_writel(s, offset, data, attrs);
243
+ break;
244
+ default:
245
+ r = MEMTX_ERROR;
246
+ break;
247
+ }
248
+
249
+ trace_smmuv3_write_mmio(offset, data, size, r);
250
+ return r;
251
}
252
253
static MemTxResult smmu_readll(SMMUv3State *s, hwaddr offset,
254
diff --git a/hw/arm/trace-events b/hw/arm/trace-events
255
index XXXXXXX..XXXXXXX 100644
256
--- a/hw/arm/trace-events
257
+++ b/hw/arm/trace-events
258
@@ -XXX,XX +XXX,XX @@ smmuv3_cmdq_consume(uint32_t prod, uint32_t cons, uint8_t prod_wrap, uint8_t con
259
smmuv3_cmdq_opcode(const char *opcode) "<--- %s"
260
smmuv3_cmdq_consume_out(uint32_t prod, uint32_t cons, uint8_t prod_wrap, uint8_t cons_wrap) "prod:%d, cons:%d, prod_wrap:%d, cons_wrap:%d "
261
smmuv3_cmdq_consume_error(const char *cmd_name, uint8_t cmd_error) "Error on %s command execution: %d"
262
+smmuv3_update(bool is_empty, uint32_t prod, uint32_t cons, uint8_t prod_wrap, uint8_t cons_wrap) "q empty:%d prod:%d cons:%d p.wrap:%d p.cons:%d"
263
+smmuv3_update_check_cmd(int error) "cmdq not enabled or error :0x%x"
264
+smmuv3_write_mmio(uint64_t addr, uint64_t val, unsigned size, uint32_t r) "addr: 0x%"PRIx64" val:0x%"PRIx64" size: 0x%x(%d)"
265
+smmuv3_write_mmio_idr(uint64_t addr, uint64_t val) "write to RO/Unimpl reg 0x%lx val64:0x%lx"
266
+smmuv3_write_mmio_evtq_cons_bef_clear(uint32_t prod, uint32_t cons, uint8_t prod_wrap, uint8_t cons_wrap) "Before clearing interrupt prod:0x%x cons:0x%x prod.w:%d cons.w:%d"
267
+smmuv3_write_mmio_evtq_cons_after_clear(uint32_t prod, uint32_t cons, uint8_t prod_wrap, uint8_t cons_wrap) "after clearing interrupt prod:0x%x cons:0x%x prod.w:%d cons.w:%d"
268
--
28
--
269
2.17.0
29
2.20.1
270
30
271
31
diff view generated by jsdifflib
1
From: Prem Mallappa <prem.mallappa@broadcom.com>
1
From: Vikram Garhwal <fnu.vikram@xilinx.com>
2
2
3
This patch implements a skeleton for the smmuv3 device.
3
The Xilinx ZynqMP CAN controller is developed based on SocketCAN, QEMU CAN bus
4
Datatypes and register definitions are introduced. The MMIO
4
implementation. Bus connection and socketCAN connection for each CAN module
5
region, the interrupts and the queue are initialized.
5
can be set through command lines.
6
6
7
Only the MMIO read operation is implemented here.
7
Example for using single CAN:
8
-object can-bus,id=canbus0 \
9
-machine xlnx-zcu102.canbus0=canbus0 \
10
-object can-host-socketcan,id=socketcan0,if=vcan0,canbus=canbus0
8
11
9
Signed-off-by: Prem Mallappa <prem.mallappa@broadcom.com>
12
Example for connecting both CAN to same virtual CAN on host machine:
10
Signed-off-by: Eric Auger <eric.auger@redhat.com>
13
-object can-bus,id=canbus0 -object can-bus,id=canbus1 \
14
-machine xlnx-zcu102.canbus0=canbus0 \
15
-machine xlnx-zcu102.canbus1=canbus1 \
16
-object can-host-socketcan,id=socketcan0,if=vcan0,canbus=canbus0 \
17
-object can-host-socketcan,id=socketcan1,if=vcan0,canbus=canbus1
18
19
To create virtual CAN on the host machine, please check the QEMU CAN docs:
20
https://github.com/qemu/qemu/blob/master/docs/can.txt
21
22
Signed-off-by: Vikram Garhwal <fnu.vikram@xilinx.com>
23
Message-id: 1605728926-352690-2-git-send-email-fnu.vikram@xilinx.com
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
24
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
Message-id: 1524665762-31355-5-git-send-email-eric.auger@redhat.com
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
25
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
26
---
15
hw/arm/Makefile.objs | 2 +-
27
meson.build | 1 +
16
hw/arm/smmuv3-internal.h | 142 +++++++++++++++
28
hw/net/can/trace.h | 1 +
17
include/hw/arm/smmuv3.h | 87 ++++++++++
29
include/hw/net/xlnx-zynqmp-can.h | 78 ++
18
hw/arm/smmuv3.c | 366 +++++++++++++++++++++++++++++++++++++++
30
hw/net/can/xlnx-zynqmp-can.c | 1161 ++++++++++++++++++++++++++++++
19
hw/arm/trace-events | 3 +
31
hw/Kconfig | 1 +
20
5 files changed, 599 insertions(+), 1 deletion(-)
32
hw/net/can/meson.build | 1 +
21
create mode 100644 hw/arm/smmuv3-internal.h
33
hw/net/can/trace-events | 9 +
22
create mode 100644 include/hw/arm/smmuv3.h
34
7 files changed, 1252 insertions(+)
23
create mode 100644 hw/arm/smmuv3.c
35
create mode 100644 hw/net/can/trace.h
36
create mode 100644 include/hw/net/xlnx-zynqmp-can.h
37
create mode 100644 hw/net/can/xlnx-zynqmp-can.c
38
create mode 100644 hw/net/can/trace-events
24
39
25
diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
40
diff --git a/meson.build b/meson.build
26
index XXXXXXX..XXXXXXX 100644
41
index XXXXXXX..XXXXXXX 100644
27
--- a/hw/arm/Makefile.objs
42
--- a/meson.build
28
+++ b/hw/arm/Makefile.objs
43
+++ b/meson.build
29
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_MPS2) += mps2-tz.o
44
@@ -XXX,XX +XXX,XX @@ if have_system
30
obj-$(CONFIG_MSF2) += msf2-soc.o msf2-som.o
45
'hw/misc',
31
obj-$(CONFIG_IOTKIT) += iotkit.o
46
'hw/misc/macio',
32
obj-$(CONFIG_FSL_IMX7) += fsl-imx7.o mcimx7d-sabre.o
47
'hw/net',
33
-obj-$(CONFIG_ARM_SMMUV3) += smmu-common.o
48
+ 'hw/net/can',
34
+obj-$(CONFIG_ARM_SMMUV3) += smmu-common.o smmuv3.o
49
'hw/nvram',
35
diff --git a/hw/arm/smmuv3-internal.h b/hw/arm/smmuv3-internal.h
50
'hw/pci',
51
'hw/pci-host',
52
diff --git a/hw/net/can/trace.h b/hw/net/can/trace.h
36
new file mode 100644
53
new file mode 100644
37
index XXXXXXX..XXXXXXX
54
index XXXXXXX..XXXXXXX
38
--- /dev/null
55
--- /dev/null
39
+++ b/hw/arm/smmuv3-internal.h
56
+++ b/hw/net/can/trace.h
40
@@ -XXX,XX +XXX,XX @@
57
@@ -0,0 +1 @@
41
+/*
58
+#include "trace/trace-hw_net_can.h"
42
+ * ARM SMMUv3 support - Internal API
59
diff --git a/include/hw/net/xlnx-zynqmp-can.h b/include/hw/net/xlnx-zynqmp-can.h
43
+ *
44
+ * Copyright (C) 2014-2016 Broadcom Corporation
45
+ * Copyright (c) 2017 Red Hat, Inc.
46
+ * Written by Prem Mallappa, Eric Auger
47
+ *
48
+ * This program is free software; you can redistribute it and/or modify
49
+ * it under the terms of the GNU General Public License version 2 as
50
+ * published by the Free Software Foundation.
51
+ *
52
+ * This program is distributed in the hope that it will be useful,
53
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
54
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
55
+ * GNU General Public License for more details.
56
+ *
57
+ * You should have received a copy of the GNU General Public License along
58
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
59
+ */
60
+
61
+#ifndef HW_ARM_SMMU_V3_INTERNAL_H
62
+#define HW_ARM_SMMU_V3_INTERNAL_H
63
+
64
+#include "hw/arm/smmu-common.h"
65
+
66
+/* MMIO Registers */
67
+
68
+REG32(IDR0, 0x0)
69
+ FIELD(IDR0, S1P, 1 , 1)
70
+ FIELD(IDR0, TTF, 2 , 2)
71
+ FIELD(IDR0, COHACC, 4 , 1)
72
+ FIELD(IDR0, ASID16, 12, 1)
73
+ FIELD(IDR0, TTENDIAN, 21, 2)
74
+ FIELD(IDR0, STALL_MODEL, 24, 2)
75
+ FIELD(IDR0, TERM_MODEL, 26, 1)
76
+ FIELD(IDR0, STLEVEL, 27, 2)
77
+
78
+REG32(IDR1, 0x4)
79
+ FIELD(IDR1, SIDSIZE, 0 , 6)
80
+ FIELD(IDR1, EVENTQS, 16, 5)
81
+ FIELD(IDR1, CMDQS, 21, 5)
82
+
83
+#define SMMU_IDR1_SIDSIZE 16
84
+#define SMMU_CMDQS 19
85
+#define SMMU_EVENTQS 19
86
+
87
+REG32(IDR2, 0x8)
88
+REG32(IDR3, 0xc)
89
+REG32(IDR4, 0x10)
90
+REG32(IDR5, 0x14)
91
+ FIELD(IDR5, OAS, 0, 3);
92
+ FIELD(IDR5, GRAN4K, 4, 1);
93
+ FIELD(IDR5, GRAN16K, 5, 1);
94
+ FIELD(IDR5, GRAN64K, 6, 1);
95
+
96
+#define SMMU_IDR5_OAS 4
97
+
98
+REG32(IIDR, 0x1c)
99
+REG32(CR0, 0x20)
100
+ FIELD(CR0, SMMU_ENABLE, 0, 1)
101
+ FIELD(CR0, EVENTQEN, 2, 1)
102
+ FIELD(CR0, CMDQEN, 3, 1)
103
+
104
+REG32(CR0ACK, 0x24)
105
+REG32(CR1, 0x28)
106
+REG32(CR2, 0x2c)
107
+REG32(STATUSR, 0x40)
108
+REG32(IRQ_CTRL, 0x50)
109
+ FIELD(IRQ_CTRL, GERROR_IRQEN, 0, 1)
110
+ FIELD(IRQ_CTRL, PRI_IRQEN, 1, 1)
111
+ FIELD(IRQ_CTRL, EVENTQ_IRQEN, 2, 1)
112
+
113
+REG32(IRQ_CTRL_ACK, 0x54)
114
+REG32(GERROR, 0x60)
115
+ FIELD(GERROR, CMDQ_ERR, 0, 1)
116
+ FIELD(GERROR, EVENTQ_ABT_ERR, 2, 1)
117
+ FIELD(GERROR, PRIQ_ABT_ERR, 3, 1)
118
+ FIELD(GERROR, MSI_CMDQ_ABT_ERR, 4, 1)
119
+ FIELD(GERROR, MSI_EVENTQ_ABT_ERR, 5, 1)
120
+ FIELD(GERROR, MSI_PRIQ_ABT_ERR, 6, 1)
121
+ FIELD(GERROR, MSI_GERROR_ABT_ERR, 7, 1)
122
+ FIELD(GERROR, MSI_SFM_ERR, 8, 1)
123
+
124
+REG32(GERRORN, 0x64)
125
+
126
+#define A_GERROR_IRQ_CFG0 0x68 /* 64b */
127
+REG32(GERROR_IRQ_CFG1, 0x70)
128
+REG32(GERROR_IRQ_CFG2, 0x74)
129
+
130
+#define A_STRTAB_BASE 0x80 /* 64b */
131
+
132
+#define SMMU_BASE_ADDR_MASK 0xffffffffffe0
133
+
134
+REG32(STRTAB_BASE_CFG, 0x88)
135
+ FIELD(STRTAB_BASE_CFG, FMT, 16, 2)
136
+ FIELD(STRTAB_BASE_CFG, SPLIT, 6 , 5)
137
+ FIELD(STRTAB_BASE_CFG, LOG2SIZE, 0 , 6)
138
+
139
+#define A_CMDQ_BASE 0x90 /* 64b */
140
+REG32(CMDQ_PROD, 0x98)
141
+REG32(CMDQ_CONS, 0x9c)
142
+ FIELD(CMDQ_CONS, ERR, 24, 7)
143
+
144
+#define A_EVENTQ_BASE 0xa0 /* 64b */
145
+REG32(EVENTQ_PROD, 0xa8)
146
+REG32(EVENTQ_CONS, 0xac)
147
+
148
+#define A_EVENTQ_IRQ_CFG0 0xb0 /* 64b */
149
+REG32(EVENTQ_IRQ_CFG1, 0xb8)
150
+REG32(EVENTQ_IRQ_CFG2, 0xbc)
151
+
152
+#define A_IDREGS 0xfd0
153
+
154
+static inline int smmu_enabled(SMMUv3State *s)
155
+{
156
+ return FIELD_EX32(s->cr[0], CR0, SMMU_ENABLE);
157
+}
158
+
159
+/* Command Queue Entry */
160
+typedef struct Cmd {
161
+ uint32_t word[4];
162
+} Cmd;
163
+
164
+/* Event Queue Entry */
165
+typedef struct Evt {
166
+ uint32_t word[8];
167
+} Evt;
168
+
169
+static inline uint32_t smmuv3_idreg(int regoffset)
170
+{
171
+ /*
172
+ * Return the value of the Primecell/Corelink ID registers at the
173
+ * specified offset from the first ID register.
174
+ * These value indicate an ARM implementation of MMU600 p1
175
+ */
176
+ static const uint8_t smmuv3_ids[] = {
177
+ 0x04, 0, 0, 0, 0x84, 0xB4, 0xF0, 0x10, 0x0D, 0xF0, 0x05, 0xB1
178
+ };
179
+ return smmuv3_ids[regoffset / 4];
180
+}
181
+
182
+#endif
183
diff --git a/include/hw/arm/smmuv3.h b/include/hw/arm/smmuv3.h
184
new file mode 100644
60
new file mode 100644
185
index XXXXXXX..XXXXXXX
61
index XXXXXXX..XXXXXXX
186
--- /dev/null
62
--- /dev/null
187
+++ b/include/hw/arm/smmuv3.h
63
+++ b/include/hw/net/xlnx-zynqmp-can.h
188
@@ -XXX,XX +XXX,XX @@
64
@@ -XXX,XX +XXX,XX @@
189
+/*
65
+/*
190
+ * Copyright (C) 2014-2016 Broadcom Corporation
66
+ * QEMU model of the Xilinx ZynqMP CAN controller.
191
+ * Copyright (c) 2017 Red Hat, Inc.
192
+ * Written by Prem Mallappa, Eric Auger
193
+ *
67
+ *
194
+ * This program is free software; you can redistribute it and/or modify
68
+ * Copyright (c) 2020 Xilinx Inc.
195
+ * it under the terms of the GNU General Public License version 2 as
196
+ * published by the Free Software Foundation.
197
+ *
69
+ *
198
+ * This program is distributed in the hope that it will be useful,
70
+ * Written-by: Vikram Garhwal<fnu.vikram@xilinx.com>
199
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
200
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
201
+ * GNU General Public License for more details.
202
+ *
71
+ *
203
+ * You should have received a copy of the GNU General Public License along
72
+ * Based on QEMU CAN Device emulation implemented by Jin Yang, Deniz Eren and
204
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
73
+ * Pavel Pisa.
74
+ *
75
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
76
+ * of this software and associated documentation files (the "Software"), to deal
77
+ * in the Software without restriction, including without limitation the rights
78
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
79
+ * copies of the Software, and to permit persons to whom the Software is
80
+ * furnished to do so, subject to the following conditions:
81
+ *
82
+ * The above copyright notice and this permission notice shall be included in
83
+ * all copies or substantial portions of the Software.
84
+ *
85
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
86
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
87
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
88
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
89
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
90
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
91
+ * THE SOFTWARE.
205
+ */
92
+ */
206
+
93
+
207
+#ifndef HW_ARM_SMMUV3_H
94
+#ifndef XLNX_ZYNQMP_CAN_H
208
+#define HW_ARM_SMMUV3_H
95
+#define XLNX_ZYNQMP_CAN_H
209
+
96
+
210
+#include "hw/arm/smmu-common.h"
97
+#include "hw/register.h"
211
+#include "hw/registerfields.h"
98
+#include "net/can_emu.h"
212
+
99
+#include "net/can_host.h"
213
+#define TYPE_SMMUV3_IOMMU_MEMORY_REGION "smmuv3-iommu-memory-region"
100
+#include "qemu/fifo32.h"
214
+
101
+#include "hw/ptimer.h"
215
+typedef struct SMMUQueue {
102
+#include "hw/qdev-clock.h"
216
+ uint64_t base; /* base register */
103
+
217
+ uint32_t prod;
104
+#define TYPE_XLNX_ZYNQMP_CAN "xlnx.zynqmp-can"
218
+ uint32_t cons;
105
+
219
+ uint8_t entry_size;
106
+#define XLNX_ZYNQMP_CAN(obj) \
220
+ uint8_t log2size;
107
+ OBJECT_CHECK(XlnxZynqMPCANState, (obj), TYPE_XLNX_ZYNQMP_CAN)
221
+} SMMUQueue;
108
+
222
+
109
+#define MAX_CAN_CTRLS 2
223
+typedef struct SMMUv3State {
110
+#define XLNX_ZYNQMP_CAN_R_MAX (0x84 / 4)
224
+ SMMUState smmu_state;
111
+#define MAILBOX_CAPACITY 64
225
+
112
+#define CAN_TIMER_MAX 0XFFFFUL
226
+ uint32_t features;
113
+#define CAN_DEFAULT_CLOCK (24 * 1000 * 1000)
227
+ uint8_t sid_size;
114
+
228
+ uint8_t sid_split;
115
+/* Each CAN_FRAME will have 4 * 32bit size. */
229
+
116
+#define CAN_FRAME_SIZE 4
230
+ uint32_t idr[6];
117
+#define RXFIFO_SIZE (MAILBOX_CAPACITY * CAN_FRAME_SIZE)
231
+ uint32_t iidr;
118
+
232
+ uint32_t cr[3];
119
+typedef struct XlnxZynqMPCANState {
233
+ uint32_t cr0ack;
120
+ SysBusDevice parent_obj;
234
+ uint32_t statusr;
121
+ MemoryRegion iomem;
235
+ uint32_t irq_ctrl;
122
+
236
+ uint32_t gerror;
123
+ qemu_irq irq;
237
+ uint32_t gerrorn;
124
+
238
+ uint64_t gerror_irq_cfg0;
125
+ CanBusClientState bus_client;
239
+ uint32_t gerror_irq_cfg1;
126
+ CanBusState *canbus;
240
+ uint32_t gerror_irq_cfg2;
127
+
241
+ uint64_t strtab_base;
128
+ struct {
242
+ uint32_t strtab_base_cfg;
129
+ uint32_t ext_clk_freq;
243
+ uint64_t eventq_irq_cfg0;
130
+ } cfg;
244
+ uint32_t eventq_irq_cfg1;
131
+
245
+ uint32_t eventq_irq_cfg2;
132
+ RegisterInfo reg_info[XLNX_ZYNQMP_CAN_R_MAX];
246
+
133
+ uint32_t regs[XLNX_ZYNQMP_CAN_R_MAX];
247
+ SMMUQueue eventq, cmdq;
134
+
248
+
135
+ Fifo32 rx_fifo;
249
+ qemu_irq irq[4];
136
+ Fifo32 tx_fifo;
250
+} SMMUv3State;
137
+ Fifo32 txhpb_fifo;
251
+
138
+
252
+typedef enum {
139
+ ptimer_state *can_timer;
253
+ SMMU_IRQ_EVTQ,
140
+} XlnxZynqMPCANState;
254
+ SMMU_IRQ_PRIQ,
255
+ SMMU_IRQ_CMD_SYNC,
256
+ SMMU_IRQ_GERROR,
257
+} SMMUIrq;
258
+
259
+typedef struct {
260
+ /*< private >*/
261
+ SMMUBaseClass smmu_base_class;
262
+ /*< public >*/
263
+
264
+ DeviceRealize parent_realize;
265
+ DeviceReset parent_reset;
266
+} SMMUv3Class;
267
+
268
+#define TYPE_ARM_SMMUV3 "arm-smmuv3"
269
+#define ARM_SMMUV3(obj) OBJECT_CHECK(SMMUv3State, (obj), TYPE_ARM_SMMUV3)
270
+#define ARM_SMMUV3_CLASS(klass) \
271
+ OBJECT_CLASS_CHECK(SMMUv3Class, (klass), TYPE_ARM_SMMUV3)
272
+#define ARM_SMMUV3_GET_CLASS(obj) \
273
+ OBJECT_GET_CLASS(SMMUv3Class, (obj), TYPE_ARM_SMMUV3)
274
+
141
+
275
+#endif
142
+#endif
276
diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c
143
diff --git a/hw/net/can/xlnx-zynqmp-can.c b/hw/net/can/xlnx-zynqmp-can.c
277
new file mode 100644
144
new file mode 100644
278
index XXXXXXX..XXXXXXX
145
index XXXXXXX..XXXXXXX
279
--- /dev/null
146
--- /dev/null
280
+++ b/hw/arm/smmuv3.c
147
+++ b/hw/net/can/xlnx-zynqmp-can.c
281
@@ -XXX,XX +XXX,XX @@
148
@@ -XXX,XX +XXX,XX @@
282
+/*
149
+/*
283
+ * Copyright (C) 2014-2016 Broadcom Corporation
150
+ * QEMU model of the Xilinx ZynqMP CAN controller.
284
+ * Copyright (c) 2017 Red Hat, Inc.
151
+ * This implementation is based on the following datasheet:
285
+ * Written by Prem Mallappa, Eric Auger
152
+ * https://www.xilinx.com/support/documentation/user_guides/ug1085-zynq-ultrascale-trm.pdf
286
+ *
153
+ *
287
+ * This program is free software; you can redistribute it and/or modify
154
+ * Copyright (c) 2020 Xilinx Inc.
288
+ * it under the terms of the GNU General Public License version 2 as
289
+ * published by the Free Software Foundation.
290
+ *
155
+ *
291
+ * This program is distributed in the hope that it will be useful,
156
+ * Written-by: Vikram Garhwal<fnu.vikram@xilinx.com>
292
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
293
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
294
+ * GNU General Public License for more details.
295
+ *
157
+ *
296
+ * You should have received a copy of the GNU General Public License along
158
+ * Based on QEMU CAN Device emulation implemented by Jin Yang, Deniz Eren and
297
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
159
+ * Pavel Pisa
160
+ *
161
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
162
+ * of this software and associated documentation files (the "Software"), to deal
163
+ * in the Software without restriction, including without limitation the rights
164
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
165
+ * copies of the Software, and to permit persons to whom the Software is
166
+ * furnished to do so, subject to the following conditions:
167
+ *
168
+ * The above copyright notice and this permission notice shall be included in
169
+ * all copies or substantial portions of the Software.
170
+ *
171
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
172
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
173
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
174
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
175
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
176
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
177
+ * THE SOFTWARE.
298
+ */
178
+ */
299
+
179
+
300
+#include "qemu/osdep.h"
180
+#include "qemu/osdep.h"
301
+#include "hw/boards.h"
181
+#include "hw/sysbus.h"
182
+#include "hw/register.h"
183
+#include "hw/irq.h"
184
+#include "qapi/error.h"
185
+#include "qemu/bitops.h"
186
+#include "qemu/log.h"
187
+#include "qemu/cutils.h"
302
+#include "sysemu/sysemu.h"
188
+#include "sysemu/sysemu.h"
303
+#include "hw/sysbus.h"
189
+#include "migration/vmstate.h"
304
+#include "hw/qdev-core.h"
190
+#include "hw/qdev-properties.h"
305
+#include "hw/pci/pci.h"
191
+#include "net/can_emu.h"
306
+#include "exec/address-spaces.h"
192
+#include "net/can_host.h"
193
+#include "qemu/event_notifier.h"
194
+#include "qom/object_interfaces.h"
195
+#include "hw/net/xlnx-zynqmp-can.h"
307
+#include "trace.h"
196
+#include "trace.h"
308
+#include "qemu/log.h"
197
+
309
+#include "qemu/error-report.h"
198
+#ifndef XLNX_ZYNQMP_CAN_ERR_DEBUG
310
+#include "qapi/error.h"
199
+#define XLNX_ZYNQMP_CAN_ERR_DEBUG 0
311
+
200
+#endif
312
+#include "hw/arm/smmuv3.h"
201
+
313
+#include "smmuv3-internal.h"
202
+#define MAX_DLC 8
314
+
203
+#undef ERROR
315
+static void smmuv3_init_regs(SMMUv3State *s)
204
+
316
+{
205
+REG32(SOFTWARE_RESET_REGISTER, 0x0)
317
+ /**
206
+ FIELD(SOFTWARE_RESET_REGISTER, CEN, 1, 1)
318
+ * IDR0: stage1 only, AArch64 only, coherent access, 16b ASID,
207
+ FIELD(SOFTWARE_RESET_REGISTER, SRST, 0, 1)
319
+ * multi-level stream table
208
+REG32(MODE_SELECT_REGISTER, 0x4)
209
+ FIELD(MODE_SELECT_REGISTER, SNOOP, 2, 1)
210
+ FIELD(MODE_SELECT_REGISTER, LBACK, 1, 1)
211
+ FIELD(MODE_SELECT_REGISTER, SLEEP, 0, 1)
212
+REG32(ARBITRATION_PHASE_BAUD_RATE_PRESCALER_REGISTER, 0x8)
213
+ FIELD(ARBITRATION_PHASE_BAUD_RATE_PRESCALER_REGISTER, BRP, 0, 8)
214
+REG32(ARBITRATION_PHASE_BIT_TIMING_REGISTER, 0xc)
215
+ FIELD(ARBITRATION_PHASE_BIT_TIMING_REGISTER, SJW, 7, 2)
216
+ FIELD(ARBITRATION_PHASE_BIT_TIMING_REGISTER, TS2, 4, 3)
217
+ FIELD(ARBITRATION_PHASE_BIT_TIMING_REGISTER, TS1, 0, 4)
218
+REG32(ERROR_COUNTER_REGISTER, 0x10)
219
+ FIELD(ERROR_COUNTER_REGISTER, REC, 8, 8)
220
+ FIELD(ERROR_COUNTER_REGISTER, TEC, 0, 8)
221
+REG32(ERROR_STATUS_REGISTER, 0x14)
222
+ FIELD(ERROR_STATUS_REGISTER, ACKER, 4, 1)
223
+ FIELD(ERROR_STATUS_REGISTER, BERR, 3, 1)
224
+ FIELD(ERROR_STATUS_REGISTER, STER, 2, 1)
225
+ FIELD(ERROR_STATUS_REGISTER, FMER, 1, 1)
226
+ FIELD(ERROR_STATUS_REGISTER, CRCER, 0, 1)
227
+REG32(STATUS_REGISTER, 0x18)
228
+ FIELD(STATUS_REGISTER, SNOOP, 12, 1)
229
+ FIELD(STATUS_REGISTER, ACFBSY, 11, 1)
230
+ FIELD(STATUS_REGISTER, TXFLL, 10, 1)
231
+ FIELD(STATUS_REGISTER, TXBFLL, 9, 1)
232
+ FIELD(STATUS_REGISTER, ESTAT, 7, 2)
233
+ FIELD(STATUS_REGISTER, ERRWRN, 6, 1)
234
+ FIELD(STATUS_REGISTER, BBSY, 5, 1)
235
+ FIELD(STATUS_REGISTER, BIDLE, 4, 1)
236
+ FIELD(STATUS_REGISTER, NORMAL, 3, 1)
237
+ FIELD(STATUS_REGISTER, SLEEP, 2, 1)
238
+ FIELD(STATUS_REGISTER, LBACK, 1, 1)
239
+ FIELD(STATUS_REGISTER, CONFIG, 0, 1)
240
+REG32(INTERRUPT_STATUS_REGISTER, 0x1c)
241
+ FIELD(INTERRUPT_STATUS_REGISTER, TXFEMP, 14, 1)
242
+ FIELD(INTERRUPT_STATUS_REGISTER, TXFWMEMP, 13, 1)
243
+ FIELD(INTERRUPT_STATUS_REGISTER, RXFWMFLL, 12, 1)
244
+ FIELD(INTERRUPT_STATUS_REGISTER, WKUP, 11, 1)
245
+ FIELD(INTERRUPT_STATUS_REGISTER, SLP, 10, 1)
246
+ FIELD(INTERRUPT_STATUS_REGISTER, BSOFF, 9, 1)
247
+ FIELD(INTERRUPT_STATUS_REGISTER, ERROR, 8, 1)
248
+ FIELD(INTERRUPT_STATUS_REGISTER, RXNEMP, 7, 1)
249
+ FIELD(INTERRUPT_STATUS_REGISTER, RXOFLW, 6, 1)
250
+ FIELD(INTERRUPT_STATUS_REGISTER, RXUFLW, 5, 1)
251
+ FIELD(INTERRUPT_STATUS_REGISTER, RXOK, 4, 1)
252
+ FIELD(INTERRUPT_STATUS_REGISTER, TXBFLL, 3, 1)
253
+ FIELD(INTERRUPT_STATUS_REGISTER, TXFLL, 2, 1)
254
+ FIELD(INTERRUPT_STATUS_REGISTER, TXOK, 1, 1)
255
+ FIELD(INTERRUPT_STATUS_REGISTER, ARBLST, 0, 1)
256
+REG32(INTERRUPT_ENABLE_REGISTER, 0x20)
257
+ FIELD(INTERRUPT_ENABLE_REGISTER, ETXFEMP, 14, 1)
258
+ FIELD(INTERRUPT_ENABLE_REGISTER, ETXFWMEMP, 13, 1)
259
+ FIELD(INTERRUPT_ENABLE_REGISTER, ERXFWMFLL, 12, 1)
260
+ FIELD(INTERRUPT_ENABLE_REGISTER, EWKUP, 11, 1)
261
+ FIELD(INTERRUPT_ENABLE_REGISTER, ESLP, 10, 1)
262
+ FIELD(INTERRUPT_ENABLE_REGISTER, EBSOFF, 9, 1)
263
+ FIELD(INTERRUPT_ENABLE_REGISTER, EERROR, 8, 1)
264
+ FIELD(INTERRUPT_ENABLE_REGISTER, ERXNEMP, 7, 1)
265
+ FIELD(INTERRUPT_ENABLE_REGISTER, ERXOFLW, 6, 1)
266
+ FIELD(INTERRUPT_ENABLE_REGISTER, ERXUFLW, 5, 1)
267
+ FIELD(INTERRUPT_ENABLE_REGISTER, ERXOK, 4, 1)
268
+ FIELD(INTERRUPT_ENABLE_REGISTER, ETXBFLL, 3, 1)
269
+ FIELD(INTERRUPT_ENABLE_REGISTER, ETXFLL, 2, 1)
270
+ FIELD(INTERRUPT_ENABLE_REGISTER, ETXOK, 1, 1)
271
+ FIELD(INTERRUPT_ENABLE_REGISTER, EARBLST, 0, 1)
272
+REG32(INTERRUPT_CLEAR_REGISTER, 0x24)
273
+ FIELD(INTERRUPT_CLEAR_REGISTER, CTXFEMP, 14, 1)
274
+ FIELD(INTERRUPT_CLEAR_REGISTER, CTXFWMEMP, 13, 1)
275
+ FIELD(INTERRUPT_CLEAR_REGISTER, CRXFWMFLL, 12, 1)
276
+ FIELD(INTERRUPT_CLEAR_REGISTER, CWKUP, 11, 1)
277
+ FIELD(INTERRUPT_CLEAR_REGISTER, CSLP, 10, 1)
278
+ FIELD(INTERRUPT_CLEAR_REGISTER, CBSOFF, 9, 1)
279
+ FIELD(INTERRUPT_CLEAR_REGISTER, CERROR, 8, 1)
280
+ FIELD(INTERRUPT_CLEAR_REGISTER, CRXNEMP, 7, 1)
281
+ FIELD(INTERRUPT_CLEAR_REGISTER, CRXOFLW, 6, 1)
282
+ FIELD(INTERRUPT_CLEAR_REGISTER, CRXUFLW, 5, 1)
283
+ FIELD(INTERRUPT_CLEAR_REGISTER, CRXOK, 4, 1)
284
+ FIELD(INTERRUPT_CLEAR_REGISTER, CTXBFLL, 3, 1)
285
+ FIELD(INTERRUPT_CLEAR_REGISTER, CTXFLL, 2, 1)
286
+ FIELD(INTERRUPT_CLEAR_REGISTER, CTXOK, 1, 1)
287
+ FIELD(INTERRUPT_CLEAR_REGISTER, CARBLST, 0, 1)
288
+REG32(TIMESTAMP_REGISTER, 0x28)
289
+ FIELD(TIMESTAMP_REGISTER, CTS, 0, 1)
290
+REG32(WIR, 0x2c)
291
+ FIELD(WIR, EW, 8, 8)
292
+ FIELD(WIR, FW, 0, 8)
293
+REG32(TXFIFO_ID, 0x30)
294
+ FIELD(TXFIFO_ID, IDH, 21, 11)
295
+ FIELD(TXFIFO_ID, SRRRTR, 20, 1)
296
+ FIELD(TXFIFO_ID, IDE, 19, 1)
297
+ FIELD(TXFIFO_ID, IDL, 1, 18)
298
+ FIELD(TXFIFO_ID, RTR, 0, 1)
299
+REG32(TXFIFO_DLC, 0x34)
300
+ FIELD(TXFIFO_DLC, DLC, 28, 4)
301
+REG32(TXFIFO_DATA1, 0x38)
302
+ FIELD(TXFIFO_DATA1, DB0, 24, 8)
303
+ FIELD(TXFIFO_DATA1, DB1, 16, 8)
304
+ FIELD(TXFIFO_DATA1, DB2, 8, 8)
305
+ FIELD(TXFIFO_DATA1, DB3, 0, 8)
306
+REG32(TXFIFO_DATA2, 0x3c)
307
+ FIELD(TXFIFO_DATA2, DB4, 24, 8)
308
+ FIELD(TXFIFO_DATA2, DB5, 16, 8)
309
+ FIELD(TXFIFO_DATA2, DB6, 8, 8)
310
+ FIELD(TXFIFO_DATA2, DB7, 0, 8)
311
+REG32(TXHPB_ID, 0x40)
312
+ FIELD(TXHPB_ID, IDH, 21, 11)
313
+ FIELD(TXHPB_ID, SRRRTR, 20, 1)
314
+ FIELD(TXHPB_ID, IDE, 19, 1)
315
+ FIELD(TXHPB_ID, IDL, 1, 18)
316
+ FIELD(TXHPB_ID, RTR, 0, 1)
317
+REG32(TXHPB_DLC, 0x44)
318
+ FIELD(TXHPB_DLC, DLC, 28, 4)
319
+REG32(TXHPB_DATA1, 0x48)
320
+ FIELD(TXHPB_DATA1, DB0, 24, 8)
321
+ FIELD(TXHPB_DATA1, DB1, 16, 8)
322
+ FIELD(TXHPB_DATA1, DB2, 8, 8)
323
+ FIELD(TXHPB_DATA1, DB3, 0, 8)
324
+REG32(TXHPB_DATA2, 0x4c)
325
+ FIELD(TXHPB_DATA2, DB4, 24, 8)
326
+ FIELD(TXHPB_DATA2, DB5, 16, 8)
327
+ FIELD(TXHPB_DATA2, DB6, 8, 8)
328
+ FIELD(TXHPB_DATA2, DB7, 0, 8)
329
+REG32(RXFIFO_ID, 0x50)
330
+ FIELD(RXFIFO_ID, IDH, 21, 11)
331
+ FIELD(RXFIFO_ID, SRRRTR, 20, 1)
332
+ FIELD(RXFIFO_ID, IDE, 19, 1)
333
+ FIELD(RXFIFO_ID, IDL, 1, 18)
334
+ FIELD(RXFIFO_ID, RTR, 0, 1)
335
+REG32(RXFIFO_DLC, 0x54)
336
+ FIELD(RXFIFO_DLC, DLC, 28, 4)
337
+ FIELD(RXFIFO_DLC, RXT, 0, 16)
338
+REG32(RXFIFO_DATA1, 0x58)
339
+ FIELD(RXFIFO_DATA1, DB0, 24, 8)
340
+ FIELD(RXFIFO_DATA1, DB1, 16, 8)
341
+ FIELD(RXFIFO_DATA1, DB2, 8, 8)
342
+ FIELD(RXFIFO_DATA1, DB3, 0, 8)
343
+REG32(RXFIFO_DATA2, 0x5c)
344
+ FIELD(RXFIFO_DATA2, DB4, 24, 8)
345
+ FIELD(RXFIFO_DATA2, DB5, 16, 8)
346
+ FIELD(RXFIFO_DATA2, DB6, 8, 8)
347
+ FIELD(RXFIFO_DATA2, DB7, 0, 8)
348
+REG32(AFR, 0x60)
349
+ FIELD(AFR, UAF4, 3, 1)
350
+ FIELD(AFR, UAF3, 2, 1)
351
+ FIELD(AFR, UAF2, 1, 1)
352
+ FIELD(AFR, UAF1, 0, 1)
353
+REG32(AFMR1, 0x64)
354
+ FIELD(AFMR1, AMIDH, 21, 11)
355
+ FIELD(AFMR1, AMSRR, 20, 1)
356
+ FIELD(AFMR1, AMIDE, 19, 1)
357
+ FIELD(AFMR1, AMIDL, 1, 18)
358
+ FIELD(AFMR1, AMRTR, 0, 1)
359
+REG32(AFIR1, 0x68)
360
+ FIELD(AFIR1, AIIDH, 21, 11)
361
+ FIELD(AFIR1, AISRR, 20, 1)
362
+ FIELD(AFIR1, AIIDE, 19, 1)
363
+ FIELD(AFIR1, AIIDL, 1, 18)
364
+ FIELD(AFIR1, AIRTR, 0, 1)
365
+REG32(AFMR2, 0x6c)
366
+ FIELD(AFMR2, AMIDH, 21, 11)
367
+ FIELD(AFMR2, AMSRR, 20, 1)
368
+ FIELD(AFMR2, AMIDE, 19, 1)
369
+ FIELD(AFMR2, AMIDL, 1, 18)
370
+ FIELD(AFMR2, AMRTR, 0, 1)
371
+REG32(AFIR2, 0x70)
372
+ FIELD(AFIR2, AIIDH, 21, 11)
373
+ FIELD(AFIR2, AISRR, 20, 1)
374
+ FIELD(AFIR2, AIIDE, 19, 1)
375
+ FIELD(AFIR2, AIIDL, 1, 18)
376
+ FIELD(AFIR2, AIRTR, 0, 1)
377
+REG32(AFMR3, 0x74)
378
+ FIELD(AFMR3, AMIDH, 21, 11)
379
+ FIELD(AFMR3, AMSRR, 20, 1)
380
+ FIELD(AFMR3, AMIDE, 19, 1)
381
+ FIELD(AFMR3, AMIDL, 1, 18)
382
+ FIELD(AFMR3, AMRTR, 0, 1)
383
+REG32(AFIR3, 0x78)
384
+ FIELD(AFIR3, AIIDH, 21, 11)
385
+ FIELD(AFIR3, AISRR, 20, 1)
386
+ FIELD(AFIR3, AIIDE, 19, 1)
387
+ FIELD(AFIR3, AIIDL, 1, 18)
388
+ FIELD(AFIR3, AIRTR, 0, 1)
389
+REG32(AFMR4, 0x7c)
390
+ FIELD(AFMR4, AMIDH, 21, 11)
391
+ FIELD(AFMR4, AMSRR, 20, 1)
392
+ FIELD(AFMR4, AMIDE, 19, 1)
393
+ FIELD(AFMR4, AMIDL, 1, 18)
394
+ FIELD(AFMR4, AMRTR, 0, 1)
395
+REG32(AFIR4, 0x80)
396
+ FIELD(AFIR4, AIIDH, 21, 11)
397
+ FIELD(AFIR4, AISRR, 20, 1)
398
+ FIELD(AFIR4, AIIDE, 19, 1)
399
+ FIELD(AFIR4, AIIDL, 1, 18)
400
+ FIELD(AFIR4, AIRTR, 0, 1)
401
+
402
+static void can_update_irq(XlnxZynqMPCANState *s)
403
+{
404
+ uint32_t irq;
405
+
406
+ /* Watermark register interrupts. */
407
+ if ((fifo32_num_free(&s->tx_fifo) / CAN_FRAME_SIZE) >
408
+ ARRAY_FIELD_EX32(s->regs, WIR, EW)) {
409
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TXFWMEMP, 1);
410
+ }
411
+
412
+ if ((fifo32_num_used(&s->rx_fifo) / CAN_FRAME_SIZE) >
413
+ ARRAY_FIELD_EX32(s->regs, WIR, FW)) {
414
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXFWMFLL, 1);
415
+ }
416
+
417
+ /* RX Interrupts. */
418
+ if (fifo32_num_used(&s->rx_fifo) >= CAN_FRAME_SIZE) {
419
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXNEMP, 1);
420
+ }
421
+
422
+ /* TX interrupts. */
423
+ if (fifo32_is_empty(&s->tx_fifo)) {
424
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TXFEMP, 1);
425
+ }
426
+
427
+ if (fifo32_is_full(&s->tx_fifo)) {
428
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TXFLL, 1);
429
+ }
430
+
431
+ if (fifo32_is_full(&s->txhpb_fifo)) {
432
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TXBFLL, 1);
433
+ }
434
+
435
+ irq = s->regs[R_INTERRUPT_STATUS_REGISTER];
436
+ irq &= s->regs[R_INTERRUPT_ENABLE_REGISTER];
437
+
438
+ trace_xlnx_can_update_irq(s->regs[R_INTERRUPT_STATUS_REGISTER],
439
+ s->regs[R_INTERRUPT_ENABLE_REGISTER], irq);
440
+ qemu_set_irq(s->irq, irq);
441
+}
442
+
443
+static void can_ier_post_write(RegisterInfo *reg, uint64_t val)
444
+{
445
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
446
+
447
+ can_update_irq(s);
448
+}
449
+
450
+static uint64_t can_icr_pre_write(RegisterInfo *reg, uint64_t val)
451
+{
452
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
453
+
454
+ s->regs[R_INTERRUPT_STATUS_REGISTER] &= ~val;
455
+ can_update_irq(s);
456
+
457
+ return 0;
458
+}
459
+
460
+static void can_config_reset(XlnxZynqMPCANState *s)
461
+{
462
+ /* Reset all the configuration registers. */
463
+ register_reset(&s->reg_info[R_SOFTWARE_RESET_REGISTER]);
464
+ register_reset(&s->reg_info[R_MODE_SELECT_REGISTER]);
465
+ register_reset(
466
+ &s->reg_info[R_ARBITRATION_PHASE_BAUD_RATE_PRESCALER_REGISTER]);
467
+ register_reset(&s->reg_info[R_ARBITRATION_PHASE_BIT_TIMING_REGISTER]);
468
+ register_reset(&s->reg_info[R_STATUS_REGISTER]);
469
+ register_reset(&s->reg_info[R_INTERRUPT_STATUS_REGISTER]);
470
+ register_reset(&s->reg_info[R_INTERRUPT_ENABLE_REGISTER]);
471
+ register_reset(&s->reg_info[R_INTERRUPT_CLEAR_REGISTER]);
472
+ register_reset(&s->reg_info[R_WIR]);
473
+}
474
+
475
+static void can_config_mode(XlnxZynqMPCANState *s)
476
+{
477
+ register_reset(&s->reg_info[R_ERROR_COUNTER_REGISTER]);
478
+ register_reset(&s->reg_info[R_ERROR_STATUS_REGISTER]);
479
+
480
+ /* Put XlnxZynqMPCAN in configuration mode. */
481
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, CONFIG, 1);
482
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, WKUP, 0);
483
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, SLP, 0);
484
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, BSOFF, 0);
485
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, ERROR, 0);
486
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXOFLW, 0);
487
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXOK, 0);
488
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TXOK, 0);
489
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, ARBLST, 0);
490
+
491
+ can_update_irq(s);
492
+}
493
+
494
+static void update_status_register_mode_bits(XlnxZynqMPCANState *s)
495
+{
496
+ bool sleep_status = ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, SLEEP);
497
+ bool sleep_mode = ARRAY_FIELD_EX32(s->regs, MODE_SELECT_REGISTER, SLEEP);
498
+ /* Wake up interrupt bit. */
499
+ bool wakeup_irq_val = sleep_status && (sleep_mode == 0);
500
+ /* Sleep interrupt bit. */
501
+ bool sleep_irq_val = sleep_mode && (sleep_status == 0);
502
+
503
+ /* Clear previous core mode status bits. */
504
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, LBACK, 0);
505
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, SLEEP, 0);
506
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, SNOOP, 0);
507
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, NORMAL, 0);
508
+
509
+ /* set current mode bit and generate irqs accordingly. */
510
+ if (ARRAY_FIELD_EX32(s->regs, MODE_SELECT_REGISTER, LBACK)) {
511
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, LBACK, 1);
512
+ } else if (ARRAY_FIELD_EX32(s->regs, MODE_SELECT_REGISTER, SLEEP)) {
513
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, SLEEP, 1);
514
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, SLP,
515
+ sleep_irq_val);
516
+ } else if (ARRAY_FIELD_EX32(s->regs, MODE_SELECT_REGISTER, SNOOP)) {
517
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, SNOOP, 1);
518
+ } else {
519
+ /*
520
+ * If all bits are zero then XlnxZynqMPCAN is set in normal mode.
521
+ */
522
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, NORMAL, 1);
523
+ /* Set wakeup interrupt bit. */
524
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, WKUP,
525
+ wakeup_irq_val);
526
+ }
527
+
528
+ can_update_irq(s);
529
+}
530
+
531
+static void can_exit_sleep_mode(XlnxZynqMPCANState *s)
532
+{
533
+ ARRAY_FIELD_DP32(s->regs, MODE_SELECT_REGISTER, SLEEP, 0);
534
+ update_status_register_mode_bits(s);
535
+}
536
+
537
+static void generate_frame(qemu_can_frame *frame, uint32_t *data)
538
+{
539
+ frame->can_id = data[0];
540
+ frame->can_dlc = FIELD_EX32(data[1], TXFIFO_DLC, DLC);
541
+
542
+ frame->data[0] = FIELD_EX32(data[2], TXFIFO_DATA1, DB3);
543
+ frame->data[1] = FIELD_EX32(data[2], TXFIFO_DATA1, DB2);
544
+ frame->data[2] = FIELD_EX32(data[2], TXFIFO_DATA1, DB1);
545
+ frame->data[3] = FIELD_EX32(data[2], TXFIFO_DATA1, DB0);
546
+
547
+ frame->data[4] = FIELD_EX32(data[3], TXFIFO_DATA2, DB7);
548
+ frame->data[5] = FIELD_EX32(data[3], TXFIFO_DATA2, DB6);
549
+ frame->data[6] = FIELD_EX32(data[3], TXFIFO_DATA2, DB5);
550
+ frame->data[7] = FIELD_EX32(data[3], TXFIFO_DATA2, DB4);
551
+}
552
+
553
+static bool tx_ready_check(XlnxZynqMPCANState *s)
554
+{
555
+ if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, SRST)) {
556
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
557
+
558
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Attempting to transfer data while"
559
+ " data while controller is in reset mode.\n",
560
+ path);
561
+ return false;
562
+ }
563
+
564
+ if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN) == 0) {
565
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
566
+
567
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Attempting to transfer"
568
+ " data while controller is in configuration mode. Reset"
569
+ " the core so operations can start fresh.\n",
570
+ path);
571
+ return false;
572
+ }
573
+
574
+ if (ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, SNOOP)) {
575
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
576
+
577
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Attempting to transfer"
578
+ " data while controller is in SNOOP MODE.\n",
579
+ path);
580
+ return false;
581
+ }
582
+
583
+ return true;
584
+}
585
+
586
+static void transfer_fifo(XlnxZynqMPCANState *s, Fifo32 *fifo)
587
+{
588
+ qemu_can_frame frame;
589
+ uint32_t data[CAN_FRAME_SIZE];
590
+ int i;
591
+ bool can_tx = tx_ready_check(s);
592
+
593
+ if (!can_tx) {
594
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
595
+
596
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Controller is not enabled for data"
597
+ " transfer.\n", path);
598
+ can_update_irq(s);
599
+ return;
600
+ }
601
+
602
+ while (!fifo32_is_empty(fifo)) {
603
+ for (i = 0; i < CAN_FRAME_SIZE; i++) {
604
+ data[i] = fifo32_pop(fifo);
605
+ }
606
+
607
+ if (ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, LBACK)) {
608
+ /*
609
+ * Controller is in loopback. In Loopback mode, the CAN core
610
+ * transmits a recessive bitstream on to the XlnxZynqMPCAN Bus.
611
+ * Any message transmitted is looped back to the RX line and
612
+ * acknowledged. The XlnxZynqMPCAN core receives any message
613
+ * that it transmits.
614
+ */
615
+ if (fifo32_is_full(&s->rx_fifo)) {
616
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXOFLW, 1);
617
+ } else {
618
+ for (i = 0; i < CAN_FRAME_SIZE; i++) {
619
+ fifo32_push(&s->rx_fifo, data[i]);
620
+ }
621
+
622
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXOK, 1);
623
+ }
624
+ } else {
625
+ /* Normal mode Tx. */
626
+ generate_frame(&frame, data);
627
+
628
+ trace_xlnx_can_tx_data(frame.can_id, frame.can_dlc,
629
+ frame.data[0], frame.data[1],
630
+ frame.data[2], frame.data[3],
631
+ frame.data[4], frame.data[5],
632
+ frame.data[6], frame.data[7]);
633
+ can_bus_client_send(&s->bus_client, &frame, 1);
634
+ }
635
+ }
636
+
637
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TXOK, 1);
638
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, TXBFLL, 0);
639
+
640
+ if (ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, SLEEP)) {
641
+ can_exit_sleep_mode(s);
642
+ }
643
+
644
+ can_update_irq(s);
645
+}
646
+
647
+static uint64_t can_srr_pre_write(RegisterInfo *reg, uint64_t val)
648
+{
649
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
650
+
651
+ ARRAY_FIELD_DP32(s->regs, SOFTWARE_RESET_REGISTER, CEN,
652
+ FIELD_EX32(val, SOFTWARE_RESET_REGISTER, CEN));
653
+
654
+ if (FIELD_EX32(val, SOFTWARE_RESET_REGISTER, SRST)) {
655
+ trace_xlnx_can_reset(val);
656
+
657
+ /* First, core will do software reset then will enter in config mode. */
658
+ can_config_reset(s);
659
+ }
660
+
661
+ if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN) == 0) {
662
+ can_config_mode(s);
663
+ } else {
664
+ /*
665
+ * Leave config mode. Now XlnxZynqMPCAN core will enter normal,
666
+ * sleep, snoop or loopback mode depending upon LBACK, SLEEP, SNOOP
667
+ * register states.
668
+ */
669
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, CONFIG, 0);
670
+
671
+ ptimer_transaction_begin(s->can_timer);
672
+ ptimer_set_count(s->can_timer, 0);
673
+ ptimer_transaction_commit(s->can_timer);
674
+
675
+ /* XlnxZynqMPCAN is out of config mode. It will send pending data. */
676
+ transfer_fifo(s, &s->txhpb_fifo);
677
+ transfer_fifo(s, &s->tx_fifo);
678
+ }
679
+
680
+ update_status_register_mode_bits(s);
681
+
682
+ return s->regs[R_SOFTWARE_RESET_REGISTER];
683
+}
684
+
685
+static uint64_t can_msr_pre_write(RegisterInfo *reg, uint64_t val)
686
+{
687
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
688
+ uint8_t multi_mode;
689
+
690
+ /*
691
+ * Multiple mode set check. This is done to make sure user doesn't set
692
+ * multiple modes.
320
+ */
693
+ */
321
+ s->idr[0] = FIELD_DP32(s->idr[0], IDR0, S1P, 1); /* stage 1 supported */
694
+ multi_mode = FIELD_EX32(val, MODE_SELECT_REGISTER, LBACK) +
322
+ s->idr[0] = FIELD_DP32(s->idr[0], IDR0, TTF, 2); /* AArch64 PTW only */
695
+ FIELD_EX32(val, MODE_SELECT_REGISTER, SLEEP) +
323
+ s->idr[0] = FIELD_DP32(s->idr[0], IDR0, COHACC, 1); /* IO coherent */
696
+ FIELD_EX32(val, MODE_SELECT_REGISTER, SNOOP);
324
+ s->idr[0] = FIELD_DP32(s->idr[0], IDR0, ASID16, 1); /* 16-bit ASID */
697
+
325
+ s->idr[0] = FIELD_DP32(s->idr[0], IDR0, TTENDIAN, 2); /* little endian */
698
+ if (multi_mode > 1) {
326
+ s->idr[0] = FIELD_DP32(s->idr[0], IDR0, STALL_MODEL, 1); /* No stall */
699
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
327
+ /* terminated transaction will always be aborted/error returned */
700
+
328
+ s->idr[0] = FIELD_DP32(s->idr[0], IDR0, TERM_MODEL, 1);
701
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Attempting to config"
329
+ /* 2-level stream table supported */
702
+ " several modes simultaneously. One mode will be selected"
330
+ s->idr[0] = FIELD_DP32(s->idr[0], IDR0, STLEVEL, 1);
703
+ " according to their priority: LBACK > SLEEP > SNOOP.\n",
331
+
704
+ path);
332
+ s->idr[1] = FIELD_DP32(s->idr[1], IDR1, SIDSIZE, SMMU_IDR1_SIDSIZE);
705
+ }
333
+ s->idr[1] = FIELD_DP32(s->idr[1], IDR1, EVENTQS, SMMU_EVENTQS);
706
+
334
+ s->idr[1] = FIELD_DP32(s->idr[1], IDR1, CMDQS, SMMU_CMDQS);
707
+ if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN) == 0) {
335
+
708
+ /* We are in configuration mode, any mode can be selected. */
336
+ /* 4K and 64K granule support */
709
+ s->regs[R_MODE_SELECT_REGISTER] = val;
337
+ s->idr[5] = FIELD_DP32(s->idr[5], IDR5, GRAN4K, 1);
710
+ } else {
338
+ s->idr[5] = FIELD_DP32(s->idr[5], IDR5, GRAN64K, 1);
711
+ bool sleep_mode_bit = FIELD_EX32(val, MODE_SELECT_REGISTER, SLEEP);
339
+ s->idr[5] = FIELD_DP32(s->idr[5], IDR5, OAS, SMMU_IDR5_OAS); /* 44 bits */
712
+
340
+
713
+ ARRAY_FIELD_DP32(s->regs, MODE_SELECT_REGISTER, SLEEP, sleep_mode_bit);
341
+ s->cmdq.base = deposit64(s->cmdq.base, 0, 5, SMMU_CMDQS);
714
+
342
+ s->cmdq.prod = 0;
715
+ if (FIELD_EX32(val, MODE_SELECT_REGISTER, LBACK)) {
343
+ s->cmdq.cons = 0;
716
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
344
+ s->cmdq.entry_size = sizeof(struct Cmd);
717
+
345
+ s->eventq.base = deposit64(s->eventq.base, 0, 5, SMMU_EVENTQS);
718
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Attempting to set"
346
+ s->eventq.prod = 0;
719
+ " LBACK mode without setting CEN bit as 0.\n",
347
+ s->eventq.cons = 0;
720
+ path);
348
+ s->eventq.entry_size = sizeof(struct Evt);
721
+ } else if (FIELD_EX32(val, MODE_SELECT_REGISTER, SNOOP)) {
349
+
722
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
350
+ s->features = 0;
723
+
351
+ s->sid_split = 0;
724
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Attempting to set"
352
+}
725
+ " SNOOP mode without setting CEN bit as 0.\n",
353
+
726
+ path);
354
+static MemTxResult smmu_write_mmio(void *opaque, hwaddr offset, uint64_t data,
727
+ }
355
+ unsigned size, MemTxAttrs attrs)
728
+
356
+{
729
+ update_status_register_mode_bits(s);
357
+ /* not yet implemented */
730
+ }
358
+ return MEMTX_ERROR;
731
+
359
+}
732
+ return s->regs[R_MODE_SELECT_REGISTER];
360
+
733
+}
361
+static MemTxResult smmu_readll(SMMUv3State *s, hwaddr offset,
734
+
362
+ uint64_t *data, MemTxAttrs attrs)
735
+static uint64_t can_brpr_pre_write(RegisterInfo *reg, uint64_t val)
363
+{
736
+{
364
+ switch (offset) {
737
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
365
+ case A_GERROR_IRQ_CFG0:
738
+
366
+ *data = s->gerror_irq_cfg0;
739
+ /* Only allow writes when in config mode. */
367
+ return MEMTX_OK;
740
+ if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN)) {
368
+ case A_STRTAB_BASE:
741
+ return s->regs[R_ARBITRATION_PHASE_BAUD_RATE_PRESCALER_REGISTER];
369
+ *data = s->strtab_base;
742
+ }
370
+ return MEMTX_OK;
743
+
371
+ case A_CMDQ_BASE:
744
+ return val;
372
+ *data = s->cmdq.base;
745
+}
373
+ return MEMTX_OK;
746
+
374
+ case A_EVENTQ_BASE:
747
+static uint64_t can_btr_pre_write(RegisterInfo *reg, uint64_t val)
375
+ *data = s->eventq.base;
748
+{
376
+ return MEMTX_OK;
749
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
377
+ default:
750
+
378
+ *data = 0;
751
+ /* Only allow writes when in config mode. */
379
+ qemu_log_mask(LOG_UNIMP,
752
+ if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN)) {
380
+ "%s Unexpected 64-bit access to 0x%"PRIx64" (RAZ)\n",
753
+ return s->regs[R_ARBITRATION_PHASE_BIT_TIMING_REGISTER];
381
+ __func__, offset);
754
+ }
382
+ return MEMTX_OK;
755
+
383
+ }
756
+ return val;
384
+}
757
+}
385
+
758
+
386
+static MemTxResult smmu_readl(SMMUv3State *s, hwaddr offset,
759
+static uint64_t can_tcr_pre_write(RegisterInfo *reg, uint64_t val)
387
+ uint64_t *data, MemTxAttrs attrs)
760
+{
388
+{
761
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
389
+ switch (offset) {
762
+
390
+ case A_IDREGS ... A_IDREGS + 0x1f:
763
+ if (FIELD_EX32(val, TIMESTAMP_REGISTER, CTS)) {
391
+ *data = smmuv3_idreg(offset - A_IDREGS);
764
+ ptimer_transaction_begin(s->can_timer);
392
+ return MEMTX_OK;
765
+ ptimer_set_count(s->can_timer, 0);
393
+ case A_IDR0 ... A_IDR5:
766
+ ptimer_transaction_commit(s->can_timer);
394
+ *data = s->idr[(offset - A_IDR0) / 4];
767
+ }
395
+ return MEMTX_OK;
768
+
396
+ case A_IIDR:
769
+ return 0;
397
+ *data = s->iidr;
770
+}
398
+ return MEMTX_OK;
771
+
399
+ case A_CR0:
772
+static void update_rx_fifo(XlnxZynqMPCANState *s, const qemu_can_frame *frame)
400
+ *data = s->cr[0];
773
+{
401
+ return MEMTX_OK;
774
+ bool filter_pass = false;
402
+ case A_CR0ACK:
775
+ uint16_t timestamp = 0;
403
+ *data = s->cr0ack;
776
+
404
+ return MEMTX_OK;
777
+ /* If no filter is enabled. Message will be stored in FIFO. */
405
+ case A_CR1:
778
+ if (!((ARRAY_FIELD_EX32(s->regs, AFR, UAF1)) |
406
+ *data = s->cr[1];
779
+ (ARRAY_FIELD_EX32(s->regs, AFR, UAF2)) |
407
+ return MEMTX_OK;
780
+ (ARRAY_FIELD_EX32(s->regs, AFR, UAF3)) |
408
+ case A_CR2:
781
+ (ARRAY_FIELD_EX32(s->regs, AFR, UAF4)))) {
409
+ *data = s->cr[2];
782
+ filter_pass = true;
410
+ return MEMTX_OK;
783
+ }
411
+ case A_STATUSR:
784
+
412
+ *data = s->statusr;
785
+ /*
413
+ return MEMTX_OK;
786
+ * Messages that pass any of the acceptance filters will be stored in
414
+ case A_IRQ_CTRL:
787
+ * the RX FIFO.
415
+ case A_IRQ_CTRL_ACK:
788
+ */
416
+ *data = s->irq_ctrl;
789
+ if (ARRAY_FIELD_EX32(s->regs, AFR, UAF1)) {
417
+ return MEMTX_OK;
790
+ uint32_t id_masked = s->regs[R_AFMR1] & frame->can_id;
418
+ case A_GERROR:
791
+ uint32_t filter_id_masked = s->regs[R_AFMR1] & s->regs[R_AFIR1];
419
+ *data = s->gerror;
792
+
420
+ return MEMTX_OK;
793
+ if (filter_id_masked == id_masked) {
421
+ case A_GERRORN:
794
+ filter_pass = true;
422
+ *data = s->gerrorn;
795
+ }
423
+ return MEMTX_OK;
796
+ }
424
+ case A_GERROR_IRQ_CFG0: /* 64b */
797
+
425
+ *data = extract64(s->gerror_irq_cfg0, 0, 32);
798
+ if (ARRAY_FIELD_EX32(s->regs, AFR, UAF2)) {
426
+ return MEMTX_OK;
799
+ uint32_t id_masked = s->regs[R_AFMR2] & frame->can_id;
427
+ case A_GERROR_IRQ_CFG0 + 4:
800
+ uint32_t filter_id_masked = s->regs[R_AFMR2] & s->regs[R_AFIR2];
428
+ *data = extract64(s->gerror_irq_cfg0, 32, 32);
801
+
429
+ return MEMTX_OK;
802
+ if (filter_id_masked == id_masked) {
430
+ case A_GERROR_IRQ_CFG1:
803
+ filter_pass = true;
431
+ *data = s->gerror_irq_cfg1;
804
+ }
432
+ return MEMTX_OK;
805
+ }
433
+ case A_GERROR_IRQ_CFG2:
806
+
434
+ *data = s->gerror_irq_cfg2;
807
+ if (ARRAY_FIELD_EX32(s->regs, AFR, UAF3)) {
435
+ return MEMTX_OK;
808
+ uint32_t id_masked = s->regs[R_AFMR3] & frame->can_id;
436
+ case A_STRTAB_BASE: /* 64b */
809
+ uint32_t filter_id_masked = s->regs[R_AFMR3] & s->regs[R_AFIR3];
437
+ *data = extract64(s->strtab_base, 0, 32);
810
+
438
+ return MEMTX_OK;
811
+ if (filter_id_masked == id_masked) {
439
+ case A_STRTAB_BASE + 4: /* 64b */
812
+ filter_pass = true;
440
+ *data = extract64(s->strtab_base, 32, 32);
813
+ }
441
+ return MEMTX_OK;
814
+ }
442
+ case A_STRTAB_BASE_CFG:
815
+
443
+ *data = s->strtab_base_cfg;
816
+ if (ARRAY_FIELD_EX32(s->regs, AFR, UAF4)) {
444
+ return MEMTX_OK;
817
+ uint32_t id_masked = s->regs[R_AFMR4] & frame->can_id;
445
+ case A_CMDQ_BASE: /* 64b */
818
+ uint32_t filter_id_masked = s->regs[R_AFMR4] & s->regs[R_AFIR4];
446
+ *data = extract64(s->cmdq.base, 0, 32);
819
+
447
+ return MEMTX_OK;
820
+ if (filter_id_masked == id_masked) {
448
+ case A_CMDQ_BASE + 4:
821
+ filter_pass = true;
449
+ *data = extract64(s->cmdq.base, 32, 32);
822
+ }
450
+ return MEMTX_OK;
823
+ }
451
+ case A_CMDQ_PROD:
824
+
452
+ *data = s->cmdq.prod;
825
+ if (!filter_pass) {
453
+ return MEMTX_OK;
826
+ trace_xlnx_can_rx_fifo_filter_reject(frame->can_id, frame->can_dlc);
454
+ case A_CMDQ_CONS:
827
+ return;
455
+ *data = s->cmdq.cons;
828
+ }
456
+ return MEMTX_OK;
829
+
457
+ case A_EVENTQ_BASE: /* 64b */
830
+ /* Store the message in fifo if it passed through any of the filters. */
458
+ *data = extract64(s->eventq.base, 0, 32);
831
+ if (filter_pass && frame->can_dlc <= MAX_DLC) {
459
+ return MEMTX_OK;
832
+
460
+ case A_EVENTQ_BASE + 4: /* 64b */
833
+ if (fifo32_is_full(&s->rx_fifo)) {
461
+ *data = extract64(s->eventq.base, 32, 32);
834
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXOFLW, 1);
462
+ return MEMTX_OK;
835
+ } else {
463
+ case A_EVENTQ_PROD:
836
+ timestamp = CAN_TIMER_MAX - ptimer_get_count(s->can_timer);
464
+ *data = s->eventq.prod;
837
+
465
+ return MEMTX_OK;
838
+ fifo32_push(&s->rx_fifo, frame->can_id);
466
+ case A_EVENTQ_CONS:
839
+
467
+ *data = s->eventq.cons;
840
+ fifo32_push(&s->rx_fifo, deposit32(0, R_RXFIFO_DLC_DLC_SHIFT,
468
+ return MEMTX_OK;
841
+ R_RXFIFO_DLC_DLC_LENGTH,
469
+ default:
842
+ frame->can_dlc) |
470
+ *data = 0;
843
+ deposit32(0, R_RXFIFO_DLC_RXT_SHIFT,
471
+ qemu_log_mask(LOG_UNIMP,
844
+ R_RXFIFO_DLC_RXT_LENGTH,
472
+ "%s unhandled 32-bit access at 0x%"PRIx64" (RAZ)\n",
845
+ timestamp));
473
+ __func__, offset);
846
+
474
+ return MEMTX_OK;
847
+ /* First 32 bit of the data. */
475
+ }
848
+ fifo32_push(&s->rx_fifo, deposit32(0, R_TXFIFO_DATA1_DB3_SHIFT,
476
+}
849
+ R_TXFIFO_DATA1_DB3_LENGTH,
477
+
850
+ frame->data[0]) |
478
+static MemTxResult smmu_read_mmio(void *opaque, hwaddr offset, uint64_t *data,
851
+ deposit32(0, R_TXFIFO_DATA1_DB2_SHIFT,
479
+ unsigned size, MemTxAttrs attrs)
852
+ R_TXFIFO_DATA1_DB2_LENGTH,
480
+{
853
+ frame->data[1]) |
481
+ SMMUState *sys = opaque;
854
+ deposit32(0, R_TXFIFO_DATA1_DB1_SHIFT,
482
+ SMMUv3State *s = ARM_SMMUV3(sys);
855
+ R_TXFIFO_DATA1_DB1_LENGTH,
483
+ MemTxResult r;
856
+ frame->data[2]) |
484
+
857
+ deposit32(0, R_TXFIFO_DATA1_DB0_SHIFT,
485
+ /* CONSTRAINED UNPREDICTABLE choice to have page0/1 be exact aliases */
858
+ R_TXFIFO_DATA1_DB0_LENGTH,
486
+ offset &= ~0x10000;
859
+ frame->data[3]));
487
+
860
+ /* Last 32 bit of the data. */
488
+ switch (size) {
861
+ fifo32_push(&s->rx_fifo, deposit32(0, R_TXFIFO_DATA2_DB7_SHIFT,
489
+ case 8:
862
+ R_TXFIFO_DATA2_DB7_LENGTH,
490
+ r = smmu_readll(s, offset, data, attrs);
863
+ frame->data[4]) |
491
+ break;
864
+ deposit32(0, R_TXFIFO_DATA2_DB6_SHIFT,
492
+ case 4:
865
+ R_TXFIFO_DATA2_DB6_LENGTH,
493
+ r = smmu_readl(s, offset, data, attrs);
866
+ frame->data[5]) |
494
+ break;
867
+ deposit32(0, R_TXFIFO_DATA2_DB5_SHIFT,
495
+ default:
868
+ R_TXFIFO_DATA2_DB5_LENGTH,
496
+ r = MEMTX_ERROR;
869
+ frame->data[6]) |
497
+ break;
870
+ deposit32(0, R_TXFIFO_DATA2_DB4_SHIFT,
498
+ }
871
+ R_TXFIFO_DATA2_DB4_LENGTH,
499
+
872
+ frame->data[7]));
500
+ trace_smmuv3_read_mmio(offset, *data, size, r);
873
+
501
+ return r;
874
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXOK, 1);
502
+}
875
+ trace_xlnx_can_rx_data(frame->can_id, frame->can_dlc,
503
+
876
+ frame->data[0], frame->data[1],
504
+static const MemoryRegionOps smmu_mem_ops = {
877
+ frame->data[2], frame->data[3],
505
+ .read_with_attrs = smmu_read_mmio,
878
+ frame->data[4], frame->data[5],
506
+ .write_with_attrs = smmu_write_mmio,
879
+ frame->data[6], frame->data[7]);
880
+ }
881
+
882
+ can_update_irq(s);
883
+ }
884
+}
885
+
886
+static uint64_t can_rxfifo_pre_read(RegisterInfo *reg, uint64_t val)
887
+{
888
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
889
+
890
+ if (!fifo32_is_empty(&s->rx_fifo)) {
891
+ val = fifo32_pop(&s->rx_fifo);
892
+ } else {
893
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXUFLW, 1);
894
+ }
895
+
896
+ can_update_irq(s);
897
+ return val;
898
+}
899
+
900
+static void can_filter_enable_post_write(RegisterInfo *reg, uint64_t val)
901
+{
902
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
903
+
904
+ if (ARRAY_FIELD_EX32(s->regs, AFR, UAF1) &&
905
+ ARRAY_FIELD_EX32(s->regs, AFR, UAF2) &&
906
+ ARRAY_FIELD_EX32(s->regs, AFR, UAF3) &&
907
+ ARRAY_FIELD_EX32(s->regs, AFR, UAF4)) {
908
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, ACFBSY, 1);
909
+ } else {
910
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, ACFBSY, 0);
911
+ }
912
+}
913
+
914
+static uint64_t can_filter_mask_pre_write(RegisterInfo *reg, uint64_t val)
915
+{
916
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
917
+ uint32_t reg_idx = (reg->access->addr) / 4;
918
+ uint32_t filter_number = (reg_idx - R_AFMR1) / 2;
919
+
920
+ /* modify an acceptance filter, the corresponding UAF bit should be '0'. */
921
+ if (!(s->regs[R_AFR] & (1 << filter_number))) {
922
+ s->regs[reg_idx] = val;
923
+
924
+ trace_xlnx_can_filter_mask_pre_write(filter_number, s->regs[reg_idx]);
925
+ } else {
926
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
927
+
928
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Acceptance filter %d"
929
+ " mask is not set as corresponding UAF bit is not 0.\n",
930
+ path, filter_number + 1);
931
+ }
932
+
933
+ return s->regs[reg_idx];
934
+}
935
+
936
+static uint64_t can_filter_id_pre_write(RegisterInfo *reg, uint64_t val)
937
+{
938
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
939
+ uint32_t reg_idx = (reg->access->addr) / 4;
940
+ uint32_t filter_number = (reg_idx - R_AFIR1) / 2;
941
+
942
+ if (!(s->regs[R_AFR] & (1 << filter_number))) {
943
+ s->regs[reg_idx] = val;
944
+
945
+ trace_xlnx_can_filter_id_pre_write(filter_number, s->regs[reg_idx]);
946
+ } else {
947
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
948
+
949
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Acceptance filter %d"
950
+ " id is not set as corresponding UAF bit is not 0.\n",
951
+ path, filter_number + 1);
952
+ }
953
+
954
+ return s->regs[reg_idx];
955
+}
956
+
957
+static void can_tx_post_write(RegisterInfo *reg, uint64_t val)
958
+{
959
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
960
+
961
+ bool is_txhpb = reg->access->addr > A_TXFIFO_DATA2;
962
+
963
+ bool initiate_transfer = (reg->access->addr == A_TXFIFO_DATA2) ||
964
+ (reg->access->addr == A_TXHPB_DATA2);
965
+
966
+ Fifo32 *f = is_txhpb ? &s->txhpb_fifo : &s->tx_fifo;
967
+
968
+ if (!fifo32_is_full(f)) {
969
+ fifo32_push(f, val);
970
+ } else {
971
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
972
+
973
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: TX FIFO is full.\n", path);
974
+ }
975
+
976
+ /* Initiate the message send if TX register is written. */
977
+ if (initiate_transfer &&
978
+ ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN)) {
979
+ transfer_fifo(s, f);
980
+ }
981
+
982
+ can_update_irq(s);
983
+}
984
+
985
+static const RegisterAccessInfo can_regs_info[] = {
986
+ { .name = "SOFTWARE_RESET_REGISTER",
987
+ .addr = A_SOFTWARE_RESET_REGISTER,
988
+ .rsvd = 0xfffffffc,
989
+ .pre_write = can_srr_pre_write,
990
+ },{ .name = "MODE_SELECT_REGISTER",
991
+ .addr = A_MODE_SELECT_REGISTER,
992
+ .rsvd = 0xfffffff8,
993
+ .pre_write = can_msr_pre_write,
994
+ },{ .name = "ARBITRATION_PHASE_BAUD_RATE_PRESCALER_REGISTER",
995
+ .addr = A_ARBITRATION_PHASE_BAUD_RATE_PRESCALER_REGISTER,
996
+ .rsvd = 0xffffff00,
997
+ .pre_write = can_brpr_pre_write,
998
+ },{ .name = "ARBITRATION_PHASE_BIT_TIMING_REGISTER",
999
+ .addr = A_ARBITRATION_PHASE_BIT_TIMING_REGISTER,
1000
+ .rsvd = 0xfffffe00,
1001
+ .pre_write = can_btr_pre_write,
1002
+ },{ .name = "ERROR_COUNTER_REGISTER",
1003
+ .addr = A_ERROR_COUNTER_REGISTER,
1004
+ .rsvd = 0xffff0000,
1005
+ .ro = 0xffffffff,
1006
+ },{ .name = "ERROR_STATUS_REGISTER",
1007
+ .addr = A_ERROR_STATUS_REGISTER,
1008
+ .rsvd = 0xffffffe0,
1009
+ .w1c = 0x1f,
1010
+ },{ .name = "STATUS_REGISTER", .addr = A_STATUS_REGISTER,
1011
+ .reset = 0x1,
1012
+ .rsvd = 0xffffe000,
1013
+ .ro = 0x1fff,
1014
+ },{ .name = "INTERRUPT_STATUS_REGISTER",
1015
+ .addr = A_INTERRUPT_STATUS_REGISTER,
1016
+ .reset = 0x6000,
1017
+ .rsvd = 0xffff8000,
1018
+ .ro = 0x7fff,
1019
+ },{ .name = "INTERRUPT_ENABLE_REGISTER",
1020
+ .addr = A_INTERRUPT_ENABLE_REGISTER,
1021
+ .rsvd = 0xffff8000,
1022
+ .post_write = can_ier_post_write,
1023
+ },{ .name = "INTERRUPT_CLEAR_REGISTER",
1024
+ .addr = A_INTERRUPT_CLEAR_REGISTER,
1025
+ .rsvd = 0xffff8000,
1026
+ .pre_write = can_icr_pre_write,
1027
+ },{ .name = "TIMESTAMP_REGISTER",
1028
+ .addr = A_TIMESTAMP_REGISTER,
1029
+ .rsvd = 0xfffffffe,
1030
+ .pre_write = can_tcr_pre_write,
1031
+ },{ .name = "WIR", .addr = A_WIR,
1032
+ .reset = 0x3f3f,
1033
+ .rsvd = 0xffff0000,
1034
+ },{ .name = "TXFIFO_ID", .addr = A_TXFIFO_ID,
1035
+ .post_write = can_tx_post_write,
1036
+ },{ .name = "TXFIFO_DLC", .addr = A_TXFIFO_DLC,
1037
+ .rsvd = 0xfffffff,
1038
+ .post_write = can_tx_post_write,
1039
+ },{ .name = "TXFIFO_DATA1", .addr = A_TXFIFO_DATA1,
1040
+ .post_write = can_tx_post_write,
1041
+ },{ .name = "TXFIFO_DATA2", .addr = A_TXFIFO_DATA2,
1042
+ .post_write = can_tx_post_write,
1043
+ },{ .name = "TXHPB_ID", .addr = A_TXHPB_ID,
1044
+ .post_write = can_tx_post_write,
1045
+ },{ .name = "TXHPB_DLC", .addr = A_TXHPB_DLC,
1046
+ .rsvd = 0xfffffff,
1047
+ .post_write = can_tx_post_write,
1048
+ },{ .name = "TXHPB_DATA1", .addr = A_TXHPB_DATA1,
1049
+ .post_write = can_tx_post_write,
1050
+ },{ .name = "TXHPB_DATA2", .addr = A_TXHPB_DATA2,
1051
+ .post_write = can_tx_post_write,
1052
+ },{ .name = "RXFIFO_ID", .addr = A_RXFIFO_ID,
1053
+ .ro = 0xffffffff,
1054
+ .post_read = can_rxfifo_pre_read,
1055
+ },{ .name = "RXFIFO_DLC", .addr = A_RXFIFO_DLC,
1056
+ .rsvd = 0xfff0000,
1057
+ .post_read = can_rxfifo_pre_read,
1058
+ },{ .name = "RXFIFO_DATA1", .addr = A_RXFIFO_DATA1,
1059
+ .post_read = can_rxfifo_pre_read,
1060
+ },{ .name = "RXFIFO_DATA2", .addr = A_RXFIFO_DATA2,
1061
+ .post_read = can_rxfifo_pre_read,
1062
+ },{ .name = "AFR", .addr = A_AFR,
1063
+ .rsvd = 0xfffffff0,
1064
+ .post_write = can_filter_enable_post_write,
1065
+ },{ .name = "AFMR1", .addr = A_AFMR1,
1066
+ .pre_write = can_filter_mask_pre_write,
1067
+ },{ .name = "AFIR1", .addr = A_AFIR1,
1068
+ .pre_write = can_filter_id_pre_write,
1069
+ },{ .name = "AFMR2", .addr = A_AFMR2,
1070
+ .pre_write = can_filter_mask_pre_write,
1071
+ },{ .name = "AFIR2", .addr = A_AFIR2,
1072
+ .pre_write = can_filter_id_pre_write,
1073
+ },{ .name = "AFMR3", .addr = A_AFMR3,
1074
+ .pre_write = can_filter_mask_pre_write,
1075
+ },{ .name = "AFIR3", .addr = A_AFIR3,
1076
+ .pre_write = can_filter_id_pre_write,
1077
+ },{ .name = "AFMR4", .addr = A_AFMR4,
1078
+ .pre_write = can_filter_mask_pre_write,
1079
+ },{ .name = "AFIR4", .addr = A_AFIR4,
1080
+ .pre_write = can_filter_id_pre_write,
1081
+ }
1082
+};
1083
+
1084
+static void xlnx_zynqmp_can_ptimer_cb(void *opaque)
1085
+{
1086
+ /* No action required on the timer rollover. */
1087
+}
1088
+
1089
+static const MemoryRegionOps can_ops = {
1090
+ .read = register_read_memory,
1091
+ .write = register_write_memory,
507
+ .endianness = DEVICE_LITTLE_ENDIAN,
1092
+ .endianness = DEVICE_LITTLE_ENDIAN,
508
+ .valid = {
1093
+ .valid = {
509
+ .min_access_size = 4,
1094
+ .min_access_size = 4,
510
+ .max_access_size = 8,
1095
+ .max_access_size = 4,
511
+ },
512
+ .impl = {
513
+ .min_access_size = 4,
514
+ .max_access_size = 8,
515
+ },
1096
+ },
516
+};
1097
+};
517
+
1098
+
518
+static void smmu_init_irq(SMMUv3State *s, SysBusDevice *dev)
1099
+static void xlnx_zynqmp_can_reset_init(Object *obj, ResetType type)
519
+{
1100
+{
520
+ int i;
1101
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(obj);
521
+
1102
+ unsigned int i;
522
+ for (i = 0; i < ARRAY_SIZE(s->irq); i++) {
1103
+
523
+ sysbus_init_irq(dev, &s->irq[i]);
1104
+ for (i = R_RXFIFO_ID; i < ARRAY_SIZE(s->reg_info); ++i) {
524
+ }
1105
+ register_reset(&s->reg_info[i]);
525
+}
1106
+ }
526
+
1107
+
527
+static void smmu_reset(DeviceState *dev)
1108
+ ptimer_transaction_begin(s->can_timer);
528
+{
1109
+ ptimer_set_count(s->can_timer, 0);
529
+ SMMUv3State *s = ARM_SMMUV3(dev);
1110
+ ptimer_transaction_commit(s->can_timer);
530
+ SMMUv3Class *c = ARM_SMMUV3_GET_CLASS(s);
1111
+}
531
+
1112
+
532
+ c->parent_reset(dev);
1113
+static void xlnx_zynqmp_can_reset_hold(Object *obj)
533
+
1114
+{
534
+ smmuv3_init_regs(s);
1115
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(obj);
535
+}
1116
+ unsigned int i;
536
+
1117
+
537
+static void smmu_realize(DeviceState *d, Error **errp)
1118
+ for (i = 0; i < R_RXFIFO_ID; ++i) {
538
+{
1119
+ register_reset(&s->reg_info[i]);
539
+ SMMUState *sys = ARM_SMMU(d);
1120
+ }
540
+ SMMUv3State *s = ARM_SMMUV3(sys);
1121
+
541
+ SMMUv3Class *c = ARM_SMMUV3_GET_CLASS(s);
1122
+ /*
542
+ SysBusDevice *dev = SYS_BUS_DEVICE(d);
1123
+ * Reset FIFOs when CAN model is reset. This will clear the fifo writes
543
+ Error *local_err = NULL;
1124
+ * done by post_write which gets called from register_reset function,
544
+
1125
+ * post_write handle will not be able to trigger tx because CAN will be
545
+ c->parent_realize(d, &local_err);
1126
+ * disabled when software_reset_register is cleared first.
546
+ if (local_err) {
1127
+ */
547
+ error_propagate(errp, local_err);
1128
+ fifo32_reset(&s->rx_fifo);
548
+ return;
1129
+ fifo32_reset(&s->tx_fifo);
549
+ }
1130
+ fifo32_reset(&s->txhpb_fifo);
550
+
1131
+}
551
+ memory_region_init_io(&sys->iomem, OBJECT(s),
1132
+
552
+ &smmu_mem_ops, sys, TYPE_ARM_SMMUV3, 0x20000);
1133
+static bool xlnx_zynqmp_can_can_receive(CanBusClientState *client)
553
+
1134
+{
554
+ sys->mrtypename = TYPE_SMMUV3_IOMMU_MEMORY_REGION;
1135
+ XlnxZynqMPCANState *s = container_of(client, XlnxZynqMPCANState,
555
+
1136
+ bus_client);
556
+ sysbus_init_mmio(dev, &sys->iomem);
1137
+
557
+
1138
+ if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, SRST)) {
558
+ smmu_init_irq(s, dev);
1139
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
559
+}
1140
+
560
+
1141
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Controller is in reset state.\n",
561
+static const VMStateDescription vmstate_smmuv3_queue = {
1142
+ path);
562
+ .name = "smmuv3_queue",
1143
+ return false;
1144
+ }
1145
+
1146
+ if ((ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN)) == 0) {
1147
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
1148
+
1149
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Controller is disabled. Incoming"
1150
+ " messages will be discarded.\n", path);
1151
+ return false;
1152
+ }
1153
+
1154
+ return true;
1155
+}
1156
+
1157
+static ssize_t xlnx_zynqmp_can_receive(CanBusClientState *client,
1158
+ const qemu_can_frame *buf, size_t buf_size) {
1159
+ XlnxZynqMPCANState *s = container_of(client, XlnxZynqMPCANState,
1160
+ bus_client);
1161
+ const qemu_can_frame *frame = buf;
1162
+
1163
+ if (buf_size <= 0) {
1164
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
1165
+
1166
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Error in the data received.\n",
1167
+ path);
1168
+ return 0;
1169
+ }
1170
+
1171
+ if (ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, SNOOP)) {
1172
+ /* Snoop Mode: Just keep the data. no response back. */
1173
+ update_rx_fifo(s, frame);
1174
+ } else if ((ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, SLEEP))) {
1175
+ /*
1176
+ * XlnxZynqMPCAN is in sleep mode. Any data on bus will bring it to wake
1177
+ * up state.
1178
+ */
1179
+ can_exit_sleep_mode(s);
1180
+ update_rx_fifo(s, frame);
1181
+ } else if ((ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, SLEEP)) == 0) {
1182
+ update_rx_fifo(s, frame);
1183
+ } else {
1184
+ /*
1185
+ * XlnxZynqMPCAN will not participate in normal bus communication
1186
+ * and will not receive any messages transmitted by other CAN nodes.
1187
+ */
1188
+ trace_xlnx_can_rx_discard(s->regs[R_STATUS_REGISTER]);
1189
+ }
1190
+
1191
+ return 1;
1192
+}
1193
+
1194
+static CanBusClientInfo can_xilinx_bus_client_info = {
1195
+ .can_receive = xlnx_zynqmp_can_can_receive,
1196
+ .receive = xlnx_zynqmp_can_receive,
1197
+};
1198
+
1199
+static int xlnx_zynqmp_can_connect_to_bus(XlnxZynqMPCANState *s,
1200
+ CanBusState *bus)
1201
+{
1202
+ s->bus_client.info = &can_xilinx_bus_client_info;
1203
+
1204
+ if (can_bus_insert_client(bus, &s->bus_client) < 0) {
1205
+ return -1;
1206
+ }
1207
+ return 0;
1208
+}
1209
+
1210
+static void xlnx_zynqmp_can_realize(DeviceState *dev, Error **errp)
1211
+{
1212
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(dev);
1213
+
1214
+ if (s->canbus) {
1215
+ if (xlnx_zynqmp_can_connect_to_bus(s, s->canbus) < 0) {
1216
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
1217
+
1218
+ error_setg(errp, "%s: xlnx_zynqmp_can_connect_to_bus"
1219
+ " failed.", path);
1220
+ return;
1221
+ }
1222
+ }
1223
+
1224
+ /* Create RX FIFO, TXFIFO, TXHPB storage. */
1225
+ fifo32_create(&s->rx_fifo, RXFIFO_SIZE);
1226
+ fifo32_create(&s->tx_fifo, RXFIFO_SIZE);
1227
+ fifo32_create(&s->txhpb_fifo, CAN_FRAME_SIZE);
1228
+
1229
+ /* Allocate a new timer. */
1230
+ s->can_timer = ptimer_init(xlnx_zynqmp_can_ptimer_cb, s,
1231
+ PTIMER_POLICY_DEFAULT);
1232
+
1233
+ ptimer_transaction_begin(s->can_timer);
1234
+
1235
+ ptimer_set_freq(s->can_timer, s->cfg.ext_clk_freq);
1236
+ ptimer_set_limit(s->can_timer, CAN_TIMER_MAX, 1);
1237
+ ptimer_run(s->can_timer, 0);
1238
+ ptimer_transaction_commit(s->can_timer);
1239
+}
1240
+
1241
+static void xlnx_zynqmp_can_init(Object *obj)
1242
+{
1243
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(obj);
1244
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
1245
+
1246
+ RegisterInfoArray *reg_array;
1247
+
1248
+ memory_region_init(&s->iomem, obj, TYPE_XLNX_ZYNQMP_CAN,
1249
+ XLNX_ZYNQMP_CAN_R_MAX * 4);
1250
+ reg_array = register_init_block32(DEVICE(obj), can_regs_info,
1251
+ ARRAY_SIZE(can_regs_info),
1252
+ s->reg_info, s->regs,
1253
+ &can_ops,
1254
+ XLNX_ZYNQMP_CAN_ERR_DEBUG,
1255
+ XLNX_ZYNQMP_CAN_R_MAX * 4);
1256
+
1257
+ memory_region_add_subregion(&s->iomem, 0x00, &reg_array->mem);
1258
+ sysbus_init_mmio(sbd, &s->iomem);
1259
+ sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->irq);
1260
+}
1261
+
1262
+static const VMStateDescription vmstate_can = {
1263
+ .name = TYPE_XLNX_ZYNQMP_CAN,
563
+ .version_id = 1,
1264
+ .version_id = 1,
564
+ .minimum_version_id = 1,
1265
+ .minimum_version_id = 1,
565
+ .fields = (VMStateField[]) {
1266
+ .fields = (VMStateField[]) {
566
+ VMSTATE_UINT64(base, SMMUQueue),
1267
+ VMSTATE_FIFO32(rx_fifo, XlnxZynqMPCANState),
567
+ VMSTATE_UINT32(prod, SMMUQueue),
1268
+ VMSTATE_FIFO32(tx_fifo, XlnxZynqMPCANState),
568
+ VMSTATE_UINT32(cons, SMMUQueue),
1269
+ VMSTATE_FIFO32(txhpb_fifo, XlnxZynqMPCANState),
569
+ VMSTATE_UINT8(log2size, SMMUQueue),
1270
+ VMSTATE_UINT32_ARRAY(regs, XlnxZynqMPCANState, XLNX_ZYNQMP_CAN_R_MAX),
570
+ },
1271
+ VMSTATE_PTIMER(can_timer, XlnxZynqMPCANState),
1272
+ VMSTATE_END_OF_LIST(),
1273
+ }
571
+};
1274
+};
572
+
1275
+
573
+static const VMStateDescription vmstate_smmuv3 = {
1276
+static Property xlnx_zynqmp_can_properties[] = {
574
+ .name = "smmuv3",
1277
+ DEFINE_PROP_UINT32("ext_clk_freq", XlnxZynqMPCANState, cfg.ext_clk_freq,
575
+ .version_id = 1,
1278
+ CAN_DEFAULT_CLOCK),
576
+ .minimum_version_id = 1,
1279
+ DEFINE_PROP_LINK("canbus", XlnxZynqMPCANState, canbus, TYPE_CAN_BUS,
577
+ .fields = (VMStateField[]) {
1280
+ CanBusState *),
578
+ VMSTATE_UINT32(features, SMMUv3State),
1281
+ DEFINE_PROP_END_OF_LIST(),
579
+ VMSTATE_UINT8(sid_size, SMMUv3State),
580
+ VMSTATE_UINT8(sid_split, SMMUv3State),
581
+
582
+ VMSTATE_UINT32_ARRAY(cr, SMMUv3State, 3),
583
+ VMSTATE_UINT32(cr0ack, SMMUv3State),
584
+ VMSTATE_UINT32(statusr, SMMUv3State),
585
+ VMSTATE_UINT32(irq_ctrl, SMMUv3State),
586
+ VMSTATE_UINT32(gerror, SMMUv3State),
587
+ VMSTATE_UINT32(gerrorn, SMMUv3State),
588
+ VMSTATE_UINT64(gerror_irq_cfg0, SMMUv3State),
589
+ VMSTATE_UINT32(gerror_irq_cfg1, SMMUv3State),
590
+ VMSTATE_UINT32(gerror_irq_cfg2, SMMUv3State),
591
+ VMSTATE_UINT64(strtab_base, SMMUv3State),
592
+ VMSTATE_UINT32(strtab_base_cfg, SMMUv3State),
593
+ VMSTATE_UINT64(eventq_irq_cfg0, SMMUv3State),
594
+ VMSTATE_UINT32(eventq_irq_cfg1, SMMUv3State),
595
+ VMSTATE_UINT32(eventq_irq_cfg2, SMMUv3State),
596
+
597
+ VMSTATE_STRUCT(cmdq, SMMUv3State, 0, vmstate_smmuv3_queue, SMMUQueue),
598
+ VMSTATE_STRUCT(eventq, SMMUv3State, 0, vmstate_smmuv3_queue, SMMUQueue),
599
+
600
+ VMSTATE_END_OF_LIST(),
601
+ },
602
+};
1282
+};
603
+
1283
+
604
+static void smmuv3_instance_init(Object *obj)
1284
+static void xlnx_zynqmp_can_class_init(ObjectClass *klass, void *data)
605
+{
606
+ /* Nothing much to do here as of now */
607
+}
608
+
609
+static void smmuv3_class_init(ObjectClass *klass, void *data)
610
+{
1285
+{
611
+ DeviceClass *dc = DEVICE_CLASS(klass);
1286
+ DeviceClass *dc = DEVICE_CLASS(klass);
612
+ SMMUv3Class *c = ARM_SMMUV3_CLASS(klass);
1287
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
613
+
1288
+
614
+ dc->vmsd = &vmstate_smmuv3;
1289
+ rc->phases.enter = xlnx_zynqmp_can_reset_init;
615
+ device_class_set_parent_reset(dc, smmu_reset, &c->parent_reset);
1290
+ rc->phases.hold = xlnx_zynqmp_can_reset_hold;
616
+ c->parent_realize = dc->realize;
1291
+ dc->realize = xlnx_zynqmp_can_realize;
617
+ dc->realize = smmu_realize;
1292
+ device_class_set_props(dc, xlnx_zynqmp_can_properties);
618
+}
1293
+ dc->vmsd = &vmstate_can;
619
+
1294
+}
620
+static void smmuv3_iommu_memory_region_class_init(ObjectClass *klass,
1295
+
621
+ void *data)
1296
+static const TypeInfo can_info = {
622
+{
1297
+ .name = TYPE_XLNX_ZYNQMP_CAN,
623
+}
1298
+ .parent = TYPE_SYS_BUS_DEVICE,
624
+
1299
+ .instance_size = sizeof(XlnxZynqMPCANState),
625
+static const TypeInfo smmuv3_type_info = {
1300
+ .class_init = xlnx_zynqmp_can_class_init,
626
+ .name = TYPE_ARM_SMMUV3,
1301
+ .instance_init = xlnx_zynqmp_can_init,
627
+ .parent = TYPE_ARM_SMMU,
628
+ .instance_size = sizeof(SMMUv3State),
629
+ .instance_init = smmuv3_instance_init,
630
+ .class_size = sizeof(SMMUv3Class),
631
+ .class_init = smmuv3_class_init,
632
+};
1302
+};
633
+
1303
+
634
+static const TypeInfo smmuv3_iommu_memory_region_info = {
1304
+static void can_register_types(void)
635
+ .parent = TYPE_IOMMU_MEMORY_REGION,
1305
+{
636
+ .name = TYPE_SMMUV3_IOMMU_MEMORY_REGION,
1306
+ type_register_static(&can_info);
637
+ .class_init = smmuv3_iommu_memory_region_class_init,
1307
+}
638
+};
1308
+
639
+
1309
+type_init(can_register_types)
640
+static void smmuv3_register_types(void)
1310
diff --git a/hw/Kconfig b/hw/Kconfig
641
+{
642
+ type_register(&smmuv3_type_info);
643
+ type_register(&smmuv3_iommu_memory_region_info);
644
+}
645
+
646
+type_init(smmuv3_register_types)
647
+
648
diff --git a/hw/arm/trace-events b/hw/arm/trace-events
649
index XXXXXXX..XXXXXXX 100644
1311
index XXXXXXX..XXXXXXX 100644
650
--- a/hw/arm/trace-events
1312
--- a/hw/Kconfig
651
+++ b/hw/arm/trace-events
1313
+++ b/hw/Kconfig
652
@@ -XXX,XX +XXX,XX @@ smmu_ptw_invalid_pte(int stage, int level, uint64_t baseaddr, uint64_t pteaddr,
1314
@@ -XXX,XX +XXX,XX @@ config XILINX_AXI
653
smmu_ptw_page_pte(int stage, int level, uint64_t iova, uint64_t baseaddr, uint64_t pteaddr, uint64_t pte, uint64_t address) "stage=%d level=%d iova=0x%"PRIx64" base@=0x%"PRIx64" pte@=0x%"PRIx64" pte=0x%"PRIx64" page address = 0x%"PRIx64
1315
config XLNX_ZYNQMP
654
smmu_ptw_block_pte(int stage, int level, uint64_t baseaddr, uint64_t pteaddr, uint64_t pte, uint64_t iova, uint64_t gpa, int bsize_mb) "stage=%d level=%d base@=0x%"PRIx64" pte@=0x%"PRIx64" pte=0x%"PRIx64" iova=0x%"PRIx64" block address = 0x%"PRIx64" block size = %d MiB"
1316
bool
655
smmu_get_pte(uint64_t baseaddr, int index, uint64_t pteaddr, uint64_t pte) "baseaddr=0x%"PRIx64" index=0x%x, pteaddr=0x%"PRIx64", pte=0x%"PRIx64
1317
select REGISTER
656
+
1318
+ select CAN_BUS
657
+#hw/arm/smmuv3.c
1319
diff --git a/hw/net/can/meson.build b/hw/net/can/meson.build
658
+smmuv3_read_mmio(uint64_t addr, uint64_t val, unsigned size, uint32_t r) "addr: 0x%"PRIx64" val:0x%"PRIx64" size: 0x%x(%d)"
1320
index XXXXXXX..XXXXXXX 100644
1321
--- a/hw/net/can/meson.build
1322
+++ b/hw/net/can/meson.build
1323
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_CAN_PCI', if_true: files('can_pcm3680_pci.c'))
1324
softmmu_ss.add(when: 'CONFIG_CAN_PCI', if_true: files('can_mioe3680_pci.c'))
1325
softmmu_ss.add(when: 'CONFIG_CAN_CTUCANFD', if_true: files('ctucan_core.c'))
1326
softmmu_ss.add(when: 'CONFIG_CAN_CTUCANFD_PCI', if_true: files('ctucan_pci.c'))
1327
+softmmu_ss.add(when: 'CONFIG_XLNX_ZYNQMP', if_true: files('xlnx-zynqmp-can.c'))
1328
diff --git a/hw/net/can/trace-events b/hw/net/can/trace-events
1329
new file mode 100644
1330
index XXXXXXX..XXXXXXX
1331
--- /dev/null
1332
+++ b/hw/net/can/trace-events
1333
@@ -XXX,XX +XXX,XX @@
1334
+# xlnx-zynqmp-can.c
1335
+xlnx_can_update_irq(uint32_t isr, uint32_t ier, uint32_t irq) "ISR: 0x%08x IER: 0x%08x IRQ: 0x%08x"
1336
+xlnx_can_reset(uint32_t val) "Resetting controller with value = 0x%08x"
1337
+xlnx_can_rx_fifo_filter_reject(uint32_t id, uint8_t dlc) "Frame: ID: 0x%08x DLC: 0x%02x"
1338
+xlnx_can_filter_id_pre_write(uint8_t filter_num, uint32_t value) "Filter%d ID: 0x%08x"
1339
+xlnx_can_filter_mask_pre_write(uint8_t filter_num, uint32_t value) "Filter%d MASK: 0x%08x"
1340
+xlnx_can_tx_data(uint32_t id, uint8_t dlc, uint8_t db0, uint8_t db1, uint8_t db2, uint8_t db3, uint8_t db4, uint8_t db5, uint8_t db6, uint8_t db7) "Frame: ID: 0x%08x DLC: 0x%02x DATA: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x"
1341
+xlnx_can_rx_data(uint32_t id, uint32_t dlc, uint8_t db0, uint8_t db1, uint8_t db2, uint8_t db3, uint8_t db4, uint8_t db5, uint8_t db6, uint8_t db7) "Frame: ID: 0x%08x DLC: 0x%02x DATA: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x"
1342
+xlnx_can_rx_discard(uint32_t status) "Controller is not enabled for bus communication. Status Register: 0x%08x"
659
--
1343
--
660
2.17.0
1344
2.20.1
661
1345
662
1346
diff view generated by jsdifflib
1
From: Prem Mallappa <prem.mallappa@broadcom.com>
1
From: Vikram Garhwal <fnu.vikram@xilinx.com>
2
2
3
Add code to instantiate an smmuv3 in virt machine. A new iommu
3
Connect CAN0 and CAN1 on the ZynqMP.
4
integer member is introduced in VirtMachineState to store the type
5
of the iommu in use.
6
4
7
Signed-off-by: Prem Mallappa <prem.mallappa@broadcom.com>
5
Reviewed-by: Francisco Iglesias <francisco.iglesias@xilinx.com>
8
Signed-off-by: Eric Auger <eric.auger@redhat.com>
6
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Vikram Garhwal <fnu.vikram@xilinx.com>
10
Message-id: 1524665762-31355-13-git-send-email-eric.auger@redhat.com
8
Message-id: 1605728926-352690-3-git-send-email-fnu.vikram@xilinx.com
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
10
---
13
include/hw/arm/virt.h | 10 +++++++
11
include/hw/arm/xlnx-zynqmp.h | 8 ++++++++
14
hw/arm/virt.c | 64 ++++++++++++++++++++++++++++++++++++++++++-
12
hw/arm/xlnx-zcu102.c | 20 ++++++++++++++++++++
15
2 files changed, 73 insertions(+), 1 deletion(-)
13
hw/arm/xlnx-zynqmp.c | 34 ++++++++++++++++++++++++++++++++++
14
3 files changed, 62 insertions(+)
16
15
17
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
16
diff --git a/include/hw/arm/xlnx-zynqmp.h b/include/hw/arm/xlnx-zynqmp.h
18
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
19
--- a/include/hw/arm/virt.h
18
--- a/include/hw/arm/xlnx-zynqmp.h
20
+++ b/include/hw/arm/virt.h
19
+++ b/include/hw/arm/xlnx-zynqmp.h
21
@@ -XXX,XX +XXX,XX @@
20
@@ -XXX,XX +XXX,XX @@
22
21
#include "hw/intc/arm_gic.h"
23
#define NUM_GICV2M_SPIS 64
22
#include "hw/net/cadence_gem.h"
24
#define NUM_VIRTIO_TRANSPORTS 32
23
#include "hw/char/cadence_uart.h"
25
+#define NUM_SMMU_IRQS 4
24
+#include "hw/net/xlnx-zynqmp-can.h"
26
25
#include "hw/ide/ahci.h"
27
#define ARCH_GICV3_MAINT_IRQ 9
26
#include "hw/sd/sdhci.h"
28
27
#include "hw/ssi/xilinx_spips.h"
29
@@ -XXX,XX +XXX,XX @@ enum {
28
@@ -XXX,XX +XXX,XX @@
30
VIRT_GIC_V2M,
29
#include "hw/cpu/cluster.h"
31
VIRT_GIC_ITS,
30
#include "target/arm/cpu.h"
32
VIRT_GIC_REDIST,
31
#include "qom/object.h"
33
+ VIRT_SMMU,
32
+#include "net/can_emu.h"
34
VIRT_UART,
33
35
VIRT_MMIO,
34
#define TYPE_XLNX_ZYNQMP "xlnx,zynqmp"
36
VIRT_RTC,
35
OBJECT_DECLARE_SIMPLE_TYPE(XlnxZynqMPState, XLNX_ZYNQMP)
37
@@ -XXX,XX +XXX,XX @@ enum {
36
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_SIMPLE_TYPE(XlnxZynqMPState, XLNX_ZYNQMP)
38
VIRT_SECURE_MEM,
37
#define XLNX_ZYNQMP_NUM_RPU_CPUS 2
38
#define XLNX_ZYNQMP_NUM_GEMS 4
39
#define XLNX_ZYNQMP_NUM_UARTS 2
40
+#define XLNX_ZYNQMP_NUM_CAN 2
41
+#define XLNX_ZYNQMP_CAN_REF_CLK (24 * 1000 * 1000)
42
#define XLNX_ZYNQMP_NUM_SDHCI 2
43
#define XLNX_ZYNQMP_NUM_SPIS 2
44
#define XLNX_ZYNQMP_NUM_GDMA_CH 8
45
@@ -XXX,XX +XXX,XX @@ struct XlnxZynqMPState {
46
47
CadenceGEMState gem[XLNX_ZYNQMP_NUM_GEMS];
48
CadenceUARTState uart[XLNX_ZYNQMP_NUM_UARTS];
49
+ XlnxZynqMPCANState can[XLNX_ZYNQMP_NUM_CAN];
50
SysbusAHCIState sata;
51
SDHCIState sdhci[XLNX_ZYNQMP_NUM_SDHCI];
52
XilinxSPIPS spi[XLNX_ZYNQMP_NUM_SPIS];
53
@@ -XXX,XX +XXX,XX @@ struct XlnxZynqMPState {
54
bool virt;
55
/* Has the RPU subsystem? */
56
bool has_rpu;
57
+
58
+ /* CAN bus. */
59
+ CanBusState *canbus[XLNX_ZYNQMP_NUM_CAN];
39
};
60
};
40
61
41
+typedef enum VirtIOMMUType {
62
#endif
42
+ VIRT_IOMMU_NONE,
63
diff --git a/hw/arm/xlnx-zcu102.c b/hw/arm/xlnx-zcu102.c
43
+ VIRT_IOMMU_SMMUV3,
64
index XXXXXXX..XXXXXXX 100644
44
+ VIRT_IOMMU_VIRTIO,
65
--- a/hw/arm/xlnx-zcu102.c
45
+} VirtIOMMUType;
66
+++ b/hw/arm/xlnx-zcu102.c
67
@@ -XXX,XX +XXX,XX @@
68
#include "sysemu/qtest.h"
69
#include "sysemu/device_tree.h"
70
#include "qom/object.h"
71
+#include "net/can_emu.h"
72
73
struct XlnxZCU102 {
74
MachineState parent_obj;
75
@@ -XXX,XX +XXX,XX @@ struct XlnxZCU102 {
76
bool secure;
77
bool virt;
78
79
+ CanBusState *canbus[XLNX_ZYNQMP_NUM_CAN];
46
+
80
+
47
typedef struct MemMapEntry {
81
struct arm_boot_info binfo;
48
hwaddr base;
49
hwaddr size;
50
@@ -XXX,XX +XXX,XX @@ typedef struct {
51
bool its;
52
bool virt;
53
int32_t gic_version;
54
+ VirtIOMMUType iommu;
55
struct arm_boot_info bootinfo;
56
const MemMapEntry *memmap;
57
const int *irqmap;
58
@@ -XXX,XX +XXX,XX @@ typedef struct {
59
uint32_t clock_phandle;
60
uint32_t gic_phandle;
61
uint32_t msi_phandle;
62
+ uint32_t iommu_phandle;
63
int psci_conduit;
64
} VirtMachineState;
65
66
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
67
index XXXXXXX..XXXXXXX 100644
68
--- a/hw/arm/virt.c
69
+++ b/hw/arm/virt.c
70
@@ -XXX,XX +XXX,XX @@
71
#include "hw/smbios/smbios.h"
72
#include "qapi/visitor.h"
73
#include "standard-headers/linux/input.h"
74
+#include "hw/arm/smmuv3.h"
75
76
#define DEFINE_VIRT_MACHINE_LATEST(major, minor, latest) \
77
static void virt_##major##_##minor##_class_init(ObjectClass *oc, \
78
@@ -XXX,XX +XXX,XX @@ static const MemMapEntry a15memmap[] = {
79
[VIRT_FW_CFG] = { 0x09020000, 0x00000018 },
80
[VIRT_GPIO] = { 0x09030000, 0x00001000 },
81
[VIRT_SECURE_UART] = { 0x09040000, 0x00001000 },
82
+ [VIRT_SMMU] = { 0x09050000, 0x00020000 },
83
[VIRT_MMIO] = { 0x0a000000, 0x00000200 },
84
/* ...repeating for a total of NUM_VIRTIO_TRANSPORTS, each of that size */
85
[VIRT_PLATFORM_BUS] = { 0x0c000000, 0x02000000 },
86
@@ -XXX,XX +XXX,XX @@ static const int a15irqmap[] = {
87
[VIRT_SECURE_UART] = 8,
88
[VIRT_MMIO] = 16, /* ...to 16 + NUM_VIRTIO_TRANSPORTS - 1 */
89
[VIRT_GIC_V2M] = 48, /* ...to 48 + NUM_GICV2M_SPIS - 1 */
90
+ [VIRT_SMMU] = 74, /* ...to 74 + NUM_SMMU_IRQS - 1 */
91
[VIRT_PLATFORM_BUS] = 112, /* ...to 112 + PLATFORM_BUS_NUM_IRQS -1 */
92
};
82
};
93
83
94
@@ -XXX,XX +XXX,XX @@ static void create_pcie_irq_map(const VirtMachineState *vms,
84
@@ -XXX,XX +XXX,XX @@ static void xlnx_zcu102_init(MachineState *machine)
95
0x7 /* PCI irq */);
85
object_property_set_bool(OBJECT(&s->soc), "virtualization", s->virt,
96
}
86
&error_fatal);
97
87
98
-static void create_pcie(const VirtMachineState *vms, qemu_irq *pic)
88
+ for (i = 0; i < XLNX_ZYNQMP_NUM_CAN; i++) {
99
+static void create_smmu(const VirtMachineState *vms, qemu_irq *pic,
89
+ gchar *bus_name = g_strdup_printf("canbus%d", i);
100
+ PCIBus *bus)
101
+{
102
+ char *node;
103
+ const char compat[] = "arm,smmu-v3";
104
+ int irq = vms->irqmap[VIRT_SMMU];
105
+ int i;
106
+ hwaddr base = vms->memmap[VIRT_SMMU].base;
107
+ hwaddr size = vms->memmap[VIRT_SMMU].size;
108
+ const char irq_names[] = "eventq\0priq\0cmdq-sync\0gerror";
109
+ DeviceState *dev;
110
+
90
+
111
+ if (vms->iommu != VIRT_IOMMU_SMMUV3 || !vms->iommu_phandle) {
91
+ object_property_set_link(OBJECT(&s->soc), bus_name,
112
+ return;
92
+ OBJECT(s->canbus[i]), &error_fatal);
93
+ g_free(bus_name);
113
+ }
94
+ }
114
+
95
+
115
+ dev = qdev_create(NULL, "arm-smmuv3");
96
qdev_realize(DEVICE(&s->soc), NULL, &error_fatal);
97
98
/* Create and plug in the SD cards */
99
@@ -XXX,XX +XXX,XX @@ static void xlnx_zcu102_machine_instance_init(Object *obj)
100
s->secure = false;
101
/* Default to virt (EL2) being disabled */
102
s->virt = false;
103
+ object_property_add_link(obj, "xlnx-zcu102.canbus0", TYPE_CAN_BUS,
104
+ (Object **)&s->canbus[0],
105
+ object_property_allow_set_link,
106
+ 0);
116
+
107
+
117
+ object_property_set_link(OBJECT(dev), OBJECT(bus), "primary-bus",
108
+ object_property_add_link(obj, "xlnx-zcu102.canbus1", TYPE_CAN_BUS,
118
+ &error_abort);
109
+ (Object **)&s->canbus[1],
119
+ qdev_init_nofail(dev);
110
+ object_property_allow_set_link,
120
+ sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
111
+ 0);
121
+ for (i = 0; i < NUM_SMMU_IRQS; i++) {
112
}
122
+ sysbus_connect_irq(SYS_BUS_DEVICE(dev), i, pic[irq + i]);
113
114
static void xlnx_zcu102_machine_class_init(ObjectClass *oc, void *data)
115
diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c
116
index XXXXXXX..XXXXXXX 100644
117
--- a/hw/arm/xlnx-zynqmp.c
118
+++ b/hw/arm/xlnx-zynqmp.c
119
@@ -XXX,XX +XXX,XX @@ static const int uart_intr[XLNX_ZYNQMP_NUM_UARTS] = {
120
21, 22,
121
};
122
123
+static const uint64_t can_addr[XLNX_ZYNQMP_NUM_CAN] = {
124
+ 0xFF060000, 0xFF070000,
125
+};
126
+
127
+static const int can_intr[XLNX_ZYNQMP_NUM_CAN] = {
128
+ 23, 24,
129
+};
130
+
131
static const uint64_t sdhci_addr[XLNX_ZYNQMP_NUM_SDHCI] = {
132
0xFF160000, 0xFF170000,
133
};
134
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_init(Object *obj)
135
TYPE_CADENCE_UART);
136
}
137
138
+ for (i = 0; i < XLNX_ZYNQMP_NUM_CAN; i++) {
139
+ object_initialize_child(obj, "can[*]", &s->can[i],
140
+ TYPE_XLNX_ZYNQMP_CAN);
123
+ }
141
+ }
124
+
142
+
125
+ node = g_strdup_printf("/smmuv3@%" PRIx64, base);
143
object_initialize_child(obj, "sata", &s->sata, TYPE_SYSBUS_AHCI);
126
+ qemu_fdt_add_subnode(vms->fdt, node);
144
127
+ qemu_fdt_setprop(vms->fdt, node, "compatible", compat, sizeof(compat));
145
for (i = 0; i < XLNX_ZYNQMP_NUM_SDHCI; i++) {
128
+ qemu_fdt_setprop_sized_cells(vms->fdt, node, "reg", 2, base, 2, size);
146
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
147
gic_spi[uart_intr[i]]);
148
}
149
150
+ for (i = 0; i < XLNX_ZYNQMP_NUM_CAN; i++) {
151
+ object_property_set_int(OBJECT(&s->can[i]), "ext_clk_freq",
152
+ XLNX_ZYNQMP_CAN_REF_CLK, &error_abort);
129
+
153
+
130
+ qemu_fdt_setprop_cells(vms->fdt, node, "interrupts",
154
+ object_property_set_link(OBJECT(&s->can[i]), "canbus",
131
+ GIC_FDT_IRQ_TYPE_SPI, irq , GIC_FDT_IRQ_FLAGS_EDGE_LO_HI,
155
+ OBJECT(s->canbus[i]), &error_fatal);
132
+ GIC_FDT_IRQ_TYPE_SPI, irq + 1, GIC_FDT_IRQ_FLAGS_EDGE_LO_HI,
133
+ GIC_FDT_IRQ_TYPE_SPI, irq + 2, GIC_FDT_IRQ_FLAGS_EDGE_LO_HI,
134
+ GIC_FDT_IRQ_TYPE_SPI, irq + 3, GIC_FDT_IRQ_FLAGS_EDGE_LO_HI);
135
+
156
+
136
+ qemu_fdt_setprop(vms->fdt, node, "interrupt-names", irq_names,
157
+ sysbus_realize(SYS_BUS_DEVICE(&s->can[i]), &err);
137
+ sizeof(irq_names));
158
+ if (err) {
138
+
159
+ error_propagate(errp, err);
139
+ qemu_fdt_setprop_cell(vms->fdt, node, "clocks", vms->clock_phandle);
160
+ return;
140
+ qemu_fdt_setprop_string(vms->fdt, node, "clock-names", "apb_pclk");
161
+ }
141
+ qemu_fdt_setprop(vms->fdt, node, "dma-coherent", NULL, 0);
162
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->can[i]), 0, can_addr[i]);
142
+
163
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->can[i]), 0,
143
+ qemu_fdt_setprop_cell(vms->fdt, node, "#iommu-cells", 1);
164
+ gic_spi[can_intr[i]]);
144
+
145
+ qemu_fdt_setprop_cell(vms->fdt, node, "phandle", vms->iommu_phandle);
146
+ g_free(node);
147
+}
148
+
149
+static void create_pcie(VirtMachineState *vms, qemu_irq *pic)
150
{
151
hwaddr base_mmio = vms->memmap[VIRT_PCIE_MMIO].base;
152
hwaddr size_mmio = vms->memmap[VIRT_PCIE_MMIO].size;
153
@@ -XXX,XX +XXX,XX @@ static void create_pcie(const VirtMachineState *vms, qemu_irq *pic)
154
qemu_fdt_setprop_cell(vms->fdt, nodename, "#interrupt-cells", 1);
155
create_pcie_irq_map(vms, vms->gic_phandle, irq, nodename);
156
157
+ if (vms->iommu) {
158
+ vms->iommu_phandle = qemu_fdt_alloc_phandle(vms->fdt);
159
+
160
+ create_smmu(vms, pic, pci->bus);
161
+
162
+ qemu_fdt_setprop_cells(vms->fdt, nodename, "iommu-map",
163
+ 0x0, vms->iommu_phandle, 0x0, 0x10000);
164
+ }
165
+ }
165
+
166
+
166
g_free(nodename);
167
object_property_set_int(OBJECT(&s->sata), "num-ports", SATA_NUM_PORTS,
167
}
168
&error_abort);
169
if (!sysbus_realize(SYS_BUS_DEVICE(&s->sata), errp)) {
170
@@ -XXX,XX +XXX,XX @@ static Property xlnx_zynqmp_props[] = {
171
DEFINE_PROP_BOOL("has_rpu", XlnxZynqMPState, has_rpu, false),
172
DEFINE_PROP_LINK("ddr-ram", XlnxZynqMPState, ddr_ram, TYPE_MEMORY_REGION,
173
MemoryRegion *),
174
+ DEFINE_PROP_LINK("canbus0", XlnxZynqMPState, canbus[0], TYPE_CAN_BUS,
175
+ CanBusState *),
176
+ DEFINE_PROP_LINK("canbus1", XlnxZynqMPState, canbus[1], TYPE_CAN_BUS,
177
+ CanBusState *),
178
DEFINE_PROP_END_OF_LIST()
179
};
168
180
169
--
181
--
170
2.17.0
182
2.20.1
171
183
172
184
diff view generated by jsdifflib
1
From: Eric Auger <eric.auger@redhat.com>
1
From: Vikram Garhwal <fnu.vikram@xilinx.com>
2
2
3
The patch introduces the smmu base device and class for the ARM
3
The QTests perform five tests on the Xilinx ZynqMP CAN controller:
4
smmu. Devices for specific versions will be derived from this
4
Tests the CAN controller in loopback, sleep and snoop mode.
5
base device.
5
Tests filtering of incoming CAN messages.
6
6
7
We also introduce some important datatypes.
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
8
Reviewed-by: Francisco Iglesias <francisco.iglesias@xilinx.com>
9
Signed-off-by: Eric Auger <eric.auger@redhat.com>
9
Signed-off-by: Vikram Garhwal <fnu.vikram@xilinx.com>
10
Signed-off-by: Prem Mallappa <prem.mallappa@broadcom.com>
10
Message-id: 1605728926-352690-4-git-send-email-fnu.vikram@xilinx.com
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
Message-id: 1524665762-31355-2-git-send-email-eric.auger@redhat.com
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
12
---
15
hw/arm/Makefile.objs | 1 +
13
tests/qtest/xlnx-can-test.c | 360 ++++++++++++++++++++++++++++++++++++
16
include/hw/arm/smmu-common.h | 123 ++++++++++++++++++++++++++++
14
tests/qtest/meson.build | 1 +
17
hw/arm/smmu-common.c | 81 ++++++++++++++++++
15
2 files changed, 361 insertions(+)
18
default-configs/aarch64-softmmu.mak | 1 +
16
create mode 100644 tests/qtest/xlnx-can-test.c
19
4 files changed, 206 insertions(+)
17
20
create mode 100644 include/hw/arm/smmu-common.h
18
diff --git a/tests/qtest/xlnx-can-test.c b/tests/qtest/xlnx-can-test.c
21
create mode 100644 hw/arm/smmu-common.c
22
23
diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
24
index XXXXXXX..XXXXXXX 100644
25
--- a/hw/arm/Makefile.objs
26
+++ b/hw/arm/Makefile.objs
27
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_MPS2) += mps2-tz.o
28
obj-$(CONFIG_MSF2) += msf2-soc.o msf2-som.o
29
obj-$(CONFIG_IOTKIT) += iotkit.o
30
obj-$(CONFIG_FSL_IMX7) += fsl-imx7.o mcimx7d-sabre.o
31
+obj-$(CONFIG_ARM_SMMUV3) += smmu-common.o
32
diff --git a/include/hw/arm/smmu-common.h b/include/hw/arm/smmu-common.h
33
new file mode 100644
19
new file mode 100644
34
index XXXXXXX..XXXXXXX
20
index XXXXXXX..XXXXXXX
35
--- /dev/null
21
--- /dev/null
36
+++ b/include/hw/arm/smmu-common.h
22
+++ b/tests/qtest/xlnx-can-test.c
37
@@ -XXX,XX +XXX,XX @@
23
@@ -XXX,XX +XXX,XX @@
38
+/*
24
+/*
39
+ * ARM SMMU Support
25
+ * QTests for the Xilinx ZynqMP CAN controller.
40
+ *
26
+ *
41
+ * Copyright (C) 2015-2016 Broadcom Corporation
27
+ * Copyright (c) 2020 Xilinx Inc.
42
+ * Copyright (c) 2017 Red Hat, Inc.
28
+ *
43
+ * Written by Prem Mallappa, Eric Auger
29
+ * Written-by: Vikram Garhwal<fnu.vikram@xilinx.com>
44
+ *
30
+ *
45
+ * This program is free software; you can redistribute it and/or modify
31
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
46
+ * it under the terms of the GNU General Public License version 2 as
32
+ * of this software and associated documentation files (the "Software"), to deal
47
+ * published by the Free Software Foundation.
33
+ * in the Software without restriction, including without limitation the rights
48
+ *
34
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
49
+ * This program is distributed in the hope that it will be useful,
35
+ * copies of the Software, and to permit persons to whom the Software is
50
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
36
+ * furnished to do so, subject to the following conditions:
51
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
37
+ *
52
+ * GNU General Public License for more details.
38
+ * The above copyright notice and this permission notice shall be included in
53
+ *
39
+ * all copies or substantial portions of the Software.
40
+ *
41
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
42
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
43
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
44
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
45
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
46
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
47
+ * THE SOFTWARE.
54
+ */
48
+ */
55
+
49
+
56
+#ifndef HW_ARM_SMMU_COMMON_H
50
+#include "qemu/osdep.h"
57
+#define HW_ARM_SMMU_COMMON_H
51
+#include "libqos/libqtest.h"
58
+
52
+
59
+#include "hw/sysbus.h"
53
+/* Base address. */
60
+#include "hw/pci/pci.h"
54
+#define CAN0_BASE_ADDR 0xFF060000
61
+
55
+#define CAN1_BASE_ADDR 0xFF070000
62
+#define SMMU_PCI_BUS_MAX 256
56
+
63
+#define SMMU_PCI_DEVFN_MAX 256
57
+/* Register addresses. */
64
+
58
+#define R_SRR_OFFSET 0x00
65
+#define SMMU_MAX_VA_BITS 48
59
+#define R_MSR_OFFSET 0x04
60
+#define R_SR_OFFSET 0x18
61
+#define R_ISR_OFFSET 0x1C
62
+#define R_ICR_OFFSET 0x24
63
+#define R_TXID_OFFSET 0x30
64
+#define R_TXDLC_OFFSET 0x34
65
+#define R_TXDATA1_OFFSET 0x38
66
+#define R_TXDATA2_OFFSET 0x3C
67
+#define R_RXID_OFFSET 0x50
68
+#define R_RXDLC_OFFSET 0x54
69
+#define R_RXDATA1_OFFSET 0x58
70
+#define R_RXDATA2_OFFSET 0x5C
71
+#define R_AFR 0x60
72
+#define R_AFMR1 0x64
73
+#define R_AFIR1 0x68
74
+#define R_AFMR2 0x6C
75
+#define R_AFIR2 0x70
76
+#define R_AFMR3 0x74
77
+#define R_AFIR3 0x78
78
+#define R_AFMR4 0x7C
79
+#define R_AFIR4 0x80
80
+
81
+/* CAN modes. */
82
+#define CONFIG_MODE 0x00
83
+#define NORMAL_MODE 0x00
84
+#define LOOPBACK_MODE 0x02
85
+#define SNOOP_MODE 0x04
86
+#define SLEEP_MODE 0x01
87
+#define ENABLE_CAN (1 << 1)
88
+#define STATUS_NORMAL_MODE (1 << 3)
89
+#define STATUS_LOOPBACK_MODE (1 << 1)
90
+#define STATUS_SNOOP_MODE (1 << 12)
91
+#define STATUS_SLEEP_MODE (1 << 2)
92
+#define ISR_TXOK (1 << 1)
93
+#define ISR_RXOK (1 << 4)
94
+
95
+static void match_rx_tx_data(const uint32_t *buf_tx, const uint32_t *buf_rx,
96
+ uint8_t can_timestamp)
97
+{
98
+ uint16_t size = 0;
99
+ uint8_t len = 4;
100
+
101
+ while (size < len) {
102
+ if (R_RXID_OFFSET + 4 * size == R_RXDLC_OFFSET) {
103
+ g_assert_cmpint(buf_rx[size], ==, buf_tx[size] + can_timestamp);
104
+ } else {
105
+ g_assert_cmpint(buf_rx[size], ==, buf_tx[size]);
106
+ }
107
+
108
+ size++;
109
+ }
110
+}
111
+
112
+static void read_data(QTestState *qts, uint64_t can_base_addr, uint32_t *buf_rx)
113
+{
114
+ uint32_t int_status;
115
+
116
+ /* Read the interrupt on CAN rx. */
117
+ int_status = qtest_readl(qts, can_base_addr + R_ISR_OFFSET) & ISR_RXOK;
118
+
119
+ g_assert_cmpint(int_status, ==, ISR_RXOK);
120
+
121
+ /* Read the RX register data for CAN. */
122
+ buf_rx[0] = qtest_readl(qts, can_base_addr + R_RXID_OFFSET);
123
+ buf_rx[1] = qtest_readl(qts, can_base_addr + R_RXDLC_OFFSET);
124
+ buf_rx[2] = qtest_readl(qts, can_base_addr + R_RXDATA1_OFFSET);
125
+ buf_rx[3] = qtest_readl(qts, can_base_addr + R_RXDATA2_OFFSET);
126
+
127
+ /* Clear the RX interrupt. */
128
+ qtest_writel(qts, CAN1_BASE_ADDR + R_ICR_OFFSET, ISR_RXOK);
129
+}
130
+
131
+static void send_data(QTestState *qts, uint64_t can_base_addr,
132
+ const uint32_t *buf_tx)
133
+{
134
+ uint32_t int_status;
135
+
136
+ /* Write the TX register data for CAN. */
137
+ qtest_writel(qts, can_base_addr + R_TXID_OFFSET, buf_tx[0]);
138
+ qtest_writel(qts, can_base_addr + R_TXDLC_OFFSET, buf_tx[1]);
139
+ qtest_writel(qts, can_base_addr + R_TXDATA1_OFFSET, buf_tx[2]);
140
+ qtest_writel(qts, can_base_addr + R_TXDATA2_OFFSET, buf_tx[3]);
141
+
142
+ /* Read the interrupt on CAN for tx. */
143
+ int_status = qtest_readl(qts, can_base_addr + R_ISR_OFFSET) & ISR_TXOK;
144
+
145
+ g_assert_cmpint(int_status, ==, ISR_TXOK);
146
+
147
+ /* Clear the interrupt for tx. */
148
+ qtest_writel(qts, CAN0_BASE_ADDR + R_ICR_OFFSET, ISR_TXOK);
149
+}
66
+
150
+
67
+/*
151
+/*
68
+ * Page table walk error types
152
+ * This test will be transferring data from CAN0 and CAN1 through canbus. CAN0
153
+ * initiate the data transfer to can-bus, CAN1 receives the data. Test compares
154
+ * the data sent from CAN0 with received on CAN1.
69
+ */
155
+ */
70
+typedef enum {
156
+static void test_can_bus(void)
71
+ SMMU_PTW_ERR_NONE,
157
+{
72
+ SMMU_PTW_ERR_WALK_EABT, /* Translation walk external abort */
158
+ const uint32_t buf_tx[4] = { 0xFF, 0x80000000, 0x12345678, 0x87654321 };
73
+ SMMU_PTW_ERR_TRANSLATION, /* Translation fault */
159
+ uint32_t buf_rx[4] = { 0x00, 0x00, 0x00, 0x00 };
74
+ SMMU_PTW_ERR_ADDR_SIZE, /* Address Size fault */
160
+ uint32_t status = 0;
75
+ SMMU_PTW_ERR_ACCESS, /* Access fault */
161
+ uint8_t can_timestamp = 1;
76
+ SMMU_PTW_ERR_PERMISSION, /* Permission fault */
162
+
77
+} SMMUPTWEventType;
163
+ QTestState *qts = qtest_init("-machine xlnx-zcu102"
78
+
164
+ " -object can-bus,id=canbus0"
79
+typedef struct SMMUPTWEventInfo {
165
+ " -machine xlnx-zcu102.canbus0=canbus0"
80
+ SMMUPTWEventType type;
166
+ " -machine xlnx-zcu102.canbus1=canbus0"
81
+ dma_addr_t addr; /* fetched address that induced an abort, if any */
167
+ );
82
+} SMMUPTWEventInfo;
168
+
83
+
169
+ /* Configure the CAN0 and CAN1. */
84
+typedef struct SMMUTransTableInfo {
170
+ qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
85
+ bool disabled; /* is the translation table disabled? */
171
+ qtest_writel(qts, CAN0_BASE_ADDR + R_MSR_OFFSET, NORMAL_MODE);
86
+ uint64_t ttb; /* TT base address */
172
+ qtest_writel(qts, CAN1_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
87
+ uint8_t tsz; /* input range, ie. 2^(64 -tsz)*/
173
+ qtest_writel(qts, CAN1_BASE_ADDR + R_MSR_OFFSET, NORMAL_MODE);
88
+ uint8_t granule_sz; /* granule page shift */
174
+
89
+} SMMUTransTableInfo;
175
+ /* Check here if CAN0 and CAN1 are in normal mode. */
176
+ status = qtest_readl(qts, CAN0_BASE_ADDR + R_SR_OFFSET);
177
+ g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
178
+
179
+ status = qtest_readl(qts, CAN1_BASE_ADDR + R_SR_OFFSET);
180
+ g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
181
+
182
+ send_data(qts, CAN0_BASE_ADDR, buf_tx);
183
+
184
+ read_data(qts, CAN1_BASE_ADDR, buf_rx);
185
+ match_rx_tx_data(buf_tx, buf_rx, can_timestamp);
186
+
187
+ qtest_quit(qts);
188
+}
90
+
189
+
91
+/*
190
+/*
92
+ * Generic structure populated by derived SMMU devices
191
+ * This test is performing loopback mode on CAN0 and CAN1. Data sent from TX of
93
+ * after decoding the configuration information and used as
192
+ * each CAN0 and CAN1 are compared with RX register data for respective CAN.
94
+ * input to the page table walk
95
+ */
193
+ */
96
+typedef struct SMMUTransCfg {
194
+static void test_can_loopback(void)
97
+ int stage; /* translation stage */
195
+{
98
+ bool aa64; /* arch64 or aarch32 translation table */
196
+ uint32_t buf_tx[4] = { 0xFF, 0x80000000, 0x12345678, 0x87654321 };
99
+ bool disabled; /* smmu is disabled */
197
+ uint32_t buf_rx[4] = { 0x00, 0x00, 0x00, 0x00 };
100
+ bool bypassed; /* translation is bypassed */
198
+ uint32_t status = 0;
101
+ bool aborted; /* translation is aborted */
199
+
102
+ uint64_t ttb; /* TT base address */
200
+ QTestState *qts = qtest_init("-machine xlnx-zcu102"
103
+ uint8_t oas; /* output address width */
201
+ " -object can-bus,id=canbus0"
104
+ uint8_t tbi; /* Top Byte Ignore */
202
+ " -machine xlnx-zcu102.canbus0=canbus0"
105
+ uint16_t asid;
203
+ " -machine xlnx-zcu102.canbus1=canbus0"
106
+ SMMUTransTableInfo tt[2];
204
+ );
107
+} SMMUTransCfg;
205
+
108
+
206
+ /* Configure the CAN0 in loopback mode. */
109
+typedef struct SMMUDevice {
207
+ qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, CONFIG_MODE);
110
+ void *smmu;
208
+ qtest_writel(qts, CAN0_BASE_ADDR + R_MSR_OFFSET, LOOPBACK_MODE);
111
+ PCIBus *bus;
209
+ qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
112
+ int devfn;
210
+
113
+ IOMMUMemoryRegion iommu;
211
+ /* Check here if CAN0 is set in loopback mode. */
114
+ AddressSpace as;
212
+ status = qtest_readl(qts, CAN0_BASE_ADDR + R_SR_OFFSET);
115
+} SMMUDevice;
213
+
116
+
214
+ g_assert_cmpint(status, ==, STATUS_LOOPBACK_MODE);
117
+typedef struct SMMUNotifierNode {
215
+
118
+ SMMUDevice *sdev;
216
+ send_data(qts, CAN0_BASE_ADDR, buf_tx);
119
+ QLIST_ENTRY(SMMUNotifierNode) next;
217
+ read_data(qts, CAN0_BASE_ADDR, buf_rx);
120
+} SMMUNotifierNode;
218
+ match_rx_tx_data(buf_tx, buf_rx, 0);
121
+
219
+
122
+typedef struct SMMUPciBus {
220
+ /* Configure the CAN1 in loopback mode. */
123
+ PCIBus *bus;
221
+ qtest_writel(qts, CAN1_BASE_ADDR + R_SRR_OFFSET, CONFIG_MODE);
124
+ SMMUDevice *pbdev[0]; /* Parent array is sparse, so dynamically alloc */
222
+ qtest_writel(qts, CAN1_BASE_ADDR + R_MSR_OFFSET, LOOPBACK_MODE);
125
+} SMMUPciBus;
223
+ qtest_writel(qts, CAN1_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
126
+
224
+
127
+typedef struct SMMUState {
225
+ /* Check here if CAN1 is set in loopback mode. */
128
+ /* <private> */
226
+ status = qtest_readl(qts, CAN1_BASE_ADDR + R_SR_OFFSET);
129
+ SysBusDevice dev;
227
+
130
+ const char *mrtypename;
228
+ g_assert_cmpint(status, ==, STATUS_LOOPBACK_MODE);
131
+ MemoryRegion iomem;
229
+
132
+
230
+ send_data(qts, CAN1_BASE_ADDR, buf_tx);
133
+ GHashTable *smmu_pcibus_by_busptr;
231
+ read_data(qts, CAN1_BASE_ADDR, buf_rx);
134
+ GHashTable *configs; /* cache for configuration data */
232
+ match_rx_tx_data(buf_tx, buf_rx, 0);
135
+ GHashTable *iotlb;
233
+
136
+ SMMUPciBus *smmu_pcibus_by_bus_num[SMMU_PCI_BUS_MAX];
234
+ qtest_quit(qts);
137
+ PCIBus *pci_bus;
235
+}
138
+ QLIST_HEAD(, SMMUNotifierNode) notifiers_list;
236
+
139
+ uint8_t bus_num;
140
+ PCIBus *primary_bus;
141
+} SMMUState;
142
+
143
+typedef struct {
144
+ /* <private> */
145
+ SysBusDeviceClass parent_class;
146
+
147
+ /*< public >*/
148
+
149
+ DeviceRealize parent_realize;
150
+
151
+} SMMUBaseClass;
152
+
153
+#define TYPE_ARM_SMMU "arm-smmu"
154
+#define ARM_SMMU(obj) OBJECT_CHECK(SMMUState, (obj), TYPE_ARM_SMMU)
155
+#define ARM_SMMU_CLASS(klass) \
156
+ OBJECT_CLASS_CHECK(SMMUBaseClass, (klass), TYPE_ARM_SMMU)
157
+#define ARM_SMMU_GET_CLASS(obj) \
158
+ OBJECT_GET_CLASS(SMMUBaseClass, (obj), TYPE_ARM_SMMU)
159
+
160
+#endif /* HW_ARM_SMMU_COMMON */
161
diff --git a/hw/arm/smmu-common.c b/hw/arm/smmu-common.c
162
new file mode 100644
163
index XXXXXXX..XXXXXXX
164
--- /dev/null
165
+++ b/hw/arm/smmu-common.c
166
@@ -XXX,XX +XXX,XX @@
167
+/*
237
+/*
168
+ * Copyright (C) 2014-2016 Broadcom Corporation
238
+ * Enable filters for CAN1. This will filter incoming messages with ID. In this
169
+ * Copyright (c) 2017 Red Hat, Inc.
239
+ * test message will pass through filter 2.
170
+ * Written by Prem Mallappa, Eric Auger
171
+ *
172
+ * This program is free software; you can redistribute it and/or modify
173
+ * it under the terms of the GNU General Public License version 2 as
174
+ * published by the Free Software Foundation.
175
+ *
176
+ * This program is distributed in the hope that it will be useful,
177
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
178
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
179
+ * GNU General Public License for more details.
180
+ *
181
+ * Author: Prem Mallappa <pmallapp@broadcom.com>
182
+ *
183
+ */
240
+ */
184
+
241
+static void test_can_filter(void)
185
+#include "qemu/osdep.h"
242
+{
186
+#include "sysemu/sysemu.h"
243
+ uint32_t buf_tx[4] = { 0x14, 0x80000000, 0x12345678, 0x87654321 };
187
+#include "exec/address-spaces.h"
244
+ uint32_t buf_rx[4] = { 0x00, 0x00, 0x00, 0x00 };
188
+#include "trace.h"
245
+ uint32_t status = 0;
189
+#include "exec/target_page.h"
246
+ uint8_t can_timestamp = 1;
190
+#include "qom/cpu.h"
247
+
191
+#include "hw/qdev-properties.h"
248
+ QTestState *qts = qtest_init("-machine xlnx-zcu102"
192
+#include "qapi/error.h"
249
+ " -object can-bus,id=canbus0"
193
+
250
+ " -machine xlnx-zcu102.canbus0=canbus0"
194
+#include "qemu/error-report.h"
251
+ " -machine xlnx-zcu102.canbus1=canbus0"
195
+#include "hw/arm/smmu-common.h"
252
+ );
196
+
253
+
197
+static void smmu_base_realize(DeviceState *dev, Error **errp)
254
+ /* Configure the CAN0 and CAN1. */
198
+{
255
+ qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
199
+ SMMUBaseClass *sbc = ARM_SMMU_GET_CLASS(dev);
256
+ qtest_writel(qts, CAN0_BASE_ADDR + R_MSR_OFFSET, NORMAL_MODE);
200
+ Error *local_err = NULL;
257
+ qtest_writel(qts, CAN1_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
201
+
258
+ qtest_writel(qts, CAN1_BASE_ADDR + R_MSR_OFFSET, NORMAL_MODE);
202
+ sbc->parent_realize(dev, &local_err);
259
+
203
+ if (local_err) {
260
+ /* Check here if CAN0 and CAN1 are in normal mode. */
204
+ error_propagate(errp, local_err);
261
+ status = qtest_readl(qts, CAN0_BASE_ADDR + R_SR_OFFSET);
205
+ return;
262
+ g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
206
+ }
263
+
207
+}
264
+ status = qtest_readl(qts, CAN1_BASE_ADDR + R_SR_OFFSET);
208
+
265
+ g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
209
+static void smmu_base_reset(DeviceState *dev)
266
+
210
+{
267
+ /* Set filter for CAN1 for incoming messages. */
211
+ /* will be filled later on */
268
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFR, 0x0);
212
+}
269
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFMR1, 0xF7);
213
+
270
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFIR1, 0x121F);
214
+static Property smmu_dev_properties[] = {
271
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFMR2, 0x5431);
215
+ DEFINE_PROP_UINT8("bus_num", SMMUState, bus_num, 0),
272
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFIR2, 0x14);
216
+ DEFINE_PROP_LINK("primary-bus", SMMUState, primary_bus, "PCI", PCIBus *),
273
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFMR3, 0x1234);
217
+ DEFINE_PROP_END_OF_LIST(),
274
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFIR3, 0x5431);
218
+};
275
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFMR4, 0xFFF);
219
+
276
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFIR4, 0x1234);
220
+static void smmu_base_class_init(ObjectClass *klass, void *data)
277
+
221
+{
278
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFR, 0xF);
222
+ DeviceClass *dc = DEVICE_CLASS(klass);
279
+
223
+ SMMUBaseClass *sbc = ARM_SMMU_CLASS(klass);
280
+ send_data(qts, CAN0_BASE_ADDR, buf_tx);
224
+
281
+
225
+ dc->props = smmu_dev_properties;
282
+ read_data(qts, CAN1_BASE_ADDR, buf_rx);
226
+ device_class_set_parent_realize(dc, smmu_base_realize,
283
+ match_rx_tx_data(buf_tx, buf_rx, can_timestamp);
227
+ &sbc->parent_realize);
284
+
228
+ dc->reset = smmu_base_reset;
285
+ qtest_quit(qts);
229
+}
286
+}
230
+
287
+
231
+static const TypeInfo smmu_base_info = {
288
+/* Testing sleep mode on CAN0 while CAN1 is in normal mode. */
232
+ .name = TYPE_ARM_SMMU,
289
+static void test_can_sleepmode(void)
233
+ .parent = TYPE_SYS_BUS_DEVICE,
290
+{
234
+ .instance_size = sizeof(SMMUState),
291
+ uint32_t buf_tx[4] = { 0x14, 0x80000000, 0x12345678, 0x87654321 };
235
+ .class_data = NULL,
292
+ uint32_t buf_rx[4] = { 0x00, 0x00, 0x00, 0x00 };
236
+ .class_size = sizeof(SMMUBaseClass),
293
+ uint32_t status = 0;
237
+ .class_init = smmu_base_class_init,
294
+ uint8_t can_timestamp = 1;
238
+ .abstract = true,
295
+
239
+};
296
+ QTestState *qts = qtest_init("-machine xlnx-zcu102"
240
+
297
+ " -object can-bus,id=canbus0"
241
+static void smmu_base_register_types(void)
298
+ " -machine xlnx-zcu102.canbus0=canbus0"
242
+{
299
+ " -machine xlnx-zcu102.canbus1=canbus0"
243
+ type_register_static(&smmu_base_info);
300
+ );
244
+}
301
+
245
+
302
+ /* Configure the CAN0. */
246
+type_init(smmu_base_register_types)
303
+ qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, CONFIG_MODE);
247
+
304
+ qtest_writel(qts, CAN0_BASE_ADDR + R_MSR_OFFSET, SLEEP_MODE);
248
diff --git a/default-configs/aarch64-softmmu.mak b/default-configs/aarch64-softmmu.mak
305
+ qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
306
+
307
+ qtest_writel(qts, CAN1_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
308
+ qtest_writel(qts, CAN1_BASE_ADDR + R_MSR_OFFSET, NORMAL_MODE);
309
+
310
+ /* Check here if CAN0 is in SLEEP mode and CAN1 in normal mode. */
311
+ status = qtest_readl(qts, CAN0_BASE_ADDR + R_SR_OFFSET);
312
+ g_assert_cmpint(status, ==, STATUS_SLEEP_MODE);
313
+
314
+ status = qtest_readl(qts, CAN1_BASE_ADDR + R_SR_OFFSET);
315
+ g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
316
+
317
+ send_data(qts, CAN1_BASE_ADDR, buf_tx);
318
+
319
+ /*
320
+ * Once CAN1 sends data on can-bus. CAN0 should exit sleep mode.
321
+ * Check the CAN0 status now. It should exit the sleep mode and receive the
322
+ * incoming data.
323
+ */
324
+ status = qtest_readl(qts, CAN0_BASE_ADDR + R_SR_OFFSET);
325
+ g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
326
+
327
+ read_data(qts, CAN0_BASE_ADDR, buf_rx);
328
+
329
+ match_rx_tx_data(buf_tx, buf_rx, can_timestamp);
330
+
331
+ qtest_quit(qts);
332
+}
333
+
334
+/* Testing Snoop mode on CAN0 while CAN1 is in normal mode. */
335
+static void test_can_snoopmode(void)
336
+{
337
+ uint32_t buf_tx[4] = { 0x14, 0x80000000, 0x12345678, 0x87654321 };
338
+ uint32_t buf_rx[4] = { 0x00, 0x00, 0x00, 0x00 };
339
+ uint32_t status = 0;
340
+ uint8_t can_timestamp = 1;
341
+
342
+ QTestState *qts = qtest_init("-machine xlnx-zcu102"
343
+ " -object can-bus,id=canbus0"
344
+ " -machine xlnx-zcu102.canbus0=canbus0"
345
+ " -machine xlnx-zcu102.canbus1=canbus0"
346
+ );
347
+
348
+ /* Configure the CAN0. */
349
+ qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, CONFIG_MODE);
350
+ qtest_writel(qts, CAN0_BASE_ADDR + R_MSR_OFFSET, SNOOP_MODE);
351
+ qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
352
+
353
+ qtest_writel(qts, CAN1_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
354
+ qtest_writel(qts, CAN1_BASE_ADDR + R_MSR_OFFSET, NORMAL_MODE);
355
+
356
+ /* Check here if CAN0 is in SNOOP mode and CAN1 in normal mode. */
357
+ status = qtest_readl(qts, CAN0_BASE_ADDR + R_SR_OFFSET);
358
+ g_assert_cmpint(status, ==, STATUS_SNOOP_MODE);
359
+
360
+ status = qtest_readl(qts, CAN1_BASE_ADDR + R_SR_OFFSET);
361
+ g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
362
+
363
+ send_data(qts, CAN1_BASE_ADDR, buf_tx);
364
+
365
+ read_data(qts, CAN0_BASE_ADDR, buf_rx);
366
+
367
+ match_rx_tx_data(buf_tx, buf_rx, can_timestamp);
368
+
369
+ qtest_quit(qts);
370
+}
371
+
372
+int main(int argc, char **argv)
373
+{
374
+ g_test_init(&argc, &argv, NULL);
375
+
376
+ qtest_add_func("/net/can/can_bus", test_can_bus);
377
+ qtest_add_func("/net/can/can_loopback", test_can_loopback);
378
+ qtest_add_func("/net/can/can_filter", test_can_filter);
379
+ qtest_add_func("/net/can/can_test_snoopmode", test_can_snoopmode);
380
+ qtest_add_func("/net/can/can_test_sleepmode", test_can_sleepmode);
381
+
382
+ return g_test_run();
383
+}
384
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
249
index XXXXXXX..XXXXXXX 100644
385
index XXXXXXX..XXXXXXX 100644
250
--- a/default-configs/aarch64-softmmu.mak
386
--- a/tests/qtest/meson.build
251
+++ b/default-configs/aarch64-softmmu.mak
387
+++ b/tests/qtest/meson.build
252
@@ -XXX,XX +XXX,XX @@ CONFIG_DDC=y
388
@@ -XXX,XX +XXX,XX @@ qtests_aarch64 = \
253
CONFIG_DPCD=y
389
['arm-cpu-features',
254
CONFIG_XLNX_ZYNQMP=y
390
'numa-test',
255
CONFIG_XLNX_ZYNQMP_ARM=y
391
'boot-serial-test',
256
+CONFIG_ARM_SMMUV3=y
392
+ 'xlnx-can-test',
393
'migration-test']
394
395
qtests_s390x = \
257
--
396
--
258
2.17.0
397
2.20.1
259
398
260
399
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Vikram Garhwal <fnu.vikram@xilinx.com>
2
2
3
The (size > 3 && !is_q) condition is identical to the preceeding test
3
Reviewed-by: Francisco Iglesias <francisco.iglesias@xilinx.com>
4
of bit 3 in immh; eliminate it. For the benefit of Coverity, assert
4
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
5
that size is within the bounds we expect.
5
Signed-off-by: Vikram Garhwal <fnu.vikram@xilinx.com>
6
6
Message-id: 1605728926-352690-5-git-send-email-fnu.vikram@xilinx.com
7
Fixes: Coverity CID1385846
8
Fixes: Coverity CID1385849
9
Fixes: Coverity CID1385852
10
Fixes: Coverity CID1385857
11
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
12
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
13
Message-id: 20180501180455.11214-2-richard.henderson@linaro.org
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
---
8
---
16
target/arm/translate-a64.c | 6 +-----
9
MAINTAINERS | 8 ++++++++
17
1 file changed, 1 insertion(+), 5 deletions(-)
10
1 file changed, 8 insertions(+)
18
11
19
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
12
diff --git a/MAINTAINERS b/MAINTAINERS
20
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
21
--- a/target/arm/translate-a64.c
14
--- a/MAINTAINERS
22
+++ b/target/arm/translate-a64.c
15
+++ b/MAINTAINERS
23
@@ -XXX,XX +XXX,XX @@ static void handle_vec_simd_shri(DisasContext *s, bool is_q, bool is_u,
16
@@ -XXX,XX +XXX,XX @@ F: hw/net/opencores_eth.c
24
unallocated_encoding(s);
17
25
return;
18
Devices
26
}
19
-------
27
-
20
+Xilinx CAN
28
- if (size > 3 && !is_q) {
21
+M: Vikram Garhwal <fnu.vikram@xilinx.com>
29
- unallocated_encoding(s);
22
+M: Francisco Iglesias <francisco.iglesias@xilinx.com>
30
- return;
23
+S: Maintained
31
- }
24
+F: hw/net/can/xlnx-*
32
+ tcg_debug_assert(size <= 3);
25
+F: include/hw/net/xlnx-*
33
26
+F: tests/qtest/xlnx-can-test*
34
if (!fp_access_check(s)) {
27
+
35
return;
28
EDU
29
M: Jiri Slaby <jslaby@suse.cz>
30
S: Maintained
36
--
31
--
37
2.17.0
32
2.20.1
38
33
39
34
diff view generated by jsdifflib
1
From: Eric Auger <eric.auger@redhat.com>
1
From: Marcin Juszkiewicz <marcin.juszkiewicz@linaro.org>
2
2
3
We set up the infrastructure to enumerate all the PCI devices
3
Trusted Firmware now supports A72 on sbsa-ref by default [1] so enable
4
attached to the SMMU and create an associated IOMMU memory
4
it for QEMU as well. A53 was already enabled there.
5
region and address space.
6
5
7
Those info are stored in SMMUDevice objects. The devices are
6
1. https://review.trustedfirmware.org/c/TF-A/trusted-firmware-a/+/7117
8
grouped according to the PCIBus they belong to. A hash table
9
indexed by the PCIBus pointer is used. Also an array indexed by
10
the bus number allows to find the list of SMMUDevices.
11
7
12
Signed-off-by: Eric Auger <eric.auger@redhat.com>
8
Signed-off-by: Marcin Juszkiewicz <marcin.juszkiewicz@linaro.org>
13
Signed-off-by: Prem Mallappa <prem.mallappa@broadcom.com>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20201120141705.246690-1-marcin.juszkiewicz@linaro.org
14
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
15
Message-id: 1524665762-31355-3-git-send-email-eric.auger@redhat.com
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
---
13
---
18
include/hw/arm/smmu-common.h | 8 +++++
14
hw/arm/sbsa-ref.c | 23 ++++++++++++++++++++---
19
hw/arm/smmu-common.c | 69 ++++++++++++++++++++++++++++++++++++
15
1 file changed, 20 insertions(+), 3 deletions(-)
20
hw/arm/trace-events | 3 ++
21
3 files changed, 80 insertions(+)
22
16
23
diff --git a/include/hw/arm/smmu-common.h b/include/hw/arm/smmu-common.h
17
diff --git a/hw/arm/sbsa-ref.c b/hw/arm/sbsa-ref.c
24
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
25
--- a/include/hw/arm/smmu-common.h
19
--- a/hw/arm/sbsa-ref.c
26
+++ b/include/hw/arm/smmu-common.h
20
+++ b/hw/arm/sbsa-ref.c
27
@@ -XXX,XX +XXX,XX @@ typedef struct {
21
@@ -XXX,XX +XXX,XX @@ static const int sbsa_ref_irqmap[] = {
28
#define ARM_SMMU_GET_CLASS(obj) \
22
[SBSA_GWDT] = 16,
29
OBJECT_GET_CLASS(SMMUBaseClass, (obj), TYPE_ARM_SMMU)
23
};
30
24
31
+/* Return the SMMUPciBus handle associated to a PCI bus number */
25
+static const char * const valid_cpus[] = {
32
+SMMUPciBus *smmu_find_smmu_pcibus(SMMUState *s, uint8_t bus_num);
26
+ ARM_CPU_TYPE_NAME("cortex-a53"),
27
+ ARM_CPU_TYPE_NAME("cortex-a57"),
28
+ ARM_CPU_TYPE_NAME("cortex-a72"),
29
+};
33
+
30
+
34
+/* Return the stream ID of an SMMU device */
31
+static bool cpu_type_valid(const char *cpu)
35
+static inline uint16_t smmu_get_sid(SMMUDevice *sdev)
36
+{
32
+{
37
+ return PCI_BUILD_BDF(pci_bus_num(sdev->bus), sdev->devfn);
33
+ int i;
38
+}
39
#endif /* HW_ARM_SMMU_COMMON */
40
diff --git a/hw/arm/smmu-common.c b/hw/arm/smmu-common.c
41
index XXXXXXX..XXXXXXX 100644
42
--- a/hw/arm/smmu-common.c
43
+++ b/hw/arm/smmu-common.c
44
@@ -XXX,XX +XXX,XX @@
45
#include "qemu/error-report.h"
46
#include "hw/arm/smmu-common.h"
47
48
+/**
49
+ * The bus number is used for lookup when SID based invalidation occurs.
50
+ * In that case we lazily populate the SMMUPciBus array from the bus hash
51
+ * table. At the time the SMMUPciBus is created (smmu_find_add_as), the bus
52
+ * numbers may not be always initialized yet.
53
+ */
54
+SMMUPciBus *smmu_find_smmu_pcibus(SMMUState *s, uint8_t bus_num)
55
+{
56
+ SMMUPciBus *smmu_pci_bus = s->smmu_pcibus_by_bus_num[bus_num];
57
+
34
+
58
+ if (!smmu_pci_bus) {
35
+ for (i = 0; i < ARRAY_SIZE(valid_cpus); i++) {
59
+ GHashTableIter iter;
36
+ if (strcmp(cpu, valid_cpus[i]) == 0) {
60
+
37
+ return true;
61
+ g_hash_table_iter_init(&iter, s->smmu_pcibus_by_busptr);
62
+ while (g_hash_table_iter_next(&iter, NULL, (void **)&smmu_pci_bus)) {
63
+ if (pci_bus_num(smmu_pci_bus->bus) == bus_num) {
64
+ s->smmu_pcibus_by_bus_num[bus_num] = smmu_pci_bus;
65
+ return smmu_pci_bus;
66
+ }
67
+ }
38
+ }
68
+ }
39
+ }
69
+ return smmu_pci_bus;
40
+ return false;
70
+}
41
+}
71
+
42
+
72
+static AddressSpace *smmu_find_add_as(PCIBus *bus, void *opaque, int devfn)
43
static uint64_t sbsa_ref_cpu_mp_affinity(SBSAMachineState *sms, int idx)
73
+{
74
+ SMMUState *s = opaque;
75
+ SMMUPciBus *sbus = g_hash_table_lookup(s->smmu_pcibus_by_busptr, bus);
76
+ SMMUDevice *sdev;
77
+
78
+ if (!sbus) {
79
+ sbus = g_malloc0(sizeof(SMMUPciBus) +
80
+ sizeof(SMMUDevice *) * SMMU_PCI_DEVFN_MAX);
81
+ sbus->bus = bus;
82
+ g_hash_table_insert(s->smmu_pcibus_by_busptr, bus, sbus);
83
+ }
84
+
85
+ sdev = sbus->pbdev[devfn];
86
+ if (!sdev) {
87
+ char *name = g_strdup_printf("%s-%d-%d",
88
+ s->mrtypename,
89
+ pci_bus_num(bus), devfn);
90
+ sdev = sbus->pbdev[devfn] = g_new0(SMMUDevice, 1);
91
+
92
+ sdev->smmu = s;
93
+ sdev->bus = bus;
94
+ sdev->devfn = devfn;
95
+
96
+ memory_region_init_iommu(&sdev->iommu, sizeof(sdev->iommu),
97
+ s->mrtypename,
98
+ OBJECT(s), name, 1ULL << SMMU_MAX_VA_BITS);
99
+ address_space_init(&sdev->as,
100
+ MEMORY_REGION(&sdev->iommu), name);
101
+ trace_smmu_add_mr(name);
102
+ g_free(name);
103
+ }
104
+
105
+ return &sdev->as;
106
+}
107
+
108
static void smmu_base_realize(DeviceState *dev, Error **errp)
109
{
44
{
110
+ SMMUState *s = ARM_SMMU(dev);
45
uint8_t clustersz = ARM_DEFAULT_CPUS_PER_CLUSTER;
111
SMMUBaseClass *sbc = ARM_SMMU_GET_CLASS(dev);
46
@@ -XXX,XX +XXX,XX @@ static void sbsa_ref_init(MachineState *machine)
112
Error *local_err = NULL;
47
const CPUArchIdList *possible_cpus;
113
48
int n, sbsa_max_cpus;
114
@@ -XXX,XX +XXX,XX @@ static void smmu_base_realize(DeviceState *dev, Error **errp)
49
115
error_propagate(errp, local_err);
50
- if (strcmp(machine->cpu_type, ARM_CPU_TYPE_NAME("cortex-a57"))) {
116
return;
51
- error_report("sbsa-ref: CPU type other than the built-in "
52
- "cortex-a57 not supported");
53
+ if (!cpu_type_valid(machine->cpu_type)) {
54
+ error_report("mach-virt: CPU type %s not supported", machine->cpu_type);
55
exit(1);
117
}
56
}
118
+
57
119
+ s->smmu_pcibus_by_busptr = g_hash_table_new(NULL, NULL);
120
+
121
+ if (s->primary_bus) {
122
+ pci_setup_iommu(s->primary_bus, smmu_find_add_as, s);
123
+ } else {
124
+ error_setg(errp, "SMMU is not attached to any PCI bus!");
125
+ }
126
}
127
128
static void smmu_base_reset(DeviceState *dev)
129
diff --git a/hw/arm/trace-events b/hw/arm/trace-events
130
index XXXXXXX..XXXXXXX 100644
131
--- a/hw/arm/trace-events
132
+++ b/hw/arm/trace-events
133
@@ -XXX,XX +XXX,XX @@
134
135
# hw/arm/virt-acpi-build.c
136
virt_acpi_setup(void) "No fw cfg or ACPI disabled. Bailing out."
137
+
138
+# hw/arm/smmu-common.c
139
+smmu_add_mr(const char *name) "%s"
140
\ No newline at end of file
141
--
58
--
142
2.17.0
59
2.20.1
143
60
144
61
diff view generated by jsdifflib
1
From: Eric Auger <eric.auger@redhat.com>
1
From: Havard Skinnemoen <hskinnemoen@google.com>
2
2
3
This patch implements the IOMMU Memory Region translate()
3
Dump the collected random data after a randomness test failure.
4
callback. Most of the code relates to the translation
5
configuration decoding and check (STE, CD).
6
4
7
Signed-off-by: Eric Auger <eric.auger@redhat.com>
5
Note that this relies on the test having called
8
Signed-off-by: Prem Mallappa <prem.mallappa@broadcom.com>
6
g_test_set_nonfatal_assertions() so we don't abort immediately on the
9
Message-id: 1524665762-31355-10-git-send-email-eric.auger@redhat.com
7
assertion failure.
8
9
Signed-off-by: Havard Skinnemoen <hskinnemoen@google.com>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
[PMM: minor commit message tweak]
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
13
---
13
hw/arm/smmuv3-internal.h | 160 +++++++++++++++++
14
tests/qtest/npcm7xx_rng-test.c | 12 ++++++++++++
14
hw/arm/smmuv3.c | 358 +++++++++++++++++++++++++++++++++++++++
15
1 file changed, 12 insertions(+)
15
hw/arm/trace-events | 9 +
16
3 files changed, 527 insertions(+)
17
16
18
diff --git a/hw/arm/smmuv3-internal.h b/hw/arm/smmuv3-internal.h
17
diff --git a/tests/qtest/npcm7xx_rng-test.c b/tests/qtest/npcm7xx_rng-test.c
19
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
20
--- a/hw/arm/smmuv3-internal.h
19
--- a/tests/qtest/npcm7xx_rng-test.c
21
+++ b/hw/arm/smmuv3-internal.h
20
+++ b/tests/qtest/npcm7xx_rng-test.c
22
@@ -XXX,XX +XXX,XX @@ typedef struct SMMUEventInfo {
21
@@ -XXX,XX +XXX,XX @@
23
22
24
void smmuv3_record_event(SMMUv3State *s, SMMUEventInfo *event);
23
#include "libqtest-single.h"
25
24
#include "qemu/bitops.h"
26
+/* Configuration Data */
25
+#include "qemu-common.h"
27
+
26
28
+/* STE Level 1 Descriptor */
27
#define RNG_BASE_ADDR 0xf000b000
29
+typedef struct STEDesc {
28
30
+ uint32_t word[2];
29
@@ -XXX,XX +XXX,XX @@
31
+} STEDesc;
30
/* Number of bits to collect for randomness tests. */
32
+
31
#define TEST_INPUT_BITS (128)
33
+/* CD Level 1 Descriptor */
32
34
+typedef struct CDDesc {
33
+static void dump_buf_if_failed(const uint8_t *buf, size_t size)
35
+ uint32_t word[2];
36
+} CDDesc;
37
+
38
+/* Stream Table Entry(STE) */
39
+typedef struct STE {
40
+ uint32_t word[16];
41
+} STE;
42
+
43
+/* Context Descriptor(CD) */
44
+typedef struct CD {
45
+ uint32_t word[16];
46
+} CD;
47
+
48
+/* STE fields */
49
+
50
+#define STE_VALID(x) extract32((x)->word[0], 0, 1)
51
+
52
+#define STE_CONFIG(x) extract32((x)->word[0], 1, 3)
53
+#define STE_CFG_S1_ENABLED(config) (config & 0x1)
54
+#define STE_CFG_S2_ENABLED(config) (config & 0x2)
55
+#define STE_CFG_ABORT(config) (!(config & 0x4))
56
+#define STE_CFG_BYPASS(config) (config == 0x4)
57
+
58
+#define STE_S1FMT(x) extract32((x)->word[0], 4 , 2)
59
+#define STE_S1CDMAX(x) extract32((x)->word[1], 27, 5)
60
+#define STE_S1STALLD(x) extract32((x)->word[2], 27, 1)
61
+#define STE_EATS(x) extract32((x)->word[2], 28, 2)
62
+#define STE_STRW(x) extract32((x)->word[2], 30, 2)
63
+#define STE_S2VMID(x) extract32((x)->word[4], 0 , 16)
64
+#define STE_S2T0SZ(x) extract32((x)->word[5], 0 , 6)
65
+#define STE_S2SL0(x) extract32((x)->word[5], 6 , 2)
66
+#define STE_S2TG(x) extract32((x)->word[5], 14, 2)
67
+#define STE_S2PS(x) extract32((x)->word[5], 16, 3)
68
+#define STE_S2AA64(x) extract32((x)->word[5], 19, 1)
69
+#define STE_S2HD(x) extract32((x)->word[5], 24, 1)
70
+#define STE_S2HA(x) extract32((x)->word[5], 25, 1)
71
+#define STE_S2S(x) extract32((x)->word[5], 26, 1)
72
+#define STE_CTXPTR(x) \
73
+ ({ \
74
+ unsigned long addr; \
75
+ addr = (uint64_t)extract32((x)->word[1], 0, 16) << 32; \
76
+ addr |= (uint64_t)((x)->word[0] & 0xffffffc0); \
77
+ addr; \
78
+ })
79
+
80
+#define STE_S2TTB(x) \
81
+ ({ \
82
+ unsigned long addr; \
83
+ addr = (uint64_t)extract32((x)->word[7], 0, 16) << 32; \
84
+ addr |= (uint64_t)((x)->word[6] & 0xfffffff0); \
85
+ addr; \
86
+ })
87
+
88
+static inline int oas2bits(int oas_field)
89
+{
34
+{
90
+ switch (oas_field) {
35
+ if (g_test_failed()) {
91
+ case 0:
36
+ qemu_hexdump(stderr, "", buf, size);
92
+ return 32;
93
+ case 1:
94
+ return 36;
95
+ case 2:
96
+ return 40;
97
+ case 3:
98
+ return 42;
99
+ case 4:
100
+ return 44;
101
+ case 5:
102
+ return 48;
103
+ }
104
+ return -1;
105
+}
106
+
107
+static inline int pa_range(STE *ste)
108
+{
109
+ int oas_field = MIN(STE_S2PS(ste), SMMU_IDR5_OAS);
110
+
111
+ if (!STE_S2AA64(ste)) {
112
+ return 40;
113
+ }
114
+
115
+ return oas2bits(oas_field);
116
+}
117
+
118
+#define MAX_PA(ste) ((1 << pa_range(ste)) - 1)
119
+
120
+/* CD fields */
121
+
122
+#define CD_VALID(x) extract32((x)->word[0], 30, 1)
123
+#define CD_ASID(x) extract32((x)->word[1], 16, 16)
124
+#define CD_TTB(x, sel) \
125
+ ({ \
126
+ uint64_t hi, lo; \
127
+ hi = extract32((x)->word[(sel) * 2 + 3], 0, 19); \
128
+ hi <<= 32; \
129
+ lo = (x)->word[(sel) * 2 + 2] & ~0xfULL; \
130
+ hi | lo; \
131
+ })
132
+
133
+#define CD_TSZ(x, sel) extract32((x)->word[0], (16 * (sel)) + 0, 6)
134
+#define CD_TG(x, sel) extract32((x)->word[0], (16 * (sel)) + 6, 2)
135
+#define CD_EPD(x, sel) extract32((x)->word[0], (16 * (sel)) + 14, 1)
136
+#define CD_ENDI(x) extract32((x)->word[0], 15, 1)
137
+#define CD_IPS(x) extract32((x)->word[1], 0 , 3)
138
+#define CD_TBI(x) extract32((x)->word[1], 6 , 2)
139
+#define CD_HD(x) extract32((x)->word[1], 10 , 1)
140
+#define CD_HA(x) extract32((x)->word[1], 11 , 1)
141
+#define CD_S(x) extract32((x)->word[1], 12, 1)
142
+#define CD_R(x) extract32((x)->word[1], 13, 1)
143
+#define CD_A(x) extract32((x)->word[1], 14, 1)
144
+#define CD_AARCH64(x) extract32((x)->word[1], 9 , 1)
145
+
146
+#define CDM_VALID(x) ((x)->word[0] & 0x1)
147
+
148
+static inline int is_cd_valid(SMMUv3State *s, STE *ste, CD *cd)
149
+{
150
+ return CD_VALID(cd);
151
+}
152
+
153
+/**
154
+ * tg2granule - Decodes the CD translation granule size field according
155
+ * to the ttbr in use
156
+ * @bits: TG0/1 fields
157
+ * @ttbr: ttbr index in use
158
+ */
159
+static inline int tg2granule(int bits, int ttbr)
160
+{
161
+ switch (bits) {
162
+ case 0:
163
+ return ttbr ? 0 : 12;
164
+ case 1:
165
+ return ttbr ? 14 : 16;
166
+ case 2:
167
+ return ttbr ? 12 : 14;
168
+ case 3:
169
+ return ttbr ? 16 : 0;
170
+ default:
171
+ return 0;
172
+ }
37
+ }
173
+}
38
+}
174
+
39
+
175
+static inline uint64_t l1std_l2ptr(STEDesc *desc)
40
static void rng_writeb(unsigned int offset, uint8_t value)
176
+{
41
{
177
+ uint64_t hi, lo;
42
writeb(RNG_BASE_ADDR + offset, value);
178
+
43
@@ -XXX,XX +XXX,XX @@ static void test_continuous_monobit(void)
179
+ hi = desc->word[1];
44
}
180
+ lo = desc->word[0] & ~0x1fULL;
45
181
+ return hi << 32 | lo;
46
g_assert_cmpfloat(calc_monobit_p(buf, sizeof(buf)), >, 0.01);
182
+}
47
+ dump_buf_if_failed(buf, sizeof(buf));
183
+
184
+#define L1STD_SPAN(stm) (extract32((stm)->word[0], 0, 4))
185
+
186
#endif
187
diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c
188
index XXXXXXX..XXXXXXX 100644
189
--- a/hw/arm/smmuv3.c
190
+++ b/hw/arm/smmuv3.c
191
@@ -XXX,XX +XXX,XX @@ static void smmuv3_init_regs(SMMUv3State *s)
192
s->sid_split = 0;
193
}
48
}
194
49
195
+static int smmu_get_ste(SMMUv3State *s, dma_addr_t addr, STE *buf,
50
/*
196
+ SMMUEventInfo *event)
51
@@ -XXX,XX +XXX,XX @@ static void test_continuous_runs(void)
197
+{
52
}
198
+ int ret;
53
199
+
54
g_assert_cmpfloat(calc_runs_p(buf.l, sizeof(buf) * BITS_PER_BYTE), >, 0.01);
200
+ trace_smmuv3_get_ste(addr);
55
+ dump_buf_if_failed(buf.c, sizeof(buf));
201
+ /* TODO: guarantee 64-bit single-copy atomicity */
202
+ ret = dma_memory_read(&address_space_memory, addr,
203
+ (void *)buf, sizeof(*buf));
204
+ if (ret != MEMTX_OK) {
205
+ qemu_log_mask(LOG_GUEST_ERROR,
206
+ "Cannot fetch pte at address=0x%"PRIx64"\n", addr);
207
+ event->type = SMMU_EVT_F_STE_FETCH;
208
+ event->u.f_ste_fetch.addr = addr;
209
+ return -EINVAL;
210
+ }
211
+ return 0;
212
+
213
+}
214
+
215
+/* @ssid > 0 not supported yet */
216
+static int smmu_get_cd(SMMUv3State *s, STE *ste, uint32_t ssid,
217
+ CD *buf, SMMUEventInfo *event)
218
+{
219
+ dma_addr_t addr = STE_CTXPTR(ste);
220
+ int ret;
221
+
222
+ trace_smmuv3_get_cd(addr);
223
+ /* TODO: guarantee 64-bit single-copy atomicity */
224
+ ret = dma_memory_read(&address_space_memory, addr,
225
+ (void *)buf, sizeof(*buf));
226
+ if (ret != MEMTX_OK) {
227
+ qemu_log_mask(LOG_GUEST_ERROR,
228
+ "Cannot fetch pte at address=0x%"PRIx64"\n", addr);
229
+ event->type = SMMU_EVT_F_CD_FETCH;
230
+ event->u.f_ste_fetch.addr = addr;
231
+ return -EINVAL;
232
+ }
233
+ return 0;
234
+}
235
+
236
+/* Returns <0 if the caller has no need to continue the translation */
237
+static int decode_ste(SMMUv3State *s, SMMUTransCfg *cfg,
238
+ STE *ste, SMMUEventInfo *event)
239
+{
240
+ uint32_t config;
241
+ int ret = -EINVAL;
242
+
243
+ if (!STE_VALID(ste)) {
244
+ goto bad_ste;
245
+ }
246
+
247
+ config = STE_CONFIG(ste);
248
+
249
+ if (STE_CFG_ABORT(config)) {
250
+ cfg->aborted = true; /* abort but don't record any event */
251
+ return ret;
252
+ }
253
+
254
+ if (STE_CFG_BYPASS(config)) {
255
+ cfg->bypassed = true;
256
+ return ret;
257
+ }
258
+
259
+ if (STE_CFG_S2_ENABLED(config)) {
260
+ qemu_log_mask(LOG_UNIMP, "SMMUv3 does not support stage 2 yet\n");
261
+ goto bad_ste;
262
+ }
263
+
264
+ if (STE_S1CDMAX(ste) != 0) {
265
+ qemu_log_mask(LOG_UNIMP,
266
+ "SMMUv3 does not support multiple context descriptors yet\n");
267
+ goto bad_ste;
268
+ }
269
+
270
+ if (STE_S1STALLD(ste)) {
271
+ qemu_log_mask(LOG_UNIMP,
272
+ "SMMUv3 S1 stalling fault model not allowed yet\n");
273
+ goto bad_ste;
274
+ }
275
+ return 0;
276
+
277
+bad_ste:
278
+ event->type = SMMU_EVT_C_BAD_STE;
279
+ return -EINVAL;
280
+}
281
+
282
+/**
283
+ * smmu_find_ste - Return the stream table entry associated
284
+ * to the sid
285
+ *
286
+ * @s: smmuv3 handle
287
+ * @sid: stream ID
288
+ * @ste: returned stream table entry
289
+ * @event: handle to an event info
290
+ *
291
+ * Supports linear and 2-level stream table
292
+ * Return 0 on success, -EINVAL otherwise
293
+ */
294
+static int smmu_find_ste(SMMUv3State *s, uint32_t sid, STE *ste,
295
+ SMMUEventInfo *event)
296
+{
297
+ dma_addr_t addr;
298
+ int ret;
299
+
300
+ trace_smmuv3_find_ste(sid, s->features, s->sid_split);
301
+ /* Check SID range */
302
+ if (sid > (1 << SMMU_IDR1_SIDSIZE)) {
303
+ event->type = SMMU_EVT_C_BAD_STREAMID;
304
+ return -EINVAL;
305
+ }
306
+ if (s->features & SMMU_FEATURE_2LVL_STE) {
307
+ int l1_ste_offset, l2_ste_offset, max_l2_ste, span;
308
+ dma_addr_t strtab_base, l1ptr, l2ptr;
309
+ STEDesc l1std;
310
+
311
+ strtab_base = s->strtab_base & SMMU_BASE_ADDR_MASK;
312
+ l1_ste_offset = sid >> s->sid_split;
313
+ l2_ste_offset = sid & ((1 << s->sid_split) - 1);
314
+ l1ptr = (dma_addr_t)(strtab_base + l1_ste_offset * sizeof(l1std));
315
+ /* TODO: guarantee 64-bit single-copy atomicity */
316
+ ret = dma_memory_read(&address_space_memory, l1ptr,
317
+ (uint8_t *)&l1std, sizeof(l1std));
318
+ if (ret != MEMTX_OK) {
319
+ qemu_log_mask(LOG_GUEST_ERROR,
320
+ "Could not read L1PTR at 0X%"PRIx64"\n", l1ptr);
321
+ event->type = SMMU_EVT_F_STE_FETCH;
322
+ event->u.f_ste_fetch.addr = l1ptr;
323
+ return -EINVAL;
324
+ }
325
+
326
+ span = L1STD_SPAN(&l1std);
327
+
328
+ if (!span) {
329
+ /* l2ptr is not valid */
330
+ qemu_log_mask(LOG_GUEST_ERROR,
331
+ "invalid sid=%d (L1STD span=0)\n", sid);
332
+ event->type = SMMU_EVT_C_BAD_STREAMID;
333
+ return -EINVAL;
334
+ }
335
+ max_l2_ste = (1 << span) - 1;
336
+ l2ptr = l1std_l2ptr(&l1std);
337
+ trace_smmuv3_find_ste_2lvl(s->strtab_base, l1ptr, l1_ste_offset,
338
+ l2ptr, l2_ste_offset, max_l2_ste);
339
+ if (l2_ste_offset > max_l2_ste) {
340
+ qemu_log_mask(LOG_GUEST_ERROR,
341
+ "l2_ste_offset=%d > max_l2_ste=%d\n",
342
+ l2_ste_offset, max_l2_ste);
343
+ event->type = SMMU_EVT_C_BAD_STE;
344
+ return -EINVAL;
345
+ }
346
+ addr = l2ptr + l2_ste_offset * sizeof(*ste);
347
+ } else {
348
+ addr = s->strtab_base + sid * sizeof(*ste);
349
+ }
350
+
351
+ if (smmu_get_ste(s, addr, ste, event)) {
352
+ return -EINVAL;
353
+ }
354
+
355
+ return 0;
356
+}
357
+
358
+static int decode_cd(SMMUTransCfg *cfg, CD *cd, SMMUEventInfo *event)
359
+{
360
+ int ret = -EINVAL;
361
+ int i;
362
+
363
+ if (!CD_VALID(cd) || !CD_AARCH64(cd)) {
364
+ goto bad_cd;
365
+ }
366
+ if (!CD_A(cd)) {
367
+ goto bad_cd; /* SMMU_IDR0.TERM_MODEL == 1 */
368
+ }
369
+ if (CD_S(cd)) {
370
+ goto bad_cd; /* !STE_SECURE && SMMU_IDR0.STALL_MODEL == 1 */
371
+ }
372
+ if (CD_HA(cd) || CD_HD(cd)) {
373
+ goto bad_cd; /* HTTU = 0 */
374
+ }
375
+
376
+ /* we support only those at the moment */
377
+ cfg->aa64 = true;
378
+ cfg->stage = 1;
379
+
380
+ cfg->oas = oas2bits(CD_IPS(cd));
381
+ cfg->oas = MIN(oas2bits(SMMU_IDR5_OAS), cfg->oas);
382
+ cfg->tbi = CD_TBI(cd);
383
+ cfg->asid = CD_ASID(cd);
384
+
385
+ trace_smmuv3_decode_cd(cfg->oas);
386
+
387
+ /* decode data dependent on TT */
388
+ for (i = 0; i <= 1; i++) {
389
+ int tg, tsz;
390
+ SMMUTransTableInfo *tt = &cfg->tt[i];
391
+
392
+ cfg->tt[i].disabled = CD_EPD(cd, i);
393
+ if (cfg->tt[i].disabled) {
394
+ continue;
395
+ }
396
+
397
+ tsz = CD_TSZ(cd, i);
398
+ if (tsz < 16 || tsz > 39) {
399
+ goto bad_cd;
400
+ }
401
+
402
+ tg = CD_TG(cd, i);
403
+ tt->granule_sz = tg2granule(tg, i);
404
+ if ((tt->granule_sz != 12 && tt->granule_sz != 16) || CD_ENDI(cd)) {
405
+ goto bad_cd;
406
+ }
407
+
408
+ tt->tsz = tsz;
409
+ tt->ttb = CD_TTB(cd, i);
410
+ if (tt->ttb & ~(MAKE_64BIT_MASK(0, cfg->oas))) {
411
+ goto bad_cd;
412
+ }
413
+ trace_smmuv3_decode_cd_tt(i, tt->tsz, tt->ttb, tt->granule_sz);
414
+ }
415
+
416
+ event->record_trans_faults = CD_R(cd);
417
+
418
+ return 0;
419
+
420
+bad_cd:
421
+ event->type = SMMU_EVT_C_BAD_CD;
422
+ return ret;
423
+}
424
+
425
+/**
426
+ * smmuv3_decode_config - Prepare the translation configuration
427
+ * for the @mr iommu region
428
+ * @mr: iommu memory region the translation config must be prepared for
429
+ * @cfg: output translation configuration which is populated through
430
+ * the different configuration decoding steps
431
+ * @event: must be zero'ed by the caller
432
+ *
433
+ * return < 0 if the translation needs to be aborted (@event is filled
434
+ * accordingly). Return 0 otherwise.
435
+ */
436
+static int smmuv3_decode_config(IOMMUMemoryRegion *mr, SMMUTransCfg *cfg,
437
+ SMMUEventInfo *event)
438
+{
439
+ SMMUDevice *sdev = container_of(mr, SMMUDevice, iommu);
440
+ uint32_t sid = smmu_get_sid(sdev);
441
+ SMMUv3State *s = sdev->smmu;
442
+ int ret = -EINVAL;
443
+ STE ste;
444
+ CD cd;
445
+
446
+ if (smmu_find_ste(s, sid, &ste, event)) {
447
+ return ret;
448
+ }
449
+
450
+ if (decode_ste(s, cfg, &ste, event)) {
451
+ return ret;
452
+ }
453
+
454
+ if (smmu_get_cd(s, &ste, 0 /* ssid */, &cd, event)) {
455
+ return ret;
456
+ }
457
+
458
+ return decode_cd(cfg, &cd, event);
459
+}
460
+
461
+static IOMMUTLBEntry smmuv3_translate(IOMMUMemoryRegion *mr, hwaddr addr,
462
+ IOMMUAccessFlags flag)
463
+{
464
+ SMMUDevice *sdev = container_of(mr, SMMUDevice, iommu);
465
+ SMMUv3State *s = sdev->smmu;
466
+ uint32_t sid = smmu_get_sid(sdev);
467
+ SMMUEventInfo event = {.type = SMMU_EVT_OK, .sid = sid};
468
+ SMMUPTWEventInfo ptw_info = {};
469
+ SMMUTransCfg cfg = {};
470
+ IOMMUTLBEntry entry = {
471
+ .target_as = &address_space_memory,
472
+ .iova = addr,
473
+ .translated_addr = addr,
474
+ .addr_mask = ~(hwaddr)0,
475
+ .perm = IOMMU_NONE,
476
+ };
477
+ int ret = 0;
478
+
479
+ if (!smmu_enabled(s)) {
480
+ goto out;
481
+ }
482
+
483
+ ret = smmuv3_decode_config(mr, &cfg, &event);
484
+ if (ret) {
485
+ goto out;
486
+ }
487
+
488
+ if (cfg.aborted) {
489
+ goto out;
490
+ }
491
+
492
+ ret = smmu_ptw(&cfg, addr, flag, &entry, &ptw_info);
493
+ if (ret) {
494
+ switch (ptw_info.type) {
495
+ case SMMU_PTW_ERR_WALK_EABT:
496
+ event.type = SMMU_EVT_F_WALK_EABT;
497
+ event.u.f_walk_eabt.addr = addr;
498
+ event.u.f_walk_eabt.rnw = flag & 0x1;
499
+ event.u.f_walk_eabt.class = 0x1;
500
+ event.u.f_walk_eabt.addr2 = ptw_info.addr;
501
+ break;
502
+ case SMMU_PTW_ERR_TRANSLATION:
503
+ if (event.record_trans_faults) {
504
+ event.type = SMMU_EVT_F_TRANSLATION;
505
+ event.u.f_translation.addr = addr;
506
+ event.u.f_translation.rnw = flag & 0x1;
507
+ }
508
+ break;
509
+ case SMMU_PTW_ERR_ADDR_SIZE:
510
+ if (event.record_trans_faults) {
511
+ event.type = SMMU_EVT_F_ADDR_SIZE;
512
+ event.u.f_addr_size.addr = addr;
513
+ event.u.f_addr_size.rnw = flag & 0x1;
514
+ }
515
+ break;
516
+ case SMMU_PTW_ERR_ACCESS:
517
+ if (event.record_trans_faults) {
518
+ event.type = SMMU_EVT_F_ACCESS;
519
+ event.u.f_access.addr = addr;
520
+ event.u.f_access.rnw = flag & 0x1;
521
+ }
522
+ break;
523
+ case SMMU_PTW_ERR_PERMISSION:
524
+ if (event.record_trans_faults) {
525
+ event.type = SMMU_EVT_F_PERMISSION;
526
+ event.u.f_permission.addr = addr;
527
+ event.u.f_permission.rnw = flag & 0x1;
528
+ }
529
+ break;
530
+ default:
531
+ g_assert_not_reached();
532
+ }
533
+ }
534
+out:
535
+ if (ret) {
536
+ qemu_log_mask(LOG_GUEST_ERROR,
537
+ "%s translation failed for iova=0x%"PRIx64"(%d)\n",
538
+ mr->parent_obj.name, addr, ret);
539
+ entry.perm = IOMMU_NONE;
540
+ smmuv3_record_event(s, &event);
541
+ } else if (!cfg.aborted) {
542
+ entry.perm = flag;
543
+ trace_smmuv3_translate(mr->parent_obj.name, sid, addr,
544
+ entry.translated_addr, entry.perm);
545
+ }
546
+
547
+ return entry;
548
+}
549
+
550
static int smmuv3_cmdq_consume(SMMUv3State *s)
551
{
552
SMMUCmdError cmd_error = SMMU_CERROR_NONE;
553
@@ -XXX,XX +XXX,XX @@ static void smmuv3_class_init(ObjectClass *klass, void *data)
554
static void smmuv3_iommu_memory_region_class_init(ObjectClass *klass,
555
void *data)
556
{
557
+ IOMMUMemoryRegionClass *imrc = IOMMU_MEMORY_REGION_CLASS(klass);
558
+
559
+ imrc->translate = smmuv3_translate;
560
}
56
}
561
57
562
static const TypeInfo smmuv3_type_info = {
58
/*
563
diff --git a/hw/arm/trace-events b/hw/arm/trace-events
59
@@ -XXX,XX +XXX,XX @@ static void test_first_byte_monobit(void)
564
index XXXXXXX..XXXXXXX 100644
60
}
565
--- a/hw/arm/trace-events
61
566
+++ b/hw/arm/trace-events
62
g_assert_cmpfloat(calc_monobit_p(buf, sizeof(buf)), >, 0.01);
567
@@ -XXX,XX +XXX,XX @@ smmuv3_write_mmio_idr(uint64_t addr, uint64_t val) "write to RO/Unimpl reg 0x%lx
63
+ dump_buf_if_failed(buf, sizeof(buf));
568
smmuv3_write_mmio_evtq_cons_bef_clear(uint32_t prod, uint32_t cons, uint8_t prod_wrap, uint8_t cons_wrap) "Before clearing interrupt prod:0x%x cons:0x%x prod.w:%d cons.w:%d"
64
}
569
smmuv3_write_mmio_evtq_cons_after_clear(uint32_t prod, uint32_t cons, uint8_t prod_wrap, uint8_t cons_wrap) "after clearing interrupt prod:0x%x cons:0x%x prod.w:%d cons.w:%d"
65
570
smmuv3_record_event(const char *type, uint32_t sid) "%s sid=%d"
66
/*
571
+smmuv3_find_ste(uint16_t sid, uint32_t features, uint16_t sid_split) "SID:0x%x features:0x%x, sid_split:0x%x"
67
@@ -XXX,XX +XXX,XX @@ static void test_first_byte_runs(void)
572
+smmuv3_find_ste_2lvl(uint64_t strtab_base, uint64_t l1ptr, int l1_ste_offset, uint64_t l2ptr, int l2_ste_offset, int max_l2_ste) "strtab_base:0x%lx l1ptr:0x%"PRIx64" l1_off:0x%x, l2ptr:0x%"PRIx64" l2_off:0x%x max_l2_ste:%d"
68
}
573
+smmuv3_get_ste(uint64_t addr) "STE addr: 0x%"PRIx64
69
574
+smmuv3_translate_bypass(const char *n, uint16_t sid, uint64_t addr, bool is_write) "%s sid=%d bypass iova:0x%"PRIx64" is_write=%d"
70
g_assert_cmpfloat(calc_runs_p(buf.l, sizeof(buf) * BITS_PER_BYTE), >, 0.01);
575
+smmuv3_translate_in(uint16_t sid, int pci_bus_num, uint64_t strtab_base) "SID:0x%x bus:%d strtab_base:0x%"PRIx64
71
+ dump_buf_if_failed(buf.c, sizeof(buf));
576
+smmuv3_get_cd(uint64_t addr) "CD addr: 0x%"PRIx64
72
}
577
+smmuv3_translate(const char *n, uint16_t sid, uint64_t iova, uint64_t translated, int perm) "%s sid=%d iova=0x%"PRIx64" translated=0x%"PRIx64" perm=0x%x"
73
578
+smmuv3_decode_cd(uint32_t oas) "oas=%d"
74
int main(int argc, char **argv)
579
+smmuv3_decode_cd_tt(int i, uint32_t tsz, uint64_t ttb, uint32_t granule_sz) "TT[%d]:tsz:%d ttb:0x%"PRIx64" granule_sz:%d"
580
--
75
--
581
2.17.0
76
2.20.1
582
77
583
78
diff view generated by jsdifflib
1
From: Eric Auger <eric.auger@redhat.com>
1
From: Alex Chen <alex.chen@huawei.com>
2
2
3
ARM virt machine now exposes a new "iommu" option.
3
We should use printf format specifier "%u" instead of "%d" for
4
The SMMUv3 IOMMU is instantiated using -machine virt,iommu=smmuv3.
4
argument of type "unsigned int".
5
5
6
Signed-off-by: Eric Auger <eric.auger@redhat.com>
6
Reported-by: Euler Robot <euler.robot@huawei.com>
7
Signed-off-by: Prem Mallappa <prem.mallappa@broadcom.com>
7
Signed-off-by: Alex Chen <alex.chen@huawei.com>
8
Message-id: 20201126111109.112238-2-alex.chen@huawei.com
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Message-id: 1524665762-31355-15-git-send-email-eric.auger@redhat.com
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
11
---
12
hw/arm/virt.c | 36 ++++++++++++++++++++++++++++++++++++
12
hw/misc/imx25_ccm.c | 12 ++++++------
13
1 file changed, 36 insertions(+)
13
1 file changed, 6 insertions(+), 6 deletions(-)
14
14
15
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
15
diff --git a/hw/misc/imx25_ccm.c b/hw/misc/imx25_ccm.c
16
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/arm/virt.c
17
--- a/hw/misc/imx25_ccm.c
18
+++ b/hw/arm/virt.c
18
+++ b/hw/misc/imx25_ccm.c
19
@@ -XXX,XX +XXX,XX @@ static void virt_set_gic_version(Object *obj, const char *value, Error **errp)
19
@@ -XXX,XX +XXX,XX @@ static const char *imx25_ccm_reg_name(uint32_t reg)
20
case IMX25_CCM_LPIMR1_REG:
21
return "lpimr1";
22
default:
23
- sprintf(unknown, "[%d ?]", reg);
24
+ sprintf(unknown, "[%u ?]", reg);
25
return unknown;
20
}
26
}
21
}
27
}
22
28
@@ -XXX,XX +XXX,XX @@ static uint32_t imx25_ccm_get_mpll_clk(IMXCCMState *dev)
23
+static char *virt_get_iommu(Object *obj, Error **errp)
29
freq = imx_ccm_calc_pll(s->reg[IMX25_CCM_MPCTL_REG], CKIH_FREQ);
24
+{
25
+ VirtMachineState *vms = VIRT_MACHINE(obj);
26
+
27
+ switch (vms->iommu) {
28
+ case VIRT_IOMMU_NONE:
29
+ return g_strdup("none");
30
+ case VIRT_IOMMU_SMMUV3:
31
+ return g_strdup("smmuv3");
32
+ default:
33
+ g_assert_not_reached();
34
+ }
35
+}
36
+
37
+static void virt_set_iommu(Object *obj, const char *value, Error **errp)
38
+{
39
+ VirtMachineState *vms = VIRT_MACHINE(obj);
40
+
41
+ if (!strcmp(value, "smmuv3")) {
42
+ vms->iommu = VIRT_IOMMU_SMMUV3;
43
+ } else if (!strcmp(value, "none")) {
44
+ vms->iommu = VIRT_IOMMU_NONE;
45
+ } else {
46
+ error_setg(errp, "Invalid iommu value");
47
+ error_append_hint(errp, "Valid values are none, smmuv3.\n");
48
+ }
49
+}
50
+
51
static CpuInstanceProperties
52
virt_cpu_index_to_props(MachineState *ms, unsigned cpu_index)
53
{
54
@@ -XXX,XX +XXX,XX @@ static void virt_2_12_instance_init(Object *obj)
55
NULL);
56
}
30
}
57
31
58
+ /* Default disallows iommu instantiation */
32
- DPRINTF("freq = %d\n", freq);
59
+ vms->iommu = VIRT_IOMMU_NONE;
33
+ DPRINTF("freq = %u\n", freq);
60
+ object_property_add_str(obj, "iommu", virt_get_iommu, virt_set_iommu, NULL);
34
61
+ object_property_set_description(obj, "iommu",
35
return freq;
62
+ "Set the IOMMU type. "
36
}
63
+ "Valid values are none and smmuv3",
37
@@ -XXX,XX +XXX,XX @@ static uint32_t imx25_ccm_get_mcu_clk(IMXCCMState *dev)
64
+ NULL);
38
65
+
39
freq = freq / (1 + EXTRACT(s->reg[IMX25_CCM_CCTL_REG], ARM_CLK_DIV));
66
vms->memmap = a15memmap;
40
67
vms->irqmap = a15irqmap;
41
- DPRINTF("freq = %d\n", freq);
42
+ DPRINTF("freq = %u\n", freq);
43
44
return freq;
45
}
46
@@ -XXX,XX +XXX,XX @@ static uint32_t imx25_ccm_get_ahb_clk(IMXCCMState *dev)
47
freq = imx25_ccm_get_mcu_clk(dev)
48
/ (1 + EXTRACT(s->reg[IMX25_CCM_CCTL_REG], AHB_CLK_DIV));
49
50
- DPRINTF("freq = %d\n", freq);
51
+ DPRINTF("freq = %u\n", freq);
52
53
return freq;
54
}
55
@@ -XXX,XX +XXX,XX @@ static uint32_t imx25_ccm_get_ipg_clk(IMXCCMState *dev)
56
57
freq = imx25_ccm_get_ahb_clk(dev) / 2;
58
59
- DPRINTF("freq = %d\n", freq);
60
+ DPRINTF("freq = %u\n", freq);
61
62
return freq;
63
}
64
@@ -XXX,XX +XXX,XX @@ static uint32_t imx25_ccm_get_clock_frequency(IMXCCMState *dev, IMXClk clock)
65
break;
66
}
67
68
- DPRINTF("Clock = %d) = %d\n", clock, freq);
69
+ DPRINTF("Clock = %d) = %u\n", clock, freq);
70
71
return freq;
68
}
72
}
69
--
73
--
70
2.17.0
74
2.20.1
71
75
72
76
diff view generated by jsdifflib
1
From: Thomas Huth <thuth@redhat.com>
1
From: Alex Chen <alex.chen@huawei.com>
2
2
3
When running omap1/2 or pxa2xx based ARM machines with -nodefaults,
3
We should use printf format specifier "%u" instead of "%d" for
4
they bail out immediately complaining about a "missing SecureDigital
4
argument of type "unsigned int".
5
device". That's not how the "default" devices in vl.c are meant to
6
work - it should be possible for a board to also start up without
7
default devices. So let's turn the error message and exit() into
8
a warning instead.
9
5
10
Signed-off-by: Thomas Huth <thuth@redhat.com>
6
Reported-by: Euler Robot <euler.robot@huawei.com>
11
Message-id: 1525326811-3233-1-git-send-email-thuth@redhat.com
7
Signed-off-by: Alex Chen <alex.chen@huawei.com>
12
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Message-id: 20201126111109.112238-3-alex.chen@huawei.com
13
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
---
11
---
16
hw/arm/omap1.c | 8 ++++----
12
hw/misc/imx31_ccm.c | 14 +++++++-------
17
hw/arm/omap2.c | 8 ++++----
13
hw/misc/imx_ccm.c | 4 ++--
18
hw/arm/pxa2xx.c | 15 +++++++--------
14
2 files changed, 9 insertions(+), 9 deletions(-)
19
3 files changed, 15 insertions(+), 16 deletions(-)
20
15
21
diff --git a/hw/arm/omap1.c b/hw/arm/omap1.c
16
diff --git a/hw/misc/imx31_ccm.c b/hw/misc/imx31_ccm.c
22
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
23
--- a/hw/arm/omap1.c
18
--- a/hw/misc/imx31_ccm.c
24
+++ b/hw/arm/omap1.c
19
+++ b/hw/misc/imx31_ccm.c
25
@@ -XXX,XX +XXX,XX @@
20
@@ -XXX,XX +XXX,XX @@ static const char *imx31_ccm_reg_name(uint32_t reg)
26
#include "hw/arm/soc_dma.h"
21
case IMX31_CCM_PDR2_REG:
27
#include "sysemu/block-backend.h"
22
return "PDR2";
28
#include "sysemu/blockdev.h"
23
default:
29
+#include "sysemu/qtest.h"
24
- sprintf(unknown, "[%d ?]", reg);
30
#include "qemu/range.h"
25
+ sprintf(unknown, "[%u ?]", reg);
31
#include "hw/sysbus.h"
26
return unknown;
32
#include "qemu/cutils.h"
33
@@ -XXX,XX +XXX,XX @@ struct omap_mpu_state_s *omap310_mpu_init(MemoryRegion *system_memory,
34
omap_findclk(s, "dpll3"));
35
36
dinfo = drive_get(IF_SD, 0, 0);
37
- if (!dinfo) {
38
- error_report("missing SecureDigital device");
39
- exit(1);
40
+ if (!dinfo && !qtest_enabled()) {
41
+ warn_report("missing SecureDigital device");
42
}
27
}
43
s->mmc = omap_mmc_init(0xfffb7800, system_memory,
28
}
44
- blk_by_legacy_dinfo(dinfo),
29
@@ -XXX,XX +XXX,XX @@ static uint32_t imx31_ccm_get_pll_ref_clk(IMXCCMState *dev)
45
+ dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
30
freq = CKIH_FREQ;
46
qdev_get_gpio_in(s->ih[1], OMAP_INT_OQN),
31
}
47
&s->drq[OMAP_DMA_MMC_TX],
32
48
omap_findclk(s, "mmc_ck"));
33
- DPRINTF("freq = %d\n", freq);
49
diff --git a/hw/arm/omap2.c b/hw/arm/omap2.c
34
+ DPRINTF("freq = %u\n", freq);
35
36
return freq;
37
}
38
@@ -XXX,XX +XXX,XX @@ static uint32_t imx31_ccm_get_mpll_clk(IMXCCMState *dev)
39
freq = imx_ccm_calc_pll(s->reg[IMX31_CCM_MPCTL_REG],
40
imx31_ccm_get_pll_ref_clk(dev));
41
42
- DPRINTF("freq = %d\n", freq);
43
+ DPRINTF("freq = %u\n", freq);
44
45
return freq;
46
}
47
@@ -XXX,XX +XXX,XX @@ static uint32_t imx31_ccm_get_mcu_main_clk(IMXCCMState *dev)
48
freq = imx31_ccm_get_mpll_clk(dev);
49
}
50
51
- DPRINTF("freq = %d\n", freq);
52
+ DPRINTF("freq = %u\n", freq);
53
54
return freq;
55
}
56
@@ -XXX,XX +XXX,XX @@ static uint32_t imx31_ccm_get_hclk_clk(IMXCCMState *dev)
57
freq = imx31_ccm_get_mcu_main_clk(dev)
58
/ (1 + EXTRACT(s->reg[IMX31_CCM_PDR0_REG], MAX));
59
60
- DPRINTF("freq = %d\n", freq);
61
+ DPRINTF("freq = %u\n", freq);
62
63
return freq;
64
}
65
@@ -XXX,XX +XXX,XX @@ static uint32_t imx31_ccm_get_ipg_clk(IMXCCMState *dev)
66
freq = imx31_ccm_get_hclk_clk(dev)
67
/ (1 + EXTRACT(s->reg[IMX31_CCM_PDR0_REG], IPG));
68
69
- DPRINTF("freq = %d\n", freq);
70
+ DPRINTF("freq = %u\n", freq);
71
72
return freq;
73
}
74
@@ -XXX,XX +XXX,XX @@ static uint32_t imx31_ccm_get_clock_frequency(IMXCCMState *dev, IMXClk clock)
75
break;
76
}
77
78
- DPRINTF("Clock = %d) = %d\n", clock, freq);
79
+ DPRINTF("Clock = %d) = %u\n", clock, freq);
80
81
return freq;
82
}
83
diff --git a/hw/misc/imx_ccm.c b/hw/misc/imx_ccm.c
50
index XXXXXXX..XXXXXXX 100644
84
index XXXXXXX..XXXXXXX 100644
51
--- a/hw/arm/omap2.c
85
--- a/hw/misc/imx_ccm.c
52
+++ b/hw/arm/omap2.c
86
+++ b/hw/misc/imx_ccm.c
53
@@ -XXX,XX +XXX,XX @@
87
@@ -XXX,XX +XXX,XX @@ uint32_t imx_ccm_get_clock_frequency(IMXCCMState *dev, IMXClk clock)
54
#include "cpu.h"
88
freq = klass->get_clock_frequency(dev, clock);
55
#include "sysemu/block-backend.h"
56
#include "sysemu/blockdev.h"
57
+#include "sysemu/qtest.h"
58
#include "hw/boards.h"
59
#include "hw/hw.h"
60
#include "hw/arm/arm.h"
61
@@ -XXX,XX +XXX,XX @@ struct omap_mpu_state_s *omap2420_mpu_init(MemoryRegion *sysmem,
62
s->drq[OMAP24XX_DMA_GPMC]);
63
64
dinfo = drive_get(IF_SD, 0, 0);
65
- if (!dinfo) {
66
- error_report("missing SecureDigital device");
67
- exit(1);
68
+ if (!dinfo && !qtest_enabled()) {
69
+ warn_report("missing SecureDigital device");
70
}
89
}
71
s->mmc = omap2_mmc_init(omap_l4tao(s->l4, 9),
90
72
- blk_by_legacy_dinfo(dinfo),
91
- DPRINTF("(clock = %d) = %d\n", clock, freq);
73
+ dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
92
+ DPRINTF("(clock = %d) = %u\n", clock, freq);
74
qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_MMC_IRQ),
93
75
&s->drq[OMAP24XX_DMA_MMC1_TX],
94
return freq;
76
omap_findclk(s, "mmc_fclk"), omap_findclk(s, "mmc_iclk"));
95
}
77
diff --git a/hw/arm/pxa2xx.c b/hw/arm/pxa2xx.c
96
@@ -XXX,XX +XXX,XX @@ uint32_t imx_ccm_calc_pll(uint32_t pllreg, uint32_t base_freq)
78
index XXXXXXX..XXXXXXX 100644
97
freq = ((2 * (base_freq >> 10) * (mfi * mfd + mfn)) /
79
--- a/hw/arm/pxa2xx.c
98
(mfd * pd)) << 10;
80
+++ b/hw/arm/pxa2xx.c
99
81
@@ -XXX,XX +XXX,XX @@
100
- DPRINTF("(pllreg = 0x%08x, base_freq = %d) = %d\n", pllreg, base_freq,
82
#include "chardev/char-fe.h"
101
+ DPRINTF("(pllreg = 0x%08x, base_freq = %u) = %d\n", pllreg, base_freq,
83
#include "sysemu/block-backend.h"
102
freq);
84
#include "sysemu/blockdev.h"
103
85
+#include "sysemu/qtest.h"
104
return freq;
86
#include "qemu/cutils.h"
87
88
static struct {
89
@@ -XXX,XX +XXX,XX @@ PXA2xxState *pxa270_init(MemoryRegion *address_space,
90
s->gpio = pxa2xx_gpio_init(0x40e00000, s->cpu, s->pic, 121);
91
92
dinfo = drive_get(IF_SD, 0, 0);
93
- if (!dinfo) {
94
- error_report("missing SecureDigital device");
95
- exit(1);
96
+ if (!dinfo && !qtest_enabled()) {
97
+ warn_report("missing SecureDigital device");
98
}
99
s->mmc = pxa2xx_mmci_init(address_space, 0x41100000,
100
- blk_by_legacy_dinfo(dinfo),
101
+ dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
102
qdev_get_gpio_in(s->pic, PXA2XX_PIC_MMC),
103
qdev_get_gpio_in(s->dma, PXA2XX_RX_RQ_MMCI),
104
qdev_get_gpio_in(s->dma, PXA2XX_TX_RQ_MMCI));
105
@@ -XXX,XX +XXX,XX @@ PXA2xxState *pxa255_init(MemoryRegion *address_space, unsigned int sdram_size)
106
s->gpio = pxa2xx_gpio_init(0x40e00000, s->cpu, s->pic, 85);
107
108
dinfo = drive_get(IF_SD, 0, 0);
109
- if (!dinfo) {
110
- error_report("missing SecureDigital device");
111
- exit(1);
112
+ if (!dinfo && !qtest_enabled()) {
113
+ warn_report("missing SecureDigital device");
114
}
115
s->mmc = pxa2xx_mmci_init(address_space, 0x41100000,
116
- blk_by_legacy_dinfo(dinfo),
117
+ dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
118
qdev_get_gpio_in(s->pic, PXA2XX_PIC_MMC),
119
qdev_get_gpio_in(s->dma, PXA2XX_RX_RQ_MMCI),
120
qdev_get_gpio_in(s->dma, PXA2XX_TX_RQ_MMCI));
121
--
105
--
122
2.17.0
106
2.20.1
123
107
124
108
diff view generated by jsdifflib
1
From: Patrick Oppenlander <patrick.oppenlander@gmail.com>
1
From: Alex Chen <alex.chen@huawei.com>
2
2
3
The character frontend needs to be notified that the uart receive buffer
3
We should use printf format specifier "%u" instead of "%d" for
4
is empty and ready to handle another character.
4
argument of type "unsigned int".
5
5
6
Previously, the uart only worked correctly when receiving one character
6
Reported-by: Euler Robot <euler.robot@huawei.com>
7
at a time.
7
Signed-off-by: Alex Chen <alex.chen@huawei.com>
8
8
Message-id: 20201126111109.112238-4-alex.chen@huawei.com
9
Signed-off-by: Patrick Oppenlander <patrick.oppenlander@gmail.com>
10
Message-id: CAEg67GkRTw=cXei3o9hvpxG_L4zSrNzR0bFyAgny+sSEUb_kPw@mail.gmail.com
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
11
---
14
hw/char/cmsdk-apb-uart.c | 1 +
12
hw/misc/imx6_ccm.c | 20 ++++++++++----------
15
1 file changed, 1 insertion(+)
13
hw/misc/imx6_src.c | 2 +-
14
2 files changed, 11 insertions(+), 11 deletions(-)
16
15
17
diff --git a/hw/char/cmsdk-apb-uart.c b/hw/char/cmsdk-apb-uart.c
16
diff --git a/hw/misc/imx6_ccm.c b/hw/misc/imx6_ccm.c
18
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/char/cmsdk-apb-uart.c
18
--- a/hw/misc/imx6_ccm.c
20
+++ b/hw/char/cmsdk-apb-uart.c
19
+++ b/hw/misc/imx6_ccm.c
21
@@ -XXX,XX +XXX,XX @@ static uint64_t uart_read(void *opaque, hwaddr offset, unsigned size)
20
@@ -XXX,XX +XXX,XX @@ static const char *imx6_ccm_reg_name(uint32_t reg)
22
r = s->rxbuf;
21
case CCM_CMEOR:
23
s->state &= ~R_STATE_RXFULL_MASK;
22
return "CMEOR";
24
cmsdk_apb_uart_update(s);
23
default:
25
+ qemu_chr_fe_accept_input(&s->chr);
24
- sprintf(unknown, "%d ?", reg);
25
+ sprintf(unknown, "%u ?", reg);
26
return unknown;
27
}
28
}
29
@@ -XXX,XX +XXX,XX @@ static const char *imx6_analog_reg_name(uint32_t reg)
30
case USB_ANALOG_DIGPROG:
31
return "USB_ANALOG_DIGPROG";
32
default:
33
- sprintf(unknown, "%d ?", reg);
34
+ sprintf(unknown, "%u ?", reg);
35
return unknown;
36
}
37
}
38
@@ -XXX,XX +XXX,XX @@ static uint64_t imx6_analog_get_pll2_clk(IMX6CCMState *dev)
39
freq *= 20;
40
}
41
42
- DPRINTF("freq = %d\n", (uint32_t)freq);
43
+ DPRINTF("freq = %u\n", (uint32_t)freq);
44
45
return freq;
46
}
47
@@ -XXX,XX +XXX,XX @@ static uint64_t imx6_analog_get_pll2_pfd0_clk(IMX6CCMState *dev)
48
freq = imx6_analog_get_pll2_clk(dev) * 18
49
/ EXTRACT(dev->analog[CCM_ANALOG_PFD_528], PFD0_FRAC);
50
51
- DPRINTF("freq = %d\n", (uint32_t)freq);
52
+ DPRINTF("freq = %u\n", (uint32_t)freq);
53
54
return freq;
55
}
56
@@ -XXX,XX +XXX,XX @@ static uint64_t imx6_analog_get_pll2_pfd2_clk(IMX6CCMState *dev)
57
freq = imx6_analog_get_pll2_clk(dev) * 18
58
/ EXTRACT(dev->analog[CCM_ANALOG_PFD_528], PFD2_FRAC);
59
60
- DPRINTF("freq = %d\n", (uint32_t)freq);
61
+ DPRINTF("freq = %u\n", (uint32_t)freq);
62
63
return freq;
64
}
65
@@ -XXX,XX +XXX,XX @@ static uint64_t imx6_analog_get_periph_clk(IMX6CCMState *dev)
26
break;
66
break;
27
case A_STATE:
67
}
28
r = s->state;
68
69
- DPRINTF("freq = %d\n", (uint32_t)freq);
70
+ DPRINTF("freq = %u\n", (uint32_t)freq);
71
72
return freq;
73
}
74
@@ -XXX,XX +XXX,XX @@ static uint64_t imx6_ccm_get_ahb_clk(IMX6CCMState *dev)
75
freq = imx6_analog_get_periph_clk(dev)
76
/ (1 + EXTRACT(dev->ccm[CCM_CBCDR], AHB_PODF));
77
78
- DPRINTF("freq = %d\n", (uint32_t)freq);
79
+ DPRINTF("freq = %u\n", (uint32_t)freq);
80
81
return freq;
82
}
83
@@ -XXX,XX +XXX,XX @@ static uint64_t imx6_ccm_get_ipg_clk(IMX6CCMState *dev)
84
freq = imx6_ccm_get_ahb_clk(dev)
85
/ (1 + EXTRACT(dev->ccm[CCM_CBCDR], IPG_PODF));
86
87
- DPRINTF("freq = %d\n", (uint32_t)freq);
88
+ DPRINTF("freq = %u\n", (uint32_t)freq);
89
90
return freq;
91
}
92
@@ -XXX,XX +XXX,XX @@ static uint64_t imx6_ccm_get_per_clk(IMX6CCMState *dev)
93
freq = imx6_ccm_get_ipg_clk(dev)
94
/ (1 + EXTRACT(dev->ccm[CCM_CSCMR1], PERCLK_PODF));
95
96
- DPRINTF("freq = %d\n", (uint32_t)freq);
97
+ DPRINTF("freq = %u\n", (uint32_t)freq);
98
99
return freq;
100
}
101
@@ -XXX,XX +XXX,XX @@ static uint32_t imx6_ccm_get_clock_frequency(IMXCCMState *dev, IMXClk clock)
102
break;
103
}
104
105
- DPRINTF("Clock = %d) = %d\n", clock, freq);
106
+ DPRINTF("Clock = %d) = %u\n", clock, freq);
107
108
return freq;
109
}
110
diff --git a/hw/misc/imx6_src.c b/hw/misc/imx6_src.c
111
index XXXXXXX..XXXXXXX 100644
112
--- a/hw/misc/imx6_src.c
113
+++ b/hw/misc/imx6_src.c
114
@@ -XXX,XX +XXX,XX @@ static const char *imx6_src_reg_name(uint32_t reg)
115
case SRC_GPR10:
116
return "SRC_GPR10";
117
default:
118
- sprintf(unknown, "%d ?", reg);
119
+ sprintf(unknown, "%u ?", reg);
120
return unknown;
121
}
122
}
29
--
123
--
30
2.17.0
124
2.20.1
31
125
32
126
diff view generated by jsdifflib
1
From: Igor Mammedov <imammedo@redhat.com>
1
From: Alex Chen <alex.chen@huawei.com>
2
2
3
Even though nothing is currently broken (since all boards
3
We should use printf format specifier "%u" instead of "%d" for
4
use first_cpu as boot cpu), make sure that boot_info is set
4
argument of type "unsigned int".
5
on all CPUs.
6
If some board would like support heterogenuos setup (i.e.
7
init boot_info on subset of CPUs) in future, it should add
8
a reasonable API to do it, instead of starting assigning
9
boot_info from some CPU and till the end of present CPUs
10
list.
11
5
12
Ref:
6
Reported-by: Euler Robot <euler.robot@huawei.com>
13
"Message-ID: <CAFEAcA_NMWuA8WSs3cNeY6xX1kerO_uAcN_3=fK02BEhHJW86g@mail.gmail.com>"
7
Signed-off-by: Alex Chen <alex.chen@huawei.com>
14
8
Message-id: 20201126111109.112238-5-alex.chen@huawei.com
15
Signed-off-by: Igor Mammedov <imammedo@redhat.com>
16
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
17
Message-id: 1525176522-200354-5-git-send-email-imammedo@redhat.com
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
---
11
---
20
hw/arm/boot.c | 2 +-
12
hw/misc/imx6ul_ccm.c | 4 ++--
21
1 file changed, 1 insertion(+), 1 deletion(-)
13
1 file changed, 2 insertions(+), 2 deletions(-)
22
14
23
diff --git a/hw/arm/boot.c b/hw/arm/boot.c
15
diff --git a/hw/misc/imx6ul_ccm.c b/hw/misc/imx6ul_ccm.c
24
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
25
--- a/hw/arm/boot.c
17
--- a/hw/misc/imx6ul_ccm.c
26
+++ b/hw/arm/boot.c
18
+++ b/hw/misc/imx6ul_ccm.c
27
@@ -XXX,XX +XXX,XX @@ static void arm_load_kernel_notify(Notifier *notifier, void *data)
19
@@ -XXX,XX +XXX,XX @@ static const char *imx6ul_ccm_reg_name(uint32_t reg)
20
case CCM_CMEOR:
21
return "CMEOR";
22
default:
23
- sprintf(unknown, "%d ?", reg);
24
+ sprintf(unknown, "%u ?", reg);
25
return unknown;
28
}
26
}
29
info->is_linux = is_linux;
27
}
30
28
@@ -XXX,XX +XXX,XX @@ static const char *imx6ul_analog_reg_name(uint32_t reg)
31
- for (cs = CPU(cpu); cs; cs = CPU_NEXT(cs)) {
29
case USB_ANALOG_DIGPROG:
32
+ for (cs = first_cpu; cs; cs = CPU_NEXT(cs)) {
30
return "USB_ANALOG_DIGPROG";
33
ARM_CPU(cs)->env.boot_info = info;
31
default:
32
- sprintf(unknown, "%d ?", reg);
33
+ sprintf(unknown, "%u ?", reg);
34
return unknown;
34
}
35
}
35
}
36
}
36
--
37
--
37
2.17.0
38
2.20.1
38
39
39
40
diff view generated by jsdifflib
1
From: Eric Auger <eric.auger@redhat.com>
1
For M-profile CPUs, the range from 0xe0000000 to 0xe00fffff is the
2
Private Peripheral Bus range, which includes all of the memory mapped
3
devices and registers that are part of the CPU itself, including the
4
NVIC, systick timer, and debug and trace components like the Data
5
Watchpoint and Trace unit (DWT). Within this large region, the range
6
0xe000e000 to 0xe000efff is the System Control Space (NVIC, system
7
registers, systick) and 0xe002e000 to 0exe002efff is its Non-secure
8
alias.
2
9
3
Let's introduce a helper function aiming at recording an
10
The architecture is clear that within the SCS unimplemented registers
4
event in the event queue.
11
should be RES0 for privileged accesses and generate BusFault for
12
unprivileged accesses, and we currently implement this.
5
13
6
Signed-off-by: Eric Auger <eric.auger@redhat.com>
14
It is less clear about how to handle accesses to unimplemented
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
15
regions of the wider PPB. Unprivileged accesses should definitely
8
Message-id: 1524665762-31355-9-git-send-email-eric.auger@redhat.com
16
cause BusFaults (R_DQQS), but the behaviour of privileged accesses is
17
not given as a general rule. However, the register definitions of
18
individual registers for components like the DWT all state that they
19
are RES0 if the relevant component is not implemented, so the
20
simplest way to provide that is to provide RAZ/WI for the whole range
21
for privileged accesses. (The v7M Arm ARM does say that reserved
22
registers should be UNK/SBZP.)
23
24
Expand the container MemoryRegion that the NVIC exposes so that
25
it covers the whole PPB space. This means:
26
* moving the address that the ARMV7M device maps it to down by
27
0xe000 bytes
28
* moving the off and the offsets within the container of all the
29
subregions forward by 0xe000 bytes
30
* adding a new default MemoryRegion that covers the whole container
31
at a lower priority than anything else and which provides the
32
RAZWI/BusFault behaviour
33
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
34
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
35
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
36
Message-id: 20201119215617.29887-2-peter.maydell@linaro.org
10
---
37
---
11
hw/arm/smmuv3-internal.h | 148 ++++++++++++++++++++++++++++++++++++++-
38
include/hw/intc/armv7m_nvic.h | 1 +
12
hw/arm/smmuv3.c | 108 ++++++++++++++++++++++++++--
39
hw/arm/armv7m.c | 2 +-
13
hw/arm/trace-events | 1 +
40
hw/intc/armv7m_nvic.c | 78 ++++++++++++++++++++++++++++++-----
14
3 files changed, 249 insertions(+), 8 deletions(-)
41
3 files changed, 69 insertions(+), 12 deletions(-)
15
42
16
diff --git a/hw/arm/smmuv3-internal.h b/hw/arm/smmuv3-internal.h
43
diff --git a/include/hw/intc/armv7m_nvic.h b/include/hw/intc/armv7m_nvic.h
17
index XXXXXXX..XXXXXXX 100644
44
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/arm/smmuv3-internal.h
45
--- a/include/hw/intc/armv7m_nvic.h
19
+++ b/hw/arm/smmuv3-internal.h
46
+++ b/include/hw/intc/armv7m_nvic.h
20
@@ -XXX,XX +XXX,XX @@ static inline void smmu_write_cmdq_err(SMMUv3State *s, uint32_t err_type)
47
@@ -XXX,XX +XXX,XX @@ struct NVICState {
21
s->cmdq.cons = FIELD_DP32(s->cmdq.cons, CMDQ_CONS, ERR, err_type);
48
MemoryRegion systickmem;
22
}
49
MemoryRegion systick_ns_mem;
23
50
MemoryRegion container;
24
-void smmuv3_write_eventq(SMMUv3State *s, Evt *evt);
51
+ MemoryRegion defaultmem;
25
-
52
26
/* Commands */
53
uint32_t num_irq;
27
54
qemu_irq excpout;
28
typedef enum SMMUCommandType {
55
diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c
29
@@ -XXX,XX +XXX,XX @@ enum { /* Command completion notification */
56
index XXXXXXX..XXXXXXX 100644
30
57
--- a/hw/arm/armv7m.c
31
#define SMMU_FEATURE_2LVL_STE (1 << 0)
58
+++ b/hw/arm/armv7m.c
32
59
@@ -XXX,XX +XXX,XX @@ static void armv7m_realize(DeviceState *dev, Error **errp)
33
+/* Events */
60
sysbus_connect_irq(sbd, 0,
34
+
61
qdev_get_gpio_in(DEVICE(s->cpu), ARM_CPU_IRQ));
35
+typedef enum SMMUEventType {
62
36
+ SMMU_EVT_OK = 0x00,
63
- memory_region_add_subregion(&s->container, 0xe000e000,
37
+ SMMU_EVT_F_UUT ,
64
+ memory_region_add_subregion(&s->container, 0xe0000000,
38
+ SMMU_EVT_C_BAD_STREAMID ,
65
sysbus_mmio_get_region(sbd, 0));
39
+ SMMU_EVT_F_STE_FETCH ,
66
40
+ SMMU_EVT_C_BAD_STE ,
67
for (i = 0; i < ARRAY_SIZE(s->bitband); i++) {
41
+ SMMU_EVT_F_BAD_ATS_TREQ ,
68
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
42
+ SMMU_EVT_F_STREAM_DISABLED ,
69
index XXXXXXX..XXXXXXX 100644
43
+ SMMU_EVT_F_TRANS_FORBIDDEN ,
70
--- a/hw/intc/armv7m_nvic.c
44
+ SMMU_EVT_C_BAD_SUBSTREAMID ,
71
+++ b/hw/intc/armv7m_nvic.c
45
+ SMMU_EVT_F_CD_FETCH ,
72
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps nvic_systick_ops = {
46
+ SMMU_EVT_C_BAD_CD ,
73
.endianness = DEVICE_NATIVE_ENDIAN,
47
+ SMMU_EVT_F_WALK_EABT ,
74
};
48
+ SMMU_EVT_F_TRANSLATION = 0x10,
75
49
+ SMMU_EVT_F_ADDR_SIZE ,
76
+/*
50
+ SMMU_EVT_F_ACCESS ,
77
+ * Unassigned portions of the PPB space are RAZ/WI for privileged
51
+ SMMU_EVT_F_PERMISSION ,
78
+ * accesses, and fault for non-privileged accesses.
52
+ SMMU_EVT_F_TLB_CONFLICT = 0x20,
79
+ */
53
+ SMMU_EVT_F_CFG_CONFLICT ,
80
+static MemTxResult ppb_default_read(void *opaque, hwaddr addr,
54
+ SMMU_EVT_E_PAGE_REQ = 0x24,
81
+ uint64_t *data, unsigned size,
55
+} SMMUEventType;
82
+ MemTxAttrs attrs)
56
+
57
+static const char *event_stringify[] = {
58
+ [SMMU_EVT_OK] = "SMMU_EVT_OK",
59
+ [SMMU_EVT_F_UUT] = "SMMU_EVT_F_UUT",
60
+ [SMMU_EVT_C_BAD_STREAMID] = "SMMU_EVT_C_BAD_STREAMID",
61
+ [SMMU_EVT_F_STE_FETCH] = "SMMU_EVT_F_STE_FETCH",
62
+ [SMMU_EVT_C_BAD_STE] = "SMMU_EVT_C_BAD_STE",
63
+ [SMMU_EVT_F_BAD_ATS_TREQ] = "SMMU_EVT_F_BAD_ATS_TREQ",
64
+ [SMMU_EVT_F_STREAM_DISABLED] = "SMMU_EVT_F_STREAM_DISABLED",
65
+ [SMMU_EVT_F_TRANS_FORBIDDEN] = "SMMU_EVT_F_TRANS_FORBIDDEN",
66
+ [SMMU_EVT_C_BAD_SUBSTREAMID] = "SMMU_EVT_C_BAD_SUBSTREAMID",
67
+ [SMMU_EVT_F_CD_FETCH] = "SMMU_EVT_F_CD_FETCH",
68
+ [SMMU_EVT_C_BAD_CD] = "SMMU_EVT_C_BAD_CD",
69
+ [SMMU_EVT_F_WALK_EABT] = "SMMU_EVT_F_WALK_EABT",
70
+ [SMMU_EVT_F_TRANSLATION] = "SMMU_EVT_F_TRANSLATION",
71
+ [SMMU_EVT_F_ADDR_SIZE] = "SMMU_EVT_F_ADDR_SIZE",
72
+ [SMMU_EVT_F_ACCESS] = "SMMU_EVT_F_ACCESS",
73
+ [SMMU_EVT_F_PERMISSION] = "SMMU_EVT_F_PERMISSION",
74
+ [SMMU_EVT_F_TLB_CONFLICT] = "SMMU_EVT_F_TLB_CONFLICT",
75
+ [SMMU_EVT_F_CFG_CONFLICT] = "SMMU_EVT_F_CFG_CONFLICT",
76
+ [SMMU_EVT_E_PAGE_REQ] = "SMMU_EVT_E_PAGE_REQ",
77
+};
78
+
79
+static inline const char *smmu_event_string(SMMUEventType type)
80
+{
83
+{
81
+ if (type < ARRAY_SIZE(event_stringify)) {
84
+ qemu_log_mask(LOG_UNIMP, "Read of unassigned area of PPB: offset 0x%x\n",
82
+ return event_stringify[type] ? event_stringify[type] : "UNKNOWN";
85
+ (uint32_t)addr);
83
+ } else {
86
+ if (attrs.user) {
84
+ return "INVALID";
87
+ return MEMTX_ERROR;
85
+ }
88
+ }
89
+ *data = 0;
90
+ return MEMTX_OK;
86
+}
91
+}
87
+
92
+
88
+/* Encode an event record */
93
+static MemTxResult ppb_default_write(void *opaque, hwaddr addr,
89
+typedef struct SMMUEventInfo {
94
+ uint64_t value, unsigned size,
90
+ SMMUEventType type;
95
+ MemTxAttrs attrs)
91
+ uint32_t sid;
96
+{
92
+ bool recorded;
97
+ qemu_log_mask(LOG_UNIMP, "Write of unassigned area of PPB: offset 0x%x\n",
93
+ bool record_trans_faults;
98
+ (uint32_t)addr);
94
+ union {
99
+ if (attrs.user) {
95
+ struct {
96
+ uint32_t ssid;
97
+ bool ssv;
98
+ dma_addr_t addr;
99
+ bool rnw;
100
+ bool pnu;
101
+ bool ind;
102
+ } f_uut;
103
+ struct SSIDInfo {
104
+ uint32_t ssid;
105
+ bool ssv;
106
+ } c_bad_streamid;
107
+ struct SSIDAddrInfo {
108
+ uint32_t ssid;
109
+ bool ssv;
110
+ dma_addr_t addr;
111
+ } f_ste_fetch;
112
+ struct SSIDInfo c_bad_ste;
113
+ struct {
114
+ dma_addr_t addr;
115
+ bool rnw;
116
+ } f_transl_forbidden;
117
+ struct {
118
+ uint32_t ssid;
119
+ } c_bad_substream;
120
+ struct SSIDAddrInfo f_cd_fetch;
121
+ struct SSIDInfo c_bad_cd;
122
+ struct FullInfo {
123
+ bool stall;
124
+ uint16_t stag;
125
+ uint32_t ssid;
126
+ bool ssv;
127
+ bool s2;
128
+ dma_addr_t addr;
129
+ bool rnw;
130
+ bool pnu;
131
+ bool ind;
132
+ uint8_t class;
133
+ dma_addr_t addr2;
134
+ } f_walk_eabt;
135
+ struct FullInfo f_translation;
136
+ struct FullInfo f_addr_size;
137
+ struct FullInfo f_access;
138
+ struct FullInfo f_permission;
139
+ struct SSIDInfo f_cfg_conflict;
140
+ /**
141
+ * not supported yet:
142
+ * F_BAD_ATS_TREQ
143
+ * F_BAD_ATS_TREQ
144
+ * F_TLB_CONFLICT
145
+ * E_PAGE_REQUEST
146
+ * IMPDEF_EVENTn
147
+ */
148
+ } u;
149
+} SMMUEventInfo;
150
+
151
+/* EVTQ fields */
152
+
153
+#define EVT_Q_OVERFLOW (1 << 31)
154
+
155
+#define EVT_SET_TYPE(x, v) deposit32((x)->word[0], 0 , 8 , v)
156
+#define EVT_SET_SSV(x, v) deposit32((x)->word[0], 11, 1 , v)
157
+#define EVT_SET_SSID(x, v) deposit32((x)->word[0], 12, 20, v)
158
+#define EVT_SET_SID(x, v) ((x)->word[1] = v)
159
+#define EVT_SET_STAG(x, v) deposit32((x)->word[2], 0 , 16, v)
160
+#define EVT_SET_STALL(x, v) deposit32((x)->word[2], 31, 1 , v)
161
+#define EVT_SET_PNU(x, v) deposit32((x)->word[3], 1 , 1 , v)
162
+#define EVT_SET_IND(x, v) deposit32((x)->word[3], 2 , 1 , v)
163
+#define EVT_SET_RNW(x, v) deposit32((x)->word[3], 3 , 1 , v)
164
+#define EVT_SET_S2(x, v) deposit32((x)->word[3], 7 , 1 , v)
165
+#define EVT_SET_CLASS(x, v) deposit32((x)->word[3], 8 , 2 , v)
166
+#define EVT_SET_ADDR(x, addr) \
167
+ do { \
168
+ (x)->word[5] = (uint32_t)(addr >> 32); \
169
+ (x)->word[4] = (uint32_t)(addr & 0xffffffff); \
170
+ } while (0)
171
+#define EVT_SET_ADDR2(x, addr) \
172
+ do { \
173
+ deposit32((x)->word[7], 3, 29, addr >> 16); \
174
+ deposit32((x)->word[7], 0, 16, addr & 0xffff);\
175
+ } while (0)
176
+
177
+void smmuv3_record_event(SMMUv3State *s, SMMUEventInfo *event);
178
+
179
#endif
180
diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c
181
index XXXXXXX..XXXXXXX 100644
182
--- a/hw/arm/smmuv3.c
183
+++ b/hw/arm/smmuv3.c
184
@@ -XXX,XX +XXX,XX @@ static MemTxResult queue_write(SMMUQueue *q, void *data)
185
return MEMTX_OK;
186
}
187
188
-void smmuv3_write_eventq(SMMUv3State *s, Evt *evt)
189
+static MemTxResult smmuv3_write_eventq(SMMUv3State *s, Evt *evt)
190
{
191
SMMUQueue *q = &s->eventq;
192
+ MemTxResult r;
193
+
194
+ if (!smmuv3_eventq_enabled(s)) {
195
+ return MEMTX_ERROR;
100
+ return MEMTX_ERROR;
196
+ }
197
+
198
+ if (smmuv3_q_full(q)) {
199
+ return MEMTX_ERROR;
200
+ }
201
+
202
+ r = queue_write(q, evt);
203
+ if (r != MEMTX_OK) {
204
+ return r;
205
+ }
206
+
207
+ if (smmuv3_q_empty(q)) {
208
+ smmuv3_trigger_irq(s, SMMU_IRQ_EVTQ, 0);
209
+ }
101
+ }
210
+ return MEMTX_OK;
102
+ return MEMTX_OK;
211
+}
103
+}
212
+
104
+
213
+void smmuv3_record_event(SMMUv3State *s, SMMUEventInfo *info)
105
+static const MemoryRegionOps ppb_default_ops = {
214
+{
106
+ .read_with_attrs = ppb_default_read,
215
+ Evt evt;
107
+ .write_with_attrs = ppb_default_write,
216
+ MemTxResult r;
108
+ .endianness = DEVICE_NATIVE_ENDIAN,
217
109
+ .valid.min_access_size = 1,
218
if (!smmuv3_eventq_enabled(s)) {
110
+ .valid.max_access_size = 8,
219
return;
111
+};
112
+
113
static int nvic_post_load(void *opaque, int version_id)
114
{
115
NVICState *s = opaque;
116
@@ -XXX,XX +XXX,XX @@ static void nvic_systick_trigger(void *opaque, int n, int level)
117
static void armv7m_nvic_realize(DeviceState *dev, Error **errp)
118
{
119
NVICState *s = NVIC(dev);
120
- int regionlen;
121
122
/* The armv7m container object will have set our CPU pointer */
123
if (!s->cpu || !arm_feature(&s->cpu->env, ARM_FEATURE_M)) {
124
@@ -XXX,XX +XXX,XX @@ static void armv7m_nvic_realize(DeviceState *dev, Error **errp)
125
M_REG_S));
220
}
126
}
221
127
222
- if (smmuv3_q_full(q)) {
128
- /* The NVIC and System Control Space (SCS) starts at 0xe000e000
223
+ EVT_SET_TYPE(&evt, info->type);
129
+ /*
224
+ EVT_SET_SID(&evt, info->sid);
130
+ * This device provides a single sysbus memory region which
225
+
131
+ * represents the whole of the "System PPB" space. This is the
226
+ switch (info->type) {
132
+ * range from 0xe0000000 to 0xe00fffff and includes the NVIC,
227
+ case SMMU_EVT_OK:
133
+ * the System Control Space (system registers), the systick timer,
228
return;
134
+ * and for CPUs with the Security extension an NS banked version
229
+ case SMMU_EVT_F_UUT:
135
+ * of all of these.
230
+ EVT_SET_SSID(&evt, info->u.f_uut.ssid);
136
+ *
231
+ EVT_SET_SSV(&evt, info->u.f_uut.ssv);
137
+ * The default behaviour for unimplemented registers/ranges
232
+ EVT_SET_ADDR(&evt, info->u.f_uut.addr);
138
+ * (for instance the Data Watchpoint and Trace unit at 0xe0001000)
233
+ EVT_SET_RNW(&evt, info->u.f_uut.rnw);
139
+ * is to RAZ/WI for privileged access and BusFault for non-privileged
234
+ EVT_SET_PNU(&evt, info->u.f_uut.pnu);
140
+ * access.
235
+ EVT_SET_IND(&evt, info->u.f_uut.ind);
141
+ *
236
+ break;
142
+ * The NVIC and System Control Space (SCS) starts at 0xe000e000
237
+ case SMMU_EVT_C_BAD_STREAMID:
143
* and looks like this:
238
+ EVT_SET_SSID(&evt, info->u.c_bad_streamid.ssid);
144
* 0x004 - ICTR
239
+ EVT_SET_SSV(&evt, info->u.c_bad_streamid.ssv);
145
* 0x010 - 0xff - systick
240
+ break;
146
@@ -XXX,XX +XXX,XX @@ static void armv7m_nvic_realize(DeviceState *dev, Error **errp)
241
+ case SMMU_EVT_F_STE_FETCH:
147
* generally code determining which banked register to use should
242
+ EVT_SET_SSID(&evt, info->u.f_ste_fetch.ssid);
148
* use attrs.secure; code determining actual behaviour of the system
243
+ EVT_SET_SSV(&evt, info->u.f_ste_fetch.ssv);
149
* should use env->v7m.secure.
244
+ EVT_SET_ADDR(&evt, info->u.f_ste_fetch.addr);
150
+ *
245
+ break;
151
+ * The container covers the whole PPB space. Within it the priority
246
+ case SMMU_EVT_C_BAD_STE:
152
+ * of overlapping regions is:
247
+ EVT_SET_SSID(&evt, info->u.c_bad_ste.ssid);
153
+ * - default region (for RAZ/WI and BusFault) : -1
248
+ EVT_SET_SSV(&evt, info->u.c_bad_ste.ssv);
154
+ * - system register regions : 0
249
+ break;
155
+ * - systick : 1
250
+ case SMMU_EVT_F_STREAM_DISABLED:
156
+ * This is because the systick device is a small block of registers
251
+ break;
157
+ * in the middle of the other system control registers.
252
+ case SMMU_EVT_F_TRANS_FORBIDDEN:
158
*/
253
+ EVT_SET_ADDR(&evt, info->u.f_transl_forbidden.addr);
159
- regionlen = arm_feature(&s->cpu->env, ARM_FEATURE_V8) ? 0x21000 : 0x1000;
254
+ EVT_SET_RNW(&evt, info->u.f_transl_forbidden.rnw);
160
- memory_region_init(&s->container, OBJECT(s), "nvic", regionlen);
255
+ break;
161
- /* The system register region goes at the bottom of the priority
256
+ case SMMU_EVT_C_BAD_SUBSTREAMID:
162
- * stack as it covers the whole page.
257
+ EVT_SET_SSID(&evt, info->u.c_bad_substream.ssid);
163
- */
258
+ break;
164
+ memory_region_init(&s->container, OBJECT(s), "nvic", 0x100000);
259
+ case SMMU_EVT_F_CD_FETCH:
165
+ memory_region_init_io(&s->defaultmem, OBJECT(s), &ppb_default_ops, s,
260
+ EVT_SET_SSID(&evt, info->u.f_cd_fetch.ssid);
166
+ "nvic-default", 0x100000);
261
+ EVT_SET_SSV(&evt, info->u.f_cd_fetch.ssv);
167
+ memory_region_add_subregion_overlap(&s->container, 0, &s->defaultmem, -1);
262
+ EVT_SET_ADDR(&evt, info->u.f_cd_fetch.addr);
168
memory_region_init_io(&s->sysregmem, OBJECT(s), &nvic_sysreg_ops, s,
263
+ break;
169
"nvic_sysregs", 0x1000);
264
+ case SMMU_EVT_C_BAD_CD:
170
- memory_region_add_subregion(&s->container, 0, &s->sysregmem);
265
+ EVT_SET_SSID(&evt, info->u.c_bad_cd.ssid);
171
+ memory_region_add_subregion(&s->container, 0xe000, &s->sysregmem);
266
+ EVT_SET_SSV(&evt, info->u.c_bad_cd.ssv);
172
267
+ break;
173
memory_region_init_io(&s->systickmem, OBJECT(s),
268
+ case SMMU_EVT_F_WALK_EABT:
174
&nvic_systick_ops, s,
269
+ case SMMU_EVT_F_TRANSLATION:
175
"nvic_systick", 0xe0);
270
+ case SMMU_EVT_F_ADDR_SIZE:
176
271
+ case SMMU_EVT_F_ACCESS:
177
- memory_region_add_subregion_overlap(&s->container, 0x10,
272
+ case SMMU_EVT_F_PERMISSION:
178
+ memory_region_add_subregion_overlap(&s->container, 0xe010,
273
+ EVT_SET_STALL(&evt, info->u.f_walk_eabt.stall);
179
&s->systickmem, 1);
274
+ EVT_SET_STAG(&evt, info->u.f_walk_eabt.stag);
180
275
+ EVT_SET_SSID(&evt, info->u.f_walk_eabt.ssid);
181
if (arm_feature(&s->cpu->env, ARM_FEATURE_V8)) {
276
+ EVT_SET_SSV(&evt, info->u.f_walk_eabt.ssv);
182
memory_region_init_io(&s->sysreg_ns_mem, OBJECT(s),
277
+ EVT_SET_S2(&evt, info->u.f_walk_eabt.s2);
183
&nvic_sysreg_ns_ops, &s->sysregmem,
278
+ EVT_SET_ADDR(&evt, info->u.f_walk_eabt.addr);
184
"nvic_sysregs_ns", 0x1000);
279
+ EVT_SET_RNW(&evt, info->u.f_walk_eabt.rnw);
185
- memory_region_add_subregion(&s->container, 0x20000, &s->sysreg_ns_mem);
280
+ EVT_SET_PNU(&evt, info->u.f_walk_eabt.pnu);
186
+ memory_region_add_subregion(&s->container, 0x2e000, &s->sysreg_ns_mem);
281
+ EVT_SET_IND(&evt, info->u.f_walk_eabt.ind);
187
memory_region_init_io(&s->systick_ns_mem, OBJECT(s),
282
+ EVT_SET_CLASS(&evt, info->u.f_walk_eabt.class);
188
&nvic_sysreg_ns_ops, &s->systickmem,
283
+ EVT_SET_ADDR2(&evt, info->u.f_walk_eabt.addr2);
189
"nvic_systick_ns", 0xe0);
284
+ break;
190
- memory_region_add_subregion_overlap(&s->container, 0x20010,
285
+ case SMMU_EVT_F_CFG_CONFLICT:
191
+ memory_region_add_subregion_overlap(&s->container, 0x2e010,
286
+ EVT_SET_SSID(&evt, info->u.f_cfg_conflict.ssid);
192
&s->systick_ns_mem, 1);
287
+ EVT_SET_SSV(&evt, info->u.f_cfg_conflict.ssv);
288
+ break;
289
+ /* rest is not implemented */
290
+ case SMMU_EVT_F_BAD_ATS_TREQ:
291
+ case SMMU_EVT_F_TLB_CONFLICT:
292
+ case SMMU_EVT_E_PAGE_REQ:
293
+ default:
294
+ g_assert_not_reached();
295
}
193
}
296
194
297
- queue_write(q, evt);
298
-
299
- if (smmuv3_q_empty(q)) {
300
- smmuv3_trigger_irq(s, SMMU_IRQ_EVTQ, 0);
301
+ trace_smmuv3_record_event(smmu_event_string(info->type), info->sid);
302
+ r = smmuv3_write_eventq(s, &evt);
303
+ if (r != MEMTX_OK) {
304
+ smmuv3_trigger_irq(s, SMMU_IRQ_GERROR, R_GERROR_EVENTQ_ABT_ERR_MASK);
305
}
306
+ info->recorded = true;
307
}
308
309
static void smmuv3_init_regs(SMMUv3State *s)
310
diff --git a/hw/arm/trace-events b/hw/arm/trace-events
311
index XXXXXXX..XXXXXXX 100644
312
--- a/hw/arm/trace-events
313
+++ b/hw/arm/trace-events
314
@@ -XXX,XX +XXX,XX @@ smmuv3_write_mmio(uint64_t addr, uint64_t val, unsigned size, uint32_t r) "addr:
315
smmuv3_write_mmio_idr(uint64_t addr, uint64_t val) "write to RO/Unimpl reg 0x%lx val64:0x%lx"
316
smmuv3_write_mmio_evtq_cons_bef_clear(uint32_t prod, uint32_t cons, uint8_t prod_wrap, uint8_t cons_wrap) "Before clearing interrupt prod:0x%x cons:0x%x prod.w:%d cons.w:%d"
317
smmuv3_write_mmio_evtq_cons_after_clear(uint32_t prod, uint32_t cons, uint8_t prod_wrap, uint8_t cons_wrap) "after clearing interrupt prod:0x%x cons:0x%x prod.w:%d cons.w:%d"
318
+smmuv3_record_event(const char *type, uint32_t sid) "%s sid=%d"
319
--
195
--
320
2.17.0
196
2.20.1
321
197
322
198
diff view generated by jsdifflib
1
From: Mathew Maidment <mathew1800@gmail.com>
1
In v8.1M the PXN architecture extension adds a new PXN bit to the
2
MPU_RLAR registers, which forbids execution of code in the region
3
from a privileged mode.
2
4
3
The duplication of id_tlbtr_reginfo was unintentionally added within
5
This is another feature which is just in the generic "in v8.1M" set
4
3281af8114c6b8ead02f08b58e3c36895c1ea047 which should have been
6
and has no ID register field indicating its presence.
5
id_mpuir_reginfo.
6
7
7
The effect was that for OMAP and StrongARM CPUs we would
8
incorrectly UNDEF writes to MPUIR rather than NOPing them.
9
10
Signed-off-by: Mathew Maidment <mathew1800@gmail.com>
11
Message-id: 20180501184933.37609-2-mathew1800@gmail.com
12
[PMM: tweak commit message]
13
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20201119215617.29887-3-peter.maydell@linaro.org
15
---
11
---
16
target/arm/helper.c | 2 +-
12
target/arm/helper.c | 7 ++++++-
17
1 file changed, 1 insertion(+), 1 deletion(-)
13
1 file changed, 6 insertions(+), 1 deletion(-)
18
14
19
diff --git a/target/arm/helper.c b/target/arm/helper.c
15
diff --git a/target/arm/helper.c b/target/arm/helper.c
20
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
21
--- a/target/arm/helper.c
17
--- a/target/arm/helper.c
22
+++ b/target/arm/helper.c
18
+++ b/target/arm/helper.c
23
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
19
@@ -XXX,XX +XXX,XX @@ bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address,
24
for (r = id_cp_reginfo; r->type != ARM_CP_SENTINEL; r++) {
20
} else {
25
r->access = PL1_RW;
21
uint32_t ap = extract32(env->pmsav8.rbar[secure][matchregion], 1, 2);
26
}
22
uint32_t xn = extract32(env->pmsav8.rbar[secure][matchregion], 0, 1);
27
- id_tlbtr_reginfo.access = PL1_RW;
23
+ bool pxn = false;
28
+ id_mpuir_reginfo.access = PL1_RW;
24
+
29
id_tlbtr_reginfo.access = PL1_RW;
25
+ if (arm_feature(env, ARM_FEATURE_V8_1M)) {
26
+ pxn = extract32(env->pmsav8.rlar[secure][matchregion], 4, 1);
27
+ }
28
29
if (m_is_system_region(env, address)) {
30
/* System space is always execute never */
31
@@ -XXX,XX +XXX,XX @@ bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address,
30
}
32
}
31
if (arm_feature(env, ARM_FEATURE_V8)) {
33
34
*prot = simple_ap_to_rw_prot(env, mmu_idx, ap);
35
- if (*prot && !xn) {
36
+ if (*prot && !xn && !(pxn && !is_user)) {
37
*prot |= PAGE_EXEC;
38
}
39
/* We don't need to look the attribute up in the MAIR0/MAIR1
32
--
40
--
33
2.17.0
41
2.20.1
34
42
35
43
diff view generated by jsdifflib
New patch
1
In arm_cpu_realizefn() we check whether the board code disabled EL3
2
via the has_el3 CPU object property, which we create if the CPU
3
starts with the ARM_FEATURE_EL3 feature bit. If it is disabled, then
4
we turn off ARM_FEATURE_EL3 and also zero out the relevant fields in
5
the ID_PFR1 and ID_AA64PFR0 registers.
1
6
7
This codepath was incorrectly being taken for M-profile CPUs, which
8
do not have an EL3 and don't set ARM_FEATURE_EL3, but which may have
9
the M-profile Security extension and so should have non-zero values
10
in the ID_PFR1.Security field.
11
12
Restrict the handling of the feature flag to A/R-profile cores.
13
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
16
Message-id: 20201119215617.29887-4-peter.maydell@linaro.org
17
---
18
target/arm/cpu.c | 2 +-
19
1 file changed, 1 insertion(+), 1 deletion(-)
20
21
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
22
index XXXXXXX..XXXXXXX 100644
23
--- a/target/arm/cpu.c
24
+++ b/target/arm/cpu.c
25
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
26
}
27
}
28
29
- if (!cpu->has_el3) {
30
+ if (!arm_feature(env, ARM_FEATURE_M) && !cpu->has_el3) {
31
/* If the has_el3 CPU property is disabled then we need to disable the
32
* feature.
33
*/
34
--
35
2.20.1
36
37
diff view generated by jsdifflib
New patch
1
1
Implement the v8.1M VSCCLRM insn, which zeros floating point
2
registers if there is an active floating point context.
3
This requires support in write_neon_element32() for the MO_32
4
element size, so add it.
5
6
Because we want to use arm_gen_condlabel(), we need to move
7
the definition of that function up in translate.c so it is
8
before the #include of translate-vfp.c.inc.
9
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20201119215617.29887-5-peter.maydell@linaro.org
13
---
14
target/arm/cpu.h | 9 ++++
15
target/arm/m-nocp.decode | 8 +++-
16
target/arm/translate.c | 21 +++++----
17
target/arm/translate-vfp.c.inc | 84 ++++++++++++++++++++++++++++++++++
18
4 files changed, 111 insertions(+), 11 deletions(-)
19
20
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
21
index XXXXXXX..XXXXXXX 100644
22
--- a/target/arm/cpu.h
23
+++ b/target/arm/cpu.h
24
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa32_mprofile(const ARMISARegisters *id)
25
return FIELD_EX32(id->id_pfr1, ID_PFR1, MPROGMOD) != 0;
26
}
27
28
+static inline bool isar_feature_aa32_m_sec_state(const ARMISARegisters *id)
29
+{
30
+ /*
31
+ * Return true if M-profile state handling insns
32
+ * (VSCCLRM, CLRM, FPCTX access insns) are implemented
33
+ */
34
+ return FIELD_EX32(id->id_pfr1, ID_PFR1, SECURITY) >= 3;
35
+}
36
+
37
static inline bool isar_feature_aa32_fp16_arith(const ARMISARegisters *id)
38
{
39
/* Sadly this is encoded differently for A-profile and M-profile */
40
diff --git a/target/arm/m-nocp.decode b/target/arm/m-nocp.decode
41
index XXXXXXX..XXXXXXX 100644
42
--- a/target/arm/m-nocp.decode
43
+++ b/target/arm/m-nocp.decode
44
@@ -XXX,XX +XXX,XX @@
45
# If the coprocessor is not present or disabled then we will generate
46
# the NOCP exception; otherwise we let the insn through to the main decode.
47
48
+%vd_dp 22:1 12:4
49
+%vd_sp 12:4 22:1
50
+
51
&nocp cp
52
53
{
54
# Special cases which do not take an early NOCP: VLLDM and VLSTM
55
VLLDM_VLSTM 1110 1100 001 l:1 rn:4 0000 1010 0000 0000
56
- # TODO: VSCCLRM (new in v8.1M) is similar:
57
- #VSCCLRM 1110 1100 1-01 1111 ---- 1011 ---- ---0
58
+ # VSCCLRM (new in v8.1M) is similar:
59
+ VSCCLRM 1110 1100 1.01 1111 .... 1011 imm:7 0 vd=%vd_dp size=3
60
+ VSCCLRM 1110 1100 1.01 1111 .... 1010 imm:8 vd=%vd_sp size=2
61
62
NOCP 111- 1110 ---- ---- ---- cp:4 ---- ---- &nocp
63
NOCP 111- 110- ---- ---- ---- cp:4 ---- ---- &nocp
64
diff --git a/target/arm/translate.c b/target/arm/translate.c
65
index XXXXXXX..XXXXXXX 100644
66
--- a/target/arm/translate.c
67
+++ b/target/arm/translate.c
68
@@ -XXX,XX +XXX,XX @@ void arm_translate_init(void)
69
a64_translate_init();
70
}
71
72
+/* Generate a label used for skipping this instruction */
73
+static void arm_gen_condlabel(DisasContext *s)
74
+{
75
+ if (!s->condjmp) {
76
+ s->condlabel = gen_new_label();
77
+ s->condjmp = 1;
78
+ }
79
+}
80
+
81
/* Flags for the disas_set_da_iss info argument:
82
* lower bits hold the Rt register number, higher bits are flags.
83
*/
84
@@ -XXX,XX +XXX,XX @@ static void write_neon_element64(TCGv_i64 src, int reg, int ele, MemOp memop)
85
long off = neon_element_offset(reg, ele, memop);
86
87
switch (memop) {
88
+ case MO_32:
89
+ tcg_gen_st32_i64(src, cpu_env, off);
90
+ break;
91
case MO_64:
92
tcg_gen_st_i64(src, cpu_env, off);
93
break;
94
@@ -XXX,XX +XXX,XX @@ static void gen_srs(DisasContext *s,
95
s->base.is_jmp = DISAS_UPDATE_EXIT;
96
}
97
98
-/* Generate a label used for skipping this instruction */
99
-static void arm_gen_condlabel(DisasContext *s)
100
-{
101
- if (!s->condjmp) {
102
- s->condlabel = gen_new_label();
103
- s->condjmp = 1;
104
- }
105
-}
106
-
107
/* Skip this instruction if the ARM condition is false */
108
static void arm_skip_unless(DisasContext *s, uint32_t cond)
109
{
110
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
111
index XXXXXXX..XXXXXXX 100644
112
--- a/target/arm/translate-vfp.c.inc
113
+++ b/target/arm/translate-vfp.c.inc
114
@@ -XXX,XX +XXX,XX @@ static bool trans_VLLDM_VLSTM(DisasContext *s, arg_VLLDM_VLSTM *a)
115
return true;
116
}
117
118
+static bool trans_VSCCLRM(DisasContext *s, arg_VSCCLRM *a)
119
+{
120
+ int btmreg, topreg;
121
+ TCGv_i64 zero;
122
+ TCGv_i32 aspen, sfpa;
123
+
124
+ if (!dc_isar_feature(aa32_m_sec_state, s)) {
125
+ /* Before v8.1M, fall through in decode to NOCP check */
126
+ return false;
127
+ }
128
+
129
+ /* Explicitly UNDEF because this takes precedence over NOCP */
130
+ if (!arm_dc_feature(s, ARM_FEATURE_M_MAIN) || !s->v8m_secure) {
131
+ unallocated_encoding(s);
132
+ return true;
133
+ }
134
+
135
+ if (!dc_isar_feature(aa32_vfp_simd, s)) {
136
+ /* NOP if we have neither FP nor MVE */
137
+ return true;
138
+ }
139
+
140
+ /*
141
+ * If FPCCR.ASPEN != 0 && CONTROL_S.SFPA == 0 then there is no
142
+ * active floating point context so we must NOP (without doing
143
+ * any lazy state preservation or the NOCP check).
144
+ */
145
+ aspen = load_cpu_field(v7m.fpccr[M_REG_S]);
146
+ sfpa = load_cpu_field(v7m.control[M_REG_S]);
147
+ tcg_gen_andi_i32(aspen, aspen, R_V7M_FPCCR_ASPEN_MASK);
148
+ tcg_gen_xori_i32(aspen, aspen, R_V7M_FPCCR_ASPEN_MASK);
149
+ tcg_gen_andi_i32(sfpa, sfpa, R_V7M_CONTROL_SFPA_MASK);
150
+ tcg_gen_or_i32(sfpa, sfpa, aspen);
151
+ arm_gen_condlabel(s);
152
+ tcg_gen_brcondi_i32(TCG_COND_EQ, sfpa, 0, s->condlabel);
153
+
154
+ if (s->fp_excp_el != 0) {
155
+ gen_exception_insn(s, s->pc_curr, EXCP_NOCP,
156
+ syn_uncategorized(), s->fp_excp_el);
157
+ return true;
158
+ }
159
+
160
+ topreg = a->vd + a->imm - 1;
161
+ btmreg = a->vd;
162
+
163
+ /* Convert to Sreg numbers if the insn specified in Dregs */
164
+ if (a->size == 3) {
165
+ topreg = topreg * 2 + 1;
166
+ btmreg *= 2;
167
+ }
168
+
169
+ if (topreg > 63 || (topreg > 31 && !(topreg & 1))) {
170
+ /* UNPREDICTABLE: we choose to undef */
171
+ unallocated_encoding(s);
172
+ return true;
173
+ }
174
+
175
+ /* Silently ignore requests to clear D16-D31 if they don't exist */
176
+ if (topreg > 31 && !dc_isar_feature(aa32_simd_r32, s)) {
177
+ topreg = 31;
178
+ }
179
+
180
+ if (!vfp_access_check(s)) {
181
+ return true;
182
+ }
183
+
184
+ /* Zero the Sregs from btmreg to topreg inclusive. */
185
+ zero = tcg_const_i64(0);
186
+ if (btmreg & 1) {
187
+ write_neon_element64(zero, btmreg >> 1, 1, MO_32);
188
+ btmreg++;
189
+ }
190
+ for (; btmreg + 1 <= topreg; btmreg += 2) {
191
+ write_neon_element64(zero, btmreg >> 1, 0, MO_64);
192
+ }
193
+ if (btmreg == topreg) {
194
+ write_neon_element64(zero, btmreg >> 1, 0, MO_32);
195
+ btmreg++;
196
+ }
197
+ assert(btmreg == topreg + 1);
198
+ /* TODO: when MVE is implemented, zero VPR here */
199
+ return true;
200
+}
201
+
202
static bool trans_NOCP(DisasContext *s, arg_nocp *a)
203
{
204
/*
205
--
206
2.20.1
207
208
diff view generated by jsdifflib
1
For v8M the instructions VLLDM and VLSTM support lazy saving
1
In v8.1M the new CLRM instruction allows zeroing an arbitrary set of
2
and restoring of the secure floating-point registers. Even
2
the general-purpose registers and APSR. Implement this.
3
if the floating point extension is not implemented, these
4
instructions must act as NOPs in Secure state, so they can
5
be used as part of the secure-to-nonsecure call sequence.
6
3
7
Fixes: https://bugs.launchpad.net/qemu/+bug/1768295
4
The encoding is a subset of the LDMIA T2 encoding, using what would
8
Cc: qemu-stable@nongnu.org
5
be Rn=0b1111 (which UNDEFs for LDMIA).
6
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20180503105730.5958-1-peter.maydell@linaro.org
9
Message-id: 20201119215617.29887-6-peter.maydell@linaro.org
12
---
10
---
13
target/arm/translate.c | 17 ++++++++++++++++-
11
target/arm/t32.decode | 6 +++++-
14
1 file changed, 16 insertions(+), 1 deletion(-)
12
target/arm/translate.c | 38 ++++++++++++++++++++++++++++++++++++++
13
2 files changed, 43 insertions(+), 1 deletion(-)
15
14
15
diff --git a/target/arm/t32.decode b/target/arm/t32.decode
16
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/t32.decode
18
+++ b/target/arm/t32.decode
19
@@ -XXX,XX +XXX,XX @@ UXTAB 1111 1010 0101 .... 1111 .... 10.. .... @rrr_rot
20
21
STM_t32 1110 1000 10.0 .... ................ @ldstm i=1 b=0
22
STM_t32 1110 1001 00.0 .... ................ @ldstm i=0 b=1
23
-LDM_t32 1110 1000 10.1 .... ................ @ldstm i=1 b=0
24
+{
25
+ # Rn=15 UNDEFs for LDM; M-profile CLRM uses that encoding
26
+ CLRM 1110 1000 1001 1111 list:16
27
+ LDM_t32 1110 1000 10.1 .... ................ @ldstm i=1 b=0
28
+}
29
LDM_t32 1110 1001 00.1 .... ................ @ldstm i=0 b=1
30
31
&rfe !extern rn w pu
16
diff --git a/target/arm/translate.c b/target/arm/translate.c
32
diff --git a/target/arm/translate.c b/target/arm/translate.c
17
index XXXXXXX..XXXXXXX 100644
33
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/translate.c
34
--- a/target/arm/translate.c
19
+++ b/target/arm/translate.c
35
+++ b/target/arm/translate.c
20
@@ -XXX,XX +XXX,XX @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
36
@@ -XXX,XX +XXX,XX @@ static bool trans_LDM_t16(DisasContext *s, arg_ldst_block *a)
21
/* Coprocessor. */
37
return do_ldm(s, a, 1);
22
if (arm_dc_feature(s, ARM_FEATURE_M)) {
38
}
23
/* We don't currently implement M profile FP support,
39
24
- * so this entire space should give a NOCP fault.
40
+static bool trans_CLRM(DisasContext *s, arg_CLRM *a)
25
+ * so this entire space should give a NOCP fault, with
41
+{
26
+ * the exception of the v8M VLLDM and VLSTM insns, which
42
+ int i;
27
+ * must be NOPs in Secure state and UNDEF in Nonsecure state.
43
+ TCGv_i32 zero;
28
*/
44
+
29
+ if (arm_dc_feature(s, ARM_FEATURE_V8) &&
45
+ if (!dc_isar_feature(aa32_m_sec_state, s)) {
30
+ (insn & 0xffa00f00) == 0xec200a00) {
46
+ return false;
31
+ /* 0b1110_1100_0x1x_xxxx_xxxx_1010_xxxx_xxxx
47
+ }
32
+ * - VLLDM, VLSTM
48
+
33
+ * We choose to UNDEF if the RAZ bits are non-zero.
49
+ if (extract32(a->list, 13, 1)) {
34
+ */
50
+ return false;
35
+ if (!s->v8m_secure || (insn & 0x0040f0ff)) {
51
+ }
36
+ goto illegal_op;
52
+
37
+ }
53
+ if (!a->list) {
38
+ /* Just NOP since FP support is not implemented */
54
+ /* UNPREDICTABLE; we choose to UNDEF */
39
+ break;
55
+ return false;
40
+ }
56
+ }
41
+ /* All other insns: NOCP */
57
+
42
gen_exception_insn(s, 4, EXCP_NOCP, syn_uncategorized(),
58
+ zero = tcg_const_i32(0);
43
default_exception_el(s));
59
+ for (i = 0; i < 15; i++) {
44
break;
60
+ if (extract32(a->list, i, 1)) {
61
+ /* Clear R[i] */
62
+ tcg_gen_mov_i32(cpu_R[i], zero);
63
+ }
64
+ }
65
+ if (extract32(a->list, 15, 1)) {
66
+ /*
67
+ * Clear APSR (by calling the MSR helper with the same argument
68
+ * as for "MSR APSR_nzcvqg, Rn": mask = 0b1100, SYSM=0)
69
+ */
70
+ TCGv_i32 maskreg = tcg_const_i32(0xc << 8);
71
+ gen_helper_v7m_msr(cpu_env, maskreg, zero);
72
+ tcg_temp_free_i32(maskreg);
73
+ }
74
+ tcg_temp_free_i32(zero);
75
+ return true;
76
+}
77
+
78
/*
79
* Branch, branch with link
80
*/
45
--
81
--
46
2.17.0
82
2.20.1
47
83
48
84
diff view generated by jsdifflib
New patch
1
For M-profile before v8.1M, the only valid register for VMSR/VMRS is
2
the FPSCR. We have a comment that states this, but the actual logic
3
to forbid accesses for any other register value is missing, so we
4
would end up with A-profile style behaviour. Add the missing check.
1
5
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20201119215617.29887-7-peter.maydell@linaro.org
9
---
10
target/arm/translate-vfp.c.inc | 5 ++++-
11
1 file changed, 4 insertions(+), 1 deletion(-)
12
13
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/translate-vfp.c.inc
16
+++ b/target/arm/translate-vfp.c.inc
17
@@ -XXX,XX +XXX,XX @@ static bool trans_VMSR_VMRS(DisasContext *s, arg_VMSR_VMRS *a)
18
* Accesses to R15 are UNPREDICTABLE; we choose to undef.
19
* (FPSCR -> r15 is a special case which writes to the PSR flags.)
20
*/
21
- if (a->rt == 15 && (!a->l || a->reg != ARM_VFP_FPSCR)) {
22
+ if (a->reg != ARM_VFP_FPSCR) {
23
+ return false;
24
+ }
25
+ if (a->rt == 15 && !a->l) {
26
return false;
27
}
28
}
29
--
30
2.20.1
31
32
diff view generated by jsdifflib
1
Convert the tusb6010 device away from using the old_mmio field
1
Currently M-profile borrows the A-profile code for VMSR and VMRS
2
of MemoryRegionOps. This device is used only in the n800 and n810
2
(access to the FP system registers), because all it needs to support
3
boards.
3
is the FPSCR. In v8.1M things become significantly more complicated
4
in two ways:
5
6
* there are several new FP system registers; some have side effects
7
on read, and one (FPCXT_NS) needs to avoid the usual
8
vfp_access_check() and the "only if FPU implemented" check
9
10
* all sysregs are now accessible both by VMRS/VMSR (which
11
reads/writes a general purpose register) and also by VLDR/VSTR
12
(which reads/writes them directly to memory)
13
14
Refactor the structure of how we handle VMSR/VMRS to cope with this:
15
16
* keep the M-profile code entirely separate from the A-profile code
17
18
* abstract out the "read or write the general purpose register" part
19
of the code into a loadfn or storefn function pointer, so we can
20
reuse it for VLDR/VSTR.
4
21
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
22
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
23
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20180427173611.10281-2-peter.maydell@linaro.org
24
Message-id: 20201119215617.29887-8-peter.maydell@linaro.org
8
---
25
---
9
hw/usb/tusb6010.c | 40 ++++++++++++++++++++++++++++++++++++----
26
target/arm/cpu.h | 3 +
10
1 file changed, 36 insertions(+), 4 deletions(-)
27
target/arm/translate-vfp.c.inc | 182 ++++++++++++++++++++++++++++++---
11
28
2 files changed, 171 insertions(+), 14 deletions(-)
12
diff --git a/hw/usb/tusb6010.c b/hw/usb/tusb6010.c
29
30
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
13
index XXXXXXX..XXXXXXX 100644
31
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/usb/tusb6010.c
32
--- a/target/arm/cpu.h
15
+++ b/hw/usb/tusb6010.c
33
+++ b/target/arm/cpu.h
16
@@ -XXX,XX +XXX,XX @@ static void tusb_async_writew(void *opaque, hwaddr addr,
34
@@ -XXX,XX +XXX,XX @@ enum arm_cpu_mode {
17
}
35
#define ARM_VFP_FPINST 9
36
#define ARM_VFP_FPINST2 10
37
38
+/* QEMU-internal value meaning "FPSCR, but we care only about NZCV" */
39
+#define QEMU_VFP_FPSCR_NZCV 0xffff
40
+
41
/* iwMMXt coprocessor control registers. */
42
#define ARM_IWMMXT_wCID 0
43
#define ARM_IWMMXT_wCon 1
44
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
45
index XXXXXXX..XXXXXXX 100644
46
--- a/target/arm/translate-vfp.c.inc
47
+++ b/target/arm/translate-vfp.c.inc
48
@@ -XXX,XX +XXX,XX @@ static bool trans_VDUP(DisasContext *s, arg_VDUP *a)
49
return true;
18
}
50
}
19
51
20
+static uint64_t tusb_async_readfn(void *opaque, hwaddr addr, unsigned size)
52
+/*
21
+{
53
+ * M-profile provides two different sets of instructions that can
22
+ switch (size) {
54
+ * access floating point system registers: VMSR/VMRS (which move
23
+ case 1:
55
+ * to/from a general purpose register) and VLDR/VSTR sysreg (which
24
+ return tusb_async_readb(opaque, addr);
56
+ * move directly to/from memory). In some cases there are also side
25
+ case 2:
57
+ * effects which must happen after any write to memory (which could
26
+ return tusb_async_readh(opaque, addr);
58
+ * cause an exception). So we implement the common logic for the
27
+ case 4:
59
+ * sysreg access in gen_M_fp_sysreg_write() and gen_M_fp_sysreg_read(),
28
+ return tusb_async_readw(opaque, addr);
60
+ * which take pointers to callback functions which will perform the
61
+ * actual "read/write general purpose register" and "read/write
62
+ * memory" operations.
63
+ */
64
+
65
+/*
66
+ * Emit code to store the sysreg to its final destination; frees the
67
+ * TCG temp 'value' it is passed.
68
+ */
69
+typedef void fp_sysreg_storefn(DisasContext *s, void *opaque, TCGv_i32 value);
70
+/*
71
+ * Emit code to load the value to be copied to the sysreg; returns
72
+ * a new TCG temporary
73
+ */
74
+typedef TCGv_i32 fp_sysreg_loadfn(DisasContext *s, void *opaque);
75
+
76
+/* Common decode/access checks for fp sysreg read/write */
77
+typedef enum FPSysRegCheckResult {
78
+ FPSysRegCheckFailed, /* caller should return false */
79
+ FPSysRegCheckDone, /* caller should return true */
80
+ FPSysRegCheckContinue, /* caller should continue generating code */
81
+} FPSysRegCheckResult;
82
+
83
+static FPSysRegCheckResult fp_sysreg_checks(DisasContext *s, int regno)
84
+{
85
+ if (!dc_isar_feature(aa32_fpsp_v2, s)) {
86
+ return FPSysRegCheckFailed;
87
+ }
88
+
89
+ switch (regno) {
90
+ case ARM_VFP_FPSCR:
91
+ case QEMU_VFP_FPSCR_NZCV:
92
+ break;
93
+ default:
94
+ return FPSysRegCheckFailed;
95
+ }
96
+
97
+ if (!vfp_access_check(s)) {
98
+ return FPSysRegCheckDone;
99
+ }
100
+
101
+ return FPSysRegCheckContinue;
102
+}
103
+
104
+static bool gen_M_fp_sysreg_write(DisasContext *s, int regno,
105
+
106
+ fp_sysreg_loadfn *loadfn,
107
+ void *opaque)
108
+{
109
+ /* Do a write to an M-profile floating point system register */
110
+ TCGv_i32 tmp;
111
+
112
+ switch (fp_sysreg_checks(s, regno)) {
113
+ case FPSysRegCheckFailed:
114
+ return false;
115
+ case FPSysRegCheckDone:
116
+ return true;
117
+ case FPSysRegCheckContinue:
118
+ break;
119
+ }
120
+
121
+ switch (regno) {
122
+ case ARM_VFP_FPSCR:
123
+ tmp = loadfn(s, opaque);
124
+ gen_helper_vfp_set_fpscr(cpu_env, tmp);
125
+ tcg_temp_free_i32(tmp);
126
+ gen_lookup_tb(s);
127
+ break;
29
+ default:
128
+ default:
30
+ g_assert_not_reached();
129
+ g_assert_not_reached();
31
+ }
130
+ }
32
+}
131
+ return true;
33
+
132
+}
34
+static void tusb_async_writefn(void *opaque, hwaddr addr,
133
+
35
+ uint64_t value, unsigned size)
134
+static bool gen_M_fp_sysreg_read(DisasContext *s, int regno,
36
+{
135
+ fp_sysreg_storefn *storefn,
37
+ switch (size) {
136
+ void *opaque)
38
+ case 1:
137
+{
39
+ tusb_async_writeb(opaque, addr, value);
138
+ /* Do a read from an M-profile floating point system register */
40
+ break;
139
+ TCGv_i32 tmp;
41
+ case 2:
140
+
42
+ tusb_async_writeh(opaque, addr, value);
141
+ switch (fp_sysreg_checks(s, regno)) {
43
+ break;
142
+ case FPSysRegCheckFailed:
44
+ case 4:
143
+ return false;
45
+ tusb_async_writew(opaque, addr, value);
144
+ case FPSysRegCheckDone:
145
+ return true;
146
+ case FPSysRegCheckContinue:
147
+ break;
148
+ }
149
+
150
+ switch (regno) {
151
+ case ARM_VFP_FPSCR:
152
+ tmp = tcg_temp_new_i32();
153
+ gen_helper_vfp_get_fpscr(tmp, cpu_env);
154
+ storefn(s, opaque, tmp);
155
+ break;
156
+ case QEMU_VFP_FPSCR_NZCV:
157
+ /*
158
+ * Read just NZCV; this is a special case to avoid the
159
+ * helper call for the "VMRS to CPSR.NZCV" insn.
160
+ */
161
+ tmp = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
162
+ tcg_gen_andi_i32(tmp, tmp, 0xf0000000);
163
+ storefn(s, opaque, tmp);
46
+ break;
164
+ break;
47
+ default:
165
+ default:
48
+ g_assert_not_reached();
166
+ g_assert_not_reached();
49
+ }
167
+ }
50
+}
168
+ return true;
51
+
169
+}
52
static const MemoryRegionOps tusb_async_ops = {
170
+
53
- .old_mmio = {
171
+static void fp_sysreg_to_gpr(DisasContext *s, void *opaque, TCGv_i32 value)
54
- .read = { tusb_async_readb, tusb_async_readh, tusb_async_readw, },
172
+{
55
- .write = { tusb_async_writeb, tusb_async_writeh, tusb_async_writew, },
173
+ arg_VMSR_VMRS *a = opaque;
56
- },
174
+
57
+ .read = tusb_async_readfn,
175
+ if (a->rt == 15) {
58
+ .write = tusb_async_writefn,
176
+ /* Set the 4 flag bits in the CPSR */
59
+ .valid.min_access_size = 1,
177
+ gen_set_nzcv(value);
60
+ .valid.max_access_size = 4,
178
+ tcg_temp_free_i32(value);
61
.endianness = DEVICE_NATIVE_ENDIAN,
179
+ } else {
62
};
180
+ store_reg(s, a->rt, value);
63
181
+ }
182
+}
183
+
184
+static TCGv_i32 gpr_to_fp_sysreg(DisasContext *s, void *opaque)
185
+{
186
+ arg_VMSR_VMRS *a = opaque;
187
+
188
+ return load_reg(s, a->rt);
189
+}
190
+
191
+static bool gen_M_VMSR_VMRS(DisasContext *s, arg_VMSR_VMRS *a)
192
+{
193
+ /*
194
+ * Accesses to R15 are UNPREDICTABLE; we choose to undef.
195
+ * FPSCR -> r15 is a special case which writes to the PSR flags;
196
+ * set a->reg to a special value to tell gen_M_fp_sysreg_read()
197
+ * we only care about the top 4 bits of FPSCR there.
198
+ */
199
+ if (a->rt == 15) {
200
+ if (a->l && a->reg == ARM_VFP_FPSCR) {
201
+ a->reg = QEMU_VFP_FPSCR_NZCV;
202
+ } else {
203
+ return false;
204
+ }
205
+ }
206
+
207
+ if (a->l) {
208
+ /* VMRS, move FP system register to gp register */
209
+ return gen_M_fp_sysreg_read(s, a->reg, fp_sysreg_to_gpr, a);
210
+ } else {
211
+ /* VMSR, move gp register to FP system register */
212
+ return gen_M_fp_sysreg_write(s, a->reg, gpr_to_fp_sysreg, a);
213
+ }
214
+}
215
+
216
static bool trans_VMSR_VMRS(DisasContext *s, arg_VMSR_VMRS *a)
217
{
218
TCGv_i32 tmp;
219
bool ignore_vfp_enabled = false;
220
221
- if (!dc_isar_feature(aa32_fpsp_v2, s)) {
222
- return false;
223
+ if (arm_dc_feature(s, ARM_FEATURE_M)) {
224
+ return gen_M_VMSR_VMRS(s, a);
225
}
226
227
- if (arm_dc_feature(s, ARM_FEATURE_M)) {
228
- /*
229
- * The only M-profile VFP vmrs/vmsr sysreg is FPSCR.
230
- * Accesses to R15 are UNPREDICTABLE; we choose to undef.
231
- * (FPSCR -> r15 is a special case which writes to the PSR flags.)
232
- */
233
- if (a->reg != ARM_VFP_FPSCR) {
234
- return false;
235
- }
236
- if (a->rt == 15 && !a->l) {
237
- return false;
238
- }
239
+ if (!dc_isar_feature(aa32_fpsp_v2, s)) {
240
+ return false;
241
}
242
243
switch (a->reg) {
64
--
244
--
65
2.17.0
245
2.20.1
66
246
67
247
diff view generated by jsdifflib
1
From: Eric Auger <eric.auger@redhat.com>
1
The constant-expander functions like negate, plus_2, etc, are
2
generally useful; move them up in translate.c so we can use them in
3
the VFP/Neon decoders as well as in the A32/T32/T16 decoders.
2
4
3
This patch implements the page table walk for VMSAv8-64.
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20201119215617.29887-9-peter.maydell@linaro.org
8
---
9
target/arm/translate.c | 46 +++++++++++++++++++++++-------------------
10
1 file changed, 25 insertions(+), 21 deletions(-)
4
11
5
Signed-off-by: Eric Auger <eric.auger@redhat.com>
12
diff --git a/target/arm/translate.c b/target/arm/translate.c
6
Signed-off-by: Prem Mallappa <prem.mallappa@broadcom.com>
13
index XXXXXXX..XXXXXXX 100644
7
Message-id: 1524665762-31355-4-git-send-email-eric.auger@redhat.com
14
--- a/target/arm/translate.c
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
15
+++ b/target/arm/translate.c
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
@@ -XXX,XX +XXX,XX @@ static void arm_gen_condlabel(DisasContext *s)
10
---
17
}
11
hw/arm/smmu-internal.h | 99 ++++++++++++++++
18
}
12
include/hw/arm/smmu-common.h | 14 +++
19
13
hw/arm/smmu-common.c | 222 +++++++++++++++++++++++++++++++++++
14
hw/arm/trace-events | 9 +-
15
4 files changed, 343 insertions(+), 1 deletion(-)
16
create mode 100644 hw/arm/smmu-internal.h
17
18
diff --git a/hw/arm/smmu-internal.h b/hw/arm/smmu-internal.h
19
new file mode 100644
20
index XXXXXXX..XXXXXXX
21
--- /dev/null
22
+++ b/hw/arm/smmu-internal.h
23
@@ -XXX,XX +XXX,XX @@
24
+/*
20
+/*
25
+ * ARM SMMU support - Internal API
21
+ * Constant expanders for the decoders.
26
+ *
27
+ * Copyright (c) 2017 Red Hat, Inc.
28
+ * Copyright (C) 2014-2016 Broadcom Corporation
29
+ * Written by Prem Mallappa, Eric Auger
30
+ *
31
+ * This program is free software; you can redistribute it and/or modify
32
+ * it under the terms of the GNU General Public License version 2 as
33
+ * published by the Free Software Foundation.
34
+ *
35
+ * This program is distributed in the hope that it will be useful,
36
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
37
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
38
+ * General Public License for more details.
39
+ *
40
+ * You should have received a copy of the GNU General Public License along
41
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
42
+ */
22
+ */
43
+
23
+
44
+#ifndef HW_ARM_SMMU_INTERNAL_H
24
+static int negate(DisasContext *s, int x)
45
+#define HW_ARM_SMMU_INTERNAL_H
46
+
47
+#define TBI0(tbi) ((tbi) & 0x1)
48
+#define TBI1(tbi) ((tbi) & 0x2 >> 1)
49
+
50
+/* PTE Manipulation */
51
+
52
+#define ARM_LPAE_PTE_TYPE_SHIFT 0
53
+#define ARM_LPAE_PTE_TYPE_MASK 0x3
54
+
55
+#define ARM_LPAE_PTE_TYPE_BLOCK 1
56
+#define ARM_LPAE_PTE_TYPE_TABLE 3
57
+
58
+#define ARM_LPAE_L3_PTE_TYPE_RESERVED 1
59
+#define ARM_LPAE_L3_PTE_TYPE_PAGE 3
60
+
61
+#define ARM_LPAE_PTE_VALID (1 << 0)
62
+
63
+#define PTE_ADDRESS(pte, shift) \
64
+ (extract64(pte, shift, 47 - shift + 1) << shift)
65
+
66
+#define is_invalid_pte(pte) (!(pte & ARM_LPAE_PTE_VALID))
67
+
68
+#define is_reserved_pte(pte, level) \
69
+ ((level == 3) && \
70
+ ((pte & ARM_LPAE_PTE_TYPE_MASK) == ARM_LPAE_L3_PTE_TYPE_RESERVED))
71
+
72
+#define is_block_pte(pte, level) \
73
+ ((level < 3) && \
74
+ ((pte & ARM_LPAE_PTE_TYPE_MASK) == ARM_LPAE_PTE_TYPE_BLOCK))
75
+
76
+#define is_table_pte(pte, level) \
77
+ ((level < 3) && \
78
+ ((pte & ARM_LPAE_PTE_TYPE_MASK) == ARM_LPAE_PTE_TYPE_TABLE))
79
+
80
+#define is_page_pte(pte, level) \
81
+ ((level == 3) && \
82
+ ((pte & ARM_LPAE_PTE_TYPE_MASK) == ARM_LPAE_L3_PTE_TYPE_PAGE))
83
+
84
+/* access permissions */
85
+
86
+#define PTE_AP(pte) \
87
+ (extract64(pte, 6, 2))
88
+
89
+#define PTE_APTABLE(pte) \
90
+ (extract64(pte, 61, 2))
91
+
92
+/*
93
+ * TODO: At the moment all transactions are considered as privileged (EL1)
94
+ * as IOMMU translation callback does not pass user/priv attributes.
95
+ */
96
+#define is_permission_fault(ap, perm) \
97
+ (((perm) & IOMMU_WO) && ((ap) & 0x2))
98
+
99
+#define PTE_AP_TO_PERM(ap) \
100
+ (IOMMU_ACCESS_FLAG(true, !((ap) & 0x2)))
101
+
102
+/* Level Indexing */
103
+
104
+static inline int level_shift(int level, int granule_sz)
105
+{
25
+{
106
+ return granule_sz + (3 - level) * (granule_sz - 3);
26
+ return -x;
107
+}
27
+}
108
+
28
+
109
+static inline uint64_t level_page_mask(int level, int granule_sz)
29
+static int plus_2(DisasContext *s, int x)
110
+{
30
+{
111
+ return ~(MAKE_64BIT_MASK(0, level_shift(level, granule_sz)));
31
+ return x + 2;
112
+}
32
+}
113
+
33
+
114
+static inline
34
+static int times_2(DisasContext *s, int x)
115
+uint64_t iova_level_offset(uint64_t iova, int inputsize,
116
+ int level, int gsz)
117
+{
35
+{
118
+ return ((iova & MAKE_64BIT_MASK(0, inputsize)) >> level_shift(level, gsz)) &
36
+ return x * 2;
119
+ MAKE_64BIT_MASK(0, gsz - 3);
120
+}
37
+}
121
+
38
+
122
+#endif
39
+static int times_4(DisasContext *s, int x)
123
diff --git a/include/hw/arm/smmu-common.h b/include/hw/arm/smmu-common.h
124
index XXXXXXX..XXXXXXX 100644
125
--- a/include/hw/arm/smmu-common.h
126
+++ b/include/hw/arm/smmu-common.h
127
@@ -XXX,XX +XXX,XX @@ static inline uint16_t smmu_get_sid(SMMUDevice *sdev)
128
{
129
return PCI_BUILD_BDF(pci_bus_num(sdev->bus), sdev->devfn);
130
}
131
+
132
+/**
133
+ * smmu_ptw - Perform the page table walk for a given iova / access flags
134
+ * pair, according to @cfg translation config
135
+ */
136
+int smmu_ptw(SMMUTransCfg *cfg, dma_addr_t iova, IOMMUAccessFlags perm,
137
+ IOMMUTLBEntry *tlbe, SMMUPTWEventInfo *info);
138
+
139
+/**
140
+ * select_tt - compute which translation table shall be used according to
141
+ * the input iova and translation config and return the TT specific info
142
+ */
143
+SMMUTransTableInfo *select_tt(SMMUTransCfg *cfg, dma_addr_t iova);
144
+
145
#endif /* HW_ARM_SMMU_COMMON */
146
diff --git a/hw/arm/smmu-common.c b/hw/arm/smmu-common.c
147
index XXXXXXX..XXXXXXX 100644
148
--- a/hw/arm/smmu-common.c
149
+++ b/hw/arm/smmu-common.c
150
@@ -XXX,XX +XXX,XX @@
151
152
#include "qemu/error-report.h"
153
#include "hw/arm/smmu-common.h"
154
+#include "smmu-internal.h"
155
+
156
+/* VMSAv8-64 Translation */
157
+
158
+/**
159
+ * get_pte - Get the content of a page table entry located at
160
+ * @base_addr[@index]
161
+ */
162
+static int get_pte(dma_addr_t baseaddr, uint32_t index, uint64_t *pte,
163
+ SMMUPTWEventInfo *info)
164
+{
40
+{
165
+ int ret;
41
+ return x * 4;
166
+ dma_addr_t addr = baseaddr + index * sizeof(*pte);
167
+
168
+ /* TODO: guarantee 64-bit single-copy atomicity */
169
+ ret = dma_memory_read(&address_space_memory, addr,
170
+ (uint8_t *)pte, sizeof(*pte));
171
+
172
+ if (ret != MEMTX_OK) {
173
+ info->type = SMMU_PTW_ERR_WALK_EABT;
174
+ info->addr = addr;
175
+ return -EINVAL;
176
+ }
177
+ trace_smmu_get_pte(baseaddr, index, addr, *pte);
178
+ return 0;
179
+}
42
+}
180
+
43
+
181
+/* VMSAv8-64 Translation Table Format Descriptor Decoding */
44
/* Flags for the disas_set_da_iss info argument:
182
+
45
* lower bits hold the Rt register number, higher bits are flags.
183
+/**
46
*/
184
+ * get_page_pte_address - returns the L3 descriptor output address,
47
@@ -XXX,XX +XXX,XX @@ static void arm_skip_unless(DisasContext *s, uint32_t cond)
185
+ * ie. the page frame
48
186
+ * ARM ARM spec: Figure D4-17 VMSAv8-64 level 3 descriptor format
49
187
+ */
50
/*
188
+static inline hwaddr get_page_pte_address(uint64_t pte, int granule_sz)
51
- * Constant expanders for the decoders.
189
+{
52
+ * Constant expanders used by T16/T32 decode
190
+ return PTE_ADDRESS(pte, granule_sz);
53
*/
191
+}
54
192
+
55
-static int negate(DisasContext *s, int x)
193
+/**
56
-{
194
+ * get_table_pte_address - return table descriptor output address,
57
- return -x;
195
+ * ie. address of next level table
58
-}
196
+ * ARM ARM Figure D4-16 VMSAv8-64 level0, level1, and level 2 descriptor formats
59
-
197
+ */
60
-static int plus_2(DisasContext *s, int x)
198
+static inline hwaddr get_table_pte_address(uint64_t pte, int granule_sz)
61
-{
199
+{
62
- return x + 2;
200
+ return PTE_ADDRESS(pte, granule_sz);
63
-}
201
+}
64
-
202
+
65
-static int times_2(DisasContext *s, int x)
203
+/**
66
-{
204
+ * get_block_pte_address - return block descriptor output address and block size
67
- return x * 2;
205
+ * ARM ARM Figure D4-16 VMSAv8-64 level0, level1, and level 2 descriptor formats
68
-}
206
+ */
69
-
207
+static inline hwaddr get_block_pte_address(uint64_t pte, int level,
70
-static int times_4(DisasContext *s, int x)
208
+ int granule_sz, uint64_t *bsz)
71
-{
209
+{
72
- return x * 4;
210
+ int n = (granule_sz - 3) * (4 - level) + 3;
73
-}
211
+
74
-
212
+ *bsz = 1 << n;
75
/* Return only the rotation part of T32ExpandImm. */
213
+ return PTE_ADDRESS(pte, n);
76
static int t32_expandimm_rot(DisasContext *s, int x)
214
+}
77
{
215
+
216
+SMMUTransTableInfo *select_tt(SMMUTransCfg *cfg, dma_addr_t iova)
217
+{
218
+ bool tbi = extract64(iova, 55, 1) ? TBI1(cfg->tbi) : TBI0(cfg->tbi);
219
+ uint8_t tbi_byte = tbi * 8;
220
+
221
+ if (cfg->tt[0].tsz &&
222
+ !extract64(iova, 64 - cfg->tt[0].tsz, cfg->tt[0].tsz - tbi_byte)) {
223
+ /* there is a ttbr0 region and we are in it (high bits all zero) */
224
+ return &cfg->tt[0];
225
+ } else if (cfg->tt[1].tsz &&
226
+ !extract64(iova, 64 - cfg->tt[1].tsz, cfg->tt[1].tsz - tbi_byte)) {
227
+ /* there is a ttbr1 region and we are in it (high bits all one) */
228
+ return &cfg->tt[1];
229
+ } else if (!cfg->tt[0].tsz) {
230
+ /* ttbr0 region is "everything not in the ttbr1 region" */
231
+ return &cfg->tt[0];
232
+ } else if (!cfg->tt[1].tsz) {
233
+ /* ttbr1 region is "everything not in the ttbr0 region" */
234
+ return &cfg->tt[1];
235
+ }
236
+ /* in the gap between the two regions, this is a Translation fault */
237
+ return NULL;
238
+}
239
+
240
+/**
241
+ * smmu_ptw_64 - VMSAv8-64 Walk of the page tables for a given IOVA
242
+ * @cfg: translation config
243
+ * @iova: iova to translate
244
+ * @perm: access type
245
+ * @tlbe: IOMMUTLBEntry (out)
246
+ * @info: handle to an error info
247
+ *
248
+ * Return 0 on success, < 0 on error. In case of error, @info is filled
249
+ * and tlbe->perm is set to IOMMU_NONE.
250
+ * Upon success, @tlbe is filled with translated_addr and entry
251
+ * permission rights.
252
+ */
253
+static int smmu_ptw_64(SMMUTransCfg *cfg,
254
+ dma_addr_t iova, IOMMUAccessFlags perm,
255
+ IOMMUTLBEntry *tlbe, SMMUPTWEventInfo *info)
256
+{
257
+ dma_addr_t baseaddr, indexmask;
258
+ int stage = cfg->stage;
259
+ SMMUTransTableInfo *tt = select_tt(cfg, iova);
260
+ uint8_t level, granule_sz, inputsize, stride;
261
+
262
+ if (!tt || tt->disabled) {
263
+ info->type = SMMU_PTW_ERR_TRANSLATION;
264
+ goto error;
265
+ }
266
+
267
+ granule_sz = tt->granule_sz;
268
+ stride = granule_sz - 3;
269
+ inputsize = 64 - tt->tsz;
270
+ level = 4 - (inputsize - 4) / stride;
271
+ indexmask = (1ULL << (inputsize - (stride * (4 - level)))) - 1;
272
+ baseaddr = extract64(tt->ttb, 0, 48);
273
+ baseaddr &= ~indexmask;
274
+
275
+ tlbe->iova = iova;
276
+ tlbe->addr_mask = (1 << granule_sz) - 1;
277
+
278
+ while (level <= 3) {
279
+ uint64_t subpage_size = 1ULL << level_shift(level, granule_sz);
280
+ uint64_t mask = subpage_size - 1;
281
+ uint32_t offset = iova_level_offset(iova, inputsize, level, granule_sz);
282
+ uint64_t pte;
283
+ dma_addr_t pte_addr = baseaddr + offset * sizeof(pte);
284
+ uint8_t ap;
285
+
286
+ if (get_pte(baseaddr, offset, &pte, info)) {
287
+ goto error;
288
+ }
289
+ trace_smmu_ptw_level(level, iova, subpage_size,
290
+ baseaddr, offset, pte);
291
+
292
+ if (is_invalid_pte(pte) || is_reserved_pte(pte, level)) {
293
+ trace_smmu_ptw_invalid_pte(stage, level, baseaddr,
294
+ pte_addr, offset, pte);
295
+ info->type = SMMU_PTW_ERR_TRANSLATION;
296
+ goto error;
297
+ }
298
+
299
+ if (is_page_pte(pte, level)) {
300
+ uint64_t gpa = get_page_pte_address(pte, granule_sz);
301
+
302
+ ap = PTE_AP(pte);
303
+ if (is_permission_fault(ap, perm)) {
304
+ info->type = SMMU_PTW_ERR_PERMISSION;
305
+ goto error;
306
+ }
307
+
308
+ tlbe->translated_addr = gpa + (iova & mask);
309
+ tlbe->perm = PTE_AP_TO_PERM(ap);
310
+ trace_smmu_ptw_page_pte(stage, level, iova,
311
+ baseaddr, pte_addr, pte, gpa);
312
+ return 0;
313
+ }
314
+ if (is_block_pte(pte, level)) {
315
+ uint64_t block_size;
316
+ hwaddr gpa = get_block_pte_address(pte, level, granule_sz,
317
+ &block_size);
318
+
319
+ ap = PTE_AP(pte);
320
+ if (is_permission_fault(ap, perm)) {
321
+ info->type = SMMU_PTW_ERR_PERMISSION;
322
+ goto error;
323
+ }
324
+
325
+ trace_smmu_ptw_block_pte(stage, level, baseaddr,
326
+ pte_addr, pte, iova, gpa,
327
+ block_size >> 20);
328
+
329
+ tlbe->translated_addr = gpa + (iova & mask);
330
+ tlbe->perm = PTE_AP_TO_PERM(ap);
331
+ return 0;
332
+ }
333
+
334
+ /* table pte */
335
+ ap = PTE_APTABLE(pte);
336
+
337
+ if (is_permission_fault(ap, perm)) {
338
+ info->type = SMMU_PTW_ERR_PERMISSION;
339
+ goto error;
340
+ }
341
+ baseaddr = get_table_pte_address(pte, granule_sz);
342
+ level++;
343
+ }
344
+
345
+ info->type = SMMU_PTW_ERR_TRANSLATION;
346
+
347
+error:
348
+ tlbe->perm = IOMMU_NONE;
349
+ return -EINVAL;
350
+}
351
+
352
+/**
353
+ * smmu_ptw - Walk the page tables for an IOVA, according to @cfg
354
+ *
355
+ * @cfg: translation configuration
356
+ * @iova: iova to translate
357
+ * @perm: tentative access type
358
+ * @tlbe: returned entry
359
+ * @info: ptw event handle
360
+ *
361
+ * return 0 on success
362
+ */
363
+inline int smmu_ptw(SMMUTransCfg *cfg, dma_addr_t iova, IOMMUAccessFlags perm,
364
+ IOMMUTLBEntry *tlbe, SMMUPTWEventInfo *info)
365
+{
366
+ if (!cfg->aa64) {
367
+ /*
368
+ * This code path is not entered as we check this while decoding
369
+ * the configuration data in the derived SMMU model.
370
+ */
371
+ g_assert_not_reached();
372
+ }
373
+
374
+ return smmu_ptw_64(cfg, iova, perm, tlbe, info);
375
+}
376
377
/**
378
* The bus number is used for lookup when SID based invalidation occurs.
379
diff --git a/hw/arm/trace-events b/hw/arm/trace-events
380
index XXXXXXX..XXXXXXX 100644
381
--- a/hw/arm/trace-events
382
+++ b/hw/arm/trace-events
383
@@ -XXX,XX +XXX,XX @@
384
virt_acpi_setup(void) "No fw cfg or ACPI disabled. Bailing out."
385
386
# hw/arm/smmu-common.c
387
-smmu_add_mr(const char *name) "%s"
388
\ No newline at end of file
389
+smmu_add_mr(const char *name) "%s"
390
+smmu_page_walk(int stage, uint64_t baseaddr, int first_level, uint64_t start, uint64_t end) "stage=%d, baseaddr=0x%"PRIx64", first level=%d, start=0x%"PRIx64", end=0x%"PRIx64
391
+smmu_lookup_table(int level, uint64_t baseaddr, int granule_sz, uint64_t start, uint64_t end, int flags, uint64_t subpage_size) "level=%d baseaddr=0x%"PRIx64" granule=%d, start=0x%"PRIx64" end=0x%"PRIx64" flags=%d subpage_size=0x%"PRIx64
392
+smmu_ptw_level(int level, uint64_t iova, size_t subpage_size, uint64_t baseaddr, uint32_t offset, uint64_t pte) "level=%d iova=0x%"PRIx64" subpage_sz=0x%lx baseaddr=0x%"PRIx64" offset=%d => pte=0x%"PRIx64
393
+smmu_ptw_invalid_pte(int stage, int level, uint64_t baseaddr, uint64_t pteaddr, uint32_t offset, uint64_t pte) "stage=%d level=%d base@=0x%"PRIx64" pte@=0x%"PRIx64" offset=%d pte=0x%"PRIx64
394
+smmu_ptw_page_pte(int stage, int level, uint64_t iova, uint64_t baseaddr, uint64_t pteaddr, uint64_t pte, uint64_t address) "stage=%d level=%d iova=0x%"PRIx64" base@=0x%"PRIx64" pte@=0x%"PRIx64" pte=0x%"PRIx64" page address = 0x%"PRIx64
395
+smmu_ptw_block_pte(int stage, int level, uint64_t baseaddr, uint64_t pteaddr, uint64_t pte, uint64_t iova, uint64_t gpa, int bsize_mb) "stage=%d level=%d base@=0x%"PRIx64" pte@=0x%"PRIx64" pte=0x%"PRIx64" iova=0x%"PRIx64" block address = 0x%"PRIx64" block size = %d MiB"
396
+smmu_get_pte(uint64_t baseaddr, int index, uint64_t pteaddr, uint64_t pte) "baseaddr=0x%"PRIx64" index=0x%x, pteaddr=0x%"PRIx64", pte=0x%"PRIx64
397
--
78
--
398
2.17.0
79
2.20.1
399
80
400
81
diff view generated by jsdifflib
1
From: Eric Auger <eric.auger@redhat.com>
1
Implement the new-in-v8.1M VLDR/VSTR variants which directly
2
read or write FP system registers to memory.
2
3
3
We introduce some helpers to handle wired IRQs and especially
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
GERROR interrupt. SMMU writes GERROR register on GERROR event
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
and SW acks GERROR interrupts by setting GERRORn.
6
Message-id: 20201119215617.29887-10-peter.maydell@linaro.org
7
---
8
target/arm/vfp.decode | 14 ++++++
9
target/arm/translate-vfp.c.inc | 91 ++++++++++++++++++++++++++++++++++
10
2 files changed, 105 insertions(+)
6
11
7
The Wired interrupts are edge sensitive hence the pulse usage.
12
diff --git a/target/arm/vfp.decode b/target/arm/vfp.decode
8
9
Signed-off-by: Eric Auger <eric.auger@redhat.com>
10
Signed-off-by: Prem Mallappa <prem.mallappa@broadcom.com>
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
Message-id: 1524665762-31355-6-git-send-email-eric.auger@redhat.com
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
15
hw/arm/smmuv3-internal.h | 14 +++++++++
16
hw/arm/smmuv3.c | 64 ++++++++++++++++++++++++++++++++++++++++
17
hw/arm/trace-events | 3 ++
18
3 files changed, 81 insertions(+)
19
20
diff --git a/hw/arm/smmuv3-internal.h b/hw/arm/smmuv3-internal.h
21
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
22
--- a/hw/arm/smmuv3-internal.h
14
--- a/target/arm/vfp.decode
23
+++ b/hw/arm/smmuv3-internal.h
15
+++ b/target/arm/vfp.decode
24
@@ -XXX,XX +XXX,XX @@ static inline uint32_t smmuv3_idreg(int regoffset)
16
@@ -XXX,XX +XXX,XX @@ VLDR_VSTR_hp ---- 1101 u:1 .0 l:1 rn:4 .... 1001 imm:8 vd=%vd_sp
25
return smmuv3_ids[regoffset / 4];
17
VLDR_VSTR_sp ---- 1101 u:1 .0 l:1 rn:4 .... 1010 imm:8 vd=%vd_sp
18
VLDR_VSTR_dp ---- 1101 u:1 .0 l:1 rn:4 .... 1011 imm:8 vd=%vd_dp
19
20
+# M-profile VLDR/VSTR to sysreg
21
+%vldr_sysreg 22:1 13:3
22
+%imm7_0x4 0:7 !function=times_4
23
+
24
+&vldr_sysreg rn reg imm a w p
25
+@vldr_sysreg .... ... . a:1 . . . rn:4 ... . ... .. ....... \
26
+ reg=%vldr_sysreg imm=%imm7_0x4 &vldr_sysreg
27
+
28
+# P=0 W=0 is SEE "Related encodings", so split into two patterns
29
+VLDR_sysreg ---- 110 1 . . w:1 1 .... ... 0 111 11 ....... @vldr_sysreg p=1
30
+VLDR_sysreg ---- 110 0 . . 1 1 .... ... 0 111 11 ....... @vldr_sysreg p=0 w=1
31
+VSTR_sysreg ---- 110 1 . . w:1 0 .... ... 0 111 11 ....... @vldr_sysreg p=1
32
+VSTR_sysreg ---- 110 0 . . 1 0 .... ... 0 111 11 ....... @vldr_sysreg p=0 w=1
33
+
34
# We split the load/store multiple up into two patterns to avoid
35
# overlap with other insns in the "Advanced SIMD load/store and 64-bit move"
36
# grouping:
37
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
38
index XXXXXXX..XXXXXXX 100644
39
--- a/target/arm/translate-vfp.c.inc
40
+++ b/target/arm/translate-vfp.c.inc
41
@@ -XXX,XX +XXX,XX @@ static bool trans_VMSR_VMRS(DisasContext *s, arg_VMSR_VMRS *a)
42
return true;
26
}
43
}
27
44
28
+static inline bool smmuv3_eventq_irq_enabled(SMMUv3State *s)
45
+static void fp_sysreg_to_memory(DisasContext *s, void *opaque, TCGv_i32 value)
29
+{
46
+{
30
+ return FIELD_EX32(s->irq_ctrl, IRQ_CTRL, EVENTQ_IRQEN);
47
+ arg_vldr_sysreg *a = opaque;
31
+}
48
+ uint32_t offset = a->imm;
49
+ TCGv_i32 addr;
32
+
50
+
33
+static inline bool smmuv3_gerror_irq_enabled(SMMUv3State *s)
51
+ if (!a->a) {
34
+{
52
+ offset = - offset;
35
+ return FIELD_EX32(s->irq_ctrl, IRQ_CTRL, GERROR_IRQEN);
53
+ }
36
+}
37
+
54
+
38
+/* public until callers get introduced */
55
+ addr = load_reg(s, a->rn);
39
+void smmuv3_trigger_irq(SMMUv3State *s, SMMUIrq irq, uint32_t gerror_mask);
56
+ if (a->p) {
40
+void smmuv3_write_gerrorn(SMMUv3State *s, uint32_t gerrorn);
57
+ tcg_gen_addi_i32(addr, addr, offset);
58
+ }
41
+
59
+
42
#endif
60
+ if (s->v8m_stackcheck && a->rn == 13 && a->w) {
43
diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c
61
+ gen_helper_v8m_stackcheck(cpu_env, addr);
44
index XXXXXXX..XXXXXXX 100644
62
+ }
45
--- a/hw/arm/smmuv3.c
46
+++ b/hw/arm/smmuv3.c
47
@@ -XXX,XX +XXX,XX @@
48
#include "hw/arm/smmuv3.h"
49
#include "smmuv3-internal.h"
50
51
+/**
52
+ * smmuv3_trigger_irq - pulse @irq if enabled and update
53
+ * GERROR register in case of GERROR interrupt
54
+ *
55
+ * @irq: irq type
56
+ * @gerror_mask: mask of gerrors to toggle (relevant if @irq is GERROR)
57
+ */
58
+void smmuv3_trigger_irq(SMMUv3State *s, SMMUIrq irq, uint32_t gerror_mask)
59
+{
60
+
63
+
61
+ bool pulse = false;
64
+ gen_aa32_st_i32(s, value, addr, get_mem_index(s),
65
+ MO_UL | MO_ALIGN | s->be_data);
66
+ tcg_temp_free_i32(value);
62
+
67
+
63
+ switch (irq) {
68
+ if (a->w) {
64
+ case SMMU_IRQ_EVTQ:
69
+ /* writeback */
65
+ pulse = smmuv3_eventq_irq_enabled(s);
70
+ if (!a->p) {
66
+ break;
71
+ tcg_gen_addi_i32(addr, addr, offset);
67
+ case SMMU_IRQ_PRIQ:
68
+ qemu_log_mask(LOG_UNIMP, "PRI not yet supported\n");
69
+ break;
70
+ case SMMU_IRQ_CMD_SYNC:
71
+ pulse = true;
72
+ break;
73
+ case SMMU_IRQ_GERROR:
74
+ {
75
+ uint32_t pending = s->gerror ^ s->gerrorn;
76
+ uint32_t new_gerrors = ~pending & gerror_mask;
77
+
78
+ if (!new_gerrors) {
79
+ /* only toggle non pending errors */
80
+ return;
81
+ }
72
+ }
82
+ s->gerror ^= new_gerrors;
73
+ store_reg(s, a->rn, addr);
83
+ trace_smmuv3_write_gerror(new_gerrors, s->gerror);
74
+ } else {
84
+
75
+ tcg_temp_free_i32(addr);
85
+ pulse = smmuv3_gerror_irq_enabled(s);
86
+ break;
87
+ }
88
+ }
89
+ if (pulse) {
90
+ trace_smmuv3_trigger_irq(irq);
91
+ qemu_irq_pulse(s->irq[irq]);
92
+ }
76
+ }
93
+}
77
+}
94
+
78
+
95
+void smmuv3_write_gerrorn(SMMUv3State *s, uint32_t new_gerrorn)
79
+static TCGv_i32 memory_to_fp_sysreg(DisasContext *s, void *opaque)
96
+{
80
+{
97
+ uint32_t pending = s->gerror ^ s->gerrorn;
81
+ arg_vldr_sysreg *a = opaque;
98
+ uint32_t toggled = s->gerrorn ^ new_gerrorn;
82
+ uint32_t offset = a->imm;
83
+ TCGv_i32 addr;
84
+ TCGv_i32 value = tcg_temp_new_i32();
99
+
85
+
100
+ if (toggled & ~pending) {
86
+ if (!a->a) {
101
+ qemu_log_mask(LOG_GUEST_ERROR,
87
+ offset = - offset;
102
+ "guest toggles non pending errors = 0x%x\n",
103
+ toggled & ~pending);
104
+ }
88
+ }
105
+
89
+
106
+ /*
90
+ addr = load_reg(s, a->rn);
107
+ * We do not raise any error in case guest toggles bits corresponding
91
+ if (a->p) {
108
+ * to not active IRQs (CONSTRAINED UNPREDICTABLE)
92
+ tcg_gen_addi_i32(addr, addr, offset);
109
+ */
93
+ }
110
+ s->gerrorn = new_gerrorn;
111
+
94
+
112
+ trace_smmuv3_write_gerrorn(toggled & pending, s->gerrorn);
95
+ if (s->v8m_stackcheck && a->rn == 13 && a->w) {
96
+ gen_helper_v8m_stackcheck(cpu_env, addr);
97
+ }
98
+
99
+ gen_aa32_ld_i32(s, value, addr, get_mem_index(s),
100
+ MO_UL | MO_ALIGN | s->be_data);
101
+
102
+ if (a->w) {
103
+ /* writeback */
104
+ if (!a->p) {
105
+ tcg_gen_addi_i32(addr, addr, offset);
106
+ }
107
+ store_reg(s, a->rn, addr);
108
+ } else {
109
+ tcg_temp_free_i32(addr);
110
+ }
111
+ return value;
113
+}
112
+}
114
+
113
+
115
static void smmuv3_init_regs(SMMUv3State *s)
114
+static bool trans_VLDR_sysreg(DisasContext *s, arg_vldr_sysreg *a)
115
+{
116
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
117
+ return false;
118
+ }
119
+ if (a->rn == 15) {
120
+ return false;
121
+ }
122
+ return gen_M_fp_sysreg_write(s, a->reg, memory_to_fp_sysreg, a);
123
+}
124
+
125
+static bool trans_VSTR_sysreg(DisasContext *s, arg_vldr_sysreg *a)
126
+{
127
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
128
+ return false;
129
+ }
130
+ if (a->rn == 15) {
131
+ return false;
132
+ }
133
+ return gen_M_fp_sysreg_read(s, a->reg, fp_sysreg_to_memory, a);
134
+}
135
+
136
static bool trans_VMOV_half(DisasContext *s, arg_VMOV_single *a)
116
{
137
{
117
/**
138
TCGv_i32 tmp;
118
diff --git a/hw/arm/trace-events b/hw/arm/trace-events
119
index XXXXXXX..XXXXXXX 100644
120
--- a/hw/arm/trace-events
121
+++ b/hw/arm/trace-events
122
@@ -XXX,XX +XXX,XX @@ smmu_get_pte(uint64_t baseaddr, int index, uint64_t pteaddr, uint64_t pte) "base
123
124
#hw/arm/smmuv3.c
125
smmuv3_read_mmio(uint64_t addr, uint64_t val, unsigned size, uint32_t r) "addr: 0x%"PRIx64" val:0x%"PRIx64" size: 0x%x(%d)"
126
+smmuv3_trigger_irq(int irq) "irq=%d"
127
+smmuv3_write_gerror(uint32_t toggled, uint32_t gerror) "toggled=0x%x, new GERROR=0x%x"
128
+smmuv3_write_gerrorn(uint32_t acked, uint32_t gerrorn) "acked=0x%x, new GERRORN=0x%x"
129
--
139
--
130
2.17.0
140
2.20.1
131
141
132
142
diff view generated by jsdifflib
New patch
1
v8.1M defines a new FP system register FPSCR_nzcvqc; this behaves
2
like the existing FPSCR, except that it reads and writes only bits
3
[31:27] of the FPSCR (the N, Z, C, V and QC flag bits). (Unlike the
4
FPSCR, the special case for Rt=15 of writing the CPSR.NZCV is not
5
permitted.)
1
6
7
Implement the register. Since we don't yet implement MVE, we handle
8
the QC bit as RES0, with todo comments for where we will need to add
9
support later.
10
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
13
Message-id: 20201119215617.29887-11-peter.maydell@linaro.org
14
---
15
target/arm/cpu.h | 13 +++++++++++++
16
target/arm/translate-vfp.c.inc | 27 +++++++++++++++++++++++++++
17
2 files changed, 40 insertions(+)
18
19
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
20
index XXXXXXX..XXXXXXX 100644
21
--- a/target/arm/cpu.h
22
+++ b/target/arm/cpu.h
23
@@ -XXX,XX +XXX,XX @@ void vfp_set_fpscr(CPUARMState *env, uint32_t val);
24
#define FPCR_FZ (1 << 24) /* Flush-to-zero enable bit */
25
#define FPCR_DN (1 << 25) /* Default NaN enable bit */
26
#define FPCR_QC (1 << 27) /* Cumulative saturation bit */
27
+#define FPCR_V (1 << 28) /* FP overflow flag */
28
+#define FPCR_C (1 << 29) /* FP carry flag */
29
+#define FPCR_Z (1 << 30) /* FP zero flag */
30
+#define FPCR_N (1 << 31) /* FP negative flag */
31
+
32
+#define FPCR_NZCV_MASK (FPCR_N | FPCR_Z | FPCR_C | FPCR_V)
33
+#define FPCR_NZCVQC_MASK (FPCR_NZCV_MASK | FPCR_QC)
34
35
static inline uint32_t vfp_get_fpsr(CPUARMState *env)
36
{
37
@@ -XXX,XX +XXX,XX @@ enum arm_cpu_mode {
38
#define ARM_VFP_FPEXC 8
39
#define ARM_VFP_FPINST 9
40
#define ARM_VFP_FPINST2 10
41
+/* These ones are M-profile only */
42
+#define ARM_VFP_FPSCR_NZCVQC 2
43
+#define ARM_VFP_VPR 12
44
+#define ARM_VFP_P0 13
45
+#define ARM_VFP_FPCXT_NS 14
46
+#define ARM_VFP_FPCXT_S 15
47
48
/* QEMU-internal value meaning "FPSCR, but we care only about NZCV" */
49
#define QEMU_VFP_FPSCR_NZCV 0xffff
50
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
51
index XXXXXXX..XXXXXXX 100644
52
--- a/target/arm/translate-vfp.c.inc
53
+++ b/target/arm/translate-vfp.c.inc
54
@@ -XXX,XX +XXX,XX @@ static FPSysRegCheckResult fp_sysreg_checks(DisasContext *s, int regno)
55
case ARM_VFP_FPSCR:
56
case QEMU_VFP_FPSCR_NZCV:
57
break;
58
+ case ARM_VFP_FPSCR_NZCVQC:
59
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
60
+ return false;
61
+ }
62
+ break;
63
default:
64
return FPSysRegCheckFailed;
65
}
66
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_write(DisasContext *s, int regno,
67
tcg_temp_free_i32(tmp);
68
gen_lookup_tb(s);
69
break;
70
+ case ARM_VFP_FPSCR_NZCVQC:
71
+ {
72
+ TCGv_i32 fpscr;
73
+ tmp = loadfn(s, opaque);
74
+ /*
75
+ * TODO: when we implement MVE, write the QC bit.
76
+ * For non-MVE, QC is RES0.
77
+ */
78
+ tcg_gen_andi_i32(tmp, tmp, FPCR_NZCV_MASK);
79
+ fpscr = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
80
+ tcg_gen_andi_i32(fpscr, fpscr, ~FPCR_NZCV_MASK);
81
+ tcg_gen_or_i32(fpscr, fpscr, tmp);
82
+ store_cpu_field(fpscr, vfp.xregs[ARM_VFP_FPSCR]);
83
+ tcg_temp_free_i32(tmp);
84
+ break;
85
+ }
86
default:
87
g_assert_not_reached();
88
}
89
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_read(DisasContext *s, int regno,
90
gen_helper_vfp_get_fpscr(tmp, cpu_env);
91
storefn(s, opaque, tmp);
92
break;
93
+ case ARM_VFP_FPSCR_NZCVQC:
94
+ /*
95
+ * TODO: MVE has a QC bit, which we probably won't store
96
+ * in the xregs[] field. For non-MVE, where QC is RES0,
97
+ * we can just fall through to the FPSCR_NZCV case.
98
+ */
99
case QEMU_VFP_FPSCR_NZCV:
100
/*
101
* Read just NZCV; this is a special case to avoid the
102
--
103
2.20.1
104
105
diff view generated by jsdifflib
New patch
1
We defined a constant name for the mask of NZCV bits in the FPCR/FPSCR
2
in the previous commit; use it in a couple of places in existing code,
3
where we're masking out everything except NZCV for the "load to Rt=15
4
sets CPSR.NZCV" special case.
1
5
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20201119215617.29887-12-peter.maydell@linaro.org
9
---
10
target/arm/translate-vfp.c.inc | 4 ++--
11
1 file changed, 2 insertions(+), 2 deletions(-)
12
13
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/translate-vfp.c.inc
16
+++ b/target/arm/translate-vfp.c.inc
17
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_read(DisasContext *s, int regno,
18
* helper call for the "VMRS to CPSR.NZCV" insn.
19
*/
20
tmp = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
21
- tcg_gen_andi_i32(tmp, tmp, 0xf0000000);
22
+ tcg_gen_andi_i32(tmp, tmp, FPCR_NZCV_MASK);
23
storefn(s, opaque, tmp);
24
break;
25
default:
26
@@ -XXX,XX +XXX,XX @@ static bool trans_VMSR_VMRS(DisasContext *s, arg_VMSR_VMRS *a)
27
case ARM_VFP_FPSCR:
28
if (a->rt == 15) {
29
tmp = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
30
- tcg_gen_andi_i32(tmp, tmp, 0xf0000000);
31
+ tcg_gen_andi_i32(tmp, tmp, FPCR_NZCV_MASK);
32
} else {
33
tmp = tcg_temp_new_i32();
34
gen_helper_vfp_get_fpscr(tmp, cpu_env);
35
--
36
2.20.1
37
38
diff view generated by jsdifflib
1
From: Eric Auger <eric.auger@redhat.com>
1
Factor out the code which handles M-profile lazy FP state preservation
2
from full_vfp_access_check(); accesses to the FPCXT_NS register are
3
a special case which need to do just this part (corresponding in the
4
pseudocode to the PreserveFPState() function), and not the full
5
set of actions matching the pseudocode ExecuteFPCheck() which
6
normal FP instructions need to do.
2
7
3
At the moment, the SMMUv3 does not support notification on
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
TLB invalidation. So let's log an error as soon as such notifier
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
gets enabled.
10
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
11
Message-id: 20201119215617.29887-13-peter.maydell@linaro.org
12
---
13
target/arm/translate-vfp.c.inc | 45 ++++++++++++++++++++--------------
14
1 file changed, 27 insertions(+), 18 deletions(-)
6
15
7
Signed-off-by: Eric Auger <eric.auger@redhat.com>
16
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Message-id: 1524665762-31355-11-git-send-email-eric.auger@redhat.com
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
hw/arm/smmuv3.c | 11 +++++++++++
13
1 file changed, 11 insertions(+)
14
15
diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c
16
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/arm/smmuv3.c
18
--- a/target/arm/translate-vfp.c.inc
18
+++ b/hw/arm/smmuv3.c
19
+++ b/target/arm/translate-vfp.c.inc
19
@@ -XXX,XX +XXX,XX @@ static void smmuv3_class_init(ObjectClass *klass, void *data)
20
@@ -XXX,XX +XXX,XX @@ static inline long vfp_f16_offset(unsigned reg, bool top)
20
dc->realize = smmu_realize;
21
return offs;
21
}
22
}
22
23
23
+static void smmuv3_notify_flag_changed(IOMMUMemoryRegion *iommu,
24
+/*
24
+ IOMMUNotifierFlag old,
25
+ * Generate code for M-profile lazy FP state preservation if needed;
25
+ IOMMUNotifierFlag new)
26
+ * this corresponds to the pseudocode PreserveFPState() function.
27
+ */
28
+static void gen_preserve_fp_state(DisasContext *s)
26
+{
29
+{
27
+ if (old == IOMMU_NOTIFIER_NONE) {
30
+ if (s->v7m_lspact) {
28
+ warn_report("SMMUV3 does not support vhost/vfio integration yet: "
31
+ /*
29
+ "devices of those types will not function properly");
32
+ * Lazy state saving affects external memory and also the NVIC,
33
+ * so we must mark it as an IO operation for icount (and cause
34
+ * this to be the last insn in the TB).
35
+ */
36
+ if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
37
+ s->base.is_jmp = DISAS_UPDATE_EXIT;
38
+ gen_io_start();
39
+ }
40
+ gen_helper_v7m_preserve_fp_state(cpu_env);
41
+ /*
42
+ * If the preserve_fp_state helper doesn't throw an exception
43
+ * then it will clear LSPACT; we don't need to repeat this for
44
+ * any further FP insns in this TB.
45
+ */
46
+ s->v7m_lspact = false;
30
+ }
47
+ }
31
+}
48
+}
32
+
49
+
33
static void smmuv3_iommu_memory_region_class_init(ObjectClass *klass,
50
/*
34
void *data)
51
* Check that VFP access is enabled. If it is, do the necessary
35
{
52
* M-profile lazy-FP handling and then return true.
36
IOMMUMemoryRegionClass *imrc = IOMMU_MEMORY_REGION_CLASS(klass);
53
@@ -XXX,XX +XXX,XX @@ static bool full_vfp_access_check(DisasContext *s, bool ignore_vfp_enabled)
37
54
/* Handle M-profile lazy FP state mechanics */
38
imrc->translate = smmuv3_translate;
55
39
+ imrc->notify_flag_changed = smmuv3_notify_flag_changed;
56
/* Trigger lazy-state preservation if necessary */
40
}
57
- if (s->v7m_lspact) {
41
58
- /*
42
static const TypeInfo smmuv3_type_info = {
59
- * Lazy state saving affects external memory and also the NVIC,
60
- * so we must mark it as an IO operation for icount (and cause
61
- * this to be the last insn in the TB).
62
- */
63
- if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
64
- s->base.is_jmp = DISAS_UPDATE_EXIT;
65
- gen_io_start();
66
- }
67
- gen_helper_v7m_preserve_fp_state(cpu_env);
68
- /*
69
- * If the preserve_fp_state helper doesn't throw an exception
70
- * then it will clear LSPACT; we don't need to repeat this for
71
- * any further FP insns in this TB.
72
- */
73
- s->v7m_lspact = false;
74
- }
75
+ gen_preserve_fp_state(s);
76
77
/* Update ownership of FP context: set FPCCR.S to match current state */
78
if (s->v8m_fpccr_s_wrong) {
43
--
79
--
44
2.17.0
80
2.20.1
45
81
46
82
diff view generated by jsdifflib
New patch
1
Implement the new-in-v8.1M FPCXT_S floating point system register.
2
This is for saving and restoring the secure floating point context,
3
and it reads and writes bits [27:0] from the FPSCR and the
4
CONTROL.SFPA bit in bit [31].
1
5
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20201119215617.29887-14-peter.maydell@linaro.org
9
---
10
target/arm/translate-vfp.c.inc | 58 ++++++++++++++++++++++++++++++++++
11
1 file changed, 58 insertions(+)
12
13
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/translate-vfp.c.inc
16
+++ b/target/arm/translate-vfp.c.inc
17
@@ -XXX,XX +XXX,XX @@ static FPSysRegCheckResult fp_sysreg_checks(DisasContext *s, int regno)
18
return false;
19
}
20
break;
21
+ case ARM_VFP_FPCXT_S:
22
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
23
+ return false;
24
+ }
25
+ if (!s->v8m_secure) {
26
+ return false;
27
+ }
28
+ break;
29
default:
30
return FPSysRegCheckFailed;
31
}
32
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_write(DisasContext *s, int regno,
33
tcg_temp_free_i32(tmp);
34
break;
35
}
36
+ case ARM_VFP_FPCXT_S:
37
+ {
38
+ TCGv_i32 sfpa, control, fpscr;
39
+ /* Set FPSCR[27:0] and CONTROL.SFPA from value */
40
+ tmp = loadfn(s, opaque);
41
+ sfpa = tcg_temp_new_i32();
42
+ tcg_gen_shri_i32(sfpa, tmp, 31);
43
+ control = load_cpu_field(v7m.control[M_REG_S]);
44
+ tcg_gen_deposit_i32(control, control, sfpa,
45
+ R_V7M_CONTROL_SFPA_SHIFT, 1);
46
+ store_cpu_field(control, v7m.control[M_REG_S]);
47
+ fpscr = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
48
+ tcg_gen_andi_i32(fpscr, fpscr, FPCR_NZCV_MASK);
49
+ tcg_gen_andi_i32(tmp, tmp, ~FPCR_NZCV_MASK);
50
+ tcg_gen_or_i32(fpscr, fpscr, tmp);
51
+ store_cpu_field(fpscr, vfp.xregs[ARM_VFP_FPSCR]);
52
+ tcg_temp_free_i32(tmp);
53
+ tcg_temp_free_i32(sfpa);
54
+ break;
55
+ }
56
default:
57
g_assert_not_reached();
58
}
59
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_read(DisasContext *s, int regno,
60
tcg_gen_andi_i32(tmp, tmp, FPCR_NZCV_MASK);
61
storefn(s, opaque, tmp);
62
break;
63
+ case ARM_VFP_FPCXT_S:
64
+ {
65
+ TCGv_i32 control, sfpa, fpscr;
66
+ /* Bits [27:0] from FPSCR, bit [31] from CONTROL.SFPA */
67
+ tmp = tcg_temp_new_i32();
68
+ sfpa = tcg_temp_new_i32();
69
+ gen_helper_vfp_get_fpscr(tmp, cpu_env);
70
+ tcg_gen_andi_i32(tmp, tmp, ~FPCR_NZCV_MASK);
71
+ control = load_cpu_field(v7m.control[M_REG_S]);
72
+ tcg_gen_andi_i32(sfpa, control, R_V7M_CONTROL_SFPA_MASK);
73
+ tcg_gen_shli_i32(sfpa, sfpa, 31 - R_V7M_CONTROL_SFPA_SHIFT);
74
+ tcg_gen_or_i32(tmp, tmp, sfpa);
75
+ tcg_temp_free_i32(sfpa);
76
+ /*
77
+ * Store result before updating FPSCR etc, in case
78
+ * it is a memory write which causes an exception.
79
+ */
80
+ storefn(s, opaque, tmp);
81
+ /*
82
+ * Now we must reset FPSCR from FPDSCR_NS, and clear
83
+ * CONTROL.SFPA; so we'll end the TB here.
84
+ */
85
+ tcg_gen_andi_i32(control, control, ~R_V7M_CONTROL_SFPA_MASK);
86
+ store_cpu_field(control, v7m.control[M_REG_S]);
87
+ fpscr = load_cpu_field(v7m.fpdscr[M_REG_NS]);
88
+ gen_helper_vfp_set_fpscr(cpu_env, fpscr);
89
+ tcg_temp_free_i32(fpscr);
90
+ gen_lookup_tb(s);
91
+ break;
92
+ }
93
default:
94
g_assert_not_reached();
95
}
96
--
97
2.20.1
98
99
diff view generated by jsdifflib
New patch
1
The FPDSCR register has a similar layout to the FPSCR. In v8.1M it
2
gains new fields FZ16 (if half-precision floating point is supported)
3
and LTPSIZE (always reads as 4). Update the reset value and the code
4
that handles writes to this register accordingly.
1
5
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20201119215617.29887-16-peter.maydell@linaro.org
9
---
10
target/arm/cpu.h | 5 +++++
11
hw/intc/armv7m_nvic.c | 9 ++++++++-
12
target/arm/cpu.c | 3 +++
13
3 files changed, 16 insertions(+), 1 deletion(-)
14
15
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
16
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/cpu.h
18
+++ b/target/arm/cpu.h
19
@@ -XXX,XX +XXX,XX @@ void vfp_set_fpscr(CPUARMState *env, uint32_t val);
20
#define FPCR_IXE (1 << 12) /* Inexact exception trap enable */
21
#define FPCR_IDE (1 << 15) /* Input Denormal exception trap enable */
22
#define FPCR_FZ16 (1 << 19) /* ARMv8.2+, FP16 flush-to-zero */
23
+#define FPCR_RMODE_MASK (3 << 22) /* Rounding mode */
24
#define FPCR_FZ (1 << 24) /* Flush-to-zero enable bit */
25
#define FPCR_DN (1 << 25) /* Default NaN enable bit */
26
+#define FPCR_AHP (1 << 26) /* Alternative half-precision */
27
#define FPCR_QC (1 << 27) /* Cumulative saturation bit */
28
#define FPCR_V (1 << 28) /* FP overflow flag */
29
#define FPCR_C (1 << 29) /* FP carry flag */
30
#define FPCR_Z (1 << 30) /* FP zero flag */
31
#define FPCR_N (1 << 31) /* FP negative flag */
32
33
+#define FPCR_LTPSIZE_SHIFT 16 /* LTPSIZE, M-profile only */
34
+#define FPCR_LTPSIZE_MASK (7 << FPCR_LTPSIZE_SHIFT)
35
+
36
#define FPCR_NZCV_MASK (FPCR_N | FPCR_Z | FPCR_C | FPCR_V)
37
#define FPCR_NZCVQC_MASK (FPCR_NZCV_MASK | FPCR_QC)
38
39
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
40
index XXXXXXX..XXXXXXX 100644
41
--- a/hw/intc/armv7m_nvic.c
42
+++ b/hw/intc/armv7m_nvic.c
43
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
44
break;
45
case 0xf3c: /* FPDSCR */
46
if (cpu_isar_feature(aa32_vfp_simd, cpu)) {
47
- value &= 0x07c00000;
48
+ uint32_t mask = FPCR_AHP | FPCR_DN | FPCR_FZ | FPCR_RMODE_MASK;
49
+ if (cpu_isar_feature(any_fp16, cpu)) {
50
+ mask |= FPCR_FZ16;
51
+ }
52
+ value &= mask;
53
+ if (cpu_isar_feature(aa32_lob, cpu)) {
54
+ value |= 4 << FPCR_LTPSIZE_SHIFT;
55
+ }
56
cpu->env.v7m.fpdscr[attrs.secure] = value;
57
}
58
break;
59
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
60
index XXXXXXX..XXXXXXX 100644
61
--- a/target/arm/cpu.c
62
+++ b/target/arm/cpu.c
63
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_reset(DeviceState *dev)
64
* always reset to 4.
65
*/
66
env->v7m.ltpsize = 4;
67
+ /* The LTPSIZE field in FPDSCR is constant and reads as 4. */
68
+ env->v7m.fpdscr[M_REG_NS] = 4 << FPCR_LTPSIZE_SHIFT;
69
+ env->v7m.fpdscr[M_REG_S] = 4 << FPCR_LTPSIZE_SHIFT;
70
}
71
72
if (arm_feature(env, ARM_FEATURE_M_SECURITY)) {
73
--
74
2.20.1
75
76
diff view generated by jsdifflib
New patch
1
In v8.0M, on exception entry the registers R0-R3, R12, APSR and EPSR
2
are zeroed for an exception taken to Non-secure state; for an
3
exception taken to Secure state they become UNKNOWN, and we chose to
4
leave them at their previous values.
1
5
6
In v8.1M the behaviour is specified more tightly and these registers
7
are always zeroed regardless of the security state that the exception
8
targets (see rule R_KPZV). Implement this.
9
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20201119215617.29887-17-peter.maydell@linaro.org
13
---
14
target/arm/m_helper.c | 16 ++++++++++++----
15
1 file changed, 12 insertions(+), 4 deletions(-)
16
17
diff --git a/target/arm/m_helper.c b/target/arm/m_helper.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/m_helper.c
20
+++ b/target/arm/m_helper.c
21
@@ -XXX,XX +XXX,XX @@ static void v7m_exception_taken(ARMCPU *cpu, uint32_t lr, bool dotailchain,
22
* Clear registers if necessary to prevent non-secure exception
23
* code being able to see register values from secure code.
24
* Where register values become architecturally UNKNOWN we leave
25
- * them with their previous values.
26
+ * them with their previous values. v8.1M is tighter than v8.0M
27
+ * here and always zeroes the caller-saved registers regardless
28
+ * of the security state the exception is targeting.
29
*/
30
if (arm_feature(env, ARM_FEATURE_M_SECURITY)) {
31
- if (!targets_secure) {
32
+ if (!targets_secure || arm_feature(env, ARM_FEATURE_V8_1M)) {
33
/*
34
* Always clear the caller-saved registers (they have been
35
* pushed to the stack earlier in v7m_push_stack()).
36
@@ -XXX,XX +XXX,XX @@ static void v7m_exception_taken(ARMCPU *cpu, uint32_t lr, bool dotailchain,
37
* v7m_push_callee_stack()).
38
*/
39
int i;
40
+ /*
41
+ * r4..r11 are callee-saves, zero only if background
42
+ * state was Secure (EXCRET.S == 1) and exception
43
+ * targets Non-secure state
44
+ */
45
+ bool zero_callee_saves = !targets_secure &&
46
+ (lr & R_V7M_EXCRET_S_MASK);
47
48
for (i = 0; i < 13; i++) {
49
- /* r4..r11 are callee-saves, zero only if EXCRET.S == 1 */
50
- if (i < 4 || i > 11 || (lr & R_V7M_EXCRET_S_MASK)) {
51
+ if (i < 4 || i > 11 || zero_callee_saves) {
52
env->regs[i] = 0;
53
}
54
}
55
--
56
2.20.1
57
58
diff view generated by jsdifflib
New patch
1
In v8.1M, vector table fetch failures don't set HFSR.FORCED (see rule
2
R_LLRP). (In previous versions of the architecture this was either
3
required or IMPDEF.)
1
4
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20201119215617.29887-18-peter.maydell@linaro.org
8
---
9
target/arm/m_helper.c | 6 +++++-
10
1 file changed, 5 insertions(+), 1 deletion(-)
11
12
diff --git a/target/arm/m_helper.c b/target/arm/m_helper.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/m_helper.c
15
+++ b/target/arm/m_helper.c
16
@@ -XXX,XX +XXX,XX @@ load_fail:
17
* The HardFault is Secure if BFHFNMINS is 0 (meaning that all HFs are
18
* secure); otherwise it targets the same security state as the
19
* underlying exception.
20
+ * In v8.1M HardFaults from vector table fetch fails don't set FORCED.
21
*/
22
if (!(cpu->env.v7m.aircr & R_V7M_AIRCR_BFHFNMINS_MASK)) {
23
exc_secure = true;
24
}
25
- env->v7m.hfsr |= R_V7M_HFSR_VECTTBL_MASK | R_V7M_HFSR_FORCED_MASK;
26
+ env->v7m.hfsr |= R_V7M_HFSR_VECTTBL_MASK;
27
+ if (!arm_feature(env, ARM_FEATURE_V8_1M)) {
28
+ env->v7m.hfsr |= R_V7M_HFSR_FORCED_MASK;
29
+ }
30
armv7m_nvic_set_pending_derived(env->nvic, ARMV7M_EXCP_HARD, exc_secure);
31
return false;
32
}
33
--
34
2.20.1
35
36
diff view generated by jsdifflib
New patch
1
In v8.1M a REVIDR register is defined, which is at address 0xe00ecfc
2
and is a read-only IMPDEF register providing implementation specific
3
minor revision information, like the v8A REVIDR_EL1. Implement this.
1
4
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20201119215617.29887-19-peter.maydell@linaro.org
8
---
9
hw/intc/armv7m_nvic.c | 5 +++++
10
1 file changed, 5 insertions(+)
11
12
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/intc/armv7m_nvic.c
15
+++ b/hw/intc/armv7m_nvic.c
16
@@ -XXX,XX +XXX,XX @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
17
}
18
return val;
19
}
20
+ case 0xcfc:
21
+ if (!arm_feature(&cpu->env, ARM_FEATURE_V8_1M)) {
22
+ goto bad_offset;
23
+ }
24
+ return cpu->revidr;
25
case 0xd00: /* CPUID Base. */
26
return cpu->midr;
27
case 0xd04: /* Interrupt Control State (ICSR) */
28
--
29
2.20.1
30
31
diff view generated by jsdifflib
New patch
1
In v8.1M a new exception return check is added which may cause a NOCP
2
UsageFault (see rule R_XLTP): before we clear s0..s15 and the FPSCR
3
we must check whether access to CP10 from the Security state of the
4
returning exception is disabled; if it is then we must take a fault.
1
5
6
(Note that for our implementation CPPWR is always RAZ/WI and so can
7
never cause CP10 accesses to fail.)
8
9
The other v8.1M change to this register-clearing code is that if MVE
10
is implemented VPR must also be cleared, so add a TODO comment to
11
that effect.
12
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
Message-id: 20201119215617.29887-20-peter.maydell@linaro.org
16
---
17
target/arm/m_helper.c | 22 +++++++++++++++++++++-
18
1 file changed, 21 insertions(+), 1 deletion(-)
19
20
diff --git a/target/arm/m_helper.c b/target/arm/m_helper.c
21
index XXXXXXX..XXXXXXX 100644
22
--- a/target/arm/m_helper.c
23
+++ b/target/arm/m_helper.c
24
@@ -XXX,XX +XXX,XX @@ static void do_v7m_exception_exit(ARMCPU *cpu)
25
v7m_exception_taken(cpu, excret, true, false);
26
return;
27
} else {
28
- /* Clear s0..s15 and FPSCR */
29
+ if (arm_feature(env, ARM_FEATURE_V8_1M)) {
30
+ /* v8.1M adds this NOCP check */
31
+ bool nsacr_pass = exc_secure ||
32
+ extract32(env->v7m.nsacr, 10, 1);
33
+ bool cpacr_pass = v7m_cpacr_pass(env, exc_secure, true);
34
+ if (!nsacr_pass) {
35
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE, true);
36
+ env->v7m.cfsr[M_REG_S] |= R_V7M_CFSR_NOCP_MASK;
37
+ qemu_log_mask(CPU_LOG_INT, "...taking UsageFault on existing "
38
+ "stackframe: NSACR prevents clearing FPU registers\n");
39
+ v7m_exception_taken(cpu, excret, true, false);
40
+ } else if (!cpacr_pass) {
41
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE,
42
+ exc_secure);
43
+ env->v7m.cfsr[exc_secure] |= R_V7M_CFSR_NOCP_MASK;
44
+ qemu_log_mask(CPU_LOG_INT, "...taking UsageFault on existing "
45
+ "stackframe: CPACR prevents clearing FPU registers\n");
46
+ v7m_exception_taken(cpu, excret, true, false);
47
+ }
48
+ }
49
+ /* Clear s0..s15 and FPSCR; TODO also VPR when MVE is implemented */
50
int i;
51
52
for (i = 0; i < 16; i += 2) {
53
--
54
2.20.1
55
56
diff view generated by jsdifflib
New patch
1
v8.1M adds new encodings of VLLDM and VLSTM (where bit 7 is set).
2
The only difference is that:
3
* the old T1 encodings UNDEF if the implementation implements 32
4
Dregs (this is currently architecturally impossible for M-profile)
5
* the new T2 encodings have the implementation-defined option to
6
read from memory (discarding the data) or write UNKNOWN values to
7
memory for the stack slots that would be D16-D31
1
8
9
We choose not to make those accesses, so for us the two
10
instructions behave identically assuming they don't UNDEF.
11
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
14
Message-id: 20201119215617.29887-21-peter.maydell@linaro.org
15
---
16
target/arm/m-nocp.decode | 2 +-
17
target/arm/translate-vfp.c.inc | 25 +++++++++++++++++++++++++
18
2 files changed, 26 insertions(+), 1 deletion(-)
19
20
diff --git a/target/arm/m-nocp.decode b/target/arm/m-nocp.decode
21
index XXXXXXX..XXXXXXX 100644
22
--- a/target/arm/m-nocp.decode
23
+++ b/target/arm/m-nocp.decode
24
@@ -XXX,XX +XXX,XX @@
25
26
{
27
# Special cases which do not take an early NOCP: VLLDM and VLSTM
28
- VLLDM_VLSTM 1110 1100 001 l:1 rn:4 0000 1010 0000 0000
29
+ VLLDM_VLSTM 1110 1100 001 l:1 rn:4 0000 1010 op:1 000 0000
30
# VSCCLRM (new in v8.1M) is similar:
31
VSCCLRM 1110 1100 1.01 1111 .... 1011 imm:7 0 vd=%vd_dp size=3
32
VSCCLRM 1110 1100 1.01 1111 .... 1010 imm:8 vd=%vd_sp size=2
33
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
34
index XXXXXXX..XXXXXXX 100644
35
--- a/target/arm/translate-vfp.c.inc
36
+++ b/target/arm/translate-vfp.c.inc
37
@@ -XXX,XX +XXX,XX @@ static bool trans_VLLDM_VLSTM(DisasContext *s, arg_VLLDM_VLSTM *a)
38
!arm_dc_feature(s, ARM_FEATURE_V8)) {
39
return false;
40
}
41
+
42
+ if (a->op) {
43
+ /*
44
+ * T2 encoding ({D0-D31} reglist): v8.1M and up. We choose not
45
+ * to take the IMPDEF option to make memory accesses to the stack
46
+ * slots that correspond to the D16-D31 registers (discarding
47
+ * read data and writing UNKNOWN values), so for us the T2
48
+ * encoding behaves identically to the T1 encoding.
49
+ */
50
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
51
+ return false;
52
+ }
53
+ } else {
54
+ /*
55
+ * T1 encoding ({D0-D15} reglist); undef if we have 32 Dregs.
56
+ * This is currently architecturally impossible, but we add the
57
+ * check to stay in line with the pseudocode. Note that we must
58
+ * emit code for the UNDEF so it takes precedence over the NOCP.
59
+ */
60
+ if (dc_isar_feature(aa32_simd_r32, s)) {
61
+ unallocated_encoding(s);
62
+ return true;
63
+ }
64
+ }
65
+
66
/*
67
* If not secure, UNDEF. We must emit code for this
68
* rather than returning false so that this takes
69
--
70
2.20.1
71
72
diff view generated by jsdifflib
1
From: Jan Kiszka <jan.kiszka@siemens.com>
1
v8.1M introduces a new TRD flag in the CCR register, which enables
2
checking for stack frame integrity signatures on SG instructions.
3
This bit is not banked, and is always RAZ/WI to Non-secure code.
4
Adjust the code for handling CCR reads and writes to handle this.
2
5
3
This allows to pin the host controller in the Linux PCI domain space.
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Linux requires that property to be available consistently or not at all,
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
in which case the domain number becomes unstable on additions/removals.
8
Message-id: 20201119215617.29887-23-peter.maydell@linaro.org
6
Adding it here won't make a difference in practice for most setups as we
9
---
7
only expose one controller.
10
target/arm/cpu.h | 2 ++
11
hw/intc/armv7m_nvic.c | 26 ++++++++++++++++++--------
12
2 files changed, 20 insertions(+), 8 deletions(-)
8
13
9
However, enabling Jailhouse on top may introduce another controller, and
14
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
10
that one would like to have stable address as well. So the property is
11
needed for the first controller as well.
12
13
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
14
Message-id: 3301c5bc-7b47-1b0e-8ce4-30435057a276@web.de
15
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
---
18
hw/arm/virt.c | 1 +
19
1 file changed, 1 insertion(+)
20
21
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
22
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
23
--- a/hw/arm/virt.c
16
--- a/target/arm/cpu.h
24
+++ b/hw/arm/virt.c
17
+++ b/target/arm/cpu.h
25
@@ -XXX,XX +XXX,XX @@ static void create_pcie(const VirtMachineState *vms, qemu_irq *pic)
18
@@ -XXX,XX +XXX,XX @@ FIELD(V7M_CCR, STKOFHFNMIGN, 10, 1)
26
qemu_fdt_setprop_string(vms->fdt, nodename, "device_type", "pci");
19
FIELD(V7M_CCR, DC, 16, 1)
27
qemu_fdt_setprop_cell(vms->fdt, nodename, "#address-cells", 3);
20
FIELD(V7M_CCR, IC, 17, 1)
28
qemu_fdt_setprop_cell(vms->fdt, nodename, "#size-cells", 2);
21
FIELD(V7M_CCR, BP, 18, 1)
29
+ qemu_fdt_setprop_cell(vms->fdt, nodename, "linux,pci-domain", 0);
22
+FIELD(V7M_CCR, LOB, 19, 1)
30
qemu_fdt_setprop_cells(vms->fdt, nodename, "bus-range", 0,
23
+FIELD(V7M_CCR, TRD, 20, 1)
31
nr_pcie_buses - 1);
24
32
qemu_fdt_setprop(vms->fdt, nodename, "dma-coherent", NULL, 0);
25
/* V7M SCR bits */
26
FIELD(V7M_SCR, SLEEPONEXIT, 1, 1)
27
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
28
index XXXXXXX..XXXXXXX 100644
29
--- a/hw/intc/armv7m_nvic.c
30
+++ b/hw/intc/armv7m_nvic.c
31
@@ -XXX,XX +XXX,XX @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
32
}
33
return cpu->env.v7m.scr[attrs.secure];
34
case 0xd14: /* Configuration Control. */
35
- /* The BFHFNMIGN bit is the only non-banked bit; we
36
- * keep it in the non-secure copy of the register.
37
+ /*
38
+ * Non-banked bits: BFHFNMIGN (stored in the NS copy of the register)
39
+ * and TRD (stored in the S copy of the register)
40
*/
41
val = cpu->env.v7m.ccr[attrs.secure];
42
val |= cpu->env.v7m.ccr[M_REG_NS] & R_V7M_CCR_BFHFNMIGN_MASK;
43
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
44
cpu->env.v7m.scr[attrs.secure] = value;
45
break;
46
case 0xd14: /* Configuration Control. */
47
+ {
48
+ uint32_t mask;
49
+
50
if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) {
51
goto bad_offset;
52
}
53
54
/* Enforce RAZ/WI on reserved and must-RAZ/WI bits */
55
- value &= (R_V7M_CCR_STKALIGN_MASK |
56
- R_V7M_CCR_BFHFNMIGN_MASK |
57
- R_V7M_CCR_DIV_0_TRP_MASK |
58
- R_V7M_CCR_UNALIGN_TRP_MASK |
59
- R_V7M_CCR_USERSETMPEND_MASK |
60
- R_V7M_CCR_NONBASETHRDENA_MASK);
61
+ mask = R_V7M_CCR_STKALIGN_MASK |
62
+ R_V7M_CCR_BFHFNMIGN_MASK |
63
+ R_V7M_CCR_DIV_0_TRP_MASK |
64
+ R_V7M_CCR_UNALIGN_TRP_MASK |
65
+ R_V7M_CCR_USERSETMPEND_MASK |
66
+ R_V7M_CCR_NONBASETHRDENA_MASK;
67
+ if (arm_feature(&cpu->env, ARM_FEATURE_V8_1M) && attrs.secure) {
68
+ /* TRD is always RAZ/WI from NS */
69
+ mask |= R_V7M_CCR_TRD_MASK;
70
+ }
71
+ value &= mask;
72
73
if (arm_feature(&cpu->env, ARM_FEATURE_V8)) {
74
/* v8M makes NONBASETHRDENA and STKALIGN be RES1 */
75
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
76
77
cpu->env.v7m.ccr[attrs.secure] = value;
78
break;
79
+ }
80
case 0xd24: /* System Handler Control and State (SHCSR) */
81
if (!arm_feature(&cpu->env, ARM_FEATURE_V7)) {
82
goto bad_offset;
33
--
83
--
34
2.17.0
84
2.20.1
35
85
36
86
diff view generated by jsdifflib
1
From: Eric Auger <eric.auger@redhat.com>
1
v8.1M introduces a new TRD flag in the CCR register, which enables
2
checking for stack frame integrity signatures on SG instructions.
3
Add the code in the SG insn implementation for the new behaviour.
2
4
3
In case the MSI is translated by an IOMMU we need to fixup the
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
MSI route with the translated address.
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20201119215617.29887-24-peter.maydell@linaro.org
8
---
9
target/arm/m_helper.c | 86 +++++++++++++++++++++++++++++++++++++++++++
10
1 file changed, 86 insertions(+)
5
11
6
Signed-off-by: Eric Auger <eric.auger@redhat.com>
12
diff --git a/target/arm/m_helper.c b/target/arm/m_helper.c
7
Signed-off-by: Bharat Bhushan <Bharat.Bhushan@nxp.com>
8
Message-id: 1524665762-31355-12-git-send-email-eric.auger@redhat.com
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
target/arm/kvm.c | 38 +++++++++++++++++++++++++++++++++++++-
13
target/arm/trace-events | 3 +++
14
2 files changed, 40 insertions(+), 1 deletion(-)
15
16
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
17
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/kvm.c
14
--- a/target/arm/m_helper.c
19
+++ b/target/arm/kvm.c
15
+++ b/target/arm/m_helper.c
20
@@ -XXX,XX +XXX,XX @@
16
@@ -XXX,XX +XXX,XX @@ static bool v7m_read_half_insn(ARMCPU *cpu, ARMMMUIdx mmu_idx,
21
#include "sysemu/kvm.h"
17
return true;
22
#include "kvm_arm.h"
18
}
23
#include "cpu.h"
19
24
+#include "trace.h"
20
+static bool v7m_read_sg_stack_word(ARMCPU *cpu, ARMMMUIdx mmu_idx,
25
#include "internals.h"
21
+ uint32_t addr, uint32_t *spdata)
26
#include "hw/arm/arm.h"
22
+{
27
+#include "hw/pci/pci.h"
23
+ /*
28
#include "exec/memattrs.h"
24
+ * Read a word of data from the stack for the SG instruction,
29
#include "exec/address-spaces.h"
25
+ * writing the value into *spdata. If the load succeeds, return
30
#include "hw/boards.h"
26
+ * true; otherwise pend an appropriate exception and return false.
31
@@ -XXX,XX +XXX,XX @@ int kvm_arm_vgic_probe(void)
27
+ * (We can't use data load helpers here that throw an exception
32
int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route,
28
+ * because of the context we're called in, which is halfway through
33
uint64_t address, uint32_t data, PCIDevice *dev)
29
+ * arm_v7m_cpu_do_interrupt().)
34
{
30
+ */
35
- return 0;
31
+ CPUState *cs = CPU(cpu);
36
+ AddressSpace *as = pci_device_iommu_address_space(dev);
32
+ CPUARMState *env = &cpu->env;
37
+ hwaddr xlat, len, doorbell_gpa;
33
+ MemTxAttrs attrs = {};
38
+ MemoryRegionSection mrs;
34
+ MemTxResult txres;
39
+ MemoryRegion *mr;
35
+ target_ulong page_size;
40
+ int ret = 1;
36
+ hwaddr physaddr;
37
+ int prot;
38
+ ARMMMUFaultInfo fi = {};
39
+ ARMCacheAttrs cacheattrs = {};
40
+ uint32_t value;
41
+
41
+
42
+ if (as == &address_space_memory) {
42
+ if (get_phys_addr(env, addr, MMU_DATA_LOAD, mmu_idx, &physaddr,
43
+ return 0;
43
+ &attrs, &prot, &page_size, &fi, &cacheattrs)) {
44
+ /* MPU/SAU lookup failed */
45
+ if (fi.type == ARMFault_QEMU_SFault) {
46
+ qemu_log_mask(CPU_LOG_INT,
47
+ "...SecureFault during stack word read\n");
48
+ env->v7m.sfsr |= R_V7M_SFSR_AUVIOL_MASK | R_V7M_SFSR_SFARVALID_MASK;
49
+ env->v7m.sfar = addr;
50
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_SECURE, false);
51
+ } else {
52
+ qemu_log_mask(CPU_LOG_INT,
53
+ "...MemManageFault during stack word read\n");
54
+ env->v7m.cfsr[M_REG_S] |= R_V7M_CFSR_DACCVIOL_MASK |
55
+ R_V7M_CFSR_MMARVALID_MASK;
56
+ env->v7m.mmfar[M_REG_S] = addr;
57
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_MEM, false);
58
+ }
59
+ return false;
60
+ }
61
+ value = address_space_ldl(arm_addressspace(cs, attrs), physaddr,
62
+ attrs, &txres);
63
+ if (txres != MEMTX_OK) {
64
+ /* BusFault trying to read the data */
65
+ qemu_log_mask(CPU_LOG_INT,
66
+ "...BusFault during stack word read\n");
67
+ env->v7m.cfsr[M_REG_NS] |=
68
+ (R_V7M_CFSR_PRECISERR_MASK | R_V7M_CFSR_BFARVALID_MASK);
69
+ env->v7m.bfar = addr;
70
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_BUS, false);
71
+ return false;
44
+ }
72
+ }
45
+
73
+
46
+ /* MSI doorbell address is translated by an IOMMU */
74
+ *spdata = value;
75
+ return true;
76
+}
47
+
77
+
48
+ rcu_read_lock();
78
static bool v7m_handle_execute_nsc(ARMCPU *cpu)
49
+ mr = address_space_translate(as, address, &xlat, &len, true);
79
{
50
+ if (!mr) {
80
/*
51
+ goto unlock;
81
@@ -XXX,XX +XXX,XX @@ static bool v7m_handle_execute_nsc(ARMCPU *cpu)
52
+ }
82
*/
53
+ mrs = memory_region_find(mr, xlat, 1);
83
qemu_log_mask(CPU_LOG_INT, "...really an SG instruction at 0x%08" PRIx32
54
+ if (!mrs.mr) {
84
", executing it\n", env->regs[15]);
55
+ goto unlock;
85
+
86
+ if (cpu_isar_feature(aa32_m_sec_state, cpu) &&
87
+ !arm_v7m_is_handler_mode(env)) {
88
+ /*
89
+ * v8.1M exception stack frame integrity check. Note that we
90
+ * must perform the memory access even if CCR_S.TRD is zero
91
+ * and we aren't going to check what the data loaded is.
92
+ */
93
+ uint32_t spdata, sp;
94
+
95
+ /*
96
+ * We know we are currently NS, so the S stack pointers must be
97
+ * in other_ss_{psp,msp}, not in regs[13]/other_sp.
98
+ */
99
+ sp = v7m_using_psp(env) ? env->v7m.other_ss_psp : env->v7m.other_ss_msp;
100
+ if (!v7m_read_sg_stack_word(cpu, mmu_idx, sp, &spdata)) {
101
+ /* Stack access failed and an exception has been pended */
102
+ return false;
103
+ }
104
+
105
+ if (env->v7m.ccr[M_REG_S] & R_V7M_CCR_TRD_MASK) {
106
+ if (((spdata & ~1) == 0xfefa125a) ||
107
+ !(env->v7m.control[M_REG_S] & 1)) {
108
+ goto gen_invep;
109
+ }
110
+ }
56
+ }
111
+ }
57
+
112
+
58
+ doorbell_gpa = mrs.offset_within_address_space;
113
env->regs[14] &= ~1;
59
+ memory_region_unref(mrs.mr);
114
env->v7m.control[M_REG_S] &= ~R_V7M_CONTROL_SFPA_MASK;
60
+
115
switch_v7m_security_state(env, true);
61
+ route->u.msi.address_lo = doorbell_gpa;
62
+ route->u.msi.address_hi = doorbell_gpa >> 32;
63
+
64
+ trace_kvm_arm_fixup_msi_route(address, doorbell_gpa);
65
+
66
+ ret = 0;
67
+
68
+unlock:
69
+ rcu_read_unlock();
70
+ return ret;
71
}
72
73
int kvm_arch_add_msi_route_post(struct kvm_irq_routing_entry *route,
74
diff --git a/target/arm/trace-events b/target/arm/trace-events
75
index XXXXXXX..XXXXXXX 100644
76
--- a/target/arm/trace-events
77
+++ b/target/arm/trace-events
78
@@ -XXX,XX +XXX,XX @@ arm_gt_tval_write(int timer, uint64_t value) "gt_tval_write: timer %d value 0x%"
79
arm_gt_ctl_write(int timer, uint64_t value) "gt_ctl_write: timer %d value 0x%" PRIx64
80
arm_gt_imask_toggle(int timer, int irqstate) "gt_ctl_write: timer %d IMASK toggle, new irqstate %d"
81
arm_gt_cntvoff_write(uint64_t value) "gt_cntvoff_write: value 0x%" PRIx64
82
+
83
+# target/arm/kvm.c
84
+kvm_arm_fixup_msi_route(uint64_t iova, uint64_t gpa) "MSI iova = 0x%"PRIx64" is translated into 0x%"PRIx64
85
--
116
--
86
2.17.0
117
2.20.1
87
118
88
119
diff view generated by jsdifflib
1
From: Prem Mallappa <prem.mallappa@broadcom.com>
1
In commit 077d7449100d824a4 we added code to handle the v8M
2
requirement that returns from NMI or HardFault forcibly deactivate
3
those exceptions regardless of what interrupt the guest is trying to
4
deactivate. Unfortunately this broke the handling of the "illegal
5
exception return because the returning exception number is not
6
active" check for those cases. In the pseudocode this test is done
7
on the exception the guest asks to return from, but because our
8
implementation was doing this in armv7m_nvic_complete_irq() after the
9
new "deactivate NMI/HardFault regardless" code we ended up doing the
10
test on the VecInfo for that exception instead, which usually meant
11
failing to raise the illegal exception return fault.
2
12
3
This patch builds the smmuv3 node in the ACPI IORT table.
13
In the case for "configurable exception targeting the opposite
14
security state" we detected the illegal-return case but went ahead
15
and deactivated the VecInfo anyway, which is wrong because that is
16
the VecInfo for the other security state.
4
17
5
The RID space of the root complex, which spans 0x0-0x10000
18
Rearrange the code so that we first identify the illegal return
6
maps to streamid space 0x0-0x10000 in smmuv3, which in turn
19
cases, then see if we really need to deactivate NMI or HardFault
7
maps to deviceid space 0x0-0x10000 in the ITS group.
20
instead, and finally do the deactivation.
8
21
9
The guest must feature the IOMMU probe deferral series
22
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
(https://lkml.org/lkml/2017/4/10/214) which fixes streamid
23
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
multiple lookup. This bug is not related to the SMMU emulation.
24
Message-id: 20201119215617.29887-25-peter.maydell@linaro.org
25
---
26
hw/intc/armv7m_nvic.c | 59 +++++++++++++++++++++++--------------------
27
1 file changed, 32 insertions(+), 27 deletions(-)
12
28
13
Signed-off-by: Prem Mallappa <prem.mallappa@broadcom.com>
29
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
14
Signed-off-by: Eric Auger <eric.auger@redhat.com>
15
Reviewed-by: Shannon Zhao <zhaoshenglong@huawei.com>
16
Message-id: 1524665762-31355-14-git-send-email-eric.auger@redhat.com
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
---
19
include/hw/acpi/acpi-defs.h | 15 ++++++++++
20
hw/arm/virt-acpi-build.c | 55 ++++++++++++++++++++++++++++++++-----
21
2 files changed, 63 insertions(+), 7 deletions(-)
22
23
diff --git a/include/hw/acpi/acpi-defs.h b/include/hw/acpi/acpi-defs.h
24
index XXXXXXX..XXXXXXX 100644
30
index XXXXXXX..XXXXXXX 100644
25
--- a/include/hw/acpi/acpi-defs.h
31
--- a/hw/intc/armv7m_nvic.c
26
+++ b/include/hw/acpi/acpi-defs.h
32
+++ b/hw/intc/armv7m_nvic.c
27
@@ -XXX,XX +XXX,XX @@ struct AcpiIortItsGroup {
33
@@ -XXX,XX +XXX,XX @@ int armv7m_nvic_complete_irq(void *opaque, int irq, bool secure)
28
} QEMU_PACKED;
34
{
29
typedef struct AcpiIortItsGroup AcpiIortItsGroup;
35
NVICState *s = (NVICState *)opaque;
30
36
VecInfo *vec = NULL;
31
+struct AcpiIortSmmu3 {
37
- int ret;
32
+ ACPI_IORT_NODE_HEADER_DEF
38
+ int ret = 0;
33
+ uint64_t base_address;
39
34
+ uint32_t flags;
40
assert(irq > ARMV7M_EXCP_RESET && irq < s->num_irq);
35
+ uint32_t reserved2;
41
36
+ uint64_t vatos_address;
42
+ trace_nvic_complete_irq(irq, secure);
37
+ uint32_t model;
38
+ uint32_t event_gsiv;
39
+ uint32_t pri_gsiv;
40
+ uint32_t gerr_gsiv;
41
+ uint32_t sync_gsiv;
42
+ AcpiIortIdMapping id_mapping_array[0];
43
+} QEMU_PACKED;
44
+typedef struct AcpiIortSmmu3 AcpiIortSmmu3;
45
+
43
+
46
struct AcpiIortRC {
44
+ if (secure && exc_is_banked(irq)) {
47
ACPI_IORT_NODE_HEADER_DEF
45
+ vec = &s->sec_vectors[irq];
48
AcpiIortMemoryAccess memory_properties;
49
diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
50
index XXXXXXX..XXXXXXX 100644
51
--- a/hw/arm/virt-acpi-build.c
52
+++ b/hw/arm/virt-acpi-build.c
53
@@ -XXX,XX +XXX,XX @@ build_rsdp(GArray *rsdp_table, BIOSLinker *linker, unsigned xsdt_tbl_offset)
54
}
55
56
static void
57
-build_iort(GArray *table_data, BIOSLinker *linker)
58
+build_iort(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
59
{
60
- int iort_start = table_data->len;
61
+ int nb_nodes, iort_start = table_data->len;
62
AcpiIortIdMapping *idmap;
63
AcpiIortItsGroup *its;
64
AcpiIortTable *iort;
65
- size_t node_size, iort_length;
66
+ AcpiIortSmmu3 *smmu;
67
+ size_t node_size, iort_length, smmu_offset = 0;
68
AcpiIortRC *rc;
69
70
iort = acpi_data_push(table_data, sizeof(*iort));
71
72
+ if (vms->iommu == VIRT_IOMMU_SMMUV3) {
73
+ nb_nodes = 3; /* RC, ITS, SMMUv3 */
74
+ } else {
46
+ } else {
75
+ nb_nodes = 2; /* RC, ITS */
47
+ vec = &s->vectors[irq];
76
+ }
48
+ }
77
+
49
+
78
iort_length = sizeof(*iort);
50
+ /*
79
- iort->node_count = cpu_to_le32(2); /* RC and ITS nodes */
51
+ * Identify illegal exception return cases. We can't immediately
80
+ iort->node_count = cpu_to_le32(nb_nodes);
52
+ * return at this point because we still need to deactivate
81
iort->node_offset = cpu_to_le32(sizeof(*iort));
53
+ * (either this exception or NMI/HardFault) first.
82
54
+ */
83
/* ITS group node */
55
+ if (!exc_is_banked(irq) && exc_targets_secure(s, irq) != secure) {
84
@@ -XXX,XX +XXX,XX @@ build_iort(GArray *table_data, BIOSLinker *linker)
56
+ /*
85
its->its_count = cpu_to_le32(1);
57
+ * Return from a configurable exception targeting the opposite
86
its->identifiers[0] = 0; /* MADT translation_id */
58
+ * security state from the one we're trying to complete it for.
87
59
+ * Clear vec because it's not really the VecInfo for this
88
+ if (vms->iommu == VIRT_IOMMU_SMMUV3) {
60
+ * (irq, secstate) so we mustn't deactivate it.
89
+ int irq = vms->irqmap[VIRT_SMMU];
61
+ */
90
+
62
+ ret = -1;
91
+ /* SMMUv3 node */
63
+ vec = NULL;
92
+ smmu_offset = iort->node_offset + node_size;
64
+ } else if (!vec->active) {
93
+ node_size = sizeof(*smmu) + sizeof(*idmap);
65
+ /* Return from an inactive interrupt */
94
+ iort_length += node_size;
66
+ ret = -1;
95
+ smmu = acpi_data_push(table_data, node_size);
67
+ } else {
96
+
68
+ /* Legal return, we will return the RETTOBASE bit value to the caller */
97
+ smmu->type = ACPI_IORT_NODE_SMMU_V3;
69
+ ret = nvic_rettobase(s);
98
+ smmu->length = cpu_to_le16(node_size);
99
+ smmu->mapping_count = cpu_to_le32(1);
100
+ smmu->mapping_offset = cpu_to_le32(sizeof(*smmu));
101
+ smmu->base_address = cpu_to_le64(vms->memmap[VIRT_SMMU].base);
102
+ smmu->event_gsiv = cpu_to_le32(irq);
103
+ smmu->pri_gsiv = cpu_to_le32(irq + 1);
104
+ smmu->gerr_gsiv = cpu_to_le32(irq + 2);
105
+ smmu->sync_gsiv = cpu_to_le32(irq + 3);
106
+
107
+ /* Identity RID mapping covering the whole input RID range */
108
+ idmap = &smmu->id_mapping_array[0];
109
+ idmap->input_base = 0;
110
+ idmap->id_count = cpu_to_le32(0xFFFF);
111
+ idmap->output_base = 0;
112
+ /* output IORT node is the ITS group node (the first node) */
113
+ idmap->output_reference = cpu_to_le32(iort->node_offset);
114
+ }
70
+ }
115
+
71
+
116
/* Root Complex Node */
72
/*
117
node_size = sizeof(*rc) + sizeof(*idmap);
73
* For negative priorities, v8M will forcibly deactivate the appropriate
118
iort_length += node_size;
74
* NMI or HardFault regardless of what interrupt we're being asked to
119
@@ -XXX,XX +XXX,XX @@ build_iort(GArray *table_data, BIOSLinker *linker)
75
@@ -XXX,XX +XXX,XX @@ int armv7m_nvic_complete_irq(void *opaque, int irq, bool secure)
120
idmap->input_base = 0;
121
idmap->id_count = cpu_to_le32(0xFFFF);
122
idmap->output_base = 0;
123
- /* output IORT node is the ITS group node (the first node) */
124
- idmap->output_reference = cpu_to_le32(iort->node_offset);
125
+
126
+ if (vms->iommu == VIRT_IOMMU_SMMUV3) {
127
+ /* output IORT node is the smmuv3 node */
128
+ idmap->output_reference = cpu_to_le32(smmu_offset);
129
+ } else {
130
+ /* output IORT node is the ITS group node (the first node) */
131
+ idmap->output_reference = cpu_to_le32(iort->node_offset);
132
+ }
133
134
iort->length = cpu_to_le32(iort_length);
135
136
@@ -XXX,XX +XXX,XX @@ void virt_acpi_build(VirtMachineState *vms, AcpiBuildTables *tables)
137
138
if (its_class_name() && !vmc->no_its) {
139
acpi_add_table(table_offsets, tables_blob);
140
- build_iort(tables_blob, tables->linker);
141
+ build_iort(tables_blob, tables->linker, vms);
142
}
76
}
143
77
144
/* XSDT is pointed to by RSDP */
78
if (!vec) {
79
- if (secure && exc_is_banked(irq)) {
80
- vec = &s->sec_vectors[irq];
81
- } else {
82
- vec = &s->vectors[irq];
83
- }
84
- }
85
-
86
- trace_nvic_complete_irq(irq, secure);
87
-
88
- if (!vec->active) {
89
- /* Tell the caller this was an illegal exception return */
90
- return -1;
91
- }
92
-
93
- /*
94
- * If this is a configurable exception and it is currently
95
- * targeting the opposite security state from the one we're trying
96
- * to complete it for, this counts as an illegal exception return.
97
- * We still need to deactivate whatever vector the logic above has
98
- * selected, though, as it might not be the same as the one for the
99
- * requested exception number.
100
- */
101
- if (!exc_is_banked(irq) && exc_targets_secure(s, irq) != secure) {
102
- ret = -1;
103
- } else {
104
- ret = nvic_rettobase(s);
105
+ return ret;
106
}
107
108
vec->active = 0;
145
--
109
--
146
2.17.0
110
2.20.1
147
111
148
112
diff view generated by jsdifflib
1
Convert the smc91c111 device away from using the old_mmio field of
1
For v8.1M the architecture mandates that CPUs must provide at
2
MemoryRegionOps. This device is used by several Arm board models.
2
least the "minimal RAS implementation" from the Reliability,
3
Availability and Serviceability extension. This consists of:
4
* an ESB instruction which is a NOP
5
-- since it is in the HINT space we need only add a comment
6
* an RFSR register which will RAZ/WI
7
* a RAZ/WI AIRCR.IESB bit
8
-- the code which handles writes to AIRCR does not allow setting
9
of RES0 bits, so we already treat this as RAZ/WI; add a comment
10
noting that this is deliberate
11
* minimal implementation of the RAS register block at 0xe0005000
12
-- this will be in a subsequent commit
13
* setting the ID_PFR0.RAS field to 0b0010
14
-- we will do this when we add the Cortex-M55 CPU model
3
15
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
17
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20180427173611.10281-3-peter.maydell@linaro.org
18
Message-id: 20201119215617.29887-26-peter.maydell@linaro.org
7
---
19
---
8
hw/net/smc91c111.c | 54 +++++++++++++++++++++-------------------------
20
target/arm/cpu.h | 14 ++++++++++++++
9
1 file changed, 25 insertions(+), 29 deletions(-)
21
target/arm/t32.decode | 4 ++++
22
hw/intc/armv7m_nvic.c | 13 +++++++++++++
23
3 files changed, 31 insertions(+)
10
24
11
diff --git a/hw/net/smc91c111.c b/hw/net/smc91c111.c
25
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
12
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX 100644
13
--- a/hw/net/smc91c111.c
27
--- a/target/arm/cpu.h
14
+++ b/hw/net/smc91c111.c
28
+++ b/target/arm/cpu.h
15
@@ -XXX,XX +XXX,XX @@ static uint32_t smc91c111_readb(void *opaque, hwaddr offset)
29
@@ -XXX,XX +XXX,XX @@ FIELD(ID_MMFR4, LSM, 20, 4)
16
return 0;
30
FIELD(ID_MMFR4, CCIDX, 24, 4)
31
FIELD(ID_MMFR4, EVT, 28, 4)
32
33
+FIELD(ID_PFR0, STATE0, 0, 4)
34
+FIELD(ID_PFR0, STATE1, 4, 4)
35
+FIELD(ID_PFR0, STATE2, 8, 4)
36
+FIELD(ID_PFR0, STATE3, 12, 4)
37
+FIELD(ID_PFR0, CSV2, 16, 4)
38
+FIELD(ID_PFR0, AMU, 20, 4)
39
+FIELD(ID_PFR0, DIT, 24, 4)
40
+FIELD(ID_PFR0, RAS, 28, 4)
41
+
42
FIELD(ID_PFR1, PROGMOD, 0, 4)
43
FIELD(ID_PFR1, SECURITY, 4, 4)
44
FIELD(ID_PFR1, MPROGMOD, 8, 4)
45
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa32_predinv(const ARMISARegisters *id)
46
return FIELD_EX32(id->id_isar6, ID_ISAR6, SPECRES) != 0;
17
}
47
}
18
48
19
-static void smc91c111_writew(void *opaque, hwaddr offset,
49
+static inline bool isar_feature_aa32_ras(const ARMISARegisters *id)
20
- uint32_t value)
50
+{
21
+static uint64_t smc91c111_readfn(void *opaque, hwaddr addr, unsigned size)
51
+ return FIELD_EX32(id->id_pfr0, ID_PFR0, RAS) != 0;
52
+}
53
+
54
static inline bool isar_feature_aa32_mprofile(const ARMISARegisters *id)
22
{
55
{
23
- smc91c111_writeb(opaque, offset, value & 0xff);
56
return FIELD_EX32(id->id_pfr1, ID_PFR1, MPROGMOD) != 0;
24
- smc91c111_writeb(opaque, offset + 1, value >> 8);
57
diff --git a/target/arm/t32.decode b/target/arm/t32.decode
25
+ int i;
58
index XXXXXXX..XXXXXXX 100644
26
+ uint32_t val = 0;
59
--- a/target/arm/t32.decode
60
+++ b/target/arm/t32.decode
61
@@ -XXX,XX +XXX,XX @@ CLZ 1111 1010 1011 ---- 1111 .... 1000 .... @rdm
62
# SEV 1111 0011 1010 1111 1000 0000 0000 0100
63
# SEVL 1111 0011 1010 1111 1000 0000 0000 0101
64
65
+ # For M-profile minimal-RAS ESB can be a NOP, which is the
66
+ # default behaviour since it is in the hint space.
67
+ # ESB 1111 0011 1010 1111 1000 0000 0001 0000
27
+
68
+
28
+ for (i = 0; i < size; i++) {
69
# The canonical nop ends in 0000 0000, but the whole rest
29
+ val |= smc91c111_readb(opaque, addr + i) << (i * 8);
70
# of the space is "reserved hint, behaves as nop".
30
+ }
71
NOP 1111 0011 1010 1111 1000 0000 ---- ----
31
+ return val;
72
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
32
}
73
index XXXXXXX..XXXXXXX 100644
33
74
--- a/hw/intc/armv7m_nvic.c
34
-static void smc91c111_writel(void *opaque, hwaddr offset,
75
+++ b/hw/intc/armv7m_nvic.c
35
- uint32_t value)
76
@@ -XXX,XX +XXX,XX @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
36
+static void smc91c111_writefn(void *opaque, hwaddr addr,
77
return 0;
37
+ uint64_t value, unsigned size)
78
}
38
{
79
return cpu->env.v7m.sfar;
39
+ int i = 0;
80
+ case 0xf04: /* RFSR */
40
+
81
+ if (!cpu_isar_feature(aa32_ras, cpu)) {
41
/* 32-bit writes to offset 0xc only actually write to the bank select
82
+ goto bad_offset;
42
- register (offset 0xe) */
83
+ }
43
- if (offset != 0xc)
84
+ /* We provide minimal-RAS only: RFSR is RAZ/WI */
44
- smc91c111_writew(opaque, offset, value & 0xffff);
85
+ return 0;
45
- smc91c111_writew(opaque, offset + 2, value >> 16);
86
case 0xf34: /* FPCCR */
46
-}
87
if (!cpu_isar_feature(aa32_vfp_simd, cpu)) {
47
+ * register (offset 0xe), so skip the first two bytes we would write.
88
return 0;
48
+ */
89
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
49
+ if (addr == 0xc && size == 4) {
90
R_V7M_AIRCR_PRIGROUP_SHIFT,
50
+ i += 2;
91
R_V7M_AIRCR_PRIGROUP_LENGTH);
51
+ }
92
}
52
93
+ /* AIRCR.IESB is RAZ/WI because we implement only minimal RAS */
53
-static uint32_t smc91c111_readw(void *opaque, hwaddr offset)
94
if (attrs.secure) {
54
-{
95
/* These bits are only writable by secure */
55
- uint32_t val;
96
cpu->env.v7m.aircr = value &
56
- val = smc91c111_readb(opaque, offset);
97
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
57
- val |= smc91c111_readb(opaque, offset + 1) << 8;
98
}
58
- return val;
99
break;
59
-}
100
}
60
-
101
+ case 0xf04: /* RFSR */
61
-static uint32_t smc91c111_readl(void *opaque, hwaddr offset)
102
+ if (!cpu_isar_feature(aa32_ras, cpu)) {
62
-{
103
+ goto bad_offset;
63
- uint32_t val;
104
+ }
64
- val = smc91c111_readw(opaque, offset);
105
+ /* We provide minimal-RAS only: RFSR is RAZ/WI */
65
- val |= smc91c111_readw(opaque, offset + 2) << 16;
106
+ break;
66
- return val;
107
case 0xf34: /* FPCCR */
67
+ for (; i < size; i++) {
108
if (cpu_isar_feature(aa32_vfp_simd, cpu)) {
68
+ smc91c111_writeb(opaque, addr + i,
109
/* Not all bits here are banked. */
69
+ extract32(value, i * 8, 8));
70
+ }
71
}
72
73
static int smc91c111_can_receive_nc(NetClientState *nc)
74
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps smc91c111_mem_ops = {
75
/* The special case for 32 bit writes to 0xc means we can't just
76
* set .impl.min/max_access_size to 1, unfortunately
77
*/
78
- .old_mmio = {
79
- .read = { smc91c111_readb, smc91c111_readw, smc91c111_readl, },
80
- .write = { smc91c111_writeb, smc91c111_writew, smc91c111_writel, },
81
- },
82
+ .read = smc91c111_readfn,
83
+ .write = smc91c111_writefn,
84
+ .valid.min_access_size = 1,
85
+ .valid.max_access_size = 4,
86
.endianness = DEVICE_NATIVE_ENDIAN,
87
};
88
89
--
110
--
90
2.17.0
111
2.20.1
91
112
92
113
diff view generated by jsdifflib
1
From: Eric Auger <eric.auger@redhat.com>
1
The RAS feature has a block of memory-mapped registers at offset
2
0x5000 within the PPB. For a "minimal RAS" implementation we provide
3
no error records and so the only registers that exist in the block
4
are ERRIIDR and ERRDEVID.
2
5
3
We introduce helpers to read/write into the command and event
6
The "RAZ/WI for privileged, BusFault for nonprivileged" behaviour
4
circular queues.
7
of the "nvic-default" region is actually valid for minimal-RAS,
8
so the main benefit of providing an explicit implementation of
9
the register block is more accurate LOG_UNIMP messages, and a
10
framework for where we could add a real RAS implementation later
11
if necessary.
5
12
6
smmuv3_write_eventq and smmuv3_cmq_consume will become static
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
in subsequent patches.
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
Message-id: 20201119215617.29887-27-peter.maydell@linaro.org
16
---
17
include/hw/intc/armv7m_nvic.h | 1 +
18
hw/intc/armv7m_nvic.c | 56 +++++++++++++++++++++++++++++++++++
19
2 files changed, 57 insertions(+)
8
20
9
Invalidation commands are not yet dealt with. We do not cache
21
diff --git a/include/hw/intc/armv7m_nvic.h b/include/hw/intc/armv7m_nvic.h
10
data that need to be invalidated. This will change with vhost
11
integration.
12
13
Signed-off-by: Eric Auger <eric.auger@redhat.com>
14
Signed-off-by: Prem Mallappa <prem.mallappa@broadcom.com>
15
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
16
Message-id: 1524665762-31355-7-git-send-email-eric.auger@redhat.com
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
---
19
hw/arm/smmuv3-internal.h | 163 +++++++++++++++++++++++++++++++++++++++
20
hw/arm/smmuv3.c | 136 ++++++++++++++++++++++++++++++++
21
hw/arm/trace-events | 5 ++
22
3 files changed, 304 insertions(+)
23
24
diff --git a/hw/arm/smmuv3-internal.h b/hw/arm/smmuv3-internal.h
25
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
26
--- a/hw/arm/smmuv3-internal.h
23
--- a/include/hw/intc/armv7m_nvic.h
27
+++ b/hw/arm/smmuv3-internal.h
24
+++ b/include/hw/intc/armv7m_nvic.h
28
@@ -XXX,XX +XXX,XX @@ static inline bool smmuv3_gerror_irq_enabled(SMMUv3State *s)
25
@@ -XXX,XX +XXX,XX @@ struct NVICState {
29
void smmuv3_trigger_irq(SMMUv3State *s, SMMUIrq irq, uint32_t gerror_mask);
26
MemoryRegion sysreg_ns_mem;
30
void smmuv3_write_gerrorn(SMMUv3State *s, uint32_t gerrorn);
27
MemoryRegion systickmem;
31
28
MemoryRegion systick_ns_mem;
32
+/* Queue Handling */
29
+ MemoryRegion ras_mem;
30
MemoryRegion container;
31
MemoryRegion defaultmem;
32
33
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
34
index XXXXXXX..XXXXXXX 100644
35
--- a/hw/intc/armv7m_nvic.c
36
+++ b/hw/intc/armv7m_nvic.c
37
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps nvic_systick_ops = {
38
.endianness = DEVICE_NATIVE_ENDIAN,
39
};
40
33
+
41
+
34
+#define Q_BASE(q) ((q)->base & SMMU_BASE_ADDR_MASK)
42
+static MemTxResult ras_read(void *opaque, hwaddr addr,
35
+#define WRAP_MASK(q) (1 << (q)->log2size)
43
+ uint64_t *data, unsigned size,
36
+#define INDEX_MASK(q) (((1 << (q)->log2size)) - 1)
44
+ MemTxAttrs attrs)
37
+#define WRAP_INDEX_MASK(q) ((1 << ((q)->log2size + 1)) - 1)
38
+
39
+#define Q_CONS(q) ((q)->cons & INDEX_MASK(q))
40
+#define Q_PROD(q) ((q)->prod & INDEX_MASK(q))
41
+
42
+#define Q_CONS_ENTRY(q) (Q_BASE(q) + (q)->entry_size * Q_CONS(q))
43
+#define Q_PROD_ENTRY(q) (Q_BASE(q) + (q)->entry_size * Q_PROD(q))
44
+
45
+#define Q_CONS_WRAP(q) (((q)->cons & WRAP_MASK(q)) >> (q)->log2size)
46
+#define Q_PROD_WRAP(q) (((q)->prod & WRAP_MASK(q)) >> (q)->log2size)
47
+
48
+static inline bool smmuv3_q_full(SMMUQueue *q)
49
+{
45
+{
50
+ return ((q->cons ^ q->prod) & WRAP_INDEX_MASK(q)) == WRAP_MASK(q);
46
+ if (attrs.user) {
51
+}
47
+ return MEMTX_ERROR;
52
+
53
+static inline bool smmuv3_q_empty(SMMUQueue *q)
54
+{
55
+ return (q->cons & WRAP_INDEX_MASK(q)) == (q->prod & WRAP_INDEX_MASK(q));
56
+}
57
+
58
+static inline void queue_prod_incr(SMMUQueue *q)
59
+{
60
+ q->prod = (q->prod + 1) & WRAP_INDEX_MASK(q);
61
+}
62
+
63
+static inline void queue_cons_incr(SMMUQueue *q)
64
+{
65
+ /*
66
+ * We have to use deposit for the CONS registers to preserve
67
+ * the ERR field in the high bits.
68
+ */
69
+ q->cons = deposit32(q->cons, 0, q->log2size + 1, q->cons + 1);
70
+}
71
+
72
+static inline bool smmuv3_cmdq_enabled(SMMUv3State *s)
73
+{
74
+ return FIELD_EX32(s->cr[0], CR0, CMDQEN);
75
+}
76
+
77
+static inline bool smmuv3_eventq_enabled(SMMUv3State *s)
78
+{
79
+ return FIELD_EX32(s->cr[0], CR0, EVENTQEN);
80
+}
81
+
82
+static inline void smmu_write_cmdq_err(SMMUv3State *s, uint32_t err_type)
83
+{
84
+ s->cmdq.cons = FIELD_DP32(s->cmdq.cons, CMDQ_CONS, ERR, err_type);
85
+}
86
+
87
+void smmuv3_write_eventq(SMMUv3State *s, Evt *evt);
88
+
89
+/* Commands */
90
+
91
+typedef enum SMMUCommandType {
92
+ SMMU_CMD_NONE = 0x00,
93
+ SMMU_CMD_PREFETCH_CONFIG ,
94
+ SMMU_CMD_PREFETCH_ADDR,
95
+ SMMU_CMD_CFGI_STE,
96
+ SMMU_CMD_CFGI_STE_RANGE,
97
+ SMMU_CMD_CFGI_CD,
98
+ SMMU_CMD_CFGI_CD_ALL,
99
+ SMMU_CMD_CFGI_ALL,
100
+ SMMU_CMD_TLBI_NH_ALL = 0x10,
101
+ SMMU_CMD_TLBI_NH_ASID,
102
+ SMMU_CMD_TLBI_NH_VA,
103
+ SMMU_CMD_TLBI_NH_VAA,
104
+ SMMU_CMD_TLBI_EL3_ALL = 0x18,
105
+ SMMU_CMD_TLBI_EL3_VA = 0x1a,
106
+ SMMU_CMD_TLBI_EL2_ALL = 0x20,
107
+ SMMU_CMD_TLBI_EL2_ASID,
108
+ SMMU_CMD_TLBI_EL2_VA,
109
+ SMMU_CMD_TLBI_EL2_VAA,
110
+ SMMU_CMD_TLBI_S12_VMALL = 0x28,
111
+ SMMU_CMD_TLBI_S2_IPA = 0x2a,
112
+ SMMU_CMD_TLBI_NSNH_ALL = 0x30,
113
+ SMMU_CMD_ATC_INV = 0x40,
114
+ SMMU_CMD_PRI_RESP,
115
+ SMMU_CMD_RESUME = 0x44,
116
+ SMMU_CMD_STALL_TERM,
117
+ SMMU_CMD_SYNC,
118
+} SMMUCommandType;
119
+
120
+static const char *cmd_stringify[] = {
121
+ [SMMU_CMD_PREFETCH_CONFIG] = "SMMU_CMD_PREFETCH_CONFIG",
122
+ [SMMU_CMD_PREFETCH_ADDR] = "SMMU_CMD_PREFETCH_ADDR",
123
+ [SMMU_CMD_CFGI_STE] = "SMMU_CMD_CFGI_STE",
124
+ [SMMU_CMD_CFGI_STE_RANGE] = "SMMU_CMD_CFGI_STE_RANGE",
125
+ [SMMU_CMD_CFGI_CD] = "SMMU_CMD_CFGI_CD",
126
+ [SMMU_CMD_CFGI_CD_ALL] = "SMMU_CMD_CFGI_CD_ALL",
127
+ [SMMU_CMD_CFGI_ALL] = "SMMU_CMD_CFGI_ALL",
128
+ [SMMU_CMD_TLBI_NH_ALL] = "SMMU_CMD_TLBI_NH_ALL",
129
+ [SMMU_CMD_TLBI_NH_ASID] = "SMMU_CMD_TLBI_NH_ASID",
130
+ [SMMU_CMD_TLBI_NH_VA] = "SMMU_CMD_TLBI_NH_VA",
131
+ [SMMU_CMD_TLBI_NH_VAA] = "SMMU_CMD_TLBI_NH_VAA",
132
+ [SMMU_CMD_TLBI_EL3_ALL] = "SMMU_CMD_TLBI_EL3_ALL",
133
+ [SMMU_CMD_TLBI_EL3_VA] = "SMMU_CMD_TLBI_EL3_VA",
134
+ [SMMU_CMD_TLBI_EL2_ALL] = "SMMU_CMD_TLBI_EL2_ALL",
135
+ [SMMU_CMD_TLBI_EL2_ASID] = "SMMU_CMD_TLBI_EL2_ASID",
136
+ [SMMU_CMD_TLBI_EL2_VA] = "SMMU_CMD_TLBI_EL2_VA",
137
+ [SMMU_CMD_TLBI_EL2_VAA] = "SMMU_CMD_TLBI_EL2_VAA",
138
+ [SMMU_CMD_TLBI_S12_VMALL] = "SMMU_CMD_TLBI_S12_VMALL",
139
+ [SMMU_CMD_TLBI_S2_IPA] = "SMMU_CMD_TLBI_S2_IPA",
140
+ [SMMU_CMD_TLBI_NSNH_ALL] = "SMMU_CMD_TLBI_NSNH_ALL",
141
+ [SMMU_CMD_ATC_INV] = "SMMU_CMD_ATC_INV",
142
+ [SMMU_CMD_PRI_RESP] = "SMMU_CMD_PRI_RESP",
143
+ [SMMU_CMD_RESUME] = "SMMU_CMD_RESUME",
144
+ [SMMU_CMD_STALL_TERM] = "SMMU_CMD_STALL_TERM",
145
+ [SMMU_CMD_SYNC] = "SMMU_CMD_SYNC",
146
+};
147
+
148
+static inline const char *smmu_cmd_string(SMMUCommandType type)
149
+{
150
+ if (type > SMMU_CMD_NONE && type < ARRAY_SIZE(cmd_stringify)) {
151
+ return cmd_stringify[type] ? cmd_stringify[type] : "UNKNOWN";
152
+ } else {
153
+ return "INVALID";
154
+ }
155
+}
156
+
157
+/* CMDQ fields */
158
+
159
+typedef enum {
160
+ SMMU_CERROR_NONE = 0,
161
+ SMMU_CERROR_ILL,
162
+ SMMU_CERROR_ABT,
163
+ SMMU_CERROR_ATC_INV_SYNC,
164
+} SMMUCmdError;
165
+
166
+enum { /* Command completion notification */
167
+ CMD_SYNC_SIG_NONE,
168
+ CMD_SYNC_SIG_IRQ,
169
+ CMD_SYNC_SIG_SEV,
170
+};
171
+
172
+#define CMD_TYPE(x) extract32((x)->word[0], 0 , 8)
173
+#define CMD_SSEC(x) extract32((x)->word[0], 10, 1)
174
+#define CMD_SSV(x) extract32((x)->word[0], 11, 1)
175
+#define CMD_RESUME_AC(x) extract32((x)->word[0], 12, 1)
176
+#define CMD_RESUME_AB(x) extract32((x)->word[0], 13, 1)
177
+#define CMD_SYNC_CS(x) extract32((x)->word[0], 12, 2)
178
+#define CMD_SSID(x) extract32((x)->word[0], 12, 20)
179
+#define CMD_SID(x) ((x)->word[1])
180
+#define CMD_VMID(x) extract32((x)->word[1], 0 , 16)
181
+#define CMD_ASID(x) extract32((x)->word[1], 16, 16)
182
+#define CMD_RESUME_STAG(x) extract32((x)->word[2], 0 , 16)
183
+#define CMD_RESP(x) extract32((x)->word[2], 11, 2)
184
+#define CMD_LEAF(x) extract32((x)->word[2], 0 , 1)
185
+#define CMD_STE_RANGE(x) extract32((x)->word[2], 0 , 5)
186
+#define CMD_ADDR(x) ({ \
187
+ uint64_t high = (uint64_t)(x)->word[3]; \
188
+ uint64_t low = extract32((x)->word[2], 12, 20); \
189
+ uint64_t addr = high << 32 | (low << 12); \
190
+ addr; \
191
+ })
192
+
193
+int smmuv3_cmdq_consume(SMMUv3State *s);
194
+
195
#endif
196
diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c
197
index XXXXXXX..XXXXXXX 100644
198
--- a/hw/arm/smmuv3.c
199
+++ b/hw/arm/smmuv3.c
200
@@ -XXX,XX +XXX,XX @@ void smmuv3_write_gerrorn(SMMUv3State *s, uint32_t new_gerrorn)
201
trace_smmuv3_write_gerrorn(toggled & pending, s->gerrorn);
202
}
203
204
+static inline MemTxResult queue_read(SMMUQueue *q, void *data)
205
+{
206
+ dma_addr_t addr = Q_CONS_ENTRY(q);
207
+
208
+ return dma_memory_read(&address_space_memory, addr, data, q->entry_size);
209
+}
210
+
211
+static MemTxResult queue_write(SMMUQueue *q, void *data)
212
+{
213
+ dma_addr_t addr = Q_PROD_ENTRY(q);
214
+ MemTxResult ret;
215
+
216
+ ret = dma_memory_write(&address_space_memory, addr, data, q->entry_size);
217
+ if (ret != MEMTX_OK) {
218
+ return ret;
219
+ }
48
+ }
220
+
49
+
221
+ queue_prod_incr(q);
50
+ switch (addr) {
51
+ case 0xe10: /* ERRIIDR */
52
+ /* architect field = Arm; product/variant/revision 0 */
53
+ *data = 0x43b;
54
+ break;
55
+ case 0xfc8: /* ERRDEVID */
56
+ /* Minimal RAS: we implement 0 error record indexes */
57
+ *data = 0;
58
+ break;
59
+ default:
60
+ qemu_log_mask(LOG_UNIMP, "Read RAS register offset 0x%x\n",
61
+ (uint32_t)addr);
62
+ *data = 0;
63
+ break;
64
+ }
222
+ return MEMTX_OK;
65
+ return MEMTX_OK;
223
+}
66
+}
224
+
67
+
225
+void smmuv3_write_eventq(SMMUv3State *s, Evt *evt)
68
+static MemTxResult ras_write(void *opaque, hwaddr addr,
69
+ uint64_t value, unsigned size,
70
+ MemTxAttrs attrs)
226
+{
71
+{
227
+ SMMUQueue *q = &s->eventq;
72
+ if (attrs.user) {
228
+
73
+ return MEMTX_ERROR;
229
+ if (!smmuv3_eventq_enabled(s)) {
230
+ return;
231
+ }
74
+ }
232
+
75
+
233
+ if (smmuv3_q_full(q)) {
76
+ switch (addr) {
234
+ return;
77
+ default:
78
+ qemu_log_mask(LOG_UNIMP, "Write to RAS register offset 0x%x\n",
79
+ (uint32_t)addr);
80
+ break;
81
+ }
82
+ return MEMTX_OK;
83
+}
84
+
85
+static const MemoryRegionOps ras_ops = {
86
+ .read_with_attrs = ras_read,
87
+ .write_with_attrs = ras_write,
88
+ .endianness = DEVICE_NATIVE_ENDIAN,
89
+};
90
+
91
/*
92
* Unassigned portions of the PPB space are RAZ/WI for privileged
93
* accesses, and fault for non-privileged accesses.
94
@@ -XXX,XX +XXX,XX @@ static void armv7m_nvic_realize(DeviceState *dev, Error **errp)
95
&s->systick_ns_mem, 1);
96
}
97
98
+ if (cpu_isar_feature(aa32_ras, s->cpu)) {
99
+ memory_region_init_io(&s->ras_mem, OBJECT(s),
100
+ &ras_ops, s, "nvic_ras", 0x1000);
101
+ memory_region_add_subregion(&s->container, 0x5000, &s->ras_mem);
235
+ }
102
+ }
236
+
103
+
237
+ queue_write(q, evt);
104
sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->container);
238
+
239
+ if (smmuv3_q_empty(q)) {
240
+ smmuv3_trigger_irq(s, SMMU_IRQ_EVTQ, 0);
241
+ }
242
+}
243
+
244
static void smmuv3_init_regs(SMMUv3State *s)
245
{
246
/**
247
@@ -XXX,XX +XXX,XX @@ static void smmuv3_init_regs(SMMUv3State *s)
248
s->sid_split = 0;
249
}
105
}
250
106
251
+int smmuv3_cmdq_consume(SMMUv3State *s)
252
+{
253
+ SMMUCmdError cmd_error = SMMU_CERROR_NONE;
254
+ SMMUQueue *q = &s->cmdq;
255
+ SMMUCommandType type = 0;
256
+
257
+ if (!smmuv3_cmdq_enabled(s)) {
258
+ return 0;
259
+ }
260
+ /*
261
+ * some commands depend on register values, typically CR0. In case those
262
+ * register values change while handling the command, spec says it
263
+ * is UNPREDICTABLE whether the command is interpreted under the new
264
+ * or old value.
265
+ */
266
+
267
+ while (!smmuv3_q_empty(q)) {
268
+ uint32_t pending = s->gerror ^ s->gerrorn;
269
+ Cmd cmd;
270
+
271
+ trace_smmuv3_cmdq_consume(Q_PROD(q), Q_CONS(q),
272
+ Q_PROD_WRAP(q), Q_CONS_WRAP(q));
273
+
274
+ if (FIELD_EX32(pending, GERROR, CMDQ_ERR)) {
275
+ break;
276
+ }
277
+
278
+ if (queue_read(q, &cmd) != MEMTX_OK) {
279
+ cmd_error = SMMU_CERROR_ABT;
280
+ break;
281
+ }
282
+
283
+ type = CMD_TYPE(&cmd);
284
+
285
+ trace_smmuv3_cmdq_opcode(smmu_cmd_string(type));
286
+
287
+ switch (type) {
288
+ case SMMU_CMD_SYNC:
289
+ if (CMD_SYNC_CS(&cmd) & CMD_SYNC_SIG_IRQ) {
290
+ smmuv3_trigger_irq(s, SMMU_IRQ_CMD_SYNC, 0);
291
+ }
292
+ break;
293
+ case SMMU_CMD_PREFETCH_CONFIG:
294
+ case SMMU_CMD_PREFETCH_ADDR:
295
+ case SMMU_CMD_CFGI_STE:
296
+ case SMMU_CMD_CFGI_STE_RANGE: /* same as SMMU_CMD_CFGI_ALL */
297
+ case SMMU_CMD_CFGI_CD:
298
+ case SMMU_CMD_CFGI_CD_ALL:
299
+ case SMMU_CMD_TLBI_NH_ALL:
300
+ case SMMU_CMD_TLBI_NH_ASID:
301
+ case SMMU_CMD_TLBI_NH_VA:
302
+ case SMMU_CMD_TLBI_NH_VAA:
303
+ case SMMU_CMD_TLBI_EL3_ALL:
304
+ case SMMU_CMD_TLBI_EL3_VA:
305
+ case SMMU_CMD_TLBI_EL2_ALL:
306
+ case SMMU_CMD_TLBI_EL2_ASID:
307
+ case SMMU_CMD_TLBI_EL2_VA:
308
+ case SMMU_CMD_TLBI_EL2_VAA:
309
+ case SMMU_CMD_TLBI_S12_VMALL:
310
+ case SMMU_CMD_TLBI_S2_IPA:
311
+ case SMMU_CMD_TLBI_NSNH_ALL:
312
+ case SMMU_CMD_ATC_INV:
313
+ case SMMU_CMD_PRI_RESP:
314
+ case SMMU_CMD_RESUME:
315
+ case SMMU_CMD_STALL_TERM:
316
+ trace_smmuv3_unhandled_cmd(type);
317
+ break;
318
+ default:
319
+ cmd_error = SMMU_CERROR_ILL;
320
+ qemu_log_mask(LOG_GUEST_ERROR,
321
+ "Illegal command type: %d\n", CMD_TYPE(&cmd));
322
+ break;
323
+ }
324
+ if (cmd_error) {
325
+ break;
326
+ }
327
+ /*
328
+ * We only increment the cons index after the completion of
329
+ * the command. We do that because the SYNC returns immediately
330
+ * and does not check the completion of previous commands
331
+ */
332
+ queue_cons_incr(q);
333
+ }
334
+
335
+ if (cmd_error) {
336
+ trace_smmuv3_cmdq_consume_error(smmu_cmd_string(type), cmd_error);
337
+ smmu_write_cmdq_err(s, cmd_error);
338
+ smmuv3_trigger_irq(s, SMMU_IRQ_GERROR, R_GERROR_CMDQ_ERR_MASK);
339
+ }
340
+
341
+ trace_smmuv3_cmdq_consume_out(Q_PROD(q), Q_CONS(q),
342
+ Q_PROD_WRAP(q), Q_CONS_WRAP(q));
343
+
344
+ return 0;
345
+}
346
+
347
static MemTxResult smmu_write_mmio(void *opaque, hwaddr offset, uint64_t data,
348
unsigned size, MemTxAttrs attrs)
349
{
350
diff --git a/hw/arm/trace-events b/hw/arm/trace-events
351
index XXXXXXX..XXXXXXX 100644
352
--- a/hw/arm/trace-events
353
+++ b/hw/arm/trace-events
354
@@ -XXX,XX +XXX,XX @@ smmuv3_read_mmio(uint64_t addr, uint64_t val, unsigned size, uint32_t r) "addr:
355
smmuv3_trigger_irq(int irq) "irq=%d"
356
smmuv3_write_gerror(uint32_t toggled, uint32_t gerror) "toggled=0x%x, new GERROR=0x%x"
357
smmuv3_write_gerrorn(uint32_t acked, uint32_t gerrorn) "acked=0x%x, new GERRORN=0x%x"
358
+smmuv3_unhandled_cmd(uint32_t type) "Unhandled command type=%d"
359
+smmuv3_cmdq_consume(uint32_t prod, uint32_t cons, uint8_t prod_wrap, uint8_t cons_wrap) "prod=%d cons=%d prod.wrap=%d cons.wrap=%d"
360
+smmuv3_cmdq_opcode(const char *opcode) "<--- %s"
361
+smmuv3_cmdq_consume_out(uint32_t prod, uint32_t cons, uint8_t prod_wrap, uint8_t cons_wrap) "prod:%d, cons:%d, prod_wrap:%d, cons_wrap:%d "
362
+smmuv3_cmdq_consume_error(const char *cmd_name, uint8_t cmd_error) "Error on %s command execution: %d"
363
--
107
--
364
2.17.0
108
2.20.1
365
109
366
110
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
Correct a typo in the name we give the NVIC object.
2
2
3
Path analysis shows that size == 3 && !is_q has been eliminated.
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20201119215617.29887-28-peter.maydell@linaro.org
7
---
8
hw/arm/armv7m.c | 2 +-
9
1 file changed, 1 insertion(+), 1 deletion(-)
4
10
5
Fixes: Coverity CID1385853
11
diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
8
Message-id: 20180501180455.11214-3-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
target/arm/translate-a64.c | 6 +++++-
12
1 file changed, 5 insertions(+), 1 deletion(-)
13
14
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
15
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/translate-a64.c
13
--- a/hw/arm/armv7m.c
17
+++ b/target/arm/translate-a64.c
14
+++ b/hw/arm/armv7m.c
18
@@ -XXX,XX +XXX,XX @@ static void disas_simd_two_reg_misc(DisasContext *s, uint32_t insn)
15
@@ -XXX,XX +XXX,XX @@ static void armv7m_instance_init(Object *obj)
19
/* All 64-bit element operations can be shared with scalar 2misc */
16
20
int pass;
17
memory_region_init(&s->container, obj, "armv7m-container", UINT64_MAX);
21
18
22
- for (pass = 0; pass < (is_q ? 2 : 1); pass++) {
19
- object_initialize_child(obj, "nvnic", &s->nvic, TYPE_NVIC);
23
+ /* Coverity claims (size == 3 && !is_q) has been eliminated
20
+ object_initialize_child(obj, "nvic", &s->nvic, TYPE_NVIC);
24
+ * from all paths leading to here.
21
object_property_add_alias(obj, "num-irq",
25
+ */
22
OBJECT(&s->nvic), "num-irq");
26
+ tcg_debug_assert(is_q);
27
+ for (pass = 0; pass < 2; pass++) {
28
TCGv_i64 tcg_op = tcg_temp_new_i64();
29
TCGv_i64 tcg_res = tcg_temp_new_i64();
30
23
31
--
24
--
32
2.17.0
25
2.20.1
33
26
34
27
diff view generated by jsdifflib