1
target-arm queue: Eric's SMMUv3 patchset, and an array
1
arm pullreq for rc1. All minor bugfixes, except for the sve-default-vector-length
2
of minor bugfixes and improvements from various others.
2
patches, which are somewhere between a bugfix and a new feature.
3
3
4
thanks
4
thanks
5
-- PMM
5
-- PMM
6
6
7
The following changes since commit c8b7e627b4269a3bc3ae41d9f420547a47e6d9b9:
7
The following changes since commit c08ccd1b53f488ac86c1f65cf7623dc91acc249a:
8
8
9
Merge remote-tracking branch 'remotes/ericb/tags/pull-nbd-2018-05-04' into staging (2018-05-04 14:42:46 +0100)
9
Merge remote-tracking branch 'remotes/rth-gitlab/tags/pull-tcg-20210726' into staging (2021-07-27 08:35:01 +0100)
10
10
11
are available in the Git repository at:
11
are available in the Git repository at:
12
12
13
git://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20180504
13
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20210727
14
14
15
for you to fetch changes up to 5680740c92993e9b3f3e011f2a2c394070e33f56:
15
for you to fetch changes up to e229a179a503f2aee43a76888cf12fbdfe8a3749:
16
16
17
hw/arm/virt: Introduce the iommu option (2018-05-04 18:05:52 +0100)
17
hw: aspeed_gpio: Fix memory size (2021-07-27 11:00:00 +0100)
18
18
19
----------------------------------------------------------------
19
----------------------------------------------------------------
20
target-arm queue:
20
target-arm queue:
21
* Emulate the SMMUv3 (IOMMU); one will be created in the 'virt' board
21
* hw/arm/smmuv3: Check 31st bit to see if CD is valid
22
if the commandline includes "-machine iommu=smmuv3"
22
* qemu-options.hx: Fix formatting of -machine memory-backend option
23
* target/arm: Implement v8M VLLDM and VLSTM
23
* hw: aspeed_gpio: Fix memory size
24
* hw/arm: Don't fail qtest due to missing SD card in -nodefaults mode
24
* hw/arm/nseries: Display hexadecimal value with '0x' prefix
25
* Some fixes to silence Coverity false-positives
25
* Add sve-default-vector-length cpu property
26
* arm: boot: set boot_info starting from first_cpu
26
* docs: Update path that mentions deprecated.rst
27
(fixes a technical bug not visible in practice)
27
* hw/intc/armv7m_nvic: for v8.1M VECTPENDING hides S exceptions from NS
28
* hw/net/smc91c111: Convert away from old_mmio
28
* hw/intc/armv7m_nvic: Correct size of ICSR.VECTPENDING
29
* hw/usb/tusb6010: Convert away from old_mmio
29
* hw/intc/armv7m_nvic: ISCR.ISRPENDING is set for non-enabled pending interrupts
30
* hw/char/cmsdk-apb-uart.c: Accept more input after character read
30
* target/arm: Report M-profile alignment faults correctly to the guest
31
* target/arm: Make MPUIR write-ignored on OMAP, StrongARM
31
* target/arm: Add missing 'return's after calling v7m_exception_taken()
32
* hw/arm/virt: Add linux,pci-domain property
32
* target/arm: Enforce that M-profile SP low 2 bits are always zero
33
33
34
----------------------------------------------------------------
34
----------------------------------------------------------------
35
Eric Auger (11):
35
Joe Komlodi (1):
36
hw/arm/smmu-common: smmu base device and datatypes
36
hw/arm/smmuv3: Check 31st bit to see if CD is valid
37
hw/arm/smmu-common: IOMMU memory region and address space setup
38
hw/arm/smmu-common: VMSAv8-64 page table walk
39
hw/arm/smmuv3: Wired IRQ and GERROR helpers
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
37
48
Igor Mammedov (1):
38
Joel Stanley (1):
49
arm: boot: set boot_info starting from first_cpu
39
hw: aspeed_gpio: Fix memory size
50
40
51
Jan Kiszka (1):
41
Mao Zhongyi (1):
52
hw/arm/virt: Add linux,pci-domain property
42
docs: Update path that mentions deprecated.rst
53
43
54
Mathew Maidment (1):
44
Peter Maydell (7):
55
target/arm: Correct MPUIR privilege level in register_cp_regs_for_features() conditional case
45
qemu-options.hx: Fix formatting of -machine memory-backend option
46
target/arm: Enforce that M-profile SP low 2 bits are always zero
47
target/arm: Add missing 'return's after calling v7m_exception_taken()
48
target/arm: Report M-profile alignment faults correctly to the guest
49
hw/intc/armv7m_nvic: ISCR.ISRPENDING is set for non-enabled pending interrupts
50
hw/intc/armv7m_nvic: Correct size of ICSR.VECTPENDING
51
hw/intc/armv7m_nvic: for v8.1M VECTPENDING hides S exceptions from NS
56
52
57
Patrick Oppenlander (1):
53
Philippe Mathieu-Daudé (1):
58
hw/char/cmsdk-apb-uart.c: Accept more input after character read
54
hw/arm/nseries: Display hexadecimal value with '0x' prefix
59
55
60
Peter Maydell (3):
56
Richard Henderson (3):
61
hw/usb/tusb6010: Convert away from old_mmio
57
target/arm: Correctly bound length in sve_zcr_get_valid_len
62
hw/net/smc91c111: Convert away from old_mmio
58
target/arm: Export aarch64_sve_zcr_get_valid_len
63
target/arm: Implement v8M VLLDM and VLSTM
59
target/arm: Add sve-default-vector-length cpu property
64
60
65
Prem Mallappa (3):
61
docs/system/arm/cpu-features.rst | 15 ++++++++++
66
hw/arm/smmuv3: Skeleton
62
configure | 2 +-
67
hw/arm/virt: Add SMMUv3 to the virt board
63
hw/arm/smmuv3-internal.h | 2 +-
68
hw/arm/virt-acpi-build: Add smmuv3 node in IORT table
64
target/arm/cpu.h | 5 ++++
65
target/arm/internals.h | 10 +++++++
66
hw/arm/nseries.c | 2 +-
67
hw/gpio/aspeed_gpio.c | 3 +-
68
hw/intc/armv7m_nvic.c | 40 +++++++++++++++++++--------
69
target/arm/cpu.c | 14 ++++++++--
70
target/arm/cpu64.c | 60 ++++++++++++++++++++++++++++++++++++++++
71
target/arm/gdbstub.c | 4 +++
72
target/arm/helper.c | 8 ++++--
73
target/arm/m_helper.c | 24 ++++++++++++----
74
target/arm/translate.c | 3 ++
75
target/i386/cpu.c | 2 +-
76
MAINTAINERS | 2 +-
77
qemu-options.hx | 30 +++++++++++---------
78
17 files changed, 183 insertions(+), 43 deletions(-)
69
79
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
Deleted patch
1
From: Jan Kiszka <jan.kiszka@siemens.com>
2
1
3
This allows to pin the host controller in the Linux PCI domain space.
4
Linux requires that property to be available consistently or not at all,
5
in which case the domain number becomes unstable on additions/removals.
6
Adding it here won't make a difference in practice for most setups as we
7
only expose one controller.
8
9
However, enabling Jailhouse on top may introduce another controller, and
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
23
--- a/hw/arm/virt.c
24
+++ b/hw/arm/virt.c
25
@@ -XXX,XX +XXX,XX @@ static void create_pcie(const VirtMachineState *vms, qemu_irq *pic)
26
qemu_fdt_setprop_string(vms->fdt, nodename, "device_type", "pci");
27
qemu_fdt_setprop_cell(vms->fdt, nodename, "#address-cells", 3);
28
qemu_fdt_setprop_cell(vms->fdt, nodename, "#size-cells", 2);
29
+ qemu_fdt_setprop_cell(vms->fdt, nodename, "linux,pci-domain", 0);
30
qemu_fdt_setprop_cells(vms->fdt, nodename, "bus-range", 0,
31
nr_pcie_buses - 1);
32
qemu_fdt_setprop(vms->fdt, nodename, "dma-coherent", NULL, 0);
33
--
34
2.17.0
35
36
diff view generated by jsdifflib
1
From: Eric Auger <eric.auger@redhat.com>
1
From: Joe Komlodi <joe.komlodi@xilinx.com>
2
2
3
This patch implements the IOMMU Memory Region translate()
3
The bit to see if a CD is valid is the last bit of the first word of the CD.
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
Signed-off-by: Joe Komlodi <joe.komlodi@xilinx.com>
8
Signed-off-by: Prem Mallappa <prem.mallappa@broadcom.com>
6
Message-id: 1626728232-134665-2-git-send-email-joe.komlodi@xilinx.com
9
Message-id: 1524665762-31355-10-git-send-email-eric.auger@redhat.com
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
9
---
13
hw/arm/smmuv3-internal.h | 160 +++++++++++++++++
10
hw/arm/smmuv3-internal.h | 2 +-
14
hw/arm/smmuv3.c | 358 +++++++++++++++++++++++++++++++++++++++
11
1 file changed, 1 insertion(+), 1 deletion(-)
15
hw/arm/trace-events | 9 +
16
3 files changed, 527 insertions(+)
17
12
18
diff --git a/hw/arm/smmuv3-internal.h b/hw/arm/smmuv3-internal.h
13
diff --git a/hw/arm/smmuv3-internal.h b/hw/arm/smmuv3-internal.h
19
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
20
--- a/hw/arm/smmuv3-internal.h
15
--- a/hw/arm/smmuv3-internal.h
21
+++ b/hw/arm/smmuv3-internal.h
16
+++ b/hw/arm/smmuv3-internal.h
22
@@ -XXX,XX +XXX,XX @@ typedef struct SMMUEventInfo {
17
@@ -XXX,XX +XXX,XX @@ static inline int pa_range(STE *ste)
23
18
24
void smmuv3_record_event(SMMUv3State *s, SMMUEventInfo *event);
19
/* CD fields */
25
20
26
+/* Configuration Data */
21
-#define CD_VALID(x) extract32((x)->word[0], 30, 1)
27
+
22
+#define CD_VALID(x) extract32((x)->word[0], 31, 1)
28
+/* STE Level 1 Descriptor */
23
#define CD_ASID(x) extract32((x)->word[1], 16, 16)
29
+typedef struct STEDesc {
24
#define CD_TTB(x, sel) \
30
+ uint32_t word[2];
25
({ \
31
+} STEDesc;
32
+
33
+/* CD Level 1 Descriptor */
34
+typedef struct CDDesc {
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
+{
90
+ switch (oas_field) {
91
+ case 0:
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
+ }
173
+}
174
+
175
+static inline uint64_t l1std_l2ptr(STEDesc *desc)
176
+{
177
+ uint64_t hi, lo;
178
+
179
+ hi = desc->word[1];
180
+ lo = desc->word[0] & ~0x1fULL;
181
+ return hi << 32 | lo;
182
+}
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
}
194
195
+static int smmu_get_ste(SMMUv3State *s, dma_addr_t addr, STE *buf,
196
+ SMMUEventInfo *event)
197
+{
198
+ int ret;
199
+
200
+ trace_smmuv3_get_ste(addr);
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
}
561
562
static const TypeInfo smmuv3_type_info = {
563
diff --git a/hw/arm/trace-events b/hw/arm/trace-events
564
index XXXXXXX..XXXXXXX 100644
565
--- a/hw/arm/trace-events
566
+++ b/hw/arm/trace-events
567
@@ -XXX,XX +XXX,XX @@ smmuv3_write_mmio_idr(uint64_t addr, uint64_t val) "write to RO/Unimpl reg 0x%lx
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"
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"
570
smmuv3_record_event(const char *type, uint32_t sid) "%s sid=%d"
571
+smmuv3_find_ste(uint16_t sid, uint32_t features, uint16_t sid_split) "SID:0x%x features:0x%x, sid_split:0x%x"
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"
573
+smmuv3_get_ste(uint64_t addr) "STE addr: 0x%"PRIx64
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"
575
+smmuv3_translate_in(uint16_t sid, int pci_bus_num, uint64_t strtab_base) "SID:0x%x bus:%d strtab_base:0x%"PRIx64
576
+smmuv3_get_cd(uint64_t addr) "CD addr: 0x%"PRIx64
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"
578
+smmuv3_decode_cd(uint32_t oas) "oas=%d"
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
--
26
--
581
2.17.0
27
2.20.1
582
28
583
29
diff view generated by jsdifflib
1
From: Prem Mallappa <prem.mallappa@broadcom.com>
1
The documentation of the -machine memory-backend has some minor
2
formatting errors:
3
* Misindentation of the initial line meant that the whole option
4
section is incorrectly indented in the HTML output compared to
5
the other -machine options
6
* The examples weren't indented, which meant that they were formatted
7
as plain run-on text including outputting the "::" as text.
8
* The a) b) list has no rst-format markup so it is rendered as
9
a single run-on paragraph
2
10
3
This patch builds the smmuv3 node in the ACPI IORT table.
11
Fix the formatting.
4
12
5
The RID space of the root complex, which spans 0x0-0x10000
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
maps to streamid space 0x0-0x10000 in smmuv3, which in turn
14
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
7
maps to deviceid space 0x0-0x10000 in the ITS group.
15
Message-id: 20210719105257.3599-1-peter.maydell@linaro.org
16
---
17
qemu-options.hx | 30 +++++++++++++++++-------------
18
1 file changed, 17 insertions(+), 13 deletions(-)
8
19
9
The guest must feature the IOMMU probe deferral series
20
diff --git a/qemu-options.hx b/qemu-options.hx
10
(https://lkml.org/lkml/2017/4/10/214) which fixes streamid
11
multiple lookup. This bug is not related to the SMMU emulation.
12
13
Signed-off-by: Prem Mallappa <prem.mallappa@broadcom.com>
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
21
index XXXXXXX..XXXXXXX 100644
25
--- a/include/hw/acpi/acpi-defs.h
22
--- a/qemu-options.hx
26
+++ b/include/hw/acpi/acpi-defs.h
23
+++ b/qemu-options.hx
27
@@ -XXX,XX +XXX,XX @@ struct AcpiIortItsGroup {
24
@@ -XXX,XX +XXX,XX @@ SRST
28
} QEMU_PACKED;
25
Enables or disables ACPI Heterogeneous Memory Attribute Table
29
typedef struct AcpiIortItsGroup AcpiIortItsGroup;
26
(HMAT) support. The default is off.
30
27
31
+struct AcpiIortSmmu3 {
28
- ``memory-backend='id'``
32
+ ACPI_IORT_NODE_HEADER_DEF
29
+ ``memory-backend='id'``
33
+ uint64_t base_address;
30
An alternative to legacy ``-mem-path`` and ``mem-prealloc`` options.
34
+ uint32_t flags;
31
Allows to use a memory backend as main RAM.
35
+ uint32_t reserved2;
32
36
+ uint64_t vatos_address;
33
For example:
37
+ uint32_t model;
34
::
38
+ uint32_t event_gsiv;
35
- -object memory-backend-file,id=pc.ram,size=512M,mem-path=/hugetlbfs,prealloc=on,share=on
39
+ uint32_t pri_gsiv;
36
- -machine memory-backend=pc.ram
40
+ uint32_t gerr_gsiv;
37
- -m 512M
41
+ uint32_t sync_gsiv;
42
+ AcpiIortIdMapping id_mapping_array[0];
43
+} QEMU_PACKED;
44
+typedef struct AcpiIortSmmu3 AcpiIortSmmu3;
45
+
38
+
46
struct AcpiIortRC {
39
+ -object memory-backend-file,id=pc.ram,size=512M,mem-path=/hugetlbfs,prealloc=on,share=on
47
ACPI_IORT_NODE_HEADER_DEF
40
+ -machine memory-backend=pc.ram
48
AcpiIortMemoryAccess memory_properties;
41
+ -m 512M
49
diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
42
50
index XXXXXXX..XXXXXXX 100644
43
Migration compatibility note:
51
--- a/hw/arm/virt-acpi-build.c
44
- a) as backend id one shall use value of 'default-ram-id', advertised by
52
+++ b/hw/arm/virt-acpi-build.c
45
- machine type (available via ``query-machines`` QMP command), if migration
53
@@ -XXX,XX +XXX,XX @@ build_rsdp(GArray *rsdp_table, BIOSLinker *linker, unsigned xsdt_tbl_offset)
46
- to/from old QEMU (<5.0) is expected.
54
}
47
- b) for machine types 4.0 and older, user shall
55
48
- use ``x-use-canonical-path-for-ramblock-id=off`` backend option
56
static void
49
- if migration to/from old QEMU (<5.0) is expected.
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 {
75
+ nb_nodes = 2; /* RC, ITS */
76
+ }
77
+
50
+
78
iort_length = sizeof(*iort);
51
+ * as backend id one shall use value of 'default-ram-id', advertised by
79
- iort->node_count = cpu_to_le32(2); /* RC and ITS nodes */
52
+ machine type (available via ``query-machines`` QMP command), if migration
80
+ iort->node_count = cpu_to_le32(nb_nodes);
53
+ to/from old QEMU (<5.0) is expected.
81
iort->node_offset = cpu_to_le32(sizeof(*iort));
54
+ * for machine types 4.0 and older, user shall
82
55
+ use ``x-use-canonical-path-for-ramblock-id=off`` backend option
83
/* ITS group node */
56
+ if migration to/from old QEMU (<5.0) is expected.
84
@@ -XXX,XX +XXX,XX @@ build_iort(GArray *table_data, BIOSLinker *linker)
85
its->its_count = cpu_to_le32(1);
86
its->identifiers[0] = 0; /* MADT translation_id */
87
88
+ if (vms->iommu == VIRT_IOMMU_SMMUV3) {
89
+ int irq = vms->irqmap[VIRT_SMMU];
90
+
57
+
91
+ /* SMMUv3 node */
58
For example:
92
+ smmu_offset = iort->node_offset + node_size;
59
::
93
+ node_size = sizeof(*smmu) + sizeof(*idmap);
60
- -object memory-backend-ram,id=pc.ram,size=512M,x-use-canonical-path-for-ramblock-id=off
94
+ iort_length += node_size;
61
- -machine memory-backend=pc.ram
95
+ smmu = acpi_data_push(table_data, node_size);
62
- -m 512M
96
+
63
+
97
+ smmu->type = ACPI_IORT_NODE_SMMU_V3;
64
+ -object memory-backend-ram,id=pc.ram,size=512M,x-use-canonical-path-for-ramblock-id=off
98
+ smmu->length = cpu_to_le16(node_size);
65
+ -machine memory-backend=pc.ram
99
+ smmu->mapping_count = cpu_to_le32(1);
66
+ -m 512M
100
+ smmu->mapping_offset = cpu_to_le32(sizeof(*smmu));
67
ERST
101
+ smmu->base_address = cpu_to_le64(vms->memmap[VIRT_SMMU].base);
68
102
+ smmu->event_gsiv = cpu_to_le32(irq);
69
HXCOMM Deprecated by -machine
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
+ }
115
+
116
/* Root Complex Node */
117
node_size = sizeof(*rc) + sizeof(*idmap);
118
iort_length += node_size;
119
@@ -XXX,XX +XXX,XX @@ build_iort(GArray *table_data, BIOSLinker *linker)
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
}
143
144
/* XSDT is pointed to by RSDP */
145
--
70
--
146
2.17.0
71
2.20.1
147
72
148
73
diff view generated by jsdifflib
1
For v8M the instructions VLLDM and VLSTM support lazy saving
1
For M-profile, unlike A-profile, the low 2 bits of SP are defined to be
2
and restoring of the secure floating-point registers. Even
2
RES0H, which is to say that they must be hardwired to zero so that
3
if the floating point extension is not implemented, these
3
guest attempts to write non-zero values to them are ignored.
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
4
7
Fixes: https://bugs.launchpad.net/qemu/+bug/1768295
5
Implement this behaviour by masking out the low bits:
8
Cc: qemu-stable@nongnu.org
6
* for writes to r13 by the gdbstub
7
* for writes to any of the various flavours of SP via MSR
8
* for writes to r13 via store_reg() in generated code
9
10
Note that all the direct uses of cpu_R[] in translate.c are in places
11
where the register is definitely not r13 (usually because that has
12
been checked for as an UNDEFINED or UNPREDICTABLE case and handled as
13
UNDEF).
14
15
All the other writes to regs[13] in C code are either:
16
* A-profile only code
17
* writes of values we can guarantee to be aligned, such as
18
- writes of previous-SP-value plus or minus a 4-aligned constant
19
- writes of the value in an SP limit register (which we already
20
enforce to be aligned)
21
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
22
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
23
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20180503105730.5958-1-peter.maydell@linaro.org
24
Message-id: 20210723162146.5167-2-peter.maydell@linaro.org
12
---
25
---
13
target/arm/translate.c | 17 ++++++++++++++++-
26
target/arm/gdbstub.c | 4 ++++
14
1 file changed, 16 insertions(+), 1 deletion(-)
27
target/arm/m_helper.c | 14 ++++++++------
28
target/arm/translate.c | 3 +++
29
3 files changed, 15 insertions(+), 6 deletions(-)
15
30
31
diff --git a/target/arm/gdbstub.c b/target/arm/gdbstub.c
32
index XXXXXXX..XXXXXXX 100644
33
--- a/target/arm/gdbstub.c
34
+++ b/target/arm/gdbstub.c
35
@@ -XXX,XX +XXX,XX @@ int arm_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
36
37
if (n < 16) {
38
/* Core integer register. */
39
+ if (n == 13 && arm_feature(env, ARM_FEATURE_M)) {
40
+ /* M profile SP low bits are always 0 */
41
+ tmp &= ~3;
42
+ }
43
env->regs[n] = tmp;
44
return 4;
45
}
46
diff --git a/target/arm/m_helper.c b/target/arm/m_helper.c
47
index XXXXXXX..XXXXXXX 100644
48
--- a/target/arm/m_helper.c
49
+++ b/target/arm/m_helper.c
50
@@ -XXX,XX +XXX,XX @@ void HELPER(v7m_msr)(CPUARMState *env, uint32_t maskreg, uint32_t val)
51
if (!env->v7m.secure) {
52
return;
53
}
54
- env->v7m.other_ss_msp = val;
55
+ env->v7m.other_ss_msp = val & ~3;
56
return;
57
case 0x89: /* PSP_NS */
58
if (!env->v7m.secure) {
59
return;
60
}
61
- env->v7m.other_ss_psp = val;
62
+ env->v7m.other_ss_psp = val & ~3;
63
return;
64
case 0x8a: /* MSPLIM_NS */
65
if (!env->v7m.secure) {
66
@@ -XXX,XX +XXX,XX @@ void HELPER(v7m_msr)(CPUARMState *env, uint32_t maskreg, uint32_t val)
67
68
limit = is_psp ? env->v7m.psplim[false] : env->v7m.msplim[false];
69
70
+ val &= ~0x3;
71
+
72
if (val < limit) {
73
raise_exception_ra(env, EXCP_STKOF, 0, 1, GETPC());
74
}
75
@@ -XXX,XX +XXX,XX @@ void HELPER(v7m_msr)(CPUARMState *env, uint32_t maskreg, uint32_t val)
76
break;
77
case 8: /* MSP */
78
if (v7m_using_psp(env)) {
79
- env->v7m.other_sp = val;
80
+ env->v7m.other_sp = val & ~3;
81
} else {
82
- env->regs[13] = val;
83
+ env->regs[13] = val & ~3;
84
}
85
break;
86
case 9: /* PSP */
87
if (v7m_using_psp(env)) {
88
- env->regs[13] = val;
89
+ env->regs[13] = val & ~3;
90
} else {
91
- env->v7m.other_sp = val;
92
+ env->v7m.other_sp = val & ~3;
93
}
94
break;
95
case 10: /* MSPLIM */
16
diff --git a/target/arm/translate.c b/target/arm/translate.c
96
diff --git a/target/arm/translate.c b/target/arm/translate.c
17
index XXXXXXX..XXXXXXX 100644
97
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/translate.c
98
--- a/target/arm/translate.c
19
+++ b/target/arm/translate.c
99
+++ b/target/arm/translate.c
20
@@ -XXX,XX +XXX,XX @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
100
@@ -XXX,XX +XXX,XX @@ void store_reg(DisasContext *s, int reg, TCGv_i32 var)
21
/* Coprocessor. */
101
*/
22
if (arm_dc_feature(s, ARM_FEATURE_M)) {
102
tcg_gen_andi_i32(var, var, s->thumb ? ~1 : ~3);
23
/* We don't currently implement M profile FP support,
103
s->base.is_jmp = DISAS_JUMP;
24
- * so this entire space should give a NOCP fault.
104
+ } else if (reg == 13 && arm_dc_feature(s, ARM_FEATURE_M)) {
25
+ * so this entire space should give a NOCP fault, with
105
+ /* For M-profile SP bits [1:0] are always zero */
26
+ * the exception of the v8M VLLDM and VLSTM insns, which
106
+ tcg_gen_andi_i32(var, var, ~3);
27
+ * must be NOPs in Secure state and UNDEF in Nonsecure state.
107
}
28
*/
108
tcg_gen_mov_i32(cpu_R[reg], var);
29
+ if (arm_dc_feature(s, ARM_FEATURE_V8) &&
109
tcg_temp_free_i32(var);
30
+ (insn & 0xffa00f00) == 0xec200a00) {
31
+ /* 0b1110_1100_0x1x_xxxx_xxxx_1010_xxxx_xxxx
32
+ * - VLLDM, VLSTM
33
+ * We choose to UNDEF if the RAZ bits are non-zero.
34
+ */
35
+ if (!s->v8m_secure || (insn & 0x0040f0ff)) {
36
+ goto illegal_op;
37
+ }
38
+ /* Just NOP since FP support is not implemented */
39
+ break;
40
+ }
41
+ /* All other insns: NOCP */
42
gen_exception_insn(s, 4, EXCP_NOCP, syn_uncategorized(),
43
default_exception_el(s));
44
break;
45
--
110
--
46
2.17.0
111
2.20.1
47
112
48
113
diff view generated by jsdifflib
1
From: Prem Mallappa <prem.mallappa@broadcom.com>
1
In do_v7m_exception_exit(), we perform various checks as part of
2
performing the exception return. If one of these checks fails, the
3
architecture requires that we take an appropriate exception on the
4
existing stackframe. We implement this by calling
5
v7m_exception_taken() to set up to take the new exception, and then
6
immediately returning from do_v7m_exception_exit() without proceeding
7
any further with the unstack-and-exception-return process.
2
8
3
Add code to instantiate an smmuv3 in virt machine. A new iommu
9
In a couple of checks that are new in v8.1M, we forgot the "return"
4
integer member is introduced in VirtMachineState to store the type
10
statement, with the effect that if bad code in the guest tripped over
5
of the iommu in use.
11
these checks we would set up to take a UsageFault exception but then
12
blunder on trying to also unstack and return from the original
13
exception, with the probable result that the guest would crash.
6
14
7
Signed-off-by: Prem Mallappa <prem.mallappa@broadcom.com>
15
Add the missing return statements.
8
Signed-off-by: Eric Auger <eric.auger@redhat.com>
16
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Message-id: 1524665762-31355-13-git-send-email-eric.auger@redhat.com
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
19
Message-id: 20210723162146.5167-3-peter.maydell@linaro.org
12
---
20
---
13
include/hw/arm/virt.h | 10 +++++++
21
target/arm/m_helper.c | 2 ++
14
hw/arm/virt.c | 64 ++++++++++++++++++++++++++++++++++++++++++-
22
1 file changed, 2 insertions(+)
15
2 files changed, 73 insertions(+), 1 deletion(-)
16
23
17
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
24
diff --git a/target/arm/m_helper.c b/target/arm/m_helper.c
18
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
19
--- a/include/hw/arm/virt.h
26
--- a/target/arm/m_helper.c
20
+++ b/include/hw/arm/virt.h
27
+++ b/target/arm/m_helper.c
21
@@ -XXX,XX +XXX,XX @@
28
@@ -XXX,XX +XXX,XX @@ static void do_v7m_exception_exit(ARMCPU *cpu)
22
29
qemu_log_mask(CPU_LOG_INT, "...taking UsageFault on existing "
23
#define NUM_GICV2M_SPIS 64
30
"stackframe: NSACR prevents clearing FPU registers\n");
24
#define NUM_VIRTIO_TRANSPORTS 32
31
v7m_exception_taken(cpu, excret, true, false);
25
+#define NUM_SMMU_IRQS 4
32
+ return;
26
33
} else if (!cpacr_pass) {
27
#define ARCH_GICV3_MAINT_IRQ 9
34
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE,
28
35
exc_secure);
29
@@ -XXX,XX +XXX,XX @@ enum {
36
@@ -XXX,XX +XXX,XX @@ static void do_v7m_exception_exit(ARMCPU *cpu)
30
VIRT_GIC_V2M,
37
qemu_log_mask(CPU_LOG_INT, "...taking UsageFault on existing "
31
VIRT_GIC_ITS,
38
"stackframe: CPACR prevents clearing FPU registers\n");
32
VIRT_GIC_REDIST,
39
v7m_exception_taken(cpu, excret, true, false);
33
+ VIRT_SMMU,
40
+ return;
34
VIRT_UART,
41
}
35
VIRT_MMIO,
42
}
36
VIRT_RTC,
43
/* Clear s0..s15, FPSCR and VPR */
37
@@ -XXX,XX +XXX,XX @@ enum {
38
VIRT_SECURE_MEM,
39
};
40
41
+typedef enum VirtIOMMUType {
42
+ VIRT_IOMMU_NONE,
43
+ VIRT_IOMMU_SMMUV3,
44
+ VIRT_IOMMU_VIRTIO,
45
+} VirtIOMMUType;
46
+
47
typedef struct MemMapEntry {
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
};
93
94
@@ -XXX,XX +XXX,XX @@ static void create_pcie_irq_map(const VirtMachineState *vms,
95
0x7 /* PCI irq */);
96
}
97
98
-static void create_pcie(const VirtMachineState *vms, qemu_irq *pic)
99
+static void create_smmu(const VirtMachineState *vms, qemu_irq *pic,
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
+
111
+ if (vms->iommu != VIRT_IOMMU_SMMUV3 || !vms->iommu_phandle) {
112
+ return;
113
+ }
114
+
115
+ dev = qdev_create(NULL, "arm-smmuv3");
116
+
117
+ object_property_set_link(OBJECT(dev), OBJECT(bus), "primary-bus",
118
+ &error_abort);
119
+ qdev_init_nofail(dev);
120
+ sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
121
+ for (i = 0; i < NUM_SMMU_IRQS; i++) {
122
+ sysbus_connect_irq(SYS_BUS_DEVICE(dev), i, pic[irq + i]);
123
+ }
124
+
125
+ node = g_strdup_printf("/smmuv3@%" PRIx64, base);
126
+ qemu_fdt_add_subnode(vms->fdt, node);
127
+ qemu_fdt_setprop(vms->fdt, node, "compatible", compat, sizeof(compat));
128
+ qemu_fdt_setprop_sized_cells(vms->fdt, node, "reg", 2, base, 2, size);
129
+
130
+ qemu_fdt_setprop_cells(vms->fdt, node, "interrupts",
131
+ GIC_FDT_IRQ_TYPE_SPI, irq , GIC_FDT_IRQ_FLAGS_EDGE_LO_HI,
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
+
136
+ qemu_fdt_setprop(vms->fdt, node, "interrupt-names", irq_names,
137
+ sizeof(irq_names));
138
+
139
+ qemu_fdt_setprop_cell(vms->fdt, node, "clocks", vms->clock_phandle);
140
+ qemu_fdt_setprop_string(vms->fdt, node, "clock-names", "apb_pclk");
141
+ qemu_fdt_setprop(vms->fdt, node, "dma-coherent", NULL, 0);
142
+
143
+ qemu_fdt_setprop_cell(vms->fdt, node, "#iommu-cells", 1);
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
+
166
g_free(nodename);
167
}
168
169
--
44
--
170
2.17.0
45
2.20.1
171
46
172
47
diff view generated by jsdifflib
1
From: Eric Auger <eric.auger@redhat.com>
1
For M-profile, we weren't reporting alignment faults triggered by the
2
generic TCG code correctly to the guest. These get passed into
3
arm_v7m_cpu_do_interrupt() as an EXCP_DATA_ABORT with an A-profile
4
style exception.fsr value of 1. We didn't check for this, and so
5
they fell through into the default of "assume this is an MPU fault"
6
and were reported to the guest as a data access violation MPU fault.
2
7
3
In case the MSI is translated by an IOMMU we need to fixup the
8
Report these alignment faults as UsageFaults which set the UNALIGNED
4
MSI route with the translated address.
9
bit in the UFSR.
5
10
6
Signed-off-by: Eric Auger <eric.auger@redhat.com>
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
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
13
Message-id: 20210723162146.5167-4-peter.maydell@linaro.org
11
---
14
---
12
target/arm/kvm.c | 38 +++++++++++++++++++++++++++++++++++++-
15
target/arm/m_helper.c | 8 ++++++++
13
target/arm/trace-events | 3 +++
16
1 file changed, 8 insertions(+)
14
2 files changed, 40 insertions(+), 1 deletion(-)
15
17
16
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
18
diff --git a/target/arm/m_helper.c b/target/arm/m_helper.c
17
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/kvm.c
20
--- a/target/arm/m_helper.c
19
+++ b/target/arm/kvm.c
21
+++ b/target/arm/m_helper.c
20
@@ -XXX,XX +XXX,XX @@
22
@@ -XXX,XX +XXX,XX @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
21
#include "sysemu/kvm.h"
23
env->v7m.sfsr |= R_V7M_SFSR_LSERR_MASK;
22
#include "kvm_arm.h"
24
break;
23
#include "cpu.h"
25
case EXCP_UNALIGNED:
24
+#include "trace.h"
26
+ /* Unaligned faults reported by M-profile aware code */
25
#include "internals.h"
27
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE, env->v7m.secure);
26
#include "hw/arm/arm.h"
28
env->v7m.cfsr[env->v7m.secure] |= R_V7M_CFSR_UNALIGNED_MASK;
27
+#include "hw/pci/pci.h"
29
break;
28
#include "exec/memattrs.h"
30
@@ -XXX,XX +XXX,XX @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
29
#include "exec/address-spaces.h"
31
}
30
#include "hw/boards.h"
32
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_BUS, false);
31
@@ -XXX,XX +XXX,XX @@ int kvm_arm_vgic_probe(void)
33
break;
32
int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route,
34
+ case 0x1: /* Alignment fault reported by generic code */
33
uint64_t address, uint32_t data, PCIDevice *dev)
35
+ qemu_log_mask(CPU_LOG_INT,
34
{
36
+ "...really UsageFault with UFSR.UNALIGNED\n");
35
- return 0;
37
+ env->v7m.cfsr[env->v7m.secure] |= R_V7M_CFSR_UNALIGNED_MASK;
36
+ AddressSpace *as = pci_device_iommu_address_space(dev);
38
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE,
37
+ hwaddr xlat, len, doorbell_gpa;
39
+ env->v7m.secure);
38
+ MemoryRegionSection mrs;
40
+ break;
39
+ MemoryRegion *mr;
41
default:
40
+ int ret = 1;
42
/*
41
+
43
* All other FSR values are either MPU faults or "can't happen
42
+ if (as == &address_space_memory) {
43
+ return 0;
44
+ }
45
+
46
+ /* MSI doorbell address is translated by an IOMMU */
47
+
48
+ rcu_read_lock();
49
+ mr = address_space_translate(as, address, &xlat, &len, true);
50
+ if (!mr) {
51
+ goto unlock;
52
+ }
53
+ mrs = memory_region_find(mr, xlat, 1);
54
+ if (!mrs.mr) {
55
+ goto unlock;
56
+ }
57
+
58
+ doorbell_gpa = mrs.offset_within_address_space;
59
+ memory_region_unref(mrs.mr);
60
+
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
--
44
--
86
2.17.0
45
2.20.1
87
46
88
47
diff view generated by jsdifflib
1
Convert the smc91c111 device away from using the old_mmio field of
1
The ISCR.ISRPENDING bit is set when an external interrupt is pending.
2
MemoryRegionOps. This device is used by several Arm board models.
2
This is true whether that external interrupt is enabled or not.
3
This means that we can't use 's->vectpending == 0' as a shortcut to
4
"ISRPENDING is zero", because s->vectpending indicates only the
5
highest priority pending enabled interrupt.
6
7
Remove the incorrect optimization so that if there is no pending
8
enabled interrupt we fall through to scanning through the whole
9
interrupt array.
3
10
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20180427173611.10281-3-peter.maydell@linaro.org
13
Message-id: 20210723162146.5167-5-peter.maydell@linaro.org
7
---
14
---
8
hw/net/smc91c111.c | 54 +++++++++++++++++++++-------------------------
15
hw/intc/armv7m_nvic.c | 9 ++++-----
9
1 file changed, 25 insertions(+), 29 deletions(-)
16
1 file changed, 4 insertions(+), 5 deletions(-)
10
17
11
diff --git a/hw/net/smc91c111.c b/hw/net/smc91c111.c
18
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
12
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
13
--- a/hw/net/smc91c111.c
20
--- a/hw/intc/armv7m_nvic.c
14
+++ b/hw/net/smc91c111.c
21
+++ b/hw/intc/armv7m_nvic.c
15
@@ -XXX,XX +XXX,XX @@ static uint32_t smc91c111_readb(void *opaque, hwaddr offset)
22
@@ -XXX,XX +XXX,XX @@ static bool nvic_isrpending(NVICState *s)
16
return 0;
17
}
18
19
-static void smc91c111_writew(void *opaque, hwaddr offset,
20
- uint32_t value)
21
+static uint64_t smc91c111_readfn(void *opaque, hwaddr addr, unsigned size)
22
{
23
{
23
- smc91c111_writeb(opaque, offset, value & 0xff);
24
int irq;
24
- smc91c111_writeb(opaque, offset + 1, value >> 8);
25
25
+ int i;
26
- /* We can shortcut if the highest priority pending interrupt
26
+ uint32_t val = 0;
27
- * happens to be external or if there is nothing pending.
27
+
28
+ /*
28
+ for (i = 0; i < size; i++) {
29
+ * We can shortcut if the highest priority pending interrupt
29
+ val |= smc91c111_readb(opaque, addr + i) << (i * 8);
30
+ * happens to be external; if not we need to check the whole
30
+ }
31
+ * vectors[] array.
31
+ return val;
32
}
33
34
-static void smc91c111_writel(void *opaque, hwaddr offset,
35
- uint32_t value)
36
+static void smc91c111_writefn(void *opaque, hwaddr addr,
37
+ uint64_t value, unsigned size)
38
{
39
+ int i = 0;
40
+
41
/* 32-bit writes to offset 0xc only actually write to the bank select
42
- register (offset 0xe) */
43
- if (offset != 0xc)
44
- smc91c111_writew(opaque, offset, value & 0xffff);
45
- smc91c111_writew(opaque, offset + 2, value >> 16);
46
-}
47
+ * register (offset 0xe), so skip the first two bytes we would write.
48
+ */
49
+ if (addr == 0xc && size == 4) {
50
+ i += 2;
51
+ }
52
53
-static uint32_t smc91c111_readw(void *opaque, hwaddr offset)
54
-{
55
- uint32_t val;
56
- val = smc91c111_readb(opaque, offset);
57
- val |= smc91c111_readb(opaque, offset + 1) << 8;
58
- return val;
59
-}
60
-
61
-static uint32_t smc91c111_readl(void *opaque, hwaddr offset)
62
-{
63
- uint32_t val;
64
- val = smc91c111_readw(opaque, offset);
65
- val |= smc91c111_readw(opaque, offset + 2) << 16;
66
- return val;
67
+ for (; i < size; i++) {
68
+ smc91c111_writeb(opaque, addr + i,
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
*/
32
*/
78
- .old_mmio = {
33
if (s->vectpending > NVIC_FIRST_IRQ) {
79
- .read = { smc91c111_readb, smc91c111_readw, smc91c111_readl, },
34
return true;
80
- .write = { smc91c111_writeb, smc91c111_writew, smc91c111_writel, },
35
}
81
- },
36
- if (s->vectpending == 0) {
82
+ .read = smc91c111_readfn,
37
- return false;
83
+ .write = smc91c111_writefn,
38
- }
84
+ .valid.min_access_size = 1,
39
85
+ .valid.max_access_size = 4,
40
for (irq = NVIC_FIRST_IRQ; irq < s->num_irq; irq++) {
86
.endianness = DEVICE_NATIVE_ENDIAN,
41
if (s->vectors[irq].pending) {
87
};
88
89
--
42
--
90
2.17.0
43
2.20.1
91
44
92
45
diff view generated by jsdifflib
1
From: Igor Mammedov <imammedo@redhat.com>
1
The VECTPENDING field in the ICSR is 9 bits wide, in bits [20:12] of
2
the register. We were incorrectly masking it to 8 bits, so it would
3
report the wrong value if the pending exception was greater than 256.
4
Fix the bug.
2
5
3
Even though nothing is currently broken (since all boards
4
use first_cpu as boot cpu), make sure that boot_info is set
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
12
Ref:
13
"Message-ID: <CAFEAcA_NMWuA8WSs3cNeY6xX1kerO_uAcN_3=fK02BEhHJW86g@mail.gmail.com>"
14
15
Signed-off-by: Igor Mammedov <imammedo@redhat.com>
16
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>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20210723162146.5167-6-peter.maydell@linaro.org
19
---
9
---
20
hw/arm/boot.c | 2 +-
10
hw/intc/armv7m_nvic.c | 2 +-
21
1 file changed, 1 insertion(+), 1 deletion(-)
11
1 file changed, 1 insertion(+), 1 deletion(-)
22
12
23
diff --git a/hw/arm/boot.c b/hw/arm/boot.c
13
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
24
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
25
--- a/hw/arm/boot.c
15
--- a/hw/intc/armv7m_nvic.c
26
+++ b/hw/arm/boot.c
16
+++ b/hw/intc/armv7m_nvic.c
27
@@ -XXX,XX +XXX,XX @@ static void arm_load_kernel_notify(Notifier *notifier, void *data)
17
@@ -XXX,XX +XXX,XX @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
28
}
18
/* VECTACTIVE */
29
info->is_linux = is_linux;
19
val = cpu->env.v7m.exception;
30
20
/* VECTPENDING */
31
- for (cs = CPU(cpu); cs; cs = CPU_NEXT(cs)) {
21
- val |= (s->vectpending & 0xff) << 12;
32
+ for (cs = first_cpu; cs; cs = CPU_NEXT(cs)) {
22
+ val |= (s->vectpending & 0x1ff) << 12;
33
ARM_CPU(cs)->env.boot_info = info;
23
/* ISRPENDING - set if any external IRQ is pending */
34
}
24
if (nvic_isrpending(s)) {
35
}
25
val |= (1 << 22);
36
--
26
--
37
2.17.0
27
2.20.1
38
28
39
29
diff view generated by jsdifflib
1
Convert the tusb6010 device away from using the old_mmio field
1
In Arm v8.1M the VECTPENDING field in the ICSR has new behaviour: if
2
of MemoryRegionOps. This device is used only in the n800 and n810
2
the register is accessed NonSecure and the highest priority pending
3
boards.
3
enabled exception (that would be returned in the VECTPENDING field)
4
targets Secure, then the VECTPENDING field must read 1 rather than
5
the exception number of the pending exception. Implement this.
4
6
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20180427173611.10281-2-peter.maydell@linaro.org
9
Message-id: 20210723162146.5167-7-peter.maydell@linaro.org
8
---
10
---
9
hw/usb/tusb6010.c | 40 ++++++++++++++++++++++++++++++++++++----
11
hw/intc/armv7m_nvic.c | 31 ++++++++++++++++++++++++-------
10
1 file changed, 36 insertions(+), 4 deletions(-)
12
1 file changed, 24 insertions(+), 7 deletions(-)
11
13
12
diff --git a/hw/usb/tusb6010.c b/hw/usb/tusb6010.c
14
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
13
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/usb/tusb6010.c
16
--- a/hw/intc/armv7m_nvic.c
15
+++ b/hw/usb/tusb6010.c
17
+++ b/hw/intc/armv7m_nvic.c
16
@@ -XXX,XX +XXX,XX @@ static void tusb_async_writew(void *opaque, hwaddr addr,
18
@@ -XXX,XX +XXX,XX @@ void armv7m_nvic_acknowledge_irq(void *opaque)
17
}
19
nvic_irq_update(s);
18
}
20
}
19
21
20
+static uint64_t tusb_async_readfn(void *opaque, hwaddr addr, unsigned size)
22
+static bool vectpending_targets_secure(NVICState *s)
21
+{
23
+{
22
+ switch (size) {
24
+ /* Return true if s->vectpending targets Secure state */
23
+ case 1:
25
+ if (s->vectpending_is_s_banked) {
24
+ return tusb_async_readb(opaque, addr);
26
+ return true;
25
+ case 2:
26
+ return tusb_async_readh(opaque, addr);
27
+ case 4:
28
+ return tusb_async_readw(opaque, addr);
29
+ default:
30
+ g_assert_not_reached();
31
+ }
27
+ }
28
+ return !exc_is_banked(s->vectpending) &&
29
+ exc_targets_secure(s, s->vectpending);
32
+}
30
+}
33
+
31
+
34
+static void tusb_async_writefn(void *opaque, hwaddr addr,
32
void armv7m_nvic_get_pending_irq_info(void *opaque,
35
+ uint64_t value, unsigned size)
33
int *pirq, bool *ptargets_secure)
36
+{
34
{
37
+ switch (size) {
35
@@ -XXX,XX +XXX,XX @@ void armv7m_nvic_get_pending_irq_info(void *opaque,
38
+ case 1:
36
39
+ tusb_async_writeb(opaque, addr, value);
37
assert(pending > ARMV7M_EXCP_RESET && pending < s->num_irq);
40
+ break;
38
41
+ case 2:
39
- if (s->vectpending_is_s_banked) {
42
+ tusb_async_writeh(opaque, addr, value);
40
- targets_secure = true;
43
+ break;
41
- } else {
44
+ case 4:
42
- targets_secure = !exc_is_banked(pending) &&
45
+ tusb_async_writew(opaque, addr, value);
43
- exc_targets_secure(s, pending);
46
+ break;
44
- }
47
+ default:
45
+ targets_secure = vectpending_targets_secure(s);
48
+ g_assert_not_reached();
46
49
+ }
47
trace_nvic_get_pending_irq_info(pending, targets_secure);
50
+}
48
51
+
49
@@ -XXX,XX +XXX,XX @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
52
static const MemoryRegionOps tusb_async_ops = {
50
/* VECTACTIVE */
53
- .old_mmio = {
51
val = cpu->env.v7m.exception;
54
- .read = { tusb_async_readb, tusb_async_readh, tusb_async_readw, },
52
/* VECTPENDING */
55
- .write = { tusb_async_writeb, tusb_async_writeh, tusb_async_writew, },
53
- val |= (s->vectpending & 0x1ff) << 12;
56
- },
54
+ if (s->vectpending) {
57
+ .read = tusb_async_readfn,
55
+ /*
58
+ .write = tusb_async_writefn,
56
+ * From v8.1M VECTPENDING must read as 1 if accessed as
59
+ .valid.min_access_size = 1,
57
+ * NonSecure and the highest priority pending and enabled
60
+ .valid.max_access_size = 4,
58
+ * exception targets Secure.
61
.endianness = DEVICE_NATIVE_ENDIAN,
59
+ */
62
};
60
+ int vp = s->vectpending;
63
61
+ if (!attrs.secure && arm_feature(&cpu->env, ARM_FEATURE_V8_1M) &&
62
+ vectpending_targets_secure(s)) {
63
+ vp = 1;
64
+ }
65
+ val |= (vp & 0x1ff) << 12;
66
+ }
67
/* ISRPENDING - set if any external IRQ is pending */
68
if (nvic_isrpending(s)) {
69
val |= (1 << 22);
64
--
70
--
65
2.17.0
71
2.20.1
66
72
67
73
diff view generated by jsdifflib
1
From: Eric Auger <eric.auger@redhat.com>
1
From: Mao Zhongyi <maozhongyi@cmss.chinamobile.com>
2
2
3
At the moment, the SMMUv3 does not support notification on
3
Missed in commit f3478392 "docs: Move deprecation, build
4
TLB invalidation. So let's log an error as soon as such notifier
4
and license info out of system/"
5
gets enabled.
6
5
7
Signed-off-by: Eric Auger <eric.auger@redhat.com>
6
Signed-off-by: Mao Zhongyi <maozhongyi@cmss.chinamobile.com>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Message-id: 1524665762-31355-11-git-send-email-eric.auger@redhat.com
8
Message-id: 20210723065828.1336760-1-maozhongyi@cmss.chinamobile.com
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
10
---
12
hw/arm/smmuv3.c | 11 +++++++++++
11
configure | 2 +-
13
1 file changed, 11 insertions(+)
12
target/i386/cpu.c | 2 +-
13
MAINTAINERS | 2 +-
14
3 files changed, 3 insertions(+), 3 deletions(-)
14
15
15
diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c
16
diff --git a/configure b/configure
17
index XXXXXXX..XXXXXXX 100755
18
--- a/configure
19
+++ b/configure
20
@@ -XXX,XX +XXX,XX @@ fi
21
22
if test -n "${deprecated_features}"; then
23
echo "Warning, deprecated features enabled."
24
- echo "Please see docs/system/deprecated.rst"
25
+ echo "Please see docs/about/deprecated.rst"
26
echo " features: ${deprecated_features}"
27
fi
28
29
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
16
index XXXXXXX..XXXXXXX 100644
30
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/arm/smmuv3.c
31
--- a/target/i386/cpu.c
18
+++ b/hw/arm/smmuv3.c
32
+++ b/target/i386/cpu.c
19
@@ -XXX,XX +XXX,XX @@ static void smmuv3_class_init(ObjectClass *klass, void *data)
33
@@ -XXX,XX +XXX,XX @@ static const X86CPUDefinition builtin_x86_defs[] = {
20
dc->realize = smmu_realize;
34
* none", but this is just for compatibility while libvirt isn't
21
}
35
* adapted to resolve CPU model versions before creating VMs.
22
36
* See "Runnability guarantee of CPU models" at
23
+static void smmuv3_notify_flag_changed(IOMMUMemoryRegion *iommu,
37
- * docs/system/deprecated.rst.
24
+ IOMMUNotifierFlag old,
38
+ * docs/about/deprecated.rst.
25
+ IOMMUNotifierFlag new)
39
*/
26
+{
40
X86CPUVersion default_cpu_version = 1;
27
+ if (old == IOMMU_NOTIFIER_NONE) {
41
28
+ warn_report("SMMUV3 does not support vhost/vfio integration yet: "
42
diff --git a/MAINTAINERS b/MAINTAINERS
29
+ "devices of those types will not function properly");
43
index XXXXXXX..XXXXXXX 100644
30
+ }
44
--- a/MAINTAINERS
31
+}
45
+++ b/MAINTAINERS
32
+
46
@@ -XXX,XX +XXX,XX @@ F: contrib/gitdm/*
33
static void smmuv3_iommu_memory_region_class_init(ObjectClass *klass,
47
34
void *data)
48
Incompatible changes
35
{
49
R: libvir-list@redhat.com
36
IOMMUMemoryRegionClass *imrc = IOMMU_MEMORY_REGION_CLASS(klass);
50
-F: docs/system/deprecated.rst
37
51
+F: docs/about/deprecated.rst
38
imrc->translate = smmuv3_translate;
52
39
+ imrc->notify_flag_changed = smmuv3_notify_flag_changed;
53
Build System
40
}
54
------------
41
42
static const TypeInfo smmuv3_type_info = {
43
--
55
--
44
2.17.0
56
2.20.1
45
57
46
58
diff view generated by jsdifflib
1
From: Mathew Maidment <mathew1800@gmail.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
The duplication of id_tlbtr_reginfo was unintentionally added within
3
Currently, our only caller is sve_zcr_len_for_el, which has
4
3281af8114c6b8ead02f08b58e3c36895c1ea047 which should have been
4
already masked the length extracted from ZCR_ELx, so the
5
id_mpuir_reginfo.
5
masking done here is a nop. But we will shortly have uses
6
from other locations, where the length will be unmasked.
6
7
7
The effect was that for OMAP and StrongARM CPUs we would
8
Saturate the length to ARM_MAX_VQ instead of truncating to
8
incorrectly UNDEF writes to MPUIR rather than NOPing them.
9
the low 4 bits.
9
10
10
Signed-off-by: Mathew Maidment <mathew1800@gmail.com>
11
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20180501184933.37609-2-mathew1800@gmail.com
12
[PMM: tweak commit message]
13
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
13
Message-id: 20210723203344.968563-2-richard.henderson@linaro.org
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
---
15
---
16
target/arm/helper.c | 2 +-
16
target/arm/helper.c | 4 +++-
17
1 file changed, 1 insertion(+), 1 deletion(-)
17
1 file changed, 3 insertions(+), 1 deletion(-)
18
18
19
diff --git a/target/arm/helper.c b/target/arm/helper.c
19
diff --git a/target/arm/helper.c b/target/arm/helper.c
20
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
21
--- a/target/arm/helper.c
21
--- a/target/arm/helper.c
22
+++ b/target/arm/helper.c
22
+++ b/target/arm/helper.c
23
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
23
@@ -XXX,XX +XXX,XX @@ static uint32_t sve_zcr_get_valid_len(ARMCPU *cpu, uint32_t start_len)
24
for (r = id_cp_reginfo; r->type != ARM_CP_SENTINEL; r++) {
24
{
25
r->access = PL1_RW;
25
uint32_t end_len;
26
}
26
27
- id_tlbtr_reginfo.access = PL1_RW;
27
- end_len = start_len &= 0xf;
28
+ id_mpuir_reginfo.access = PL1_RW;
28
+ start_len = MIN(start_len, ARM_MAX_VQ - 1);
29
id_tlbtr_reginfo.access = PL1_RW;
29
+ end_len = start_len;
30
}
30
+
31
if (arm_feature(env, ARM_FEATURE_V8)) {
31
if (!test_bit(start_len, cpu->sve_vq_map)) {
32
end_len = find_last_bit(cpu->sve_vq_map, start_len);
33
assert(end_len < start_len);
32
--
34
--
33
2.17.0
35
2.20.1
34
36
35
37
diff view generated by jsdifflib
Deleted patch
1
From: Patrick Oppenlander <patrick.oppenlander@gmail.com>
2
1
3
The character frontend needs to be notified that the uart receive buffer
4
is empty and ready to handle another character.
5
6
Previously, the uart only worked correctly when receiving one character
7
at a time.
8
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>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
14
hw/char/cmsdk-apb-uart.c | 1 +
15
1 file changed, 1 insertion(+)
16
17
diff --git a/hw/char/cmsdk-apb-uart.c b/hw/char/cmsdk-apb-uart.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/char/cmsdk-apb-uart.c
20
+++ b/hw/char/cmsdk-apb-uart.c
21
@@ -XXX,XX +XXX,XX @@ static uint64_t uart_read(void *opaque, hwaddr offset, unsigned size)
22
r = s->rxbuf;
23
s->state &= ~R_STATE_RXFULL_MASK;
24
cmsdk_apb_uart_update(s);
25
+ qemu_chr_fe_accept_input(&s->chr);
26
break;
27
case A_STATE:
28
r = s->state;
29
--
30
2.17.0
31
32
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
The (size > 3 && !is_q) condition is identical to the preceeding test
4
of bit 3 in immh; eliminate it. For the benefit of Coverity, assert
5
that size is within the bounds we expect.
6
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>
15
---
16
target/arm/translate-a64.c | 6 +-----
17
1 file changed, 1 insertion(+), 5 deletions(-)
18
19
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
20
index XXXXXXX..XXXXXXX 100644
21
--- a/target/arm/translate-a64.c
22
+++ b/target/arm/translate-a64.c
23
@@ -XXX,XX +XXX,XX @@ static void handle_vec_simd_shri(DisasContext *s, bool is_q, bool is_u,
24
unallocated_encoding(s);
25
return;
26
}
27
-
28
- if (size > 3 && !is_q) {
29
- unallocated_encoding(s);
30
- return;
31
- }
32
+ tcg_debug_assert(size <= 3);
33
34
if (!fp_access_check(s)) {
35
return;
36
--
37
2.17.0
38
39
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
Path analysis shows that size == 3 && !is_q has been eliminated.
4
5
Fixes: Coverity CID1385853
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
16
--- a/target/arm/translate-a64.c
17
+++ b/target/arm/translate-a64.c
18
@@ -XXX,XX +XXX,XX @@ static void disas_simd_two_reg_misc(DisasContext *s, uint32_t insn)
19
/* All 64-bit element operations can be shared with scalar 2misc */
20
int pass;
21
22
- for (pass = 0; pass < (is_q ? 2 : 1); pass++) {
23
+ /* Coverity claims (size == 3 && !is_q) has been eliminated
24
+ * from all paths leading to here.
25
+ */
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
31
--
32
2.17.0
33
34
diff view generated by jsdifflib
Deleted patch
1
From: Thomas Huth <thuth@redhat.com>
2
1
3
When running omap1/2 or pxa2xx based ARM machines with -nodefaults,
4
they bail out immediately complaining about a "missing SecureDigital
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
10
Signed-off-by: Thomas Huth <thuth@redhat.com>
11
Message-id: 1525326811-3233-1-git-send-email-thuth@redhat.com
12
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
13
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
---
16
hw/arm/omap1.c | 8 ++++----
17
hw/arm/omap2.c | 8 ++++----
18
hw/arm/pxa2xx.c | 15 +++++++--------
19
3 files changed, 15 insertions(+), 16 deletions(-)
20
21
diff --git a/hw/arm/omap1.c b/hw/arm/omap1.c
22
index XXXXXXX..XXXXXXX 100644
23
--- a/hw/arm/omap1.c
24
+++ b/hw/arm/omap1.c
25
@@ -XXX,XX +XXX,XX @@
26
#include "hw/arm/soc_dma.h"
27
#include "sysemu/block-backend.h"
28
#include "sysemu/blockdev.h"
29
+#include "sysemu/qtest.h"
30
#include "qemu/range.h"
31
#include "hw/sysbus.h"
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
}
43
s->mmc = omap_mmc_init(0xfffb7800, system_memory,
44
- blk_by_legacy_dinfo(dinfo),
45
+ dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
46
qdev_get_gpio_in(s->ih[1], OMAP_INT_OQN),
47
&s->drq[OMAP_DMA_MMC_TX],
48
omap_findclk(s, "mmc_ck"));
49
diff --git a/hw/arm/omap2.c b/hw/arm/omap2.c
50
index XXXXXXX..XXXXXXX 100644
51
--- a/hw/arm/omap2.c
52
+++ b/hw/arm/omap2.c
53
@@ -XXX,XX +XXX,XX @@
54
#include "cpu.h"
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
}
71
s->mmc = omap2_mmc_init(omap_l4tao(s->l4, 9),
72
- blk_by_legacy_dinfo(dinfo),
73
+ dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
74
qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_MMC_IRQ),
75
&s->drq[OMAP24XX_DMA_MMC1_TX],
76
omap_findclk(s, "mmc_fclk"), omap_findclk(s, "mmc_iclk"));
77
diff --git a/hw/arm/pxa2xx.c b/hw/arm/pxa2xx.c
78
index XXXXXXX..XXXXXXX 100644
79
--- a/hw/arm/pxa2xx.c
80
+++ b/hw/arm/pxa2xx.c
81
@@ -XXX,XX +XXX,XX @@
82
#include "chardev/char-fe.h"
83
#include "sysemu/block-backend.h"
84
#include "sysemu/blockdev.h"
85
+#include "sysemu/qtest.h"
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
--
122
2.17.0
123
124
diff view generated by jsdifflib
Deleted patch
1
From: Eric Auger <eric.auger@redhat.com>
2
1
3
The patch introduces the smmu base device and class for the ARM
4
smmu. Devices for specific versions will be derived from this
5
base device.
6
7
We also introduce some important datatypes.
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-2-git-send-email-eric.auger@redhat.com
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
15
hw/arm/Makefile.objs | 1 +
16
include/hw/arm/smmu-common.h | 123 ++++++++++++++++++++++++++++
17
hw/arm/smmu-common.c | 81 ++++++++++++++++++
18
default-configs/aarch64-softmmu.mak | 1 +
19
4 files changed, 206 insertions(+)
20
create mode 100644 include/hw/arm/smmu-common.h
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
34
index XXXXXXX..XXXXXXX
35
--- /dev/null
36
+++ b/include/hw/arm/smmu-common.h
37
@@ -XXX,XX +XXX,XX @@
38
+/*
39
+ * ARM SMMU Support
40
+ *
41
+ * Copyright (C) 2015-2016 Broadcom Corporation
42
+ * Copyright (c) 2017 Red Hat, Inc.
43
+ * Written by Prem Mallappa, Eric Auger
44
+ *
45
+ * This program is free software; you can redistribute it and/or modify
46
+ * it under the terms of the GNU General Public License version 2 as
47
+ * published by the Free Software Foundation.
48
+ *
49
+ * This program is distributed in the hope that it will be useful,
50
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
51
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
52
+ * GNU General Public License for more details.
53
+ *
54
+ */
55
+
56
+#ifndef HW_ARM_SMMU_COMMON_H
57
+#define HW_ARM_SMMU_COMMON_H
58
+
59
+#include "hw/sysbus.h"
60
+#include "hw/pci/pci.h"
61
+
62
+#define SMMU_PCI_BUS_MAX 256
63
+#define SMMU_PCI_DEVFN_MAX 256
64
+
65
+#define SMMU_MAX_VA_BITS 48
66
+
67
+/*
68
+ * Page table walk error types
69
+ */
70
+typedef enum {
71
+ SMMU_PTW_ERR_NONE,
72
+ SMMU_PTW_ERR_WALK_EABT, /* Translation walk external abort */
73
+ SMMU_PTW_ERR_TRANSLATION, /* Translation fault */
74
+ SMMU_PTW_ERR_ADDR_SIZE, /* Address Size fault */
75
+ SMMU_PTW_ERR_ACCESS, /* Access fault */
76
+ SMMU_PTW_ERR_PERMISSION, /* Permission fault */
77
+} SMMUPTWEventType;
78
+
79
+typedef struct SMMUPTWEventInfo {
80
+ SMMUPTWEventType type;
81
+ dma_addr_t addr; /* fetched address that induced an abort, if any */
82
+} SMMUPTWEventInfo;
83
+
84
+typedef struct SMMUTransTableInfo {
85
+ bool disabled; /* is the translation table disabled? */
86
+ uint64_t ttb; /* TT base address */
87
+ uint8_t tsz; /* input range, ie. 2^(64 -tsz)*/
88
+ uint8_t granule_sz; /* granule page shift */
89
+} SMMUTransTableInfo;
90
+
91
+/*
92
+ * Generic structure populated by derived SMMU devices
93
+ * after decoding the configuration information and used as
94
+ * input to the page table walk
95
+ */
96
+typedef struct SMMUTransCfg {
97
+ int stage; /* translation stage */
98
+ bool aa64; /* arch64 or aarch32 translation table */
99
+ bool disabled; /* smmu is disabled */
100
+ bool bypassed; /* translation is bypassed */
101
+ bool aborted; /* translation is aborted */
102
+ uint64_t ttb; /* TT base address */
103
+ uint8_t oas; /* output address width */
104
+ uint8_t tbi; /* Top Byte Ignore */
105
+ uint16_t asid;
106
+ SMMUTransTableInfo tt[2];
107
+} SMMUTransCfg;
108
+
109
+typedef struct SMMUDevice {
110
+ void *smmu;
111
+ PCIBus *bus;
112
+ int devfn;
113
+ IOMMUMemoryRegion iommu;
114
+ AddressSpace as;
115
+} SMMUDevice;
116
+
117
+typedef struct SMMUNotifierNode {
118
+ SMMUDevice *sdev;
119
+ QLIST_ENTRY(SMMUNotifierNode) next;
120
+} SMMUNotifierNode;
121
+
122
+typedef struct SMMUPciBus {
123
+ PCIBus *bus;
124
+ SMMUDevice *pbdev[0]; /* Parent array is sparse, so dynamically alloc */
125
+} SMMUPciBus;
126
+
127
+typedef struct SMMUState {
128
+ /* <private> */
129
+ SysBusDevice dev;
130
+ const char *mrtypename;
131
+ MemoryRegion iomem;
132
+
133
+ GHashTable *smmu_pcibus_by_busptr;
134
+ GHashTable *configs; /* cache for configuration data */
135
+ GHashTable *iotlb;
136
+ SMMUPciBus *smmu_pcibus_by_bus_num[SMMU_PCI_BUS_MAX];
137
+ PCIBus *pci_bus;
138
+ QLIST_HEAD(, SMMUNotifierNode) notifiers_list;
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
+/*
168
+ * Copyright (C) 2014-2016 Broadcom Corporation
169
+ * Copyright (c) 2017 Red Hat, Inc.
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
+ */
184
+
185
+#include "qemu/osdep.h"
186
+#include "sysemu/sysemu.h"
187
+#include "exec/address-spaces.h"
188
+#include "trace.h"
189
+#include "exec/target_page.h"
190
+#include "qom/cpu.h"
191
+#include "hw/qdev-properties.h"
192
+#include "qapi/error.h"
193
+
194
+#include "qemu/error-report.h"
195
+#include "hw/arm/smmu-common.h"
196
+
197
+static void smmu_base_realize(DeviceState *dev, Error **errp)
198
+{
199
+ SMMUBaseClass *sbc = ARM_SMMU_GET_CLASS(dev);
200
+ Error *local_err = NULL;
201
+
202
+ sbc->parent_realize(dev, &local_err);
203
+ if (local_err) {
204
+ error_propagate(errp, local_err);
205
+ return;
206
+ }
207
+}
208
+
209
+static void smmu_base_reset(DeviceState *dev)
210
+{
211
+ /* will be filled later on */
212
+}
213
+
214
+static Property smmu_dev_properties[] = {
215
+ DEFINE_PROP_UINT8("bus_num", SMMUState, bus_num, 0),
216
+ DEFINE_PROP_LINK("primary-bus", SMMUState, primary_bus, "PCI", PCIBus *),
217
+ DEFINE_PROP_END_OF_LIST(),
218
+};
219
+
220
+static void smmu_base_class_init(ObjectClass *klass, void *data)
221
+{
222
+ DeviceClass *dc = DEVICE_CLASS(klass);
223
+ SMMUBaseClass *sbc = ARM_SMMU_CLASS(klass);
224
+
225
+ dc->props = smmu_dev_properties;
226
+ device_class_set_parent_realize(dc, smmu_base_realize,
227
+ &sbc->parent_realize);
228
+ dc->reset = smmu_base_reset;
229
+}
230
+
231
+static const TypeInfo smmu_base_info = {
232
+ .name = TYPE_ARM_SMMU,
233
+ .parent = TYPE_SYS_BUS_DEVICE,
234
+ .instance_size = sizeof(SMMUState),
235
+ .class_data = NULL,
236
+ .class_size = sizeof(SMMUBaseClass),
237
+ .class_init = smmu_base_class_init,
238
+ .abstract = true,
239
+};
240
+
241
+static void smmu_base_register_types(void)
242
+{
243
+ type_register_static(&smmu_base_info);
244
+}
245
+
246
+type_init(smmu_base_register_types)
247
+
248
diff --git a/default-configs/aarch64-softmmu.mak b/default-configs/aarch64-softmmu.mak
249
index XXXXXXX..XXXXXXX 100644
250
--- a/default-configs/aarch64-softmmu.mak
251
+++ b/default-configs/aarch64-softmmu.mak
252
@@ -XXX,XX +XXX,XX @@ CONFIG_DDC=y
253
CONFIG_DPCD=y
254
CONFIG_XLNX_ZYNQMP=y
255
CONFIG_XLNX_ZYNQMP_ARM=y
256
+CONFIG_ARM_SMMUV3=y
257
--
258
2.17.0
259
260
diff view generated by jsdifflib
Deleted patch
1
From: Eric Auger <eric.auger@redhat.com>
2
1
3
We set up the infrastructure to enumerate all the PCI devices
4
attached to the SMMU and create an associated IOMMU memory
5
region and address space.
6
7
Those info are stored in SMMUDevice objects. The devices are
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
12
Signed-off-by: Eric Auger <eric.auger@redhat.com>
13
Signed-off-by: Prem Mallappa <prem.mallappa@broadcom.com>
14
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>
17
---
18
include/hw/arm/smmu-common.h | 8 +++++
19
hw/arm/smmu-common.c | 69 ++++++++++++++++++++++++++++++++++++
20
hw/arm/trace-events | 3 ++
21
3 files changed, 80 insertions(+)
22
23
diff --git a/include/hw/arm/smmu-common.h b/include/hw/arm/smmu-common.h
24
index XXXXXXX..XXXXXXX 100644
25
--- a/include/hw/arm/smmu-common.h
26
+++ b/include/hw/arm/smmu-common.h
27
@@ -XXX,XX +XXX,XX @@ typedef struct {
28
#define ARM_SMMU_GET_CLASS(obj) \
29
OBJECT_GET_CLASS(SMMUBaseClass, (obj), TYPE_ARM_SMMU)
30
31
+/* Return the SMMUPciBus handle associated to a PCI bus number */
32
+SMMUPciBus *smmu_find_smmu_pcibus(SMMUState *s, uint8_t bus_num);
33
+
34
+/* Return the stream ID of an SMMU device */
35
+static inline uint16_t smmu_get_sid(SMMUDevice *sdev)
36
+{
37
+ return PCI_BUILD_BDF(pci_bus_num(sdev->bus), sdev->devfn);
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
+
58
+ if (!smmu_pci_bus) {
59
+ GHashTableIter iter;
60
+
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
+ }
68
+ }
69
+ return smmu_pci_bus;
70
+}
71
+
72
+static AddressSpace *smmu_find_add_as(PCIBus *bus, void *opaque, int devfn)
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
{
110
+ SMMUState *s = ARM_SMMU(dev);
111
SMMUBaseClass *sbc = ARM_SMMU_GET_CLASS(dev);
112
Error *local_err = NULL;
113
114
@@ -XXX,XX +XXX,XX @@ static void smmu_base_realize(DeviceState *dev, Error **errp)
115
error_propagate(errp, local_err);
116
return;
117
}
118
+
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
--
142
2.17.0
143
144
diff view generated by jsdifflib
Deleted patch
1
From: Eric Auger <eric.auger@redhat.com>
2
1
3
This patch implements the page table walk for VMSAv8-64.
4
5
Signed-off-by: Eric Auger <eric.auger@redhat.com>
6
Signed-off-by: Prem Mallappa <prem.mallappa@broadcom.com>
7
Message-id: 1524665762-31355-4-git-send-email-eric.auger@redhat.com
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
hw/arm/smmu-internal.h | 99 ++++++++++++++++
12
include/hw/arm/smmu-common.h | 14 +++
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
+/*
25
+ * ARM SMMU support - Internal API
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
+ */
43
+
44
+#ifndef HW_ARM_SMMU_INTERNAL_H
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
+{
106
+ return granule_sz + (3 - level) * (granule_sz - 3);
107
+}
108
+
109
+static inline uint64_t level_page_mask(int level, int granule_sz)
110
+{
111
+ return ~(MAKE_64BIT_MASK(0, level_shift(level, granule_sz)));
112
+}
113
+
114
+static inline
115
+uint64_t iova_level_offset(uint64_t iova, int inputsize,
116
+ int level, int gsz)
117
+{
118
+ return ((iova & MAKE_64BIT_MASK(0, inputsize)) >> level_shift(level, gsz)) &
119
+ MAKE_64BIT_MASK(0, gsz - 3);
120
+}
121
+
122
+#endif
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
+{
165
+ int ret;
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
+}
180
+
181
+/* VMSAv8-64 Translation Table Format Descriptor Decoding */
182
+
183
+/**
184
+ * get_page_pte_address - returns the L3 descriptor output address,
185
+ * ie. the page frame
186
+ * ARM ARM spec: Figure D4-17 VMSAv8-64 level 3 descriptor format
187
+ */
188
+static inline hwaddr get_page_pte_address(uint64_t pte, int granule_sz)
189
+{
190
+ return PTE_ADDRESS(pte, granule_sz);
191
+}
192
+
193
+/**
194
+ * get_table_pte_address - return table descriptor output address,
195
+ * ie. address of next level table
196
+ * ARM ARM Figure D4-16 VMSAv8-64 level0, level1, and level 2 descriptor formats
197
+ */
198
+static inline hwaddr get_table_pte_address(uint64_t pte, int granule_sz)
199
+{
200
+ return PTE_ADDRESS(pte, granule_sz);
201
+}
202
+
203
+/**
204
+ * get_block_pte_address - return block descriptor output address and block size
205
+ * ARM ARM Figure D4-16 VMSAv8-64 level0, level1, and level 2 descriptor formats
206
+ */
207
+static inline hwaddr get_block_pte_address(uint64_t pte, int level,
208
+ int granule_sz, uint64_t *bsz)
209
+{
210
+ int n = (granule_sz - 3) * (4 - level) + 3;
211
+
212
+ *bsz = 1 << n;
213
+ return PTE_ADDRESS(pte, n);
214
+}
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
--
398
2.17.0
399
400
diff view generated by jsdifflib
Deleted patch
1
From: Prem Mallappa <prem.mallappa@broadcom.com>
2
1
3
This patch implements a skeleton for the smmuv3 device.
4
Datatypes and register definitions are introduced. The MMIO
5
region, the interrupts and the queue are initialized.
6
7
Only the MMIO read operation is implemented here.
8
9
Signed-off-by: Prem Mallappa <prem.mallappa@broadcom.com>
10
Signed-off-by: Eric Auger <eric.auger@redhat.com>
11
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>
14
---
15
hw/arm/Makefile.objs | 2 +-
16
hw/arm/smmuv3-internal.h | 142 +++++++++++++++
17
include/hw/arm/smmuv3.h | 87 ++++++++++
18
hw/arm/smmuv3.c | 366 +++++++++++++++++++++++++++++++++++++++
19
hw/arm/trace-events | 3 +
20
5 files changed, 599 insertions(+), 1 deletion(-)
21
create mode 100644 hw/arm/smmuv3-internal.h
22
create mode 100644 include/hw/arm/smmuv3.h
23
create mode 100644 hw/arm/smmuv3.c
24
25
diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
26
index XXXXXXX..XXXXXXX 100644
27
--- a/hw/arm/Makefile.objs
28
+++ b/hw/arm/Makefile.objs
29
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_MPS2) += mps2-tz.o
30
obj-$(CONFIG_MSF2) += msf2-soc.o msf2-som.o
31
obj-$(CONFIG_IOTKIT) += iotkit.o
32
obj-$(CONFIG_FSL_IMX7) += fsl-imx7.o mcimx7d-sabre.o
33
-obj-$(CONFIG_ARM_SMMUV3) += smmu-common.o
34
+obj-$(CONFIG_ARM_SMMUV3) += smmu-common.o smmuv3.o
35
diff --git a/hw/arm/smmuv3-internal.h b/hw/arm/smmuv3-internal.h
36
new file mode 100644
37
index XXXXXXX..XXXXXXX
38
--- /dev/null
39
+++ b/hw/arm/smmuv3-internal.h
40
@@ -XXX,XX +XXX,XX @@
41
+/*
42
+ * ARM SMMUv3 support - Internal API
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
185
index XXXXXXX..XXXXXXX
186
--- /dev/null
187
+++ b/include/hw/arm/smmuv3.h
188
@@ -XXX,XX +XXX,XX @@
189
+/*
190
+ * Copyright (C) 2014-2016 Broadcom Corporation
191
+ * Copyright (c) 2017 Red Hat, Inc.
192
+ * Written by Prem Mallappa, Eric Auger
193
+ *
194
+ * This program is free software; you can redistribute it and/or modify
195
+ * it under the terms of the GNU General Public License version 2 as
196
+ * published by the Free Software Foundation.
197
+ *
198
+ * This program is distributed in the hope that it will be useful,
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
+ *
203
+ * You should have received a copy of the GNU General Public License along
204
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
205
+ */
206
+
207
+#ifndef HW_ARM_SMMUV3_H
208
+#define HW_ARM_SMMUV3_H
209
+
210
+#include "hw/arm/smmu-common.h"
211
+#include "hw/registerfields.h"
212
+
213
+#define TYPE_SMMUV3_IOMMU_MEMORY_REGION "smmuv3-iommu-memory-region"
214
+
215
+typedef struct SMMUQueue {
216
+ uint64_t base; /* base register */
217
+ uint32_t prod;
218
+ uint32_t cons;
219
+ uint8_t entry_size;
220
+ uint8_t log2size;
221
+} SMMUQueue;
222
+
223
+typedef struct SMMUv3State {
224
+ SMMUState smmu_state;
225
+
226
+ uint32_t features;
227
+ uint8_t sid_size;
228
+ uint8_t sid_split;
229
+
230
+ uint32_t idr[6];
231
+ uint32_t iidr;
232
+ uint32_t cr[3];
233
+ uint32_t cr0ack;
234
+ uint32_t statusr;
235
+ uint32_t irq_ctrl;
236
+ uint32_t gerror;
237
+ uint32_t gerrorn;
238
+ uint64_t gerror_irq_cfg0;
239
+ uint32_t gerror_irq_cfg1;
240
+ uint32_t gerror_irq_cfg2;
241
+ uint64_t strtab_base;
242
+ uint32_t strtab_base_cfg;
243
+ uint64_t eventq_irq_cfg0;
244
+ uint32_t eventq_irq_cfg1;
245
+ uint32_t eventq_irq_cfg2;
246
+
247
+ SMMUQueue eventq, cmdq;
248
+
249
+ qemu_irq irq[4];
250
+} SMMUv3State;
251
+
252
+typedef enum {
253
+ SMMU_IRQ_EVTQ,
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
+
275
+#endif
276
diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c
277
new file mode 100644
278
index XXXXXXX..XXXXXXX
279
--- /dev/null
280
+++ b/hw/arm/smmuv3.c
281
@@ -XXX,XX +XXX,XX @@
282
+/*
283
+ * Copyright (C) 2014-2016 Broadcom Corporation
284
+ * Copyright (c) 2017 Red Hat, Inc.
285
+ * Written by Prem Mallappa, Eric Auger
286
+ *
287
+ * This program is free software; you can redistribute it and/or modify
288
+ * it under the terms of the GNU General Public License version 2 as
289
+ * published by the Free Software Foundation.
290
+ *
291
+ * This program is distributed in the hope that it will be useful,
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
+ *
296
+ * You should have received a copy of the GNU General Public License along
297
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
298
+ */
299
+
300
+#include "qemu/osdep.h"
301
+#include "hw/boards.h"
302
+#include "sysemu/sysemu.h"
303
+#include "hw/sysbus.h"
304
+#include "hw/qdev-core.h"
305
+#include "hw/pci/pci.h"
306
+#include "exec/address-spaces.h"
307
+#include "trace.h"
308
+#include "qemu/log.h"
309
+#include "qemu/error-report.h"
310
+#include "qapi/error.h"
311
+
312
+#include "hw/arm/smmuv3.h"
313
+#include "smmuv3-internal.h"
314
+
315
+static void smmuv3_init_regs(SMMUv3State *s)
316
+{
317
+ /**
318
+ * IDR0: stage1 only, AArch64 only, coherent access, 16b ASID,
319
+ * multi-level stream table
320
+ */
321
+ s->idr[0] = FIELD_DP32(s->idr[0], IDR0, S1P, 1); /* stage 1 supported */
322
+ s->idr[0] = FIELD_DP32(s->idr[0], IDR0, TTF, 2); /* AArch64 PTW only */
323
+ s->idr[0] = FIELD_DP32(s->idr[0], IDR0, COHACC, 1); /* IO coherent */
324
+ s->idr[0] = FIELD_DP32(s->idr[0], IDR0, ASID16, 1); /* 16-bit ASID */
325
+ s->idr[0] = FIELD_DP32(s->idr[0], IDR0, TTENDIAN, 2); /* little endian */
326
+ s->idr[0] = FIELD_DP32(s->idr[0], IDR0, STALL_MODEL, 1); /* No stall */
327
+ /* terminated transaction will always be aborted/error returned */
328
+ s->idr[0] = FIELD_DP32(s->idr[0], IDR0, TERM_MODEL, 1);
329
+ /* 2-level stream table supported */
330
+ s->idr[0] = FIELD_DP32(s->idr[0], IDR0, STLEVEL, 1);
331
+
332
+ s->idr[1] = FIELD_DP32(s->idr[1], IDR1, SIDSIZE, SMMU_IDR1_SIDSIZE);
333
+ s->idr[1] = FIELD_DP32(s->idr[1], IDR1, EVENTQS, SMMU_EVENTQS);
334
+ s->idr[1] = FIELD_DP32(s->idr[1], IDR1, CMDQS, SMMU_CMDQS);
335
+
336
+ /* 4K and 64K granule support */
337
+ s->idr[5] = FIELD_DP32(s->idr[5], IDR5, GRAN4K, 1);
338
+ s->idr[5] = FIELD_DP32(s->idr[5], IDR5, GRAN64K, 1);
339
+ s->idr[5] = FIELD_DP32(s->idr[5], IDR5, OAS, SMMU_IDR5_OAS); /* 44 bits */
340
+
341
+ s->cmdq.base = deposit64(s->cmdq.base, 0, 5, SMMU_CMDQS);
342
+ s->cmdq.prod = 0;
343
+ s->cmdq.cons = 0;
344
+ s->cmdq.entry_size = sizeof(struct Cmd);
345
+ s->eventq.base = deposit64(s->eventq.base, 0, 5, SMMU_EVENTQS);
346
+ s->eventq.prod = 0;
347
+ s->eventq.cons = 0;
348
+ s->eventq.entry_size = sizeof(struct Evt);
349
+
350
+ s->features = 0;
351
+ s->sid_split = 0;
352
+}
353
+
354
+static MemTxResult smmu_write_mmio(void *opaque, hwaddr offset, uint64_t data,
355
+ unsigned size, MemTxAttrs attrs)
356
+{
357
+ /* not yet implemented */
358
+ return MEMTX_ERROR;
359
+}
360
+
361
+static MemTxResult smmu_readll(SMMUv3State *s, hwaddr offset,
362
+ uint64_t *data, MemTxAttrs attrs)
363
+{
364
+ switch (offset) {
365
+ case A_GERROR_IRQ_CFG0:
366
+ *data = s->gerror_irq_cfg0;
367
+ return MEMTX_OK;
368
+ case A_STRTAB_BASE:
369
+ *data = s->strtab_base;
370
+ return MEMTX_OK;
371
+ case A_CMDQ_BASE:
372
+ *data = s->cmdq.base;
373
+ return MEMTX_OK;
374
+ case A_EVENTQ_BASE:
375
+ *data = s->eventq.base;
376
+ return MEMTX_OK;
377
+ default:
378
+ *data = 0;
379
+ qemu_log_mask(LOG_UNIMP,
380
+ "%s Unexpected 64-bit access to 0x%"PRIx64" (RAZ)\n",
381
+ __func__, offset);
382
+ return MEMTX_OK;
383
+ }
384
+}
385
+
386
+static MemTxResult smmu_readl(SMMUv3State *s, hwaddr offset,
387
+ uint64_t *data, MemTxAttrs attrs)
388
+{
389
+ switch (offset) {
390
+ case A_IDREGS ... A_IDREGS + 0x1f:
391
+ *data = smmuv3_idreg(offset - A_IDREGS);
392
+ return MEMTX_OK;
393
+ case A_IDR0 ... A_IDR5:
394
+ *data = s->idr[(offset - A_IDR0) / 4];
395
+ return MEMTX_OK;
396
+ case A_IIDR:
397
+ *data = s->iidr;
398
+ return MEMTX_OK;
399
+ case A_CR0:
400
+ *data = s->cr[0];
401
+ return MEMTX_OK;
402
+ case A_CR0ACK:
403
+ *data = s->cr0ack;
404
+ return MEMTX_OK;
405
+ case A_CR1:
406
+ *data = s->cr[1];
407
+ return MEMTX_OK;
408
+ case A_CR2:
409
+ *data = s->cr[2];
410
+ return MEMTX_OK;
411
+ case A_STATUSR:
412
+ *data = s->statusr;
413
+ return MEMTX_OK;
414
+ case A_IRQ_CTRL:
415
+ case A_IRQ_CTRL_ACK:
416
+ *data = s->irq_ctrl;
417
+ return MEMTX_OK;
418
+ case A_GERROR:
419
+ *data = s->gerror;
420
+ return MEMTX_OK;
421
+ case A_GERRORN:
422
+ *data = s->gerrorn;
423
+ return MEMTX_OK;
424
+ case A_GERROR_IRQ_CFG0: /* 64b */
425
+ *data = extract64(s->gerror_irq_cfg0, 0, 32);
426
+ return MEMTX_OK;
427
+ case A_GERROR_IRQ_CFG0 + 4:
428
+ *data = extract64(s->gerror_irq_cfg0, 32, 32);
429
+ return MEMTX_OK;
430
+ case A_GERROR_IRQ_CFG1:
431
+ *data = s->gerror_irq_cfg1;
432
+ return MEMTX_OK;
433
+ case A_GERROR_IRQ_CFG2:
434
+ *data = s->gerror_irq_cfg2;
435
+ return MEMTX_OK;
436
+ case A_STRTAB_BASE: /* 64b */
437
+ *data = extract64(s->strtab_base, 0, 32);
438
+ return MEMTX_OK;
439
+ case A_STRTAB_BASE + 4: /* 64b */
440
+ *data = extract64(s->strtab_base, 32, 32);
441
+ return MEMTX_OK;
442
+ case A_STRTAB_BASE_CFG:
443
+ *data = s->strtab_base_cfg;
444
+ return MEMTX_OK;
445
+ case A_CMDQ_BASE: /* 64b */
446
+ *data = extract64(s->cmdq.base, 0, 32);
447
+ return MEMTX_OK;
448
+ case A_CMDQ_BASE + 4:
449
+ *data = extract64(s->cmdq.base, 32, 32);
450
+ return MEMTX_OK;
451
+ case A_CMDQ_PROD:
452
+ *data = s->cmdq.prod;
453
+ return MEMTX_OK;
454
+ case A_CMDQ_CONS:
455
+ *data = s->cmdq.cons;
456
+ return MEMTX_OK;
457
+ case A_EVENTQ_BASE: /* 64b */
458
+ *data = extract64(s->eventq.base, 0, 32);
459
+ return MEMTX_OK;
460
+ case A_EVENTQ_BASE + 4: /* 64b */
461
+ *data = extract64(s->eventq.base, 32, 32);
462
+ return MEMTX_OK;
463
+ case A_EVENTQ_PROD:
464
+ *data = s->eventq.prod;
465
+ return MEMTX_OK;
466
+ case A_EVENTQ_CONS:
467
+ *data = s->eventq.cons;
468
+ return MEMTX_OK;
469
+ default:
470
+ *data = 0;
471
+ qemu_log_mask(LOG_UNIMP,
472
+ "%s unhandled 32-bit access at 0x%"PRIx64" (RAZ)\n",
473
+ __func__, offset);
474
+ return MEMTX_OK;
475
+ }
476
+}
477
+
478
+static MemTxResult smmu_read_mmio(void *opaque, hwaddr offset, uint64_t *data,
479
+ unsigned size, MemTxAttrs attrs)
480
+{
481
+ SMMUState *sys = opaque;
482
+ SMMUv3State *s = ARM_SMMUV3(sys);
483
+ MemTxResult r;
484
+
485
+ /* CONSTRAINED UNPREDICTABLE choice to have page0/1 be exact aliases */
486
+ offset &= ~0x10000;
487
+
488
+ switch (size) {
489
+ case 8:
490
+ r = smmu_readll(s, offset, data, attrs);
491
+ break;
492
+ case 4:
493
+ r = smmu_readl(s, offset, data, attrs);
494
+ break;
495
+ default:
496
+ r = MEMTX_ERROR;
497
+ break;
498
+ }
499
+
500
+ trace_smmuv3_read_mmio(offset, *data, size, r);
501
+ return r;
502
+}
503
+
504
+static const MemoryRegionOps smmu_mem_ops = {
505
+ .read_with_attrs = smmu_read_mmio,
506
+ .write_with_attrs = smmu_write_mmio,
507
+ .endianness = DEVICE_LITTLE_ENDIAN,
508
+ .valid = {
509
+ .min_access_size = 4,
510
+ .max_access_size = 8,
511
+ },
512
+ .impl = {
513
+ .min_access_size = 4,
514
+ .max_access_size = 8,
515
+ },
516
+};
517
+
518
+static void smmu_init_irq(SMMUv3State *s, SysBusDevice *dev)
519
+{
520
+ int i;
521
+
522
+ for (i = 0; i < ARRAY_SIZE(s->irq); i++) {
523
+ sysbus_init_irq(dev, &s->irq[i]);
524
+ }
525
+}
526
+
527
+static void smmu_reset(DeviceState *dev)
528
+{
529
+ SMMUv3State *s = ARM_SMMUV3(dev);
530
+ SMMUv3Class *c = ARM_SMMUV3_GET_CLASS(s);
531
+
532
+ c->parent_reset(dev);
533
+
534
+ smmuv3_init_regs(s);
535
+}
536
+
537
+static void smmu_realize(DeviceState *d, Error **errp)
538
+{
539
+ SMMUState *sys = ARM_SMMU(d);
540
+ SMMUv3State *s = ARM_SMMUV3(sys);
541
+ SMMUv3Class *c = ARM_SMMUV3_GET_CLASS(s);
542
+ SysBusDevice *dev = SYS_BUS_DEVICE(d);
543
+ Error *local_err = NULL;
544
+
545
+ c->parent_realize(d, &local_err);
546
+ if (local_err) {
547
+ error_propagate(errp, local_err);
548
+ return;
549
+ }
550
+
551
+ memory_region_init_io(&sys->iomem, OBJECT(s),
552
+ &smmu_mem_ops, sys, TYPE_ARM_SMMUV3, 0x20000);
553
+
554
+ sys->mrtypename = TYPE_SMMUV3_IOMMU_MEMORY_REGION;
555
+
556
+ sysbus_init_mmio(dev, &sys->iomem);
557
+
558
+ smmu_init_irq(s, dev);
559
+}
560
+
561
+static const VMStateDescription vmstate_smmuv3_queue = {
562
+ .name = "smmuv3_queue",
563
+ .version_id = 1,
564
+ .minimum_version_id = 1,
565
+ .fields = (VMStateField[]) {
566
+ VMSTATE_UINT64(base, SMMUQueue),
567
+ VMSTATE_UINT32(prod, SMMUQueue),
568
+ VMSTATE_UINT32(cons, SMMUQueue),
569
+ VMSTATE_UINT8(log2size, SMMUQueue),
570
+ },
571
+};
572
+
573
+static const VMStateDescription vmstate_smmuv3 = {
574
+ .name = "smmuv3",
575
+ .version_id = 1,
576
+ .minimum_version_id = 1,
577
+ .fields = (VMStateField[]) {
578
+ VMSTATE_UINT32(features, SMMUv3State),
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
+};
603
+
604
+static void smmuv3_instance_init(Object *obj)
605
+{
606
+ /* Nothing much to do here as of now */
607
+}
608
+
609
+static void smmuv3_class_init(ObjectClass *klass, void *data)
610
+{
611
+ DeviceClass *dc = DEVICE_CLASS(klass);
612
+ SMMUv3Class *c = ARM_SMMUV3_CLASS(klass);
613
+
614
+ dc->vmsd = &vmstate_smmuv3;
615
+ device_class_set_parent_reset(dc, smmu_reset, &c->parent_reset);
616
+ c->parent_realize = dc->realize;
617
+ dc->realize = smmu_realize;
618
+}
619
+
620
+static void smmuv3_iommu_memory_region_class_init(ObjectClass *klass,
621
+ void *data)
622
+{
623
+}
624
+
625
+static const TypeInfo smmuv3_type_info = {
626
+ .name = TYPE_ARM_SMMUV3,
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
+};
633
+
634
+static const TypeInfo smmuv3_iommu_memory_region_info = {
635
+ .parent = TYPE_IOMMU_MEMORY_REGION,
636
+ .name = TYPE_SMMUV3_IOMMU_MEMORY_REGION,
637
+ .class_init = smmuv3_iommu_memory_region_class_init,
638
+};
639
+
640
+static void smmuv3_register_types(void)
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
650
--- a/hw/arm/trace-events
651
+++ b/hw/arm/trace-events
652
@@ -XXX,XX +XXX,XX @@ smmu_ptw_invalid_pte(int stage, int level, uint64_t baseaddr, uint64_t pteaddr,
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
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"
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
656
+
657
+#hw/arm/smmuv3.c
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)"
659
--
660
2.17.0
661
662
diff view generated by jsdifflib
Deleted patch
1
From: Eric Auger <eric.auger@redhat.com>
2
1
3
We introduce some helpers to handle wired IRQs and especially
4
GERROR interrupt. SMMU writes GERROR register on GERROR event
5
and SW acks GERROR interrupts by setting GERRORn.
6
7
The Wired interrupts are edge sensitive hence the pulse usage.
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
22
--- a/hw/arm/smmuv3-internal.h
23
+++ b/hw/arm/smmuv3-internal.h
24
@@ -XXX,XX +XXX,XX @@ static inline uint32_t smmuv3_idreg(int regoffset)
25
return smmuv3_ids[regoffset / 4];
26
}
27
28
+static inline bool smmuv3_eventq_irq_enabled(SMMUv3State *s)
29
+{
30
+ return FIELD_EX32(s->irq_ctrl, IRQ_CTRL, EVENTQ_IRQEN);
31
+}
32
+
33
+static inline bool smmuv3_gerror_irq_enabled(SMMUv3State *s)
34
+{
35
+ return FIELD_EX32(s->irq_ctrl, IRQ_CTRL, GERROR_IRQEN);
36
+}
37
+
38
+/* public until callers get introduced */
39
+void smmuv3_trigger_irq(SMMUv3State *s, SMMUIrq irq, uint32_t gerror_mask);
40
+void smmuv3_write_gerrorn(SMMUv3State *s, uint32_t gerrorn);
41
+
42
#endif
43
diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c
44
index XXXXXXX..XXXXXXX 100644
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
+
61
+ bool pulse = false;
62
+
63
+ switch (irq) {
64
+ case SMMU_IRQ_EVTQ:
65
+ pulse = smmuv3_eventq_irq_enabled(s);
66
+ break;
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
+ }
82
+ s->gerror ^= new_gerrors;
83
+ trace_smmuv3_write_gerror(new_gerrors, s->gerror);
84
+
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
+ }
93
+}
94
+
95
+void smmuv3_write_gerrorn(SMMUv3State *s, uint32_t new_gerrorn)
96
+{
97
+ uint32_t pending = s->gerror ^ s->gerrorn;
98
+ uint32_t toggled = s->gerrorn ^ new_gerrorn;
99
+
100
+ if (toggled & ~pending) {
101
+ qemu_log_mask(LOG_GUEST_ERROR,
102
+ "guest toggles non pending errors = 0x%x\n",
103
+ toggled & ~pending);
104
+ }
105
+
106
+ /*
107
+ * We do not raise any error in case guest toggles bits corresponding
108
+ * to not active IRQs (CONSTRAINED UNPREDICTABLE)
109
+ */
110
+ s->gerrorn = new_gerrorn;
111
+
112
+ trace_smmuv3_write_gerrorn(toggled & pending, s->gerrorn);
113
+}
114
+
115
static void smmuv3_init_regs(SMMUv3State *s)
116
{
117
/**
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
--
130
2.17.0
131
132
diff view generated by jsdifflib
1
From: Eric Auger <eric.auger@redhat.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Now we have relevant helpers for queue and irq
3
Rename from sve_zcr_get_valid_len and make accessible
4
management, let's implement MMIO write operations.
4
from outside of helper.c.
5
5
6
Signed-off-by: Eric Auger <eric.auger@redhat.com>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Prem Mallappa <prem.mallappa@broadcom.com>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Message-id: 1524665762-31355-8-git-send-email-eric.auger@redhat.com
8
Message-id: 20210723203344.968563-3-richard.henderson@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
10
---
12
hw/arm/smmuv3-internal.h | 8 +-
11
target/arm/internals.h | 10 ++++++++++
13
hw/arm/smmuv3.c | 170 +++++++++++++++++++++++++++++++++++++--
12
target/arm/helper.c | 4 ++--
14
hw/arm/trace-events | 6 ++
13
2 files changed, 12 insertions(+), 2 deletions(-)
15
3 files changed, 174 insertions(+), 10 deletions(-)
16
14
17
diff --git a/hw/arm/smmuv3-internal.h b/hw/arm/smmuv3-internal.h
15
diff --git a/target/arm/internals.h b/target/arm/internals.h
18
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/arm/smmuv3-internal.h
17
--- a/target/arm/internals.h
20
+++ b/hw/arm/smmuv3-internal.h
18
+++ b/target/arm/internals.h
21
@@ -XXX,XX +XXX,XX @@ REG32(CR0, 0x20)
19
@@ -XXX,XX +XXX,XX @@ void arm_translate_init(void);
22
FIELD(CR0, EVENTQEN, 2, 1)
20
void arm_cpu_synchronize_from_tb(CPUState *cs, const TranslationBlock *tb);
23
FIELD(CR0, CMDQEN, 3, 1)
21
#endif /* CONFIG_TCG */
24
22
25
+#define SMMU_CR0_RESERVED 0xFFFFFC20
23
+/**
26
+
24
+ * aarch64_sve_zcr_get_valid_len:
27
REG32(CR0ACK, 0x24)
25
+ * @cpu: cpu context
28
REG32(CR1, 0x28)
26
+ * @start_len: maximum len to consider
29
REG32(CR2, 0x2c)
27
+ *
30
@@ -XXX,XX +XXX,XX @@ static inline bool smmuv3_gerror_irq_enabled(SMMUv3State *s)
28
+ * Return the maximum supported sve vector length <= @start_len.
31
return FIELD_EX32(s->irq_ctrl, IRQ_CTRL, GERROR_IRQEN);
29
+ * Note that both @start_len and the return value are in units
32
}
30
+ * of ZCR_ELx.LEN, so the vector bit length is (x + 1) * 128.
33
31
+ */
34
-/* public until callers get introduced */
32
+uint32_t aarch64_sve_zcr_get_valid_len(ARMCPU *cpu, uint32_t start_len);
35
-void smmuv3_trigger_irq(SMMUv3State *s, SMMUIrq irq, uint32_t gerror_mask);
33
36
-void smmuv3_write_gerrorn(SMMUv3State *s, uint32_t gerrorn);
34
enum arm_fprounding {
37
-
35
FPROUNDING_TIEEVEN,
38
/* Queue Handling */
36
diff --git a/target/arm/helper.c b/target/arm/helper.c
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
48
#endif
49
diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c
50
index XXXXXXX..XXXXXXX 100644
37
index XXXXXXX..XXXXXXX 100644
51
--- a/hw/arm/smmuv3.c
38
--- a/target/arm/helper.c
52
+++ b/hw/arm/smmuv3.c
39
+++ b/target/arm/helper.c
53
@@ -XXX,XX +XXX,XX @@
40
@@ -XXX,XX +XXX,XX @@ int sve_exception_el(CPUARMState *env, int el)
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;
41
return 0;
83
}
42
}
84
43
85
+static MemTxResult smmu_writell(SMMUv3State *s, hwaddr offset,
44
-static uint32_t sve_zcr_get_valid_len(ARMCPU *cpu, uint32_t start_len)
86
+ uint64_t data, MemTxAttrs attrs)
45
+uint32_t aarch64_sve_zcr_get_valid_len(ARMCPU *cpu, uint32_t start_len)
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
{
46
{
228
- /* not yet implemented */
47
uint32_t end_len;
229
- return MEMTX_ERROR;
48
230
+ SMMUState *sys = opaque;
49
@@ -XXX,XX +XXX,XX @@ uint32_t sve_zcr_len_for_el(CPUARMState *env, int el)
231
+ SMMUv3State *s = ARM_SMMUV3(sys);
50
zcr_len = MIN(zcr_len, 0xf & (uint32_t)env->vfp.zcr_el[3]);
232
+ MemTxResult r;
51
}
233
+
52
234
+ /* CONSTRAINED UNPREDICTABLE choice to have page0/1 be exact aliases */
53
- return sve_zcr_get_valid_len(cpu, zcr_len);
235
+ offset &= ~0x10000;
54
+ return aarch64_sve_zcr_get_valid_len(cpu, zcr_len);
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
}
55
}
252
56
253
static MemTxResult smmu_readll(SMMUv3State *s, hwaddr offset,
57
static void zcr_write(CPUARMState *env, const ARMCPRegInfo *ri,
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
--
58
--
269
2.17.0
59
2.20.1
270
60
271
61
diff view generated by jsdifflib
1
From: Eric Auger <eric.auger@redhat.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
We introduce helpers to read/write into the command and event
3
Mirror the behavour of /proc/sys/abi/sve_default_vector_length
4
circular queues.
4
under the real linux kernel. We have no way of passing along
5
a real default across exec like the kernel can, but this is a
6
decent way of adjusting the startup vector length of a process.
5
7
6
smmuv3_write_eventq and smmuv3_cmq_consume will become static
8
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/482
7
in subsequent patches.
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
9
Invalidation commands are not yet dealt with. We do not cache
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>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
16
Message-id: 1524665762-31355-7-git-send-email-eric.auger@redhat.com
11
Message-id: 20210723203344.968563-4-richard.henderson@linaro.org
12
[PMM: tweaked docs formatting, document -1 special-case,
13
added fixup patch from RTH mentioning QEMU's maximum veclen.]
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
---
15
---
19
hw/arm/smmuv3-internal.h | 163 +++++++++++++++++++++++++++++++++++++++
16
docs/system/arm/cpu-features.rst | 15 ++++++++
20
hw/arm/smmuv3.c | 136 ++++++++++++++++++++++++++++++++
17
target/arm/cpu.h | 5 +++
21
hw/arm/trace-events | 5 ++
18
target/arm/cpu.c | 14 ++++++--
22
3 files changed, 304 insertions(+)
19
target/arm/cpu64.c | 60 ++++++++++++++++++++++++++++++++
20
4 files changed, 92 insertions(+), 2 deletions(-)
23
21
24
diff --git a/hw/arm/smmuv3-internal.h b/hw/arm/smmuv3-internal.h
22
diff --git a/docs/system/arm/cpu-features.rst b/docs/system/arm/cpu-features.rst
25
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
26
--- a/hw/arm/smmuv3-internal.h
24
--- a/docs/system/arm/cpu-features.rst
27
+++ b/hw/arm/smmuv3-internal.h
25
+++ b/docs/system/arm/cpu-features.rst
28
@@ -XXX,XX +XXX,XX @@ static inline bool smmuv3_gerror_irq_enabled(SMMUv3State *s)
26
@@ -XXX,XX +XXX,XX @@ verbose command lines. However, the recommended way to select vector
29
void smmuv3_trigger_irq(SMMUv3State *s, SMMUIrq irq, uint32_t gerror_mask);
27
lengths is to explicitly enable each desired length. Therefore only
30
void smmuv3_write_gerrorn(SMMUv3State *s, uint32_t gerrorn);
28
example's (1), (4), and (6) exhibit recommended uses of the properties.
31
29
32
+/* Queue Handling */
30
+SVE User-mode Default Vector Length Property
31
+--------------------------------------------
33
+
32
+
34
+#define Q_BASE(q) ((q)->base & SMMU_BASE_ADDR_MASK)
33
+For qemu-aarch64, the cpu property ``sve-default-vector-length=N`` is
35
+#define WRAP_MASK(q) (1 << (q)->log2size)
34
+defined to mirror the Linux kernel parameter file
36
+#define INDEX_MASK(q) (((1 << (q)->log2size)) - 1)
35
+``/proc/sys/abi/sve_default_vector_length``. The default length, ``N``,
37
+#define WRAP_INDEX_MASK(q) ((1 << ((q)->log2size + 1)) - 1)
36
+is in units of bytes and must be between 16 and 8192.
37
+If not specified, the default vector length is 64.
38
+
38
+
39
+#define Q_CONS(q) ((q)->cons & INDEX_MASK(q))
39
+If the default length is larger than the maximum vector length enabled,
40
+#define Q_PROD(q) ((q)->prod & INDEX_MASK(q))
40
+the actual vector length will be reduced. Note that the maximum vector
41
+length supported by QEMU is 256.
41
+
42
+
42
+#define Q_CONS_ENTRY(q) (Q_BASE(q) + (q)->entry_size * Q_CONS(q))
43
+If this property is set to ``-1`` then the default vector length
43
+#define Q_PROD_ENTRY(q) (Q_BASE(q) + (q)->entry_size * Q_PROD(q))
44
+is set to the maximum possible length.
45
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
46
index XXXXXXX..XXXXXXX 100644
47
--- a/target/arm/cpu.h
48
+++ b/target/arm/cpu.h
49
@@ -XXX,XX +XXX,XX @@ struct ARMCPU {
50
/* Used to set the maximum vector length the cpu will support. */
51
uint32_t sve_max_vq;
52
53
+#ifdef CONFIG_USER_ONLY
54
+ /* Used to set the default vector length at process start. */
55
+ uint32_t sve_default_vq;
56
+#endif
44
+
57
+
45
+#define Q_CONS_WRAP(q) (((q)->cons & WRAP_MASK(q)) >> (q)->log2size)
58
/*
46
+#define Q_PROD_WRAP(q) (((q)->prod & WRAP_MASK(q)) >> (q)->log2size)
59
* In sve_vq_map each set bit is a supported vector length of
60
* (bit-number + 1) * 16 bytes, i.e. each bit number + 1 is the vector
61
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
62
index XXXXXXX..XXXXXXX 100644
63
--- a/target/arm/cpu.c
64
+++ b/target/arm/cpu.c
65
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_reset(DeviceState *dev)
66
env->cp15.cpacr_el1 = deposit64(env->cp15.cpacr_el1, 16, 2, 3);
67
/* with reasonable vector length */
68
if (cpu_isar_feature(aa64_sve, cpu)) {
69
- env->vfp.zcr_el[1] = MIN(cpu->sve_max_vq - 1, 3);
70
+ env->vfp.zcr_el[1] =
71
+ aarch64_sve_zcr_get_valid_len(cpu, cpu->sve_default_vq - 1);
72
}
73
/*
74
* Enable TBI0 but not TBI1.
75
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_initfn(Object *obj)
76
QLIST_INIT(&cpu->pre_el_change_hooks);
77
QLIST_INIT(&cpu->el_change_hooks);
78
79
-#ifndef CONFIG_USER_ONLY
80
+#ifdef CONFIG_USER_ONLY
81
+# ifdef TARGET_AARCH64
82
+ /*
83
+ * The linux kernel defaults to 512-bit vectors, when sve is supported.
84
+ * See documentation for /proc/sys/abi/sve_default_vector_length, and
85
+ * our corresponding sve-default-vector-length cpu property.
86
+ */
87
+ cpu->sve_default_vq = 4;
88
+# endif
89
+#else
90
/* Our inbound IRQ and FIQ lines */
91
if (kvm_enabled()) {
92
/* VIRQ and VFIQ are unused with KVM but we add them to maintain
93
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
94
index XXXXXXX..XXXXXXX 100644
95
--- a/target/arm/cpu64.c
96
+++ b/target/arm/cpu64.c
97
@@ -XXX,XX +XXX,XX @@ static void cpu_arm_set_sve(Object *obj, bool value, Error **errp)
98
cpu->isar.id_aa64pfr0 = t;
99
}
100
101
+#ifdef CONFIG_USER_ONLY
102
+/* Mirror linux /proc/sys/abi/sve_default_vector_length. */
103
+static void cpu_arm_set_sve_default_vec_len(Object *obj, Visitor *v,
104
+ const char *name, void *opaque,
105
+ Error **errp)
106
+{
107
+ ARMCPU *cpu = ARM_CPU(obj);
108
+ int32_t default_len, default_vq, remainder;
47
+
109
+
48
+static inline bool smmuv3_q_full(SMMUQueue *q)
110
+ if (!visit_type_int32(v, name, &default_len, errp)) {
49
+{
50
+ return ((q->cons ^ q->prod) & WRAP_INDEX_MASK(q)) == WRAP_MASK(q);
51
+}
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
+ }
220
+
221
+ queue_prod_incr(q);
222
+ return MEMTX_OK;
223
+}
224
+
225
+void smmuv3_write_eventq(SMMUv3State *s, Evt *evt)
226
+{
227
+ SMMUQueue *q = &s->eventq;
228
+
229
+ if (!smmuv3_eventq_enabled(s)) {
230
+ return;
111
+ return;
231
+ }
112
+ }
232
+
113
+
233
+ if (smmuv3_q_full(q)) {
114
+ /* Undocumented, but the kernel allows -1 to indicate "maximum". */
115
+ if (default_len == -1) {
116
+ cpu->sve_default_vq = ARM_MAX_VQ;
234
+ return;
117
+ return;
235
+ }
118
+ }
236
+
119
+
237
+ queue_write(q, evt);
120
+ default_vq = default_len / 16;
121
+ remainder = default_len % 16;
238
+
122
+
239
+ if (smmuv3_q_empty(q)) {
123
+ /*
240
+ smmuv3_trigger_irq(s, SMMU_IRQ_EVTQ, 0);
124
+ * Note that the 512 max comes from include/uapi/asm/sve_context.h
125
+ * and is the maximum architectural width of ZCR_ELx.LEN.
126
+ */
127
+ if (remainder || default_vq < 1 || default_vq > 512) {
128
+ error_setg(errp, "cannot set sve-default-vector-length");
129
+ if (remainder) {
130
+ error_append_hint(errp, "Vector length not a multiple of 16\n");
131
+ } else if (default_vq < 1) {
132
+ error_append_hint(errp, "Vector length smaller than 16\n");
133
+ } else {
134
+ error_append_hint(errp, "Vector length larger than %d\n",
135
+ 512 * 16);
136
+ }
137
+ return;
241
+ }
138
+ }
139
+
140
+ cpu->sve_default_vq = default_vq;
242
+}
141
+}
243
+
142
+
244
static void smmuv3_init_regs(SMMUv3State *s)
143
+static void cpu_arm_get_sve_default_vec_len(Object *obj, Visitor *v,
144
+ const char *name, void *opaque,
145
+ Error **errp)
146
+{
147
+ ARMCPU *cpu = ARM_CPU(obj);
148
+ int32_t value = cpu->sve_default_vq * 16;
149
+
150
+ visit_type_int32(v, name, &value, errp);
151
+}
152
+#endif
153
+
154
void aarch64_add_sve_properties(Object *obj)
245
{
155
{
246
/**
156
uint32_t vq;
247
@@ -XXX,XX +XXX,XX @@ static void smmuv3_init_regs(SMMUv3State *s)
157
@@ -XXX,XX +XXX,XX @@ void aarch64_add_sve_properties(Object *obj)
248
s->sid_split = 0;
158
object_property_add(obj, name, "bool", cpu_arm_get_sve_vq,
159
cpu_arm_set_sve_vq, NULL, NULL);
160
}
161
+
162
+#ifdef CONFIG_USER_ONLY
163
+ /* Mirror linux /proc/sys/abi/sve_default_vector_length. */
164
+ object_property_add(obj, "sve-default-vector-length", "int32",
165
+ cpu_arm_get_sve_default_vec_len,
166
+ cpu_arm_set_sve_default_vec_len, NULL, NULL);
167
+#endif
249
}
168
}
250
169
251
+int smmuv3_cmdq_consume(SMMUv3State *s)
170
void arm_cpu_pauth_finalize(ARMCPU *cpu, Error **errp)
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
--
171
--
364
2.17.0
172
2.20.1
365
173
366
174
diff view generated by jsdifflib
1
From: Eric Auger <eric.auger@redhat.com>
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
2
3
Let's introduce a helper function aiming at recording an
3
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
4
event in the event queue.
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
5
Message-id: 20210726150953.1218690-1-f4bug@amsat.org
6
Signed-off-by: Eric Auger <eric.auger@redhat.com>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Message-id: 1524665762-31355-9-git-send-email-eric.auger@redhat.com
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
7
---
11
hw/arm/smmuv3-internal.h | 148 ++++++++++++++++++++++++++++++++++++++-
8
hw/arm/nseries.c | 2 +-
12
hw/arm/smmuv3.c | 108 ++++++++++++++++++++++++++--
9
1 file changed, 1 insertion(+), 1 deletion(-)
13
hw/arm/trace-events | 1 +
14
3 files changed, 249 insertions(+), 8 deletions(-)
15
10
16
diff --git a/hw/arm/smmuv3-internal.h b/hw/arm/smmuv3-internal.h
11
diff --git a/hw/arm/nseries.c b/hw/arm/nseries.c
17
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/arm/smmuv3-internal.h
13
--- a/hw/arm/nseries.c
19
+++ b/hw/arm/smmuv3-internal.h
14
+++ b/hw/arm/nseries.c
20
@@ -XXX,XX +XXX,XX @@ static inline void smmu_write_cmdq_err(SMMUv3State *s, uint32_t err_type)
15
@@ -XXX,XX +XXX,XX @@ static uint32_t mipid_txrx(void *opaque, uint32_t cmd, int len)
21
s->cmdq.cons = FIELD_DP32(s->cmdq.cons, CMDQ_CONS, ERR, err_type);
16
default:
22
}
17
bad_cmd:
23
18
qemu_log_mask(LOG_GUEST_ERROR,
24
-void smmuv3_write_eventq(SMMUv3State *s, Evt *evt);
19
- "%s: unknown command %02x\n", __func__, s->cmd);
25
-
20
+ "%s: unknown command 0x%02x\n", __func__, s->cmd);
26
/* Commands */
21
break;
27
28
typedef enum SMMUCommandType {
29
@@ -XXX,XX +XXX,XX @@ enum { /* Command completion notification */
30
31
#define SMMU_FEATURE_2LVL_STE (1 << 0)
32
33
+/* Events */
34
+
35
+typedef enum SMMUEventType {
36
+ SMMU_EVT_OK = 0x00,
37
+ SMMU_EVT_F_UUT ,
38
+ SMMU_EVT_C_BAD_STREAMID ,
39
+ SMMU_EVT_F_STE_FETCH ,
40
+ SMMU_EVT_C_BAD_STE ,
41
+ SMMU_EVT_F_BAD_ATS_TREQ ,
42
+ SMMU_EVT_F_STREAM_DISABLED ,
43
+ SMMU_EVT_F_TRANS_FORBIDDEN ,
44
+ SMMU_EVT_C_BAD_SUBSTREAMID ,
45
+ SMMU_EVT_F_CD_FETCH ,
46
+ SMMU_EVT_C_BAD_CD ,
47
+ SMMU_EVT_F_WALK_EABT ,
48
+ SMMU_EVT_F_TRANSLATION = 0x10,
49
+ SMMU_EVT_F_ADDR_SIZE ,
50
+ SMMU_EVT_F_ACCESS ,
51
+ SMMU_EVT_F_PERMISSION ,
52
+ SMMU_EVT_F_TLB_CONFLICT = 0x20,
53
+ SMMU_EVT_F_CFG_CONFLICT ,
54
+ SMMU_EVT_E_PAGE_REQ = 0x24,
55
+} SMMUEventType;
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
+{
81
+ if (type < ARRAY_SIZE(event_stringify)) {
82
+ return event_stringify[type] ? event_stringify[type] : "UNKNOWN";
83
+ } else {
84
+ return "INVALID";
85
+ }
86
+}
87
+
88
+/* Encode an event record */
89
+typedef struct SMMUEventInfo {
90
+ SMMUEventType type;
91
+ uint32_t sid;
92
+ bool recorded;
93
+ bool record_trans_faults;
94
+ union {
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;
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
+ }
210
+ return MEMTX_OK;
211
+}
212
+
213
+void smmuv3_record_event(SMMUv3State *s, SMMUEventInfo *info)
214
+{
215
+ Evt evt;
216
+ MemTxResult r;
217
218
if (!smmuv3_eventq_enabled(s)) {
219
return;
220
}
22
}
221
23
222
- if (smmuv3_q_full(q)) {
223
+ EVT_SET_TYPE(&evt, info->type);
224
+ EVT_SET_SID(&evt, info->sid);
225
+
226
+ switch (info->type) {
227
+ case SMMU_EVT_OK:
228
return;
229
+ case SMMU_EVT_F_UUT:
230
+ EVT_SET_SSID(&evt, info->u.f_uut.ssid);
231
+ EVT_SET_SSV(&evt, info->u.f_uut.ssv);
232
+ EVT_SET_ADDR(&evt, info->u.f_uut.addr);
233
+ EVT_SET_RNW(&evt, info->u.f_uut.rnw);
234
+ EVT_SET_PNU(&evt, info->u.f_uut.pnu);
235
+ EVT_SET_IND(&evt, info->u.f_uut.ind);
236
+ break;
237
+ case SMMU_EVT_C_BAD_STREAMID:
238
+ EVT_SET_SSID(&evt, info->u.c_bad_streamid.ssid);
239
+ EVT_SET_SSV(&evt, info->u.c_bad_streamid.ssv);
240
+ break;
241
+ case SMMU_EVT_F_STE_FETCH:
242
+ EVT_SET_SSID(&evt, info->u.f_ste_fetch.ssid);
243
+ EVT_SET_SSV(&evt, info->u.f_ste_fetch.ssv);
244
+ EVT_SET_ADDR(&evt, info->u.f_ste_fetch.addr);
245
+ break;
246
+ case SMMU_EVT_C_BAD_STE:
247
+ EVT_SET_SSID(&evt, info->u.c_bad_ste.ssid);
248
+ EVT_SET_SSV(&evt, info->u.c_bad_ste.ssv);
249
+ break;
250
+ case SMMU_EVT_F_STREAM_DISABLED:
251
+ break;
252
+ case SMMU_EVT_F_TRANS_FORBIDDEN:
253
+ EVT_SET_ADDR(&evt, info->u.f_transl_forbidden.addr);
254
+ EVT_SET_RNW(&evt, info->u.f_transl_forbidden.rnw);
255
+ break;
256
+ case SMMU_EVT_C_BAD_SUBSTREAMID:
257
+ EVT_SET_SSID(&evt, info->u.c_bad_substream.ssid);
258
+ break;
259
+ case SMMU_EVT_F_CD_FETCH:
260
+ EVT_SET_SSID(&evt, info->u.f_cd_fetch.ssid);
261
+ EVT_SET_SSV(&evt, info->u.f_cd_fetch.ssv);
262
+ EVT_SET_ADDR(&evt, info->u.f_cd_fetch.addr);
263
+ break;
264
+ case SMMU_EVT_C_BAD_CD:
265
+ EVT_SET_SSID(&evt, info->u.c_bad_cd.ssid);
266
+ EVT_SET_SSV(&evt, info->u.c_bad_cd.ssv);
267
+ break;
268
+ case SMMU_EVT_F_WALK_EABT:
269
+ case SMMU_EVT_F_TRANSLATION:
270
+ case SMMU_EVT_F_ADDR_SIZE:
271
+ case SMMU_EVT_F_ACCESS:
272
+ case SMMU_EVT_F_PERMISSION:
273
+ EVT_SET_STALL(&evt, info->u.f_walk_eabt.stall);
274
+ EVT_SET_STAG(&evt, info->u.f_walk_eabt.stag);
275
+ EVT_SET_SSID(&evt, info->u.f_walk_eabt.ssid);
276
+ EVT_SET_SSV(&evt, info->u.f_walk_eabt.ssv);
277
+ EVT_SET_S2(&evt, info->u.f_walk_eabt.s2);
278
+ EVT_SET_ADDR(&evt, info->u.f_walk_eabt.addr);
279
+ EVT_SET_RNW(&evt, info->u.f_walk_eabt.rnw);
280
+ EVT_SET_PNU(&evt, info->u.f_walk_eabt.pnu);
281
+ EVT_SET_IND(&evt, info->u.f_walk_eabt.ind);
282
+ EVT_SET_CLASS(&evt, info->u.f_walk_eabt.class);
283
+ EVT_SET_ADDR2(&evt, info->u.f_walk_eabt.addr2);
284
+ break;
285
+ case SMMU_EVT_F_CFG_CONFLICT:
286
+ EVT_SET_SSID(&evt, info->u.f_cfg_conflict.ssid);
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
}
296
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
--
24
--
320
2.17.0
25
2.20.1
321
26
322
27
diff view generated by jsdifflib
1
From: Eric Auger <eric.auger@redhat.com>
1
From: Joel Stanley <joel@jms.id.au>
2
2
3
ARM virt machine now exposes a new "iommu" option.
3
The macro used to calculate the maximum memory size of the MMIO region
4
The SMMUv3 IOMMU is instantiated using -machine virt,iommu=smmuv3.
4
had a mistake, causing all GPIO models to create a mapping of 0x9D8.
5
The intent was to have it be 0x9D8 - 0x800.
5
6
6
Signed-off-by: Eric Auger <eric.auger@redhat.com>
7
This extra size doesn't matter on ast2400 and ast2500, which have a 4KB
7
Signed-off-by: Prem Mallappa <prem.mallappa@broadcom.com>
8
region set aside for the GPIO controller.
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
9
Message-id: 1524665762-31355-15-git-send-email-eric.auger@redhat.com
10
On the ast2600 the 3.3V and 1.8V GPIO controllers are 2KB apart, so the
11
regions would overlap. Worse was the 1.8V controller would map over the
12
top of the following peripheral, which happens to be the RTC.
13
14
The mmio region used by each device is a maximum of 2KB, so avoid the
15
calculations and hard code this as the maximum.
16
17
Fixes: 36d737ee82b2 ("hw/gpio: Add in AST2600 specific implementation")
18
Signed-off-by: Joel Stanley <joel@jms.id.au>
19
Reviewed-by: Rashmica Gupta <rashmica.g@gmail.com>
20
Reviewed-by: Cédric Le Goater <clg@kaod.org>
21
Message-id: 20210713065854.134634-2-joel@jms.id.au
22
[PMM: fix autocorrect error in commit message]
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
23
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
24
---
12
hw/arm/virt.c | 36 ++++++++++++++++++++++++++++++++++++
25
hw/gpio/aspeed_gpio.c | 3 +--
13
1 file changed, 36 insertions(+)
26
1 file changed, 1 insertion(+), 2 deletions(-)
14
27
15
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
28
diff --git a/hw/gpio/aspeed_gpio.c b/hw/gpio/aspeed_gpio.c
16
index XXXXXXX..XXXXXXX 100644
29
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/arm/virt.c
30
--- a/hw/gpio/aspeed_gpio.c
18
+++ b/hw/arm/virt.c
31
+++ b/hw/gpio/aspeed_gpio.c
19
@@ -XXX,XX +XXX,XX @@ static void virt_set_gic_version(Object *obj, const char *value, Error **errp)
32
@@ -XXX,XX +XXX,XX @@
33
#define GPIO_1_8V_MEM_SIZE 0x9D8
34
#define GPIO_1_8V_REG_ARRAY_SIZE ((GPIO_1_8V_MEM_SIZE - \
35
GPIO_1_8V_REG_OFFSET) >> 2)
36
-#define GPIO_MAX_MEM_SIZE MAX(GPIO_3_6V_MEM_SIZE, GPIO_1_8V_MEM_SIZE)
37
38
static int aspeed_evaluate_irq(GPIOSets *regs, int gpio_prev_high, int gpio)
39
{
40
@@ -XXX,XX +XXX,XX @@ static void aspeed_gpio_realize(DeviceState *dev, Error **errp)
20
}
41
}
21
}
42
22
43
memory_region_init_io(&s->iomem, OBJECT(s), &aspeed_gpio_ops, s,
23
+static char *virt_get_iommu(Object *obj, Error **errp)
44
- TYPE_ASPEED_GPIO, GPIO_MAX_MEM_SIZE);
24
+{
45
+ TYPE_ASPEED_GPIO, 0x800);
25
+ VirtMachineState *vms = VIRT_MACHINE(obj);
46
26
+
47
sysbus_init_mmio(sbd, &s->iomem);
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
}
57
58
+ /* Default disallows iommu instantiation */
59
+ vms->iommu = VIRT_IOMMU_NONE;
60
+ object_property_add_str(obj, "iommu", virt_get_iommu, virt_set_iommu, NULL);
61
+ object_property_set_description(obj, "iommu",
62
+ "Set the IOMMU type. "
63
+ "Valid values are none and smmuv3",
64
+ NULL);
65
+
66
vms->memmap = a15memmap;
67
vms->irqmap = a15irqmap;
68
}
48
}
69
--
49
--
70
2.17.0
50
2.20.1
71
51
72
52
diff view generated by jsdifflib