1
target-arm queue: Eric's SMMUv3 patchset, and an array
1
Nothing too exciting, but does include the last bits of v8.1M support work.
2
of minor bugfixes and improvements from various others.
3
2
4
thanks
5
-- PMM
3
-- PMM
6
4
7
The following changes since commit c8b7e627b4269a3bc3ae41d9f420547a47e6d9b9:
5
The following changes since commit e79de63ab1bd1f6550e7b915e433bec1ad1a870a:
8
6
9
Merge remote-tracking branch 'remotes/ericb/tags/pull-nbd-2018-05-04' into staging (2018-05-04 14:42:46 +0100)
7
Merge remote-tracking branch 'remotes/rth-gitlab/tags/pull-tcg-20210107' into staging (2021-01-07 20:34:05 +0000)
10
8
11
are available in the Git repository at:
9
are available in the Git repository at:
12
10
13
git://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20180504
11
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20210108
14
12
15
for you to fetch changes up to 5680740c92993e9b3f3e011f2a2c394070e33f56:
13
for you to fetch changes up to c9f8511ea8d2b80723af0fea1f716d752c1b5208:
16
14
17
hw/arm/virt: Introduce the iommu option (2018-05-04 18:05:52 +0100)
15
docs/system: arm: Add sabrelite board description (2021-01-08 15:13:39 +0000)
18
16
19
----------------------------------------------------------------
17
----------------------------------------------------------------
20
target-arm queue:
18
target-arm queue:
21
* Emulate the SMMUv3 (IOMMU); one will be created in the 'virt' board
19
* intc/arm_gic: Fix gic_irq_signaling_enabled() for vCPUs
22
if the commandline includes "-machine iommu=smmuv3"
20
* target/arm: Fix MTE0_ACTIVE
23
* target/arm: Implement v8M VLLDM and VLSTM
21
* target/arm: Implement v8.1M and Cortex-M55 model
24
* hw/arm: Don't fail qtest due to missing SD card in -nodefaults mode
22
* hw/arm/highbank: Drop dead KVM support code
25
* Some fixes to silence Coverity false-positives
23
* util/qemu-timer: Make timer_free() imply timer_del()
26
* arm: boot: set boot_info starting from first_cpu
24
* various devices: Use ptimer_free() in finalize function
27
(fixes a technical bug not visible in practice)
25
* docs/system: arm: Add sabrelite board description
28
* hw/net/smc91c111: Convert away from old_mmio
26
* sabrelite: Minor fixes to allow booting U-Boot
29
* hw/usb/tusb6010: Convert away from old_mmio
30
* hw/char/cmsdk-apb-uart.c: Accept more input after character read
31
* target/arm: Make MPUIR write-ignored on OMAP, StrongARM
32
* hw/arm/virt: Add linux,pci-domain property
33
27
34
----------------------------------------------------------------
28
----------------------------------------------------------------
35
Eric Auger (11):
29
Andrew Jones (1):
36
hw/arm/smmu-common: smmu base device and datatypes
30
hw/arm/virt: Remove virt machine state 'smp_cpus'
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
31
48
Igor Mammedov (1):
32
Bin Meng (4):
49
arm: boot: set boot_info starting from first_cpu
33
hw/misc: imx6_ccm: Update PMU_MISC0 reset value
34
hw/msic: imx6_ccm: Correct register value for silicon type
35
hw/arm: sabrelite: Connect the Ethernet PHY at address 6
36
docs/system: arm: Add sabrelite board description
50
37
51
Jan Kiszka (1):
38
Edgar E. Iglesias (1):
52
hw/arm/virt: Add linux,pci-domain property
39
intc/arm_gic: Fix gic_irq_signaling_enabled() for vCPUs
53
40
54
Mathew Maidment (1):
41
Gan Qixin (7):
55
target/arm: Correct MPUIR privilege level in register_cp_regs_for_features() conditional case
42
digic-timer: Use ptimer_free() in the finalize function to avoid memleaks
43
allwinner-a10-pit: Use ptimer_free() in the finalize function to avoid memleaks
44
exynos4210_rtc: Use ptimer_free() in the finalize function to avoid memleaks
45
exynos4210_pwm: Use ptimer_free() in the finalize function to avoid memleaks
46
mss-timer: Use ptimer_free() in the finalize function to avoid memleaks
47
musicpal: Use ptimer_free() in the finalize function to avoid memleaks
48
exynos4210_mct: Use ptimer_free() in the finalize function to avoid memleaks
56
49
57
Patrick Oppenlander (1):
50
Peter Maydell (9):
58
hw/char/cmsdk-apb-uart.c: Accept more input after character read
51
hw/intc/armv7m_nvic: Correct handling of CCR.BFHFNMIGN
52
target/arm: Correct store of FPSCR value via FPCXT_S
53
target/arm: Implement FPCXT_NS fp system register
54
target/arm: Implement Cortex-M55 model
55
hw/arm/highbank: Drop dead KVM support code
56
util/qemu-timer: Make timer_free() imply timer_del()
57
scripts/coccinelle: New script to remove unnecessary timer_del() calls
58
Remove superfluous timer_del() calls
59
target/arm: Remove timer_del()/timer_deinit() before timer_free()
59
60
60
Peter Maydell (3):
61
Richard Henderson (1):
61
hw/usb/tusb6010: Convert away from old_mmio
62
target/arm: Fix MTE0_ACTIVE
62
hw/net/smc91c111: Convert away from old_mmio
63
target/arm: Implement v8M VLLDM and VLSTM
64
63
65
Prem Mallappa (3):
64
docs/system/arm/sabrelite.rst | 119 ++++++++++++++++++++++++++
66
hw/arm/smmuv3: Skeleton
65
docs/system/target-arm.rst | 1 +
67
hw/arm/virt: Add SMMUv3 to the virt board
66
scripts/coccinelle/timer-del-timer-free.cocci | 18 ++++
68
hw/arm/virt-acpi-build: Add smmuv3 node in IORT table
67
include/hw/arm/virt.h | 3 +-
68
include/qemu/timer.h | 24 +++---
69
block/iscsi.c | 2 -
70
block/nbd.c | 1 -
71
block/qcow2.c | 1 -
72
hw/arm/highbank.c | 14 +--
73
hw/arm/musicpal.c | 12 +++
74
hw/arm/sabrelite.c | 4 +
75
hw/arm/virt-acpi-build.c | 9 +-
76
hw/arm/virt.c | 21 +++--
77
hw/block/nvme.c | 2 -
78
hw/char/serial.c | 2 -
79
hw/char/virtio-serial-bus.c | 2 -
80
hw/ide/core.c | 1 -
81
hw/input/hid.c | 1 -
82
hw/intc/apic.c | 1 -
83
hw/intc/arm_gic.c | 4 +-
84
hw/intc/armv7m_nvic.c | 15 ++++
85
hw/intc/ioapic.c | 1 -
86
hw/ipmi/ipmi_bmc_extern.c | 1 -
87
hw/misc/imx6_ccm.c | 4 +-
88
hw/net/e1000.c | 3 -
89
hw/net/e1000e_core.c | 8 --
90
hw/net/pcnet-pci.c | 1 -
91
hw/net/rtl8139.c | 1 -
92
hw/net/spapr_llan.c | 1 -
93
hw/net/virtio-net.c | 2 -
94
hw/rtc/exynos4210_rtc.c | 9 ++
95
hw/s390x/s390-pci-inst.c | 1 -
96
hw/sd/sd.c | 1 -
97
hw/sd/sdhci.c | 2 -
98
hw/timer/allwinner-a10-pit.c | 11 +++
99
hw/timer/digic-timer.c | 8 ++
100
hw/timer/exynos4210_mct.c | 14 +++
101
hw/timer/exynos4210_pwm.c | 11 +++
102
hw/timer/mss-timer.c | 13 +++
103
hw/usb/dev-hub.c | 1 -
104
hw/usb/hcd-ehci.c | 1 -
105
hw/usb/hcd-ohci-pci.c | 1 -
106
hw/usb/hcd-uhci.c | 1 -
107
hw/usb/hcd-xhci.c | 1 -
108
hw/usb/redirect.c | 1 -
109
hw/vfio/display.c | 1 -
110
hw/virtio/vhost-vsock-common.c | 1 -
111
hw/virtio/virtio-balloon.c | 1 -
112
hw/virtio/virtio-rng.c | 1 -
113
hw/watchdog/wdt_diag288.c | 1 -
114
hw/watchdog/wdt_i6300esb.c | 1 -
115
migration/colo.c | 1 -
116
monitor/hmp-cmds.c | 1 -
117
net/announce.c | 1 -
118
net/colo-compare.c | 1 -
119
net/slirp.c | 1 -
120
replay/replay-debugging.c | 1 -
121
target/arm/cpu.c | 2 -
122
target/arm/cpu_tcg.c | 42 +++++++++
123
target/arm/helper.c | 2 +-
124
target/s390x/cpu.c | 2 -
125
ui/console.c | 1 -
126
ui/spice-core.c | 1 -
127
util/throttle.c | 1 -
128
target/arm/translate-vfp.c.inc | 114 ++++++++++++++++++++++--
129
65 files changed, 421 insertions(+), 111 deletions(-)
130
create mode 100644 docs/system/arm/sabrelite.rst
131
create mode 100644 scripts/coccinelle/timer-del-timer-free.cocci
69
132
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: Prem Mallappa <prem.mallappa@broadcom.com>
1
From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>
2
2
3
This patch builds the smmuv3 node in the ACPI IORT table.
3
Correct the indexing into s->cpu_ctlr for vCPUs.
4
4
5
The RID space of the root complex, which spans 0x0-0x10000
5
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
6
maps to streamid space 0x0-0x10000 in smmuv3, which in turn
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
maps to deviceid space 0x0-0x10000 in the ITS group.
7
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
8
8
Message-id: 20201214222154.3480243-2-edgar.iglesias@gmail.com
9
The guest must feature the IOMMU probe deferral series
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>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
---
10
---
19
include/hw/acpi/acpi-defs.h | 15 ++++++++++
11
hw/intc/arm_gic.c | 4 +++-
20
hw/arm/virt-acpi-build.c | 55 ++++++++++++++++++++++++++++++++-----
12
1 file changed, 3 insertions(+), 1 deletion(-)
21
2 files changed, 63 insertions(+), 7 deletions(-)
22
13
23
diff --git a/include/hw/acpi/acpi-defs.h b/include/hw/acpi/acpi-defs.h
14
diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c
24
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
25
--- a/include/hw/acpi/acpi-defs.h
16
--- a/hw/intc/arm_gic.c
26
+++ b/include/hw/acpi/acpi-defs.h
17
+++ b/hw/intc/arm_gic.c
27
@@ -XXX,XX +XXX,XX @@ struct AcpiIortItsGroup {
18
@@ -XXX,XX +XXX,XX @@ static inline void gic_get_best_virq(GICState *s, int cpu,
28
} QEMU_PACKED;
19
static inline bool gic_irq_signaling_enabled(GICState *s, int cpu, bool virt,
29
typedef struct AcpiIortItsGroup AcpiIortItsGroup;
20
int group_mask)
30
21
{
31
+struct AcpiIortSmmu3 {
22
+ int cpu_iface = virt ? (cpu + GIC_NCPU) : cpu;
32
+ ACPI_IORT_NODE_HEADER_DEF
33
+ uint64_t base_address;
34
+ uint32_t flags;
35
+ uint32_t reserved2;
36
+ uint64_t vatos_address;
37
+ uint32_t model;
38
+ uint32_t event_gsiv;
39
+ uint32_t pri_gsiv;
40
+ uint32_t gerr_gsiv;
41
+ uint32_t sync_gsiv;
42
+ AcpiIortIdMapping id_mapping_array[0];
43
+} QEMU_PACKED;
44
+typedef struct AcpiIortSmmu3 AcpiIortSmmu3;
45
+
23
+
46
struct AcpiIortRC {
24
if (!virt && !(s->ctlr & group_mask)) {
47
ACPI_IORT_NODE_HEADER_DEF
25
return false;
48
AcpiIortMemoryAccess memory_properties;
49
diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
50
index XXXXXXX..XXXXXXX 100644
51
--- a/hw/arm/virt-acpi-build.c
52
+++ b/hw/arm/virt-acpi-build.c
53
@@ -XXX,XX +XXX,XX @@ build_rsdp(GArray *rsdp_table, BIOSLinker *linker, unsigned xsdt_tbl_offset)
54
}
55
56
static void
57
-build_iort(GArray *table_data, BIOSLinker *linker)
58
+build_iort(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
59
{
60
- int iort_start = table_data->len;
61
+ int nb_nodes, iort_start = table_data->len;
62
AcpiIortIdMapping *idmap;
63
AcpiIortItsGroup *its;
64
AcpiIortTable *iort;
65
- size_t node_size, iort_length;
66
+ AcpiIortSmmu3 *smmu;
67
+ size_t node_size, iort_length, smmu_offset = 0;
68
AcpiIortRC *rc;
69
70
iort = acpi_data_push(table_data, sizeof(*iort));
71
72
+ if (vms->iommu == VIRT_IOMMU_SMMUV3) {
73
+ nb_nodes = 3; /* RC, ITS, SMMUv3 */
74
+ } else {
75
+ nb_nodes = 2; /* RC, ITS */
76
+ }
77
+
78
iort_length = sizeof(*iort);
79
- iort->node_count = cpu_to_le32(2); /* RC and ITS nodes */
80
+ iort->node_count = cpu_to_le32(nb_nodes);
81
iort->node_offset = cpu_to_le32(sizeof(*iort));
82
83
/* ITS group node */
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
+
91
+ /* SMMUv3 node */
92
+ smmu_offset = iort->node_offset + node_size;
93
+ node_size = sizeof(*smmu) + sizeof(*idmap);
94
+ iort_length += node_size;
95
+ smmu = acpi_data_push(table_data, node_size);
96
+
97
+ smmu->type = ACPI_IORT_NODE_SMMU_V3;
98
+ smmu->length = cpu_to_le16(node_size);
99
+ smmu->mapping_count = cpu_to_le32(1);
100
+ smmu->mapping_offset = cpu_to_le32(sizeof(*smmu));
101
+ smmu->base_address = cpu_to_le64(vms->memmap[VIRT_SMMU].base);
102
+ smmu->event_gsiv = cpu_to_le32(irq);
103
+ smmu->pri_gsiv = cpu_to_le32(irq + 1);
104
+ smmu->gerr_gsiv = cpu_to_le32(irq + 2);
105
+ smmu->sync_gsiv = cpu_to_le32(irq + 3);
106
+
107
+ /* Identity RID mapping covering the whole input RID range */
108
+ idmap = &smmu->id_mapping_array[0];
109
+ idmap->input_base = 0;
110
+ idmap->id_count = cpu_to_le32(0xFFFF);
111
+ idmap->output_base = 0;
112
+ /* output IORT node is the ITS group node (the first node) */
113
+ idmap->output_reference = cpu_to_le32(iort->node_offset);
114
+ }
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
}
26
}
143
27
@@ -XXX,XX +XXX,XX @@ static inline bool gic_irq_signaling_enabled(GICState *s, int cpu, bool virt,
144
/* XSDT is pointed to by RSDP */
28
return false;
29
}
30
31
- if (!(s->cpu_ctlr[cpu] & group_mask)) {
32
+ if (!(s->cpu_ctlr[cpu_iface] & group_mask)) {
33
return false;
34
}
35
145
--
36
--
146
2.17.0
37
2.20.1
147
38
148
39
diff view generated by jsdifflib
1
From: Prem Mallappa <prem.mallappa@broadcom.com>
1
From: Andrew Jones <drjones@redhat.com>
2
2
3
Add code to instantiate an smmuv3 in virt machine. A new iommu
3
virt machine's 'smp_cpus' and machine->smp.cpus must always have the
4
integer member is introduced in VirtMachineState to store the type
4
same value. And, anywhere we have virt machine state we have machine
5
of the iommu in use.
5
state. So let's remove the redundancy. Also, to make it easier to see
6
that machine->smp is the true source for "smp_cpus" and "max_cpus",
7
avoid passing them in function parameters, preferring instead to get
8
them from the state.
6
9
7
Signed-off-by: Prem Mallappa <prem.mallappa@broadcom.com>
10
No functional change intended.
8
Signed-off-by: Eric Auger <eric.auger@redhat.com>
11
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Andrew Jones <drjones@redhat.com>
10
Message-id: 1524665762-31355-13-git-send-email-eric.auger@redhat.com
13
Reviewed-by: David Edmondson <david.edmondson@oracle.com>
14
Reviewed-by: Ying Fang <fangying1@huawei.com>
15
Message-id: 20201215174815.51520-1-drjones@redhat.com
16
[PMM: minor formatting tweak to smp_cpus variable declaration]
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
18
---
13
include/hw/arm/virt.h | 10 +++++++
19
include/hw/arm/virt.h | 3 +--
14
hw/arm/virt.c | 64 ++++++++++++++++++++++++++++++++++++++++++-
20
hw/arm/virt-acpi-build.c | 9 +++++----
15
2 files changed, 73 insertions(+), 1 deletion(-)
21
hw/arm/virt.c | 21 ++++++++++-----------
22
3 files changed, 16 insertions(+), 17 deletions(-)
16
23
17
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
24
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
18
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
19
--- a/include/hw/arm/virt.h
26
--- a/include/hw/arm/virt.h
20
+++ b/include/hw/arm/virt.h
27
+++ b/include/hw/arm/virt.h
28
@@ -XXX,XX +XXX,XX @@ struct VirtMachineState {
29
MemMapEntry *memmap;
30
char *pciehb_nodename;
31
const int *irqmap;
32
- int smp_cpus;
33
void *fdt;
34
int fdt_size;
35
uint32_t clock_phandle;
36
@@ -XXX,XX +XXX,XX @@ static inline int virt_gicv3_redist_region_count(VirtMachineState *vms)
37
38
assert(vms->gic_version == VIRT_GIC_VERSION_3);
39
40
- return vms->smp_cpus > redist0_capacity ? 2 : 1;
41
+ return MACHINE(vms)->smp.cpus > redist0_capacity ? 2 : 1;
42
}
43
44
#endif /* QEMU_ARM_VIRT_H */
45
diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
46
index XXXXXXX..XXXXXXX 100644
47
--- a/hw/arm/virt-acpi-build.c
48
+++ b/hw/arm/virt-acpi-build.c
21
@@ -XXX,XX +XXX,XX @@
49
@@ -XXX,XX +XXX,XX @@
22
50
23
#define NUM_GICV2M_SPIS 64
51
#define ACPI_BUILD_TABLE_SIZE 0x20000
24
#define NUM_VIRTIO_TRANSPORTS 32
52
25
+#define NUM_SMMU_IRQS 4
53
-static void acpi_dsdt_add_cpus(Aml *scope, int smp_cpus)
26
54
+static void acpi_dsdt_add_cpus(Aml *scope, VirtMachineState *vms)
27
#define ARCH_GICV3_MAINT_IRQ 9
55
{
28
56
+ MachineState *ms = MACHINE(vms);
29
@@ -XXX,XX +XXX,XX @@ enum {
57
uint16_t i;
30
VIRT_GIC_V2M,
58
31
VIRT_GIC_ITS,
59
- for (i = 0; i < smp_cpus; i++) {
32
VIRT_GIC_REDIST,
60
+ for (i = 0; i < ms->smp.cpus; i++) {
33
+ VIRT_SMMU,
61
Aml *dev = aml_device("C%.03X", i);
34
VIRT_UART,
62
aml_append(dev, aml_name_decl("_HID", aml_string("ACPI0007")));
35
VIRT_MMIO,
63
aml_append(dev, aml_name_decl("_UID", aml_int(i)));
36
VIRT_RTC,
64
@@ -XXX,XX +XXX,XX @@ build_madt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
37
@@ -XXX,XX +XXX,XX @@ enum {
65
gicd->base_address = cpu_to_le64(memmap[VIRT_GIC_DIST].base);
38
VIRT_SECURE_MEM,
66
gicd->version = vms->gic_version;
39
};
67
40
68
- for (i = 0; i < vms->smp_cpus; i++) {
41
+typedef enum VirtIOMMUType {
69
+ for (i = 0; i < MACHINE(vms)->smp.cpus; i++) {
42
+ VIRT_IOMMU_NONE,
70
AcpiMadtGenericCpuInterface *gicc = acpi_data_push(table_data,
43
+ VIRT_IOMMU_SMMUV3,
71
sizeof(*gicc));
44
+ VIRT_IOMMU_VIRTIO,
72
ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(i));
45
+} VirtIOMMUType;
73
@@ -XXX,XX +XXX,XX @@ build_dsdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
46
+
74
* the RTC ACPI device at all when using UEFI.
47
typedef struct MemMapEntry {
75
*/
48
hwaddr base;
76
scope = aml_scope("\\_SB");
49
hwaddr size;
77
- acpi_dsdt_add_cpus(scope, vms->smp_cpus);
50
@@ -XXX,XX +XXX,XX @@ typedef struct {
78
+ acpi_dsdt_add_cpus(scope, vms);
51
bool its;
79
acpi_dsdt_add_uart(scope, &memmap[VIRT_UART],
52
bool virt;
80
(irqmap[VIRT_UART] + ARM_SPI_BASE));
53
int32_t gic_version;
81
if (vmc->acpi_expose_flash) {
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
82
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
67
index XXXXXXX..XXXXXXX 100644
83
index XXXXXXX..XXXXXXX 100644
68
--- a/hw/arm/virt.c
84
--- a/hw/arm/virt.c
69
+++ b/hw/arm/virt.c
85
+++ b/hw/arm/virt.c
70
@@ -XXX,XX +XXX,XX @@
86
@@ -XXX,XX +XXX,XX @@ static void fdt_add_timer_nodes(const VirtMachineState *vms)
71
#include "hw/smbios/smbios.h"
87
if (vms->gic_version == VIRT_GIC_VERSION_2) {
72
#include "qapi/visitor.h"
88
irqflags = deposit32(irqflags, GIC_FDT_IRQ_PPI_CPU_START,
73
#include "standard-headers/linux/input.h"
89
GIC_FDT_IRQ_PPI_CPU_WIDTH,
74
+#include "hw/arm/smmuv3.h"
90
- (1 << vms->smp_cpus) - 1);
75
91
+ (1 << MACHINE(vms)->smp.cpus) - 1);
76
#define DEFINE_VIRT_MACHINE_LATEST(major, minor, latest) \
92
}
77
static void virt_##major##_##minor##_class_init(ObjectClass *oc, \
93
78
@@ -XXX,XX +XXX,XX @@ static const MemMapEntry a15memmap[] = {
94
qemu_fdt_add_subnode(vms->fdt, "/timer");
79
[VIRT_FW_CFG] = { 0x09020000, 0x00000018 },
95
@@ -XXX,XX +XXX,XX @@ static void fdt_add_cpu_nodes(const VirtMachineState *vms)
80
[VIRT_GPIO] = { 0x09030000, 0x00001000 },
96
int cpu;
81
[VIRT_SECURE_UART] = { 0x09040000, 0x00001000 },
97
int addr_cells = 1;
82
+ [VIRT_SMMU] = { 0x09050000, 0x00020000 },
98
const MachineState *ms = MACHINE(vms);
83
[VIRT_MMIO] = { 0x0a000000, 0x00000200 },
99
+ int smp_cpus = ms->smp.cpus;
84
/* ...repeating for a total of NUM_VIRTIO_TRANSPORTS, each of that size */
100
85
[VIRT_PLATFORM_BUS] = { 0x0c000000, 0x02000000 },
101
/*
86
@@ -XXX,XX +XXX,XX @@ static const int a15irqmap[] = {
102
* From Documentation/devicetree/bindings/arm/cpus.txt
87
[VIRT_SECURE_UART] = 8,
103
@@ -XXX,XX +XXX,XX @@ static void fdt_add_cpu_nodes(const VirtMachineState *vms)
88
[VIRT_MMIO] = 16, /* ...to 16 + NUM_VIRTIO_TRANSPORTS - 1 */
104
* The simplest way to go is to examine affinity IDs of all our CPUs. If
89
[VIRT_GIC_V2M] = 48, /* ...to 48 + NUM_GICV2M_SPIS - 1 */
105
* at least one of them has Aff3 populated, we set #address-cells to 2.
90
+ [VIRT_SMMU] = 74, /* ...to 74 + NUM_SMMU_IRQS - 1 */
106
*/
91
[VIRT_PLATFORM_BUS] = 112, /* ...to 112 + PLATFORM_BUS_NUM_IRQS -1 */
107
- for (cpu = 0; cpu < vms->smp_cpus; cpu++) {
92
};
108
+ for (cpu = 0; cpu < smp_cpus; cpu++) {
93
109
ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(cpu));
94
@@ -XXX,XX +XXX,XX @@ static void create_pcie_irq_map(const VirtMachineState *vms,
110
95
0x7 /* PCI irq */);
111
if (armcpu->mp_affinity & ARM_AFF3_MASK) {
96
}
112
@@ -XXX,XX +XXX,XX @@ static void fdt_add_cpu_nodes(const VirtMachineState *vms)
97
113
qemu_fdt_setprop_cell(vms->fdt, "/cpus", "#address-cells", addr_cells);
98
-static void create_pcie(const VirtMachineState *vms, qemu_irq *pic)
114
qemu_fdt_setprop_cell(vms->fdt, "/cpus", "#size-cells", 0x0);
99
+static void create_smmu(const VirtMachineState *vms, qemu_irq *pic,
115
100
+ PCIBus *bus)
116
- for (cpu = vms->smp_cpus - 1; cpu >= 0; cpu--) {
101
+{
117
+ for (cpu = smp_cpus - 1; cpu >= 0; cpu--) {
102
+ char *node;
118
char *nodename = g_strdup_printf("/cpus/cpu@%d", cpu);
103
+ const char compat[] = "arm,smmu-v3";
119
ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(cpu));
104
+ int irq = vms->irqmap[VIRT_SMMU];
120
CPUState *cs = CPU(armcpu);
105
+ int i;
121
@@ -XXX,XX +XXX,XX @@ static void fdt_add_cpu_nodes(const VirtMachineState *vms)
106
+ hwaddr base = vms->memmap[VIRT_SMMU].base;
122
qemu_fdt_setprop_string(vms->fdt, nodename, "compatible",
107
+ hwaddr size = vms->memmap[VIRT_SMMU].size;
123
armcpu->dtb_compatible);
108
+ const char irq_names[] = "eventq\0priq\0cmdq-sync\0gerror";
124
109
+ DeviceState *dev;
125
- if (vms->psci_conduit != QEMU_PSCI_CONDUIT_DISABLED
110
+
126
- && vms->smp_cpus > 1) {
111
+ if (vms->iommu != VIRT_IOMMU_SMMUV3 || !vms->iommu_phandle) {
127
+ if (vms->psci_conduit != QEMU_PSCI_CONDUIT_DISABLED && smp_cpus > 1) {
112
+ return;
128
qemu_fdt_setprop_string(vms->fdt, nodename,
113
+ }
129
"enable-method", "psci");
114
+
130
}
115
+ dev = qdev_create(NULL, "arm-smmuv3");
131
@@ -XXX,XX +XXX,XX @@ static void fdt_add_pmu_nodes(const VirtMachineState *vms)
116
+
132
if (vms->gic_version == VIRT_GIC_VERSION_2) {
117
+ object_property_set_link(OBJECT(dev), OBJECT(bus), "primary-bus",
133
irqflags = deposit32(irqflags, GIC_FDT_IRQ_PPI_CPU_START,
118
+ &error_abort);
134
GIC_FDT_IRQ_PPI_CPU_WIDTH,
119
+ qdev_init_nofail(dev);
135
- (1 << vms->smp_cpus) - 1);
120
+ sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
136
+ (1 << MACHINE(vms)->smp.cpus) - 1);
121
+ for (i = 0; i < NUM_SMMU_IRQS; i++) {
137
}
122
+ sysbus_connect_irq(SYS_BUS_DEVICE(dev), i, pic[irq + i]);
138
123
+ }
139
qemu_fdt_add_subnode(vms->fdt, "/pmu");
124
+
140
@@ -XXX,XX +XXX,XX @@ static void finalize_gic_version(VirtMachineState *vms)
125
+ node = g_strdup_printf("/smmuv3@%" PRIx64, base);
141
* virt_cpu_post_init() must be called after the CPUs have
126
+ qemu_fdt_add_subnode(vms->fdt, node);
142
* been realized and the GIC has been created.
127
+ qemu_fdt_setprop(vms->fdt, node, "compatible", compat, sizeof(compat));
143
*/
128
+ qemu_fdt_setprop_sized_cells(vms->fdt, node, "reg", 2, base, 2, size);
144
-static void virt_cpu_post_init(VirtMachineState *vms, int max_cpus,
129
+
145
- MemoryRegion *sysmem)
130
+ qemu_fdt_setprop_cells(vms->fdt, node, "interrupts",
146
+static void virt_cpu_post_init(VirtMachineState *vms, MemoryRegion *sysmem)
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
{
147
{
151
hwaddr base_mmio = vms->memmap[VIRT_PCIE_MMIO].base;
148
+ int max_cpus = MACHINE(vms)->smp.max_cpus;
152
hwaddr size_mmio = vms->memmap[VIRT_PCIE_MMIO].size;
149
bool aarch64, pmu, steal_time;
153
@@ -XXX,XX +XXX,XX @@ static void create_pcie(const VirtMachineState *vms, qemu_irq *pic)
150
CPUState *cpu;
154
qemu_fdt_setprop_cell(vms->fdt, nodename, "#interrupt-cells", 1);
151
155
create_pcie_irq_map(vms, vms->gic_phandle, irq, nodename);
152
@@ -XXX,XX +XXX,XX @@ static void machvirt_init(MachineState *machine)
156
153
exit(1);
157
+ if (vms->iommu) {
154
}
158
+ vms->iommu_phandle = qemu_fdt_alloc_phandle(vms->fdt);
155
159
+
156
- vms->smp_cpus = smp_cpus;
160
+ create_smmu(vms, pic, pci->bus);
157
-
161
+
158
if (vms->virt && kvm_enabled()) {
162
+ qemu_fdt_setprop_cells(vms->fdt, nodename, "iommu-map",
159
error_report("mach-virt: KVM does not support providing "
163
+ 0x0, vms->iommu_phandle, 0x0, 0x10000);
160
"Virtualization extensions to the guest CPU");
164
+ }
161
@@ -XXX,XX +XXX,XX @@ static void machvirt_init(MachineState *machine)
165
+
162
create_fdt(vms);
166
g_free(nodename);
163
167
}
164
possible_cpus = mc->possible_cpu_arch_ids(machine);
165
+ assert(possible_cpus->len == max_cpus);
166
for (n = 0; n < possible_cpus->len; n++) {
167
Object *cpuobj;
168
CPUState *cs;
169
@@ -XXX,XX +XXX,XX @@ static void machvirt_init(MachineState *machine)
170
171
create_gic(vms);
172
173
- virt_cpu_post_init(vms, possible_cpus->len, sysmem);
174
+ virt_cpu_post_init(vms, sysmem);
175
176
fdt_add_pmu_nodes(vms);
168
177
169
--
178
--
170
2.17.0
179
2.20.1
171
180
172
181
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
In 50244cc76abc we updated mte_check_fail to match the ARM
4
3281af8114c6b8ead02f08b58e3c36895c1ea047 which should have been
4
pseudocode, using the correct EL to select the TCF field.
5
id_mpuir_reginfo.
5
But we failed to update MTE0_ACTIVE the same way, which led
6
to g_assert_not_reached().
6
7
7
The effect was that for OMAP and StrongARM CPUs we would
8
Cc: qemu-stable@nongnu.org
8
incorrectly UNDEF writes to MPUIR rather than NOPing them.
9
Buglink: https://bugs.launchpad.net/bugs/1907137
9
10
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
Signed-off-by: Mathew Maidment <mathew1800@gmail.com>
11
Message-id: 20201221204426.88514-1-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>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
---
14
---
16
target/arm/helper.c | 2 +-
15
target/arm/helper.c | 2 +-
17
1 file changed, 1 insertion(+), 1 deletion(-)
16
1 file changed, 1 insertion(+), 1 deletion(-)
18
17
19
diff --git a/target/arm/helper.c b/target/arm/helper.c
18
diff --git a/target/arm/helper.c b/target/arm/helper.c
20
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
21
--- a/target/arm/helper.c
20
--- a/target/arm/helper.c
22
+++ b/target/arm/helper.c
21
+++ b/target/arm/helper.c
23
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
22
@@ -XXX,XX +XXX,XX @@ static uint32_t rebuild_hflags_a64(CPUARMState *env, int el, int fp_el,
24
for (r = id_cp_reginfo; r->type != ARM_CP_SENTINEL; r++) {
23
if (FIELD_EX32(flags, TBFLAG_A64, UNPRIV)
25
r->access = PL1_RW;
24
&& tbid
26
}
25
&& !(env->pstate & PSTATE_TCO)
27
- id_tlbtr_reginfo.access = PL1_RW;
26
- && (sctlr & SCTLR_TCF0)
28
+ id_mpuir_reginfo.access = PL1_RW;
27
+ && (sctlr & SCTLR_TCF)
29
id_tlbtr_reginfo.access = PL1_RW;
28
&& allocation_tag_access_enabled(env, 0, sctlr)) {
29
flags = FIELD_DP32(flags, TBFLAG_A64, MTE0_ACTIVE, 1);
30
}
30
}
31
if (arm_feature(env, ARM_FEATURE_V8)) {
32
--
31
--
33
2.17.0
32
2.20.1
34
33
35
34
diff view generated by jsdifflib
1
From: Eric Auger <eric.auger@redhat.com>
1
The CCR is a register most of whose bits are banked between security
2
states but where BFHFNMIGN is not, and we keep it in the non-secure
3
entry of the v7m.ccr[] array. The logic which tries to handle this
4
bit fails to implement the "RAZ/WI from Nonsecure if AIRCR.BFHFNMINS
5
is zero" requirement; correct the omission.
2
6
3
In case the MSI is translated by an IOMMU we need to fixup the
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
MSI route with the translated address.
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20201210201433.26262-2-peter.maydell@linaro.org
10
---
11
hw/intc/armv7m_nvic.c | 15 +++++++++++++++
12
1 file changed, 15 insertions(+)
5
13
6
Signed-off-by: Eric Auger <eric.auger@redhat.com>
14
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
7
Signed-off-by: Bharat Bhushan <Bharat.Bhushan@nxp.com>
8
Message-id: 1524665762-31355-12-git-send-email-eric.auger@redhat.com
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
target/arm/kvm.c | 38 +++++++++++++++++++++++++++++++++++++-
13
target/arm/trace-events | 3 +++
14
2 files changed, 40 insertions(+), 1 deletion(-)
15
16
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
17
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/kvm.c
16
--- a/hw/intc/armv7m_nvic.c
19
+++ b/target/arm/kvm.c
17
+++ b/hw/intc/armv7m_nvic.c
20
@@ -XXX,XX +XXX,XX @@
18
@@ -XXX,XX +XXX,XX @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
21
#include "sysemu/kvm.h"
19
*/
22
#include "kvm_arm.h"
20
val = cpu->env.v7m.ccr[attrs.secure];
23
#include "cpu.h"
21
val |= cpu->env.v7m.ccr[M_REG_NS] & R_V7M_CCR_BFHFNMIGN_MASK;
24
+#include "trace.h"
22
+ /* BFHFNMIGN is RAZ/WI from NS if AIRCR.BFHFNMINS is 0 */
25
#include "internals.h"
23
+ if (!attrs.secure) {
26
#include "hw/arm/arm.h"
24
+ if (!(cpu->env.v7m.aircr & R_V7M_AIRCR_BFHFNMINS_MASK)) {
27
+#include "hw/pci/pci.h"
25
+ val &= ~R_V7M_CCR_BFHFNMIGN_MASK;
28
#include "exec/memattrs.h"
26
+ }
29
#include "exec/address-spaces.h"
27
+ }
30
#include "hw/boards.h"
28
return val;
31
@@ -XXX,XX +XXX,XX @@ int kvm_arm_vgic_probe(void)
29
case 0xd24: /* System Handler Control and State (SHCSR) */
32
int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route,
30
if (!arm_feature(&cpu->env, ARM_FEATURE_V7)) {
33
uint64_t address, uint32_t data, PCIDevice *dev)
31
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
34
{
32
(cpu->env.v7m.ccr[M_REG_NS] & ~R_V7M_CCR_BFHFNMIGN_MASK)
35
- return 0;
33
| (value & R_V7M_CCR_BFHFNMIGN_MASK);
36
+ AddressSpace *as = pci_device_iommu_address_space(dev);
34
value &= ~R_V7M_CCR_BFHFNMIGN_MASK;
37
+ hwaddr xlat, len, doorbell_gpa;
35
+ } else {
38
+ MemoryRegionSection mrs;
36
+ /*
39
+ MemoryRegion *mr;
37
+ * BFHFNMIGN is RAZ/WI from NS if AIRCR.BFHFNMINS is 0, so
40
+ int ret = 1;
38
+ * preserve the state currently in the NS element of the array
41
+
39
+ */
42
+ if (as == &address_space_memory) {
40
+ if (!(cpu->env.v7m.aircr & R_V7M_AIRCR_BFHFNMINS_MASK)) {
43
+ return 0;
41
+ value &= ~R_V7M_CCR_BFHFNMIGN_MASK;
44
+ }
42
+ value |= cpu->env.v7m.ccr[M_REG_NS] & R_V7M_CCR_BFHFNMIGN_MASK;
45
+
43
+ }
46
+ /* MSI doorbell address is translated by an IOMMU */
44
}
47
+
45
48
+ rcu_read_lock();
46
cpu->env.v7m.ccr[attrs.secure] = value;
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
--
47
--
86
2.17.0
48
2.20.1
87
49
88
50
diff view generated by jsdifflib
1
For v8M the instructions VLLDM and VLSTM support lazy saving
1
In commit 64f863baeedc8659 we implemented the v8.1M FPCXT_S register,
2
and restoring of the secure floating-point registers. Even
2
but we got the write behaviour wrong. On read, this register reads
3
if the floating point extension is not implemented, these
3
bits [27:0] of FPSCR plus the CONTROL.SFPA bit. On write, it doesn't
4
instructions must act as NOPs in Secure state, so they can
4
just write back those bits -- it writes a value to the whole FPSCR,
5
be used as part of the secure-to-nonsecure call sequence.
5
whose upper 4 bits are zeroes.
6
6
7
Fixes: https://bugs.launchpad.net/qemu/+bug/1768295
7
We also incorrectly implemented the write-to-FPSCR as a simple store
8
Cc: qemu-stable@nongnu.org
8
to vfp.xregs; this skips the "update the softfloat flags" part of
9
the vfp_set_fpscr helper so the value would read back correctly but
10
not actually take effect.
11
12
Fix both of these things by doing a complete write to the FPSCR
13
using the helper function.
14
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
16
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20180503105730.5958-1-peter.maydell@linaro.org
17
Message-id: 20201210201433.26262-3-peter.maydell@linaro.org
12
---
18
---
13
target/arm/translate.c | 17 ++++++++++++++++-
19
target/arm/translate-vfp.c.inc | 12 ++++++------
14
1 file changed, 16 insertions(+), 1 deletion(-)
20
1 file changed, 6 insertions(+), 6 deletions(-)
15
21
16
diff --git a/target/arm/translate.c b/target/arm/translate.c
22
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
17
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/translate.c
24
--- a/target/arm/translate-vfp.c.inc
19
+++ b/target/arm/translate.c
25
+++ b/target/arm/translate-vfp.c.inc
20
@@ -XXX,XX +XXX,XX @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
26
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_write(DisasContext *s, int regno,
21
/* Coprocessor. */
27
}
22
if (arm_dc_feature(s, ARM_FEATURE_M)) {
28
case ARM_VFP_FPCXT_S:
23
/* We don't currently implement M profile FP support,
29
{
24
- * so this entire space should give a NOCP fault.
30
- TCGv_i32 sfpa, control, fpscr;
25
+ * so this entire space should give a NOCP fault, with
31
- /* Set FPSCR[27:0] and CONTROL.SFPA from value */
26
+ * the exception of the v8M VLLDM and VLSTM insns, which
32
+ TCGv_i32 sfpa, control;
27
+ * must be NOPs in Secure state and UNDEF in Nonsecure state.
33
+ /*
28
*/
34
+ * Set FPSCR and CONTROL.SFPA from value; the new FPSCR takes
29
+ if (arm_dc_feature(s, ARM_FEATURE_V8) &&
35
+ * bits [27:0] from value and zeroes bits [31:28].
30
+ (insn & 0xffa00f00) == 0xec200a00) {
36
+ */
31
+ /* 0b1110_1100_0x1x_xxxx_xxxx_1010_xxxx_xxxx
37
tmp = loadfn(s, opaque);
32
+ * - VLLDM, VLSTM
38
sfpa = tcg_temp_new_i32();
33
+ * We choose to UNDEF if the RAZ bits are non-zero.
39
tcg_gen_shri_i32(sfpa, tmp, 31);
34
+ */
40
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_write(DisasContext *s, int regno,
35
+ if (!s->v8m_secure || (insn & 0x0040f0ff)) {
41
tcg_gen_deposit_i32(control, control, sfpa,
36
+ goto illegal_op;
42
R_V7M_CONTROL_SFPA_SHIFT, 1);
37
+ }
43
store_cpu_field(control, v7m.control[M_REG_S]);
38
+ /* Just NOP since FP support is not implemented */
44
- fpscr = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
39
+ break;
45
- tcg_gen_andi_i32(fpscr, fpscr, FPCR_NZCV_MASK);
40
+ }
46
tcg_gen_andi_i32(tmp, tmp, ~FPCR_NZCV_MASK);
41
+ /* All other insns: NOCP */
47
- tcg_gen_or_i32(fpscr, fpscr, tmp);
42
gen_exception_insn(s, 4, EXCP_NOCP, syn_uncategorized(),
48
- store_cpu_field(fpscr, vfp.xregs[ARM_VFP_FPSCR]);
43
default_exception_el(s));
49
+ gen_helper_vfp_set_fpscr(cpu_env, tmp);
44
break;
50
tcg_temp_free_i32(tmp);
51
tcg_temp_free_i32(sfpa);
52
break;
45
--
53
--
46
2.17.0
54
2.20.1
47
55
48
56
diff view generated by jsdifflib
1
From: Eric Auger <eric.auger@redhat.com>
1
Implement the v8.1M FPCXT_NS floating-point system register. This is
2
a little more complicated than FPCXT_S, because it has specific
3
handling for "current FP state is inactive", and it only wants to do
4
PreserveFPState(), not the full set of actions done by
5
ExecuteFPCheck() which vfp_access_check() implements.
2
6
3
We set up the infrastructure to enumerate all the PCI devices
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
attached to the SMMU and create an associated IOMMU memory
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
region and address space.
9
Message-id: 20201210201433.26262-4-peter.maydell@linaro.org
10
---
11
target/arm/translate-vfp.c.inc | 102 ++++++++++++++++++++++++++++++++-
12
1 file changed, 99 insertions(+), 3 deletions(-)
6
13
7
Those info are stored in SMMUDevice objects. The devices are
14
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
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
15
index XXXXXXX..XXXXXXX 100644
25
--- a/include/hw/arm/smmu-common.h
16
--- a/target/arm/translate-vfp.c.inc
26
+++ b/include/hw/arm/smmu-common.h
17
+++ b/target/arm/translate-vfp.c.inc
27
@@ -XXX,XX +XXX,XX @@ typedef struct {
18
@@ -XXX,XX +XXX,XX @@ static FPSysRegCheckResult fp_sysreg_checks(DisasContext *s, int regno)
28
#define ARM_SMMU_GET_CLASS(obj) \
19
}
29
OBJECT_GET_CLASS(SMMUBaseClass, (obj), TYPE_ARM_SMMU)
20
break;
30
21
case ARM_VFP_FPCXT_S:
31
+/* Return the SMMUPciBus handle associated to a PCI bus number */
22
+ case ARM_VFP_FPCXT_NS:
32
+SMMUPciBus *smmu_find_smmu_pcibus(SMMUState *s, uint8_t bus_num);
23
if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
24
return false;
25
}
26
@@ -XXX,XX +XXX,XX @@ static FPSysRegCheckResult fp_sysreg_checks(DisasContext *s, int regno)
27
return FPSysRegCheckFailed;
28
}
29
30
- if (!vfp_access_check(s)) {
31
+ /*
32
+ * FPCXT_NS is a special case: it has specific handling for
33
+ * "current FP state is inactive", and must do the PreserveFPState()
34
+ * but not the usual full set of actions done by ExecuteFPCheck().
35
+ * So we don't call vfp_access_check() and the callers must handle this.
36
+ */
37
+ if (regno != ARM_VFP_FPCXT_NS && !vfp_access_check(s)) {
38
return FPSysRegCheckDone;
39
}
40
-
41
return FPSysRegCheckContinue;
42
}
43
44
+static void gen_branch_fpInactive(DisasContext *s, TCGCond cond,
45
+ TCGLabel *label)
46
+{
47
+ /*
48
+ * FPCXT_NS is a special case: it has specific handling for
49
+ * "current FP state is inactive", and must do the PreserveFPState()
50
+ * but not the usual full set of actions done by ExecuteFPCheck().
51
+ * We don't have a TB flag that matches the fpInactive check, so we
52
+ * do it at runtime as we don't expect FPCXT_NS accesses to be frequent.
53
+ *
54
+ * Emit code that checks fpInactive and does a conditional
55
+ * branch to label based on it:
56
+ * if cond is TCG_COND_NE then branch if fpInactive != 0 (ie if inactive)
57
+ * if cond is TCG_COND_EQ then branch if fpInactive == 0 (ie if active)
58
+ */
59
+ assert(cond == TCG_COND_EQ || cond == TCG_COND_NE);
33
+
60
+
34
+/* Return the stream ID of an SMMU device */
61
+ /* fpInactive = FPCCR_NS.ASPEN == 1 && CONTROL.FPCA == 0 */
35
+static inline uint16_t smmu_get_sid(SMMUDevice *sdev)
62
+ TCGv_i32 aspen, fpca;
36
+{
63
+ aspen = load_cpu_field(v7m.fpccr[M_REG_NS]);
37
+ return PCI_BUILD_BDF(pci_bus_num(sdev->bus), sdev->devfn);
64
+ fpca = load_cpu_field(v7m.control[M_REG_S]);
38
+}
65
+ tcg_gen_andi_i32(aspen, aspen, R_V7M_FPCCR_ASPEN_MASK);
39
#endif /* HW_ARM_SMMU_COMMON */
66
+ tcg_gen_xori_i32(aspen, aspen, R_V7M_FPCCR_ASPEN_MASK);
40
diff --git a/hw/arm/smmu-common.c b/hw/arm/smmu-common.c
67
+ tcg_gen_andi_i32(fpca, fpca, R_V7M_CONTROL_FPCA_MASK);
41
index XXXXXXX..XXXXXXX 100644
68
+ tcg_gen_or_i32(fpca, fpca, aspen);
42
--- a/hw/arm/smmu-common.c
69
+ tcg_gen_brcondi_i32(tcg_invert_cond(cond), fpca, 0, label);
43
+++ b/hw/arm/smmu-common.c
70
+ tcg_temp_free_i32(aspen);
44
@@ -XXX,XX +XXX,XX @@
71
+ tcg_temp_free_i32(fpca);
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
+}
72
+}
71
+
73
+
72
+static AddressSpace *smmu_find_add_as(PCIBus *bus, void *opaque, int devfn)
74
static bool gen_M_fp_sysreg_write(DisasContext *s, int regno,
73
+{
75
74
+ SMMUState *s = opaque;
76
fp_sysreg_loadfn *loadfn,
75
+ SMMUPciBus *sbus = g_hash_table_lookup(s->smmu_pcibus_by_busptr, bus);
77
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_write(DisasContext *s, int regno,
76
+ SMMUDevice *sdev;
78
{
79
/* Do a write to an M-profile floating point system register */
80
TCGv_i32 tmp;
81
+ TCGLabel *lab_end = NULL;
82
83
switch (fp_sysreg_checks(s, regno)) {
84
case FPSysRegCheckFailed:
85
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_write(DisasContext *s, int regno,
86
tcg_temp_free_i32(tmp);
87
break;
88
}
89
+ case ARM_VFP_FPCXT_NS:
90
+ lab_end = gen_new_label();
91
+ /* fpInactive case: write is a NOP, so branch to end */
92
+ gen_branch_fpInactive(s, TCG_COND_NE, lab_end);
93
+ /* !fpInactive: PreserveFPState(), and reads same as FPCXT_S */
94
+ gen_preserve_fp_state(s);
95
+ /* fall through */
96
case ARM_VFP_FPCXT_S:
97
{
98
TCGv_i32 sfpa, control;
99
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_write(DisasContext *s, int regno,
100
default:
101
g_assert_not_reached();
102
}
103
+ if (lab_end) {
104
+ gen_set_label(lab_end);
105
+ }
106
return true;
107
}
108
109
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_read(DisasContext *s, int regno,
110
{
111
/* Do a read from an M-profile floating point system register */
112
TCGv_i32 tmp;
113
+ TCGLabel *lab_end = NULL;
114
+ bool lookup_tb = false;
115
116
switch (fp_sysreg_checks(s, regno)) {
117
case FPSysRegCheckFailed:
118
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_read(DisasContext *s, int regno,
119
fpscr = load_cpu_field(v7m.fpdscr[M_REG_NS]);
120
gen_helper_vfp_set_fpscr(cpu_env, fpscr);
121
tcg_temp_free_i32(fpscr);
122
- gen_lookup_tb(s);
123
+ lookup_tb = true;
124
+ break;
125
+ }
126
+ case ARM_VFP_FPCXT_NS:
127
+ {
128
+ TCGv_i32 control, sfpa, fpscr, fpdscr, zero;
129
+ TCGLabel *lab_active = gen_new_label();
77
+
130
+
78
+ if (!sbus) {
131
+ lookup_tb = true;
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
+
132
+
85
+ sdev = sbus->pbdev[devfn];
133
+ gen_branch_fpInactive(s, TCG_COND_EQ, lab_active);
86
+ if (!sdev) {
134
+ /* fpInactive case: reads as FPDSCR_NS */
87
+ char *name = g_strdup_printf("%s-%d-%d",
135
+ TCGv_i32 tmp = load_cpu_field(v7m.fpdscr[M_REG_NS]);
88
+ s->mrtypename,
136
+ storefn(s, opaque, tmp);
89
+ pci_bus_num(bus), devfn);
137
+ lab_end = gen_new_label();
90
+ sdev = sbus->pbdev[devfn] = g_new0(SMMUDevice, 1);
138
+ tcg_gen_br(lab_end);
91
+
139
+
92
+ sdev->smmu = s;
140
+ gen_set_label(lab_active);
93
+ sdev->bus = bus;
141
+ /* !fpInactive: Reads the same as FPCXT_S, but side effects differ */
94
+ sdev->devfn = devfn;
142
+ gen_preserve_fp_state(s);
95
+
143
+ tmp = tcg_temp_new_i32();
96
+ memory_region_init_iommu(&sdev->iommu, sizeof(sdev->iommu),
144
+ sfpa = tcg_temp_new_i32();
97
+ s->mrtypename,
145
+ fpscr = tcg_temp_new_i32();
98
+ OBJECT(s), name, 1ULL << SMMU_MAX_VA_BITS);
146
+ gen_helper_vfp_get_fpscr(fpscr, cpu_env);
99
+ address_space_init(&sdev->as,
147
+ tcg_gen_andi_i32(tmp, fpscr, ~FPCR_NZCV_MASK);
100
+ MEMORY_REGION(&sdev->iommu), name);
148
+ control = load_cpu_field(v7m.control[M_REG_S]);
101
+ trace_smmu_add_mr(name);
149
+ tcg_gen_andi_i32(sfpa, control, R_V7M_CONTROL_SFPA_MASK);
102
+ g_free(name);
150
+ tcg_gen_shli_i32(sfpa, sfpa, 31 - R_V7M_CONTROL_SFPA_SHIFT);
103
+ }
151
+ tcg_gen_or_i32(tmp, tmp, sfpa);
104
+
152
+ tcg_temp_free_i32(control);
105
+ return &sdev->as;
153
+ /* Store result before updating FPSCR, in case it faults */
106
+}
154
+ storefn(s, opaque, tmp);
107
+
155
+ /* If SFPA is zero then set FPSCR from FPDSCR_NS */
108
static void smmu_base_realize(DeviceState *dev, Error **errp)
156
+ fpdscr = load_cpu_field(v7m.fpdscr[M_REG_NS]);
109
{
157
+ zero = tcg_const_i32(0);
110
+ SMMUState *s = ARM_SMMU(dev);
158
+ tcg_gen_movcond_i32(TCG_COND_EQ, fpscr, sfpa, zero, fpdscr, fpscr);
111
SMMUBaseClass *sbc = ARM_SMMU_GET_CLASS(dev);
159
+ gen_helper_vfp_set_fpscr(cpu_env, fpscr);
112
Error *local_err = NULL;
160
+ tcg_temp_free_i32(zero);
113
161
+ tcg_temp_free_i32(sfpa);
114
@@ -XXX,XX +XXX,XX @@ static void smmu_base_realize(DeviceState *dev, Error **errp)
162
+ tcg_temp_free_i32(fpdscr);
115
error_propagate(errp, local_err);
163
+ tcg_temp_free_i32(fpscr);
116
return;
164
break;
165
}
166
default:
167
g_assert_not_reached();
117
}
168
}
118
+
169
+
119
+ s->smmu_pcibus_by_busptr = g_hash_table_new(NULL, NULL);
170
+ if (lab_end) {
120
+
171
+ gen_set_label(lab_end);
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
+ }
172
+ }
173
+ if (lookup_tb) {
174
+ gen_lookup_tb(s);
175
+ }
176
return true;
126
}
177
}
127
178
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
--
179
--
142
2.17.0
180
2.20.1
143
181
144
182
diff view generated by jsdifflib
1
Convert the tusb6010 device away from using the old_mmio field
1
Now that we have implemented all the features needed by the v8.1M
2
of MemoryRegionOps. This device is used only in the n800 and n810
2
architecture, we can add the model of the Cortex-M55. This is the
3
boards.
3
configuration without MVE support; we'll add MVE later.
4
4
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20180427173611.10281-2-peter.maydell@linaro.org
7
Message-id: 20201210201433.26262-5-peter.maydell@linaro.org
8
---
8
---
9
hw/usb/tusb6010.c | 40 ++++++++++++++++++++++++++++++++++++----
9
target/arm/cpu_tcg.c | 42 ++++++++++++++++++++++++++++++++++++++++++
10
1 file changed, 36 insertions(+), 4 deletions(-)
10
1 file changed, 42 insertions(+)
11
11
12
diff --git a/hw/usb/tusb6010.c b/hw/usb/tusb6010.c
12
diff --git a/target/arm/cpu_tcg.c b/target/arm/cpu_tcg.c
13
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/usb/tusb6010.c
14
--- a/target/arm/cpu_tcg.c
15
+++ b/hw/usb/tusb6010.c
15
+++ b/target/arm/cpu_tcg.c
16
@@ -XXX,XX +XXX,XX @@ static void tusb_async_writew(void *opaque, hwaddr addr,
16
@@ -XXX,XX +XXX,XX @@ static void cortex_m33_initfn(Object *obj)
17
}
17
cpu->ctr = 0x8000c000;
18
}
18
}
19
19
20
+static uint64_t tusb_async_readfn(void *opaque, hwaddr addr, unsigned size)
20
+static void cortex_m55_initfn(Object *obj)
21
+{
21
+{
22
+ switch (size) {
22
+ ARMCPU *cpu = ARM_CPU(obj);
23
+ case 1:
23
+
24
+ return tusb_async_readb(opaque, addr);
24
+ set_feature(&cpu->env, ARM_FEATURE_V8);
25
+ case 2:
25
+ set_feature(&cpu->env, ARM_FEATURE_V8_1M);
26
+ return tusb_async_readh(opaque, addr);
26
+ set_feature(&cpu->env, ARM_FEATURE_M);
27
+ case 4:
27
+ set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
28
+ return tusb_async_readw(opaque, addr);
28
+ set_feature(&cpu->env, ARM_FEATURE_M_SECURITY);
29
+ default:
29
+ set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP);
30
+ g_assert_not_reached();
30
+ cpu->midr = 0x410fd221; /* r0p1 */
31
+ }
31
+ cpu->revidr = 0;
32
+ cpu->pmsav7_dregion = 16;
33
+ cpu->sau_sregion = 8;
34
+ /*
35
+ * These are the MVFR* values for the FPU, no MVE configuration;
36
+ * we will update them later when we implement MVE
37
+ */
38
+ cpu->isar.mvfr0 = 0x10110221;
39
+ cpu->isar.mvfr1 = 0x12100011;
40
+ cpu->isar.mvfr2 = 0x00000040;
41
+ cpu->isar.id_pfr0 = 0x20000030;
42
+ cpu->isar.id_pfr1 = 0x00000230;
43
+ cpu->isar.id_dfr0 = 0x10200000;
44
+ cpu->id_afr0 = 0x00000000;
45
+ cpu->isar.id_mmfr0 = 0x00111040;
46
+ cpu->isar.id_mmfr1 = 0x00000000;
47
+ cpu->isar.id_mmfr2 = 0x01000000;
48
+ cpu->isar.id_mmfr3 = 0x00000011;
49
+ cpu->isar.id_isar0 = 0x01103110;
50
+ cpu->isar.id_isar1 = 0x02212000;
51
+ cpu->isar.id_isar2 = 0x20232232;
52
+ cpu->isar.id_isar3 = 0x01111131;
53
+ cpu->isar.id_isar4 = 0x01310132;
54
+ cpu->isar.id_isar5 = 0x00000000;
55
+ cpu->isar.id_isar6 = 0x00000000;
56
+ cpu->clidr = 0x00000000; /* caches not implemented */
57
+ cpu->ctr = 0x8303c003;
32
+}
58
+}
33
+
59
+
34
+static void tusb_async_writefn(void *opaque, hwaddr addr,
60
static const ARMCPRegInfo cortexr5_cp_reginfo[] = {
35
+ uint64_t value, unsigned size)
61
/* Dummy the TCM region regs for the moment */
36
+{
62
{ .name = "ATCM", .cp = 15, .opc1 = 0, .crn = 9, .crm = 1, .opc2 = 0,
37
+ switch (size) {
63
@@ -XXX,XX +XXX,XX @@ static const ARMCPUInfo arm_tcg_cpus[] = {
38
+ case 1:
64
.class_init = arm_v7m_class_init },
39
+ tusb_async_writeb(opaque, addr, value);
65
{ .name = "cortex-m33", .initfn = cortex_m33_initfn,
40
+ break;
66
.class_init = arm_v7m_class_init },
41
+ case 2:
67
+ { .name = "cortex-m55", .initfn = cortex_m55_initfn,
42
+ tusb_async_writeh(opaque, addr, value);
68
+ .class_init = arm_v7m_class_init },
43
+ break;
69
{ .name = "cortex-r5", .initfn = cortex_r5_initfn },
44
+ case 4:
70
{ .name = "cortex-r5f", .initfn = cortex_r5f_initfn },
45
+ tusb_async_writew(opaque, addr, value);
71
{ .name = "ti925t", .initfn = ti925t_initfn },
46
+ break;
47
+ default:
48
+ g_assert_not_reached();
49
+ }
50
+}
51
+
52
static const MemoryRegionOps tusb_async_ops = {
53
- .old_mmio = {
54
- .read = { tusb_async_readb, tusb_async_readh, tusb_async_readw, },
55
- .write = { tusb_async_writeb, tusb_async_writeh, tusb_async_writew, },
56
- },
57
+ .read = tusb_async_readfn,
58
+ .write = tusb_async_writefn,
59
+ .valid.min_access_size = 1,
60
+ .valid.max_access_size = 4,
61
.endianness = DEVICE_NATIVE_ENDIAN,
62
};
63
64
--
72
--
65
2.17.0
73
2.20.1
66
74
67
75
diff view generated by jsdifflib
1
Convert the smc91c111 device away from using the old_mmio field of
1
Support for running KVM on 32-bit Arm hosts was removed in commit
2
MemoryRegionOps. This device is used by several Arm board models.
2
82bf7ae84ce739e. You can still run a 32-bit guest on a 64-bit Arm
3
host CPU, but because Arm KVM requires the host and guest CPU types
4
to match, it is not possible to run a guest that requires a Cortex-A9
5
or Cortex-A15 CPU there. That means that the code in the
6
highbank/midway board models to support KVM is no longer used, and we
7
can delete it.
3
8
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20180427173611.10281-3-peter.maydell@linaro.org
11
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
12
Message-id: 20201215144215.28482-1-peter.maydell@linaro.org
7
---
13
---
8
hw/net/smc91c111.c | 54 +++++++++++++++++++++-------------------------
14
hw/arm/highbank.c | 14 ++++----------
9
1 file changed, 25 insertions(+), 29 deletions(-)
15
1 file changed, 4 insertions(+), 10 deletions(-)
10
16
11
diff --git a/hw/net/smc91c111.c b/hw/net/smc91c111.c
17
diff --git a/hw/arm/highbank.c b/hw/arm/highbank.c
12
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
13
--- a/hw/net/smc91c111.c
19
--- a/hw/arm/highbank.c
14
+++ b/hw/net/smc91c111.c
20
+++ b/hw/arm/highbank.c
15
@@ -XXX,XX +XXX,XX @@ static uint32_t smc91c111_readb(void *opaque, hwaddr offset)
21
@@ -XXX,XX +XXX,XX @@
16
return 0;
22
#include "hw/arm/boot.h"
23
#include "hw/loader.h"
24
#include "net/net.h"
25
-#include "sysemu/kvm.h"
26
#include "sysemu/runstate.h"
27
#include "sysemu/sysemu.h"
28
#include "hw/boards.h"
29
@@ -XXX,XX +XXX,XX @@
30
#include "hw/cpu/a15mpcore.h"
31
#include "qemu/log.h"
32
#include "qom/object.h"
33
+#include "cpu.h"
34
35
#define SMP_BOOT_ADDR 0x100
36
#define SMP_BOOT_REG 0x40
37
@@ -XXX,XX +XXX,XX @@ static void calxeda_init(MachineState *machine, enum cxmachines machine_id)
38
highbank_binfo.loader_start = 0;
39
highbank_binfo.write_secondary_boot = hb_write_secondary;
40
highbank_binfo.secondary_cpu_reset_hook = hb_reset_secondary;
41
- if (!kvm_enabled()) {
42
- highbank_binfo.board_setup_addr = BOARD_SETUP_ADDR;
43
- highbank_binfo.write_board_setup = hb_write_board_setup;
44
- highbank_binfo.secure_board_setup = true;
45
- } else {
46
- warn_report("cannot load built-in Monitor support "
47
- "if KVM is enabled. Some guests (such as Linux) "
48
- "may not boot.");
49
- }
50
+ highbank_binfo.board_setup_addr = BOARD_SETUP_ADDR;
51
+ highbank_binfo.write_board_setup = hb_write_board_setup;
52
+ highbank_binfo.secure_board_setup = true;
53
54
arm_load_kernel(ARM_CPU(first_cpu), machine, &highbank_binfo);
17
}
55
}
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
- smc91c111_writeb(opaque, offset, value & 0xff);
24
- smc91c111_writeb(opaque, offset + 1, value >> 8);
25
+ int i;
26
+ uint32_t val = 0;
27
+
28
+ for (i = 0; i < size; i++) {
29
+ val |= smc91c111_readb(opaque, addr + i) << (i * 8);
30
+ }
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
*/
78
- .old_mmio = {
79
- .read = { smc91c111_readb, smc91c111_readw, smc91c111_readl, },
80
- .write = { smc91c111_writeb, smc91c111_writew, smc91c111_writel, },
81
- },
82
+ .read = smc91c111_readfn,
83
+ .write = smc91c111_writefn,
84
+ .valid.min_access_size = 1,
85
+ .valid.max_access_size = 4,
86
.endianness = DEVICE_NATIVE_ENDIAN,
87
};
88
89
--
56
--
90
2.17.0
57
2.20.1
91
58
92
59
diff view generated by jsdifflib
1
From: Eric Auger <eric.auger@redhat.com>
1
Currently timer_free() is a simple wrapper for g_free(). This means
2
that the timer being freed must not be currently active, as otherwise
3
QEMU might crash later when the active list is processed and still
4
has a pointer to freed memory on it. As a result almost all calls to
5
timer_free() are preceded by a timer_del() call, as can be seen in
6
the output of
7
git grep -B1 '\<timer_free\>'
2
8
3
We introduce helpers to read/write into the command and event
9
This is unfortunate API design as it makes it easy to accidentally
4
circular queues.
10
misuse (by forgetting the timer_del()), and the correct use is
11
annoyingly verbose.
5
12
6
smmuv3_write_eventq and smmuv3_cmq_consume will become static
13
Make timer_free() imply a timer_del().
7
in subsequent patches.
8
14
9
Invalidation commands are not yet dealt with. We do not cache
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
data that need to be invalidated. This will change with vhost
16
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
11
integration.
17
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
18
Message-id: 20201215154107.3255-2-peter.maydell@linaro.org
19
---
20
include/qemu/timer.h | 24 +++++++++++++-----------
21
1 file changed, 13 insertions(+), 11 deletions(-)
12
22
13
Signed-off-by: Eric Auger <eric.auger@redhat.com>
23
diff --git a/include/qemu/timer.h b/include/qemu/timer.h
14
Signed-off-by: Prem Mallappa <prem.mallappa@broadcom.com>
15
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
16
Message-id: 1524665762-31355-7-git-send-email-eric.auger@redhat.com
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
---
19
hw/arm/smmuv3-internal.h | 163 +++++++++++++++++++++++++++++++++++++++
20
hw/arm/smmuv3.c | 136 ++++++++++++++++++++++++++++++++
21
hw/arm/trace-events | 5 ++
22
3 files changed, 304 insertions(+)
23
24
diff --git a/hw/arm/smmuv3-internal.h b/hw/arm/smmuv3-internal.h
25
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
26
--- a/hw/arm/smmuv3-internal.h
25
--- a/include/qemu/timer.h
27
+++ b/hw/arm/smmuv3-internal.h
26
+++ b/include/qemu/timer.h
28
@@ -XXX,XX +XXX,XX @@ static inline bool smmuv3_gerror_irq_enabled(SMMUv3State *s)
27
@@ -XXX,XX +XXX,XX @@ static inline QEMUTimer *timer_new_ms(QEMUClockType type, QEMUTimerCB *cb,
29
void smmuv3_trigger_irq(SMMUv3State *s, SMMUIrq irq, uint32_t gerror_mask);
28
*/
30
void smmuv3_write_gerrorn(SMMUv3State *s, uint32_t gerrorn);
29
void timer_deinit(QEMUTimer *ts);
31
30
32
+/* Queue Handling */
31
-/**
33
+
32
- * timer_free:
34
+#define Q_BASE(q) ((q)->base & SMMU_BASE_ADDR_MASK)
33
- * @ts: the timer
35
+#define WRAP_MASK(q) (1 << (q)->log2size)
34
- *
36
+#define INDEX_MASK(q) (((1 << (q)->log2size)) - 1)
35
- * Free a timer (it must not be on the active list)
37
+#define WRAP_INDEX_MASK(q) ((1 << ((q)->log2size + 1)) - 1)
36
- */
38
+
37
-static inline void timer_free(QEMUTimer *ts)
39
+#define Q_CONS(q) ((q)->cons & INDEX_MASK(q))
38
-{
40
+#define Q_PROD(q) ((q)->prod & INDEX_MASK(q))
39
- g_free(ts);
41
+
40
-}
42
+#define Q_CONS_ENTRY(q) (Q_BASE(q) + (q)->entry_size * Q_CONS(q))
41
-
43
+#define Q_PROD_ENTRY(q) (Q_BASE(q) + (q)->entry_size * Q_PROD(q))
42
/**
44
+
43
* timer_del:
45
+#define Q_CONS_WRAP(q) (((q)->cons & WRAP_MASK(q)) >> (q)->log2size)
44
* @ts: the timer
46
+#define Q_PROD_WRAP(q) (((q)->prod & WRAP_MASK(q)) >> (q)->log2size)
45
@@ -XXX,XX +XXX,XX @@ static inline void timer_free(QEMUTimer *ts)
47
+
46
*/
48
+static inline bool smmuv3_q_full(SMMUQueue *q)
47
void timer_del(QEMUTimer *ts);
48
49
+/**
50
+ * timer_free:
51
+ * @ts: the timer
52
+ *
53
+ * Free a timer. This will call timer_del() for you to remove
54
+ * the timer from the active list if it was still active.
55
+ */
56
+static inline void timer_free(QEMUTimer *ts)
49
+{
57
+{
50
+ return ((q->cons ^ q->prod) & WRAP_INDEX_MASK(q)) == WRAP_MASK(q);
58
+ timer_del(ts);
59
+ g_free(ts);
51
+}
60
+}
52
+
61
+
53
+static inline bool smmuv3_q_empty(SMMUQueue *q)
62
/**
54
+{
63
* timer_mod_ns:
55
+ return (q->cons & WRAP_INDEX_MASK(q)) == (q->prod & WRAP_INDEX_MASK(q));
64
* @ts: the timer
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;
231
+ }
232
+
233
+ if (smmuv3_q_full(q)) {
234
+ return;
235
+ }
236
+
237
+ queue_write(q, evt);
238
+
239
+ if (smmuv3_q_empty(q)) {
240
+ smmuv3_trigger_irq(s, SMMU_IRQ_EVTQ, 0);
241
+ }
242
+}
243
+
244
static void smmuv3_init_regs(SMMUv3State *s)
245
{
246
/**
247
@@ -XXX,XX +XXX,XX @@ static void smmuv3_init_regs(SMMUv3State *s)
248
s->sid_split = 0;
249
}
250
251
+int smmuv3_cmdq_consume(SMMUv3State *s)
252
+{
253
+ SMMUCmdError cmd_error = SMMU_CERROR_NONE;
254
+ SMMUQueue *q = &s->cmdq;
255
+ SMMUCommandType type = 0;
256
+
257
+ if (!smmuv3_cmdq_enabled(s)) {
258
+ return 0;
259
+ }
260
+ /*
261
+ * some commands depend on register values, typically CR0. In case those
262
+ * register values change while handling the command, spec says it
263
+ * is UNPREDICTABLE whether the command is interpreted under the new
264
+ * or old value.
265
+ */
266
+
267
+ while (!smmuv3_q_empty(q)) {
268
+ uint32_t pending = s->gerror ^ s->gerrorn;
269
+ Cmd cmd;
270
+
271
+ trace_smmuv3_cmdq_consume(Q_PROD(q), Q_CONS(q),
272
+ Q_PROD_WRAP(q), Q_CONS_WRAP(q));
273
+
274
+ if (FIELD_EX32(pending, GERROR, CMDQ_ERR)) {
275
+ break;
276
+ }
277
+
278
+ if (queue_read(q, &cmd) != MEMTX_OK) {
279
+ cmd_error = SMMU_CERROR_ABT;
280
+ break;
281
+ }
282
+
283
+ type = CMD_TYPE(&cmd);
284
+
285
+ trace_smmuv3_cmdq_opcode(smmu_cmd_string(type));
286
+
287
+ switch (type) {
288
+ case SMMU_CMD_SYNC:
289
+ if (CMD_SYNC_CS(&cmd) & CMD_SYNC_SIG_IRQ) {
290
+ smmuv3_trigger_irq(s, SMMU_IRQ_CMD_SYNC, 0);
291
+ }
292
+ break;
293
+ case SMMU_CMD_PREFETCH_CONFIG:
294
+ case SMMU_CMD_PREFETCH_ADDR:
295
+ case SMMU_CMD_CFGI_STE:
296
+ case SMMU_CMD_CFGI_STE_RANGE: /* same as SMMU_CMD_CFGI_ALL */
297
+ case SMMU_CMD_CFGI_CD:
298
+ case SMMU_CMD_CFGI_CD_ALL:
299
+ case SMMU_CMD_TLBI_NH_ALL:
300
+ case SMMU_CMD_TLBI_NH_ASID:
301
+ case SMMU_CMD_TLBI_NH_VA:
302
+ case SMMU_CMD_TLBI_NH_VAA:
303
+ case SMMU_CMD_TLBI_EL3_ALL:
304
+ case SMMU_CMD_TLBI_EL3_VA:
305
+ case SMMU_CMD_TLBI_EL2_ALL:
306
+ case SMMU_CMD_TLBI_EL2_ASID:
307
+ case SMMU_CMD_TLBI_EL2_VA:
308
+ case SMMU_CMD_TLBI_EL2_VAA:
309
+ case SMMU_CMD_TLBI_S12_VMALL:
310
+ case SMMU_CMD_TLBI_S2_IPA:
311
+ case SMMU_CMD_TLBI_NSNH_ALL:
312
+ case SMMU_CMD_ATC_INV:
313
+ case SMMU_CMD_PRI_RESP:
314
+ case SMMU_CMD_RESUME:
315
+ case SMMU_CMD_STALL_TERM:
316
+ trace_smmuv3_unhandled_cmd(type);
317
+ break;
318
+ default:
319
+ cmd_error = SMMU_CERROR_ILL;
320
+ qemu_log_mask(LOG_GUEST_ERROR,
321
+ "Illegal command type: %d\n", CMD_TYPE(&cmd));
322
+ break;
323
+ }
324
+ if (cmd_error) {
325
+ break;
326
+ }
327
+ /*
328
+ * We only increment the cons index after the completion of
329
+ * the command. We do that because the SYNC returns immediately
330
+ * and does not check the completion of previous commands
331
+ */
332
+ queue_cons_incr(q);
333
+ }
334
+
335
+ if (cmd_error) {
336
+ trace_smmuv3_cmdq_consume_error(smmu_cmd_string(type), cmd_error);
337
+ smmu_write_cmdq_err(s, cmd_error);
338
+ smmuv3_trigger_irq(s, SMMU_IRQ_GERROR, R_GERROR_CMDQ_ERR_MASK);
339
+ }
340
+
341
+ trace_smmuv3_cmdq_consume_out(Q_PROD(q), Q_CONS(q),
342
+ Q_PROD_WRAP(q), Q_CONS_WRAP(q));
343
+
344
+ return 0;
345
+}
346
+
347
static MemTxResult smmu_write_mmio(void *opaque, hwaddr offset, uint64_t data,
348
unsigned size, MemTxAttrs attrs)
349
{
350
diff --git a/hw/arm/trace-events b/hw/arm/trace-events
351
index XXXXXXX..XXXXXXX 100644
352
--- a/hw/arm/trace-events
353
+++ b/hw/arm/trace-events
354
@@ -XXX,XX +XXX,XX @@ smmuv3_read_mmio(uint64_t addr, uint64_t val, unsigned size, uint32_t r) "addr:
355
smmuv3_trigger_irq(int irq) "irq=%d"
356
smmuv3_write_gerror(uint32_t toggled, uint32_t gerror) "toggled=0x%x, new GERROR=0x%x"
357
smmuv3_write_gerrorn(uint32_t acked, uint32_t gerrorn) "acked=0x%x, new GERRORN=0x%x"
358
+smmuv3_unhandled_cmd(uint32_t type) "Unhandled command type=%d"
359
+smmuv3_cmdq_consume(uint32_t prod, uint32_t cons, uint8_t prod_wrap, uint8_t cons_wrap) "prod=%d cons=%d prod.wrap=%d cons.wrap=%d"
360
+smmuv3_cmdq_opcode(const char *opcode) "<--- %s"
361
+smmuv3_cmdq_consume_out(uint32_t prod, uint32_t cons, uint8_t prod_wrap, uint8_t cons_wrap) "prod:%d, cons:%d, prod_wrap:%d, cons_wrap:%d "
362
+smmuv3_cmdq_consume_error(const char *cmd_name, uint8_t cmd_error) "Error on %s command execution: %d"
363
--
65
--
364
2.17.0
66
2.20.1
365
67
366
68
diff view generated by jsdifflib
1
From: Prem Mallappa <prem.mallappa@broadcom.com>
1
Now that timer_free() implicitly calls timer_del(), sequences
2
timer_del(mytimer);
3
timer_free(mytimer);
2
4
3
This patch implements a skeleton for the smmuv3 device.
5
can be simplified to just
4
Datatypes and register definitions are introduced. The MMIO
6
timer_free(mytimer);
5
region, the interrupts and the queue are initialized.
6
7
7
Only the MMIO read operation is implemented here.
8
Add a Coccinelle script to do this transformation.
8
9
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>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Acked-by: Paolo Bonzini <pbonzini@redhat.com>
12
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
13
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
14
Message-id: 20201215154107.3255-3-peter.maydell@linaro.org
14
---
15
---
15
hw/arm/Makefile.objs | 2 +-
16
scripts/coccinelle/timer-del-timer-free.cocci | 18 ++++++++++++++++++
16
hw/arm/smmuv3-internal.h | 142 +++++++++++++++
17
1 file changed, 18 insertions(+)
17
include/hw/arm/smmuv3.h | 87 ++++++++++
18
create mode 100644 scripts/coccinelle/timer-del-timer-free.cocci
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
19
25
diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
20
diff --git a/scripts/coccinelle/timer-del-timer-free.cocci b/scripts/coccinelle/timer-del-timer-free.cocci
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
21
new file mode 100644
37
index XXXXXXX..XXXXXXX
22
index XXXXXXX..XXXXXXX
38
--- /dev/null
23
--- /dev/null
39
+++ b/hw/arm/smmuv3-internal.h
24
+++ b/scripts/coccinelle/timer-del-timer-free.cocci
40
@@ -XXX,XX +XXX,XX @@
25
@@ -XXX,XX +XXX,XX @@
41
+/*
26
+// Remove superfluous timer_del() calls
42
+ * ARM SMMUv3 support - Internal API
27
+//
43
+ *
28
+// Copyright Linaro Limited 2020
44
+ * Copyright (C) 2014-2016 Broadcom Corporation
29
+// This work is licensed under the terms of the GNU GPLv2 or later.
45
+ * Copyright (c) 2017 Red Hat, Inc.
30
+//
46
+ * Written by Prem Mallappa, Eric Auger
31
+// spatch --macro-file scripts/cocci-macro-file.h \
47
+ *
32
+// --sp-file scripts/coccinelle/timer-del-timer-free.cocci \
48
+ * This program is free software; you can redistribute it and/or modify
33
+// --in-place --dir .
49
+ * it under the terms of the GNU General Public License version 2 as
34
+//
50
+ * published by the Free Software Foundation.
35
+// The timer_free() function now implicitly calls timer_del()
51
+ *
36
+// for you, so calls to timer_del() immediately before the
52
+ * This program is distributed in the hope that it will be useful,
37
+// timer_free() of the same timer can be deleted.
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
+
38
+
61
+#ifndef HW_ARM_SMMU_V3_INTERNAL_H
39
+@@
62
+#define HW_ARM_SMMU_V3_INTERNAL_H
40
+expression T;
63
+
41
+@@
64
+#include "hw/arm/smmu-common.h"
42
+-timer_del(T);
65
+
43
+ timer_free(T);
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
--
44
--
660
2.17.0
45
2.20.1
661
46
662
47
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
This commit is the result of running the timer-del-timer-free.cocci
2
script on the whole source tree.
2
3
3
The (size > 3 && !is_q) condition is identical to the preceeding test
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
of bit 3 in immh; eliminate it. For the benefit of Coverity, assert
5
Acked-by: Corey Minyard <cminyard@mvista.com>
5
that size is within the bounds we expect.
6
Acked-by: Paolo Bonzini <pbonzini@redhat.com>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20201215154107.3255-4-peter.maydell@linaro.org
10
---
11
block/iscsi.c | 2 --
12
block/nbd.c | 1 -
13
block/qcow2.c | 1 -
14
hw/block/nvme.c | 2 --
15
hw/char/serial.c | 2 --
16
hw/char/virtio-serial-bus.c | 2 --
17
hw/ide/core.c | 1 -
18
hw/input/hid.c | 1 -
19
hw/intc/apic.c | 1 -
20
hw/intc/ioapic.c | 1 -
21
hw/ipmi/ipmi_bmc_extern.c | 1 -
22
hw/net/e1000.c | 3 ---
23
hw/net/e1000e_core.c | 8 --------
24
hw/net/pcnet-pci.c | 1 -
25
hw/net/rtl8139.c | 1 -
26
hw/net/spapr_llan.c | 1 -
27
hw/net/virtio-net.c | 2 --
28
hw/s390x/s390-pci-inst.c | 1 -
29
hw/sd/sd.c | 1 -
30
hw/sd/sdhci.c | 2 --
31
hw/usb/dev-hub.c | 1 -
32
hw/usb/hcd-ehci.c | 1 -
33
hw/usb/hcd-ohci-pci.c | 1 -
34
hw/usb/hcd-uhci.c | 1 -
35
hw/usb/hcd-xhci.c | 1 -
36
hw/usb/redirect.c | 1 -
37
hw/vfio/display.c | 1 -
38
hw/virtio/vhost-vsock-common.c | 1 -
39
hw/virtio/virtio-balloon.c | 1 -
40
hw/virtio/virtio-rng.c | 1 -
41
hw/watchdog/wdt_diag288.c | 1 -
42
hw/watchdog/wdt_i6300esb.c | 1 -
43
migration/colo.c | 1 -
44
monitor/hmp-cmds.c | 1 -
45
net/announce.c | 1 -
46
net/colo-compare.c | 1 -
47
net/slirp.c | 1 -
48
replay/replay-debugging.c | 1 -
49
target/s390x/cpu.c | 2 --
50
ui/console.c | 1 -
51
ui/spice-core.c | 1 -
52
util/throttle.c | 1 -
53
42 files changed, 58 deletions(-)
6
54
7
Fixes: Coverity CID1385846
55
diff --git a/block/iscsi.c b/block/iscsi.c
8
Fixes: Coverity CID1385849
56
index XXXXXXX..XXXXXXX 100644
9
Fixes: Coverity CID1385852
57
--- a/block/iscsi.c
10
Fixes: Coverity CID1385857
58
+++ b/block/iscsi.c
11
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
59
@@ -XXX,XX +XXX,XX @@ static void iscsi_detach_aio_context(BlockDriverState *bs)
12
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
60
iscsilun->events = 0;
13
Message-id: 20180501180455.11214-2-richard.henderson@linaro.org
61
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
62
if (iscsilun->nop_timer) {
15
---
63
- timer_del(iscsilun->nop_timer);
16
target/arm/translate-a64.c | 6 +-----
64
timer_free(iscsilun->nop_timer);
17
1 file changed, 1 insertion(+), 5 deletions(-)
65
iscsilun->nop_timer = NULL;
18
66
}
19
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
67
if (iscsilun->event_timer) {
20
index XXXXXXX..XXXXXXX 100644
68
- timer_del(iscsilun->event_timer);
21
--- a/target/arm/translate-a64.c
69
timer_free(iscsilun->event_timer);
22
+++ b/target/arm/translate-a64.c
70
iscsilun->event_timer = NULL;
23
@@ -XXX,XX +XXX,XX @@ static void handle_vec_simd_shri(DisasContext *s, bool is_q, bool is_u,
71
}
24
unallocated_encoding(s);
72
diff --git a/block/nbd.c b/block/nbd.c
73
index XXXXXXX..XXXXXXX 100644
74
--- a/block/nbd.c
75
+++ b/block/nbd.c
76
@@ -XXX,XX +XXX,XX @@ static void nbd_recv_coroutines_wake_all(BDRVNBDState *s)
77
static void reconnect_delay_timer_del(BDRVNBDState *s)
78
{
79
if (s->reconnect_delay_timer) {
80
- timer_del(s->reconnect_delay_timer);
81
timer_free(s->reconnect_delay_timer);
82
s->reconnect_delay_timer = NULL;
83
}
84
diff --git a/block/qcow2.c b/block/qcow2.c
85
index XXXXXXX..XXXXXXX 100644
86
--- a/block/qcow2.c
87
+++ b/block/qcow2.c
88
@@ -XXX,XX +XXX,XX @@ static void cache_clean_timer_del(BlockDriverState *bs)
89
{
90
BDRVQcow2State *s = bs->opaque;
91
if (s->cache_clean_timer) {
92
- timer_del(s->cache_clean_timer);
93
timer_free(s->cache_clean_timer);
94
s->cache_clean_timer = NULL;
95
}
96
diff --git a/hw/block/nvme.c b/hw/block/nvme.c
97
index XXXXXXX..XXXXXXX 100644
98
--- a/hw/block/nvme.c
99
+++ b/hw/block/nvme.c
100
@@ -XXX,XX +XXX,XX @@ static uint16_t nvme_io_cmd(NvmeCtrl *n, NvmeRequest *req)
101
static void nvme_free_sq(NvmeSQueue *sq, NvmeCtrl *n)
102
{
103
n->sq[sq->sqid] = NULL;
104
- timer_del(sq->timer);
105
timer_free(sq->timer);
106
g_free(sq->io_req);
107
if (sq->sqid) {
108
@@ -XXX,XX +XXX,XX @@ static uint16_t nvme_get_log(NvmeCtrl *n, NvmeRequest *req)
109
static void nvme_free_cq(NvmeCQueue *cq, NvmeCtrl *n)
110
{
111
n->cq[cq->cqid] = NULL;
112
- timer_del(cq->timer);
113
timer_free(cq->timer);
114
msix_vector_unuse(&n->parent_obj, cq->vector);
115
if (cq->cqid) {
116
diff --git a/hw/char/serial.c b/hw/char/serial.c
117
index XXXXXXX..XXXXXXX 100644
118
--- a/hw/char/serial.c
119
+++ b/hw/char/serial.c
120
@@ -XXX,XX +XXX,XX @@ static void serial_unrealize(DeviceState *dev)
121
122
qemu_chr_fe_deinit(&s->chr, false);
123
124
- timer_del(s->modem_status_poll);
125
timer_free(s->modem_status_poll);
126
127
- timer_del(s->fifo_timeout_timer);
128
timer_free(s->fifo_timeout_timer);
129
130
fifo8_destroy(&s->recv_fifo);
131
diff --git a/hw/char/virtio-serial-bus.c b/hw/char/virtio-serial-bus.c
132
index XXXXXXX..XXXXXXX 100644
133
--- a/hw/char/virtio-serial-bus.c
134
+++ b/hw/char/virtio-serial-bus.c
135
@@ -XXX,XX +XXX,XX @@ static void virtio_serial_post_load_timer_cb(void *opaque)
136
}
137
}
138
g_free(s->post_load->connected);
139
- timer_del(s->post_load->timer);
140
timer_free(s->post_load->timer);
141
g_free(s->post_load);
142
s->post_load = NULL;
143
@@ -XXX,XX +XXX,XX @@ static void virtio_serial_device_unrealize(DeviceState *dev)
144
g_free(vser->ports_map);
145
if (vser->post_load) {
146
g_free(vser->post_load->connected);
147
- timer_del(vser->post_load->timer);
148
timer_free(vser->post_load->timer);
149
g_free(vser->post_load);
150
}
151
diff --git a/hw/ide/core.c b/hw/ide/core.c
152
index XXXXXXX..XXXXXXX 100644
153
--- a/hw/ide/core.c
154
+++ b/hw/ide/core.c
155
@@ -XXX,XX +XXX,XX @@ void ide_init2(IDEBus *bus, qemu_irq irq)
156
157
void ide_exit(IDEState *s)
158
{
159
- timer_del(s->sector_write_timer);
160
timer_free(s->sector_write_timer);
161
qemu_vfree(s->smart_selftest_data);
162
qemu_vfree(s->io_buffer);
163
diff --git a/hw/input/hid.c b/hw/input/hid.c
164
index XXXXXXX..XXXXXXX 100644
165
--- a/hw/input/hid.c
166
+++ b/hw/input/hid.c
167
@@ -XXX,XX +XXX,XX @@ static void hid_idle_timer(void *opaque)
168
static void hid_del_idle_timer(HIDState *hs)
169
{
170
if (hs->idle_timer) {
171
- timer_del(hs->idle_timer);
172
timer_free(hs->idle_timer);
173
hs->idle_timer = NULL;
174
}
175
diff --git a/hw/intc/apic.c b/hw/intc/apic.c
176
index XXXXXXX..XXXXXXX 100644
177
--- a/hw/intc/apic.c
178
+++ b/hw/intc/apic.c
179
@@ -XXX,XX +XXX,XX @@ static void apic_unrealize(DeviceState *dev)
180
{
181
APICCommonState *s = APIC(dev);
182
183
- timer_del(s->timer);
184
timer_free(s->timer);
185
local_apics[s->id] = NULL;
186
}
187
diff --git a/hw/intc/ioapic.c b/hw/intc/ioapic.c
188
index XXXXXXX..XXXXXXX 100644
189
--- a/hw/intc/ioapic.c
190
+++ b/hw/intc/ioapic.c
191
@@ -XXX,XX +XXX,XX @@ static void ioapic_unrealize(DeviceState *dev)
192
{
193
IOAPICCommonState *s = IOAPIC_COMMON(dev);
194
195
- timer_del(s->delayed_ioapic_service_timer);
196
timer_free(s->delayed_ioapic_service_timer);
197
}
198
199
diff --git a/hw/ipmi/ipmi_bmc_extern.c b/hw/ipmi/ipmi_bmc_extern.c
200
index XXXXXXX..XXXXXXX 100644
201
--- a/hw/ipmi/ipmi_bmc_extern.c
202
+++ b/hw/ipmi/ipmi_bmc_extern.c
203
@@ -XXX,XX +XXX,XX @@ static void ipmi_bmc_extern_finalize(Object *obj)
204
{
205
IPMIBmcExtern *ibe = IPMI_BMC_EXTERN(obj);
206
207
- timer_del(ibe->extern_timer);
208
timer_free(ibe->extern_timer);
209
}
210
211
diff --git a/hw/net/e1000.c b/hw/net/e1000.c
212
index XXXXXXX..XXXXXXX 100644
213
--- a/hw/net/e1000.c
214
+++ b/hw/net/e1000.c
215
@@ -XXX,XX +XXX,XX @@ pci_e1000_uninit(PCIDevice *dev)
216
{
217
E1000State *d = E1000(dev);
218
219
- timer_del(d->autoneg_timer);
220
timer_free(d->autoneg_timer);
221
- timer_del(d->mit_timer);
222
timer_free(d->mit_timer);
223
- timer_del(d->flush_queue_timer);
224
timer_free(d->flush_queue_timer);
225
qemu_del_nic(d->nic);
226
}
227
diff --git a/hw/net/e1000e_core.c b/hw/net/e1000e_core.c
228
index XXXXXXX..XXXXXXX 100644
229
--- a/hw/net/e1000e_core.c
230
+++ b/hw/net/e1000e_core.c
231
@@ -XXX,XX +XXX,XX @@ e1000e_intrmgr_pci_unint(E1000ECore *core)
232
{
233
int i;
234
235
- timer_del(core->radv.timer);
236
timer_free(core->radv.timer);
237
- timer_del(core->rdtr.timer);
238
timer_free(core->rdtr.timer);
239
- timer_del(core->raid.timer);
240
timer_free(core->raid.timer);
241
242
- timer_del(core->tadv.timer);
243
timer_free(core->tadv.timer);
244
- timer_del(core->tidv.timer);
245
timer_free(core->tidv.timer);
246
247
- timer_del(core->itr.timer);
248
timer_free(core->itr.timer);
249
250
for (i = 0; i < E1000E_MSIX_VEC_NUM; i++) {
251
- timer_del(core->eitr[i].timer);
252
timer_free(core->eitr[i].timer);
253
}
254
}
255
@@ -XXX,XX +XXX,XX @@ e1000e_core_pci_uninit(E1000ECore *core)
256
{
257
int i;
258
259
- timer_del(core->autoneg_timer);
260
timer_free(core->autoneg_timer);
261
262
e1000e_intrmgr_pci_unint(core);
263
diff --git a/hw/net/pcnet-pci.c b/hw/net/pcnet-pci.c
264
index XXXXXXX..XXXXXXX 100644
265
--- a/hw/net/pcnet-pci.c
266
+++ b/hw/net/pcnet-pci.c
267
@@ -XXX,XX +XXX,XX @@ static void pci_pcnet_uninit(PCIDevice *dev)
268
PCIPCNetState *d = PCI_PCNET(dev);
269
270
qemu_free_irq(d->state.irq);
271
- timer_del(d->state.poll_timer);
272
timer_free(d->state.poll_timer);
273
qemu_del_nic(d->state.nic);
274
}
275
diff --git a/hw/net/rtl8139.c b/hw/net/rtl8139.c
276
index XXXXXXX..XXXXXXX 100644
277
--- a/hw/net/rtl8139.c
278
+++ b/hw/net/rtl8139.c
279
@@ -XXX,XX +XXX,XX @@ static void pci_rtl8139_uninit(PCIDevice *dev)
280
281
g_free(s->cplus_txbuffer);
282
s->cplus_txbuffer = NULL;
283
- timer_del(s->timer);
284
timer_free(s->timer);
285
qemu_del_nic(s->nic);
286
}
287
diff --git a/hw/net/spapr_llan.c b/hw/net/spapr_llan.c
288
index XXXXXXX..XXXXXXX 100644
289
--- a/hw/net/spapr_llan.c
290
+++ b/hw/net/spapr_llan.c
291
@@ -XXX,XX +XXX,XX @@ static void spapr_vlan_instance_finalize(Object *obj)
292
}
293
294
if (dev->rxp_timer) {
295
- timer_del(dev->rxp_timer);
296
timer_free(dev->rxp_timer);
297
}
298
}
299
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
300
index XXXXXXX..XXXXXXX 100644
301
--- a/hw/net/virtio-net.c
302
+++ b/hw/net/virtio-net.c
303
@@ -XXX,XX +XXX,XX @@ static void virtio_net_rsc_cleanup(VirtIONet *n)
304
g_free(seg);
305
}
306
307
- timer_del(chain->drain_timer);
308
timer_free(chain->drain_timer);
309
QTAILQ_REMOVE(&n->rsc_chains, chain, next);
310
g_free(chain);
311
@@ -XXX,XX +XXX,XX @@ static void virtio_net_del_queue(VirtIONet *n, int index)
312
313
virtio_del_queue(vdev, index * 2);
314
if (q->tx_timer) {
315
- timer_del(q->tx_timer);
316
timer_free(q->tx_timer);
317
q->tx_timer = NULL;
318
} else {
319
diff --git a/hw/s390x/s390-pci-inst.c b/hw/s390x/s390-pci-inst.c
320
index XXXXXXX..XXXXXXX 100644
321
--- a/hw/s390x/s390-pci-inst.c
322
+++ b/hw/s390x/s390-pci-inst.c
323
@@ -XXX,XX +XXX,XX @@ void pci_dereg_ioat(S390PCIIOMMU *iommu)
324
void fmb_timer_free(S390PCIBusDevice *pbdev)
325
{
326
if (pbdev->fmb_timer) {
327
- timer_del(pbdev->fmb_timer);
328
timer_free(pbdev->fmb_timer);
329
pbdev->fmb_timer = NULL;
330
}
331
diff --git a/hw/sd/sd.c b/hw/sd/sd.c
332
index XXXXXXX..XXXXXXX 100644
333
--- a/hw/sd/sd.c
334
+++ b/hw/sd/sd.c
335
@@ -XXX,XX +XXX,XX @@ static void sd_instance_finalize(Object *obj)
336
{
337
SDState *sd = SD_CARD(obj);
338
339
- timer_del(sd->ocr_power_timer);
340
timer_free(sd->ocr_power_timer);
341
}
342
343
diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
344
index XXXXXXX..XXXXXXX 100644
345
--- a/hw/sd/sdhci.c
346
+++ b/hw/sd/sdhci.c
347
@@ -XXX,XX +XXX,XX @@ void sdhci_initfn(SDHCIState *s)
348
349
void sdhci_uninitfn(SDHCIState *s)
350
{
351
- timer_del(s->insert_timer);
352
timer_free(s->insert_timer);
353
- timer_del(s->transfer_timer);
354
timer_free(s->transfer_timer);
355
356
g_free(s->fifo_buffer);
357
diff --git a/hw/usb/dev-hub.c b/hw/usb/dev-hub.c
358
index XXXXXXX..XXXXXXX 100644
359
--- a/hw/usb/dev-hub.c
360
+++ b/hw/usb/dev-hub.c
361
@@ -XXX,XX +XXX,XX @@ static void usb_hub_unrealize(USBDevice *dev)
362
&s->ports[i].port);
363
}
364
365
- timer_del(s->port_timer);
366
timer_free(s->port_timer);
367
}
368
369
diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
370
index XXXXXXX..XXXXXXX 100644
371
--- a/hw/usb/hcd-ehci.c
372
+++ b/hw/usb/hcd-ehci.c
373
@@ -XXX,XX +XXX,XX @@ void usb_ehci_unrealize(EHCIState *s, DeviceState *dev)
374
trace_usb_ehci_unrealize();
375
376
if (s->frame_timer) {
377
- timer_del(s->frame_timer);
378
timer_free(s->frame_timer);
379
s->frame_timer = NULL;
380
}
381
diff --git a/hw/usb/hcd-ohci-pci.c b/hw/usb/hcd-ohci-pci.c
382
index XXXXXXX..XXXXXXX 100644
383
--- a/hw/usb/hcd-ohci-pci.c
384
+++ b/hw/usb/hcd-ohci-pci.c
385
@@ -XXX,XX +XXX,XX @@ static void usb_ohci_exit(PCIDevice *dev)
386
usb_bus_release(&s->bus);
387
}
388
389
- timer_del(s->eof_timer);
390
timer_free(s->eof_timer);
391
}
392
393
diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c
394
index XXXXXXX..XXXXXXX 100644
395
--- a/hw/usb/hcd-uhci.c
396
+++ b/hw/usb/hcd-uhci.c
397
@@ -XXX,XX +XXX,XX @@ static void usb_uhci_exit(PCIDevice *dev)
398
trace_usb_uhci_exit();
399
400
if (s->frame_timer) {
401
- timer_del(s->frame_timer);
402
timer_free(s->frame_timer);
403
s->frame_timer = NULL;
404
}
405
diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
406
index XXXXXXX..XXXXXXX 100644
407
--- a/hw/usb/hcd-xhci.c
408
+++ b/hw/usb/hcd-xhci.c
409
@@ -XXX,XX +XXX,XX @@ static void usb_xhci_unrealize(DeviceState *dev)
410
}
411
412
if (xhci->mfwrap_timer) {
413
- timer_del(xhci->mfwrap_timer);
414
timer_free(xhci->mfwrap_timer);
415
xhci->mfwrap_timer = NULL;
416
}
417
diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c
418
index XXXXXXX..XXXXXXX 100644
419
--- a/hw/usb/redirect.c
420
+++ b/hw/usb/redirect.c
421
@@ -XXX,XX +XXX,XX @@ static void usbredir_unrealize(USBDevice *udev)
422
qemu_bh_delete(dev->chardev_close_bh);
423
qemu_bh_delete(dev->device_reject_bh);
424
425
- timer_del(dev->attach_timer);
426
timer_free(dev->attach_timer);
427
428
usbredir_cleanup_device_queues(dev);
429
diff --git a/hw/vfio/display.c b/hw/vfio/display.c
430
index XXXXXXX..XXXXXXX 100644
431
--- a/hw/vfio/display.c
432
+++ b/hw/vfio/display.c
433
@@ -XXX,XX +XXX,XX @@ static void vfio_display_edid_exit(VFIODisplay *dpy)
434
435
g_free(dpy->edid_regs);
436
g_free(dpy->edid_blob);
437
- timer_del(dpy->edid_link_timer);
438
timer_free(dpy->edid_link_timer);
439
}
440
441
diff --git a/hw/virtio/vhost-vsock-common.c b/hw/virtio/vhost-vsock-common.c
442
index XXXXXXX..XXXXXXX 100644
443
--- a/hw/virtio/vhost-vsock-common.c
444
+++ b/hw/virtio/vhost-vsock-common.c
445
@@ -XXX,XX +XXX,XX @@ static void vhost_vsock_common_post_load_timer_cleanup(VHostVSockCommon *vvc)
25
return;
446
return;
26
}
447
}
27
-
448
28
- if (size > 3 && !is_q) {
449
- timer_del(vvc->post_load_timer);
29
- unallocated_encoding(s);
450
timer_free(vvc->post_load_timer);
30
- return;
451
vvc->post_load_timer = NULL;
31
- }
452
}
32
+ tcg_debug_assert(size <= 3);
453
diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c
33
454
index XXXXXXX..XXXXXXX 100644
34
if (!fp_access_check(s)) {
455
--- a/hw/virtio/virtio-balloon.c
35
return;
456
+++ b/hw/virtio/virtio-balloon.c
457
@@ -XXX,XX +XXX,XX @@ static bool balloon_stats_enabled(const VirtIOBalloon *s)
458
static void balloon_stats_destroy_timer(VirtIOBalloon *s)
459
{
460
if (balloon_stats_enabled(s)) {
461
- timer_del(s->stats_timer);
462
timer_free(s->stats_timer);
463
s->stats_timer = NULL;
464
s->stats_poll_interval = 0;
465
diff --git a/hw/virtio/virtio-rng.c b/hw/virtio/virtio-rng.c
466
index XXXXXXX..XXXXXXX 100644
467
--- a/hw/virtio/virtio-rng.c
468
+++ b/hw/virtio/virtio-rng.c
469
@@ -XXX,XX +XXX,XX @@ static void virtio_rng_device_unrealize(DeviceState *dev)
470
VirtIORNG *vrng = VIRTIO_RNG(dev);
471
472
qemu_del_vm_change_state_handler(vrng->vmstate);
473
- timer_del(vrng->rate_limit_timer);
474
timer_free(vrng->rate_limit_timer);
475
virtio_del_queue(vdev, 0);
476
virtio_cleanup(vdev);
477
diff --git a/hw/watchdog/wdt_diag288.c b/hw/watchdog/wdt_diag288.c
478
index XXXXXXX..XXXXXXX 100644
479
--- a/hw/watchdog/wdt_diag288.c
480
+++ b/hw/watchdog/wdt_diag288.c
481
@@ -XXX,XX +XXX,XX @@ static void wdt_diag288_unrealize(DeviceState *dev)
482
{
483
DIAG288State *diag288 = DIAG288(dev);
484
485
- timer_del(diag288->timer);
486
timer_free(diag288->timer);
487
}
488
489
diff --git a/hw/watchdog/wdt_i6300esb.c b/hw/watchdog/wdt_i6300esb.c
490
index XXXXXXX..XXXXXXX 100644
491
--- a/hw/watchdog/wdt_i6300esb.c
492
+++ b/hw/watchdog/wdt_i6300esb.c
493
@@ -XXX,XX +XXX,XX @@ static void i6300esb_exit(PCIDevice *dev)
494
{
495
I6300State *d = WATCHDOG_I6300ESB_DEVICE(dev);
496
497
- timer_del(d->timer);
498
timer_free(d->timer);
499
}
500
501
diff --git a/migration/colo.c b/migration/colo.c
502
index XXXXXXX..XXXXXXX 100644
503
--- a/migration/colo.c
504
+++ b/migration/colo.c
505
@@ -XXX,XX +XXX,XX @@ out:
506
* error.
507
*/
508
colo_compare_unregister_notifier(&packets_compare_notifier);
509
- timer_del(s->colo_delay_timer);
510
timer_free(s->colo_delay_timer);
511
qemu_event_destroy(&s->colo_checkpoint_event);
512
513
diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c
514
index XXXXXXX..XXXXXXX 100644
515
--- a/monitor/hmp-cmds.c
516
+++ b/monitor/hmp-cmds.c
517
@@ -XXX,XX +XXX,XX @@ static void hmp_migrate_status_cb(void *opaque)
518
error_report("%s", info->error_desc);
519
}
520
monitor_resume(status->mon);
521
- timer_del(status->timer);
522
timer_free(status->timer);
523
g_free(status);
524
}
525
diff --git a/net/announce.c b/net/announce.c
526
index XXXXXXX..XXXXXXX 100644
527
--- a/net/announce.c
528
+++ b/net/announce.c
529
@@ -XXX,XX +XXX,XX @@ void qemu_announce_timer_del(AnnounceTimer *timer, bool free_named)
530
{
531
bool free_timer = false;
532
if (timer->tm) {
533
- timer_del(timer->tm);
534
timer_free(timer->tm);
535
timer->tm = NULL;
536
}
537
diff --git a/net/colo-compare.c b/net/colo-compare.c
538
index XXXXXXX..XXXXXXX 100644
539
--- a/net/colo-compare.c
540
+++ b/net/colo-compare.c
541
@@ -XXX,XX +XXX,XX @@ static void colo_compare_timer_init(CompareState *s)
542
static void colo_compare_timer_del(CompareState *s)
543
{
544
if (s->packet_check_timer) {
545
- timer_del(s->packet_check_timer);
546
timer_free(s->packet_check_timer);
547
s->packet_check_timer = NULL;
548
}
549
diff --git a/net/slirp.c b/net/slirp.c
550
index XXXXXXX..XXXXXXX 100644
551
--- a/net/slirp.c
552
+++ b/net/slirp.c
553
@@ -XXX,XX +XXX,XX @@ static void *net_slirp_timer_new(SlirpTimerCb cb,
554
555
static void net_slirp_timer_free(void *timer, void *opaque)
556
{
557
- timer_del(timer);
558
timer_free(timer);
559
}
560
561
diff --git a/replay/replay-debugging.c b/replay/replay-debugging.c
562
index XXXXXXX..XXXXXXX 100644
563
--- a/replay/replay-debugging.c
564
+++ b/replay/replay-debugging.c
565
@@ -XXX,XX +XXX,XX @@ static void replay_delete_break(void)
566
assert(replay_mutex_locked());
567
568
if (replay_break_timer) {
569
- timer_del(replay_break_timer);
570
timer_free(replay_break_timer);
571
replay_break_timer = NULL;
572
}
573
diff --git a/target/s390x/cpu.c b/target/s390x/cpu.c
574
index XXXXXXX..XXXXXXX 100644
575
--- a/target/s390x/cpu.c
576
+++ b/target/s390x/cpu.c
577
@@ -XXX,XX +XXX,XX @@ static void s390_cpu_finalize(Object *obj)
578
#if !defined(CONFIG_USER_ONLY)
579
S390CPU *cpu = S390_CPU(obj);
580
581
- timer_del(cpu->env.tod_timer);
582
timer_free(cpu->env.tod_timer);
583
- timer_del(cpu->env.cpu_timer);
584
timer_free(cpu->env.cpu_timer);
585
586
qemu_unregister_reset(s390_cpu_machine_reset_cb, cpu);
587
diff --git a/ui/console.c b/ui/console.c
588
index XXXXXXX..XXXXXXX 100644
589
--- a/ui/console.c
590
+++ b/ui/console.c
591
@@ -XXX,XX +XXX,XX @@ static void gui_setup_refresh(DisplayState *ds)
592
timer_mod(ds->gui_timer, qemu_clock_get_ms(QEMU_CLOCK_REALTIME));
593
}
594
if (!need_timer && ds->gui_timer != NULL) {
595
- timer_del(ds->gui_timer);
596
timer_free(ds->gui_timer);
597
ds->gui_timer = NULL;
598
}
599
diff --git a/ui/spice-core.c b/ui/spice-core.c
600
index XXXXXXX..XXXXXXX 100644
601
--- a/ui/spice-core.c
602
+++ b/ui/spice-core.c
603
@@ -XXX,XX +XXX,XX @@ static void timer_cancel(SpiceTimer *timer)
604
605
static void timer_remove(SpiceTimer *timer)
606
{
607
- timer_del(timer->timer);
608
timer_free(timer->timer);
609
g_free(timer);
610
}
611
diff --git a/util/throttle.c b/util/throttle.c
612
index XXXXXXX..XXXXXXX 100644
613
--- a/util/throttle.c
614
+++ b/util/throttle.c
615
@@ -XXX,XX +XXX,XX @@ static void throttle_timer_destroy(QEMUTimer **timer)
616
{
617
assert(*timer != NULL);
618
619
- timer_del(*timer);
620
timer_free(*timer);
621
*timer = NULL;
622
}
36
--
623
--
37
2.17.0
624
2.20.1
38
625
39
626
diff view generated by jsdifflib
1
From: Thomas Huth <thuth@redhat.com>
1
The Arm CPU finalize function uses a sequence of timer_del(), timer_deinit(),
2
timer_free() to free the timer. The timer_deinit() step in this was always
3
unnecessary, and now the timer_del() is implied by timer_free(), so we can
4
collapse this down to simply calling timer_free().
2
5
3
When running omap1/2 or pxa2xx based ARM machines with -nodefaults,
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
they bail out immediately complaining about a "missing SecureDigital
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
5
device". That's not how the "default" devices in vl.c are meant to
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
work - it should be possible for a board to also start up without
9
Message-id: 20201215154107.3255-5-peter.maydell@linaro.org
7
default devices. So let's turn the error message and exit() into
10
---
8
a warning instead.
11
target/arm/cpu.c | 2 --
12
1 file changed, 2 deletions(-)
9
13
10
Signed-off-by: Thomas Huth <thuth@redhat.com>
14
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
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
15
index XXXXXXX..XXXXXXX 100644
23
--- a/hw/arm/omap1.c
16
--- a/target/arm/cpu.c
24
+++ b/hw/arm/omap1.c
17
+++ b/target/arm/cpu.c
25
@@ -XXX,XX +XXX,XX @@
18
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_finalizefn(Object *obj)
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
}
19
}
43
s->mmc = omap_mmc_init(0xfffb7800, system_memory,
20
#ifndef CONFIG_USER_ONLY
44
- blk_by_legacy_dinfo(dinfo),
21
if (cpu->pmu_timer) {
45
+ dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
22
- timer_del(cpu->pmu_timer);
46
qdev_get_gpio_in(s->ih[1], OMAP_INT_OQN),
23
- timer_deinit(cpu->pmu_timer);
47
&s->drq[OMAP_DMA_MMC_TX],
24
timer_free(cpu->pmu_timer);
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
}
25
}
71
s->mmc = omap2_mmc_init(omap_l4tao(s->l4, 9),
26
#endif
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
--
27
--
122
2.17.0
28
2.20.1
123
29
124
30
diff view generated by jsdifflib
1
From: Eric Auger <eric.auger@redhat.com>
1
From: Gan Qixin <ganqixin@huawei.com>
2
2
3
ARM virt machine now exposes a new "iommu" option.
3
When running device-introspect-test, a memory leak occurred in the
4
The SMMUv3 IOMMU is instantiated using -machine virt,iommu=smmuv3.
4
digic_timer_init function, so use ptimer_free() in the finalize function to
5
avoid it.
5
6
6
Signed-off-by: Eric Auger <eric.auger@redhat.com>
7
ASAN shows memory leak stack:
7
Signed-off-by: Prem Mallappa <prem.mallappa@broadcom.com>
8
9
Indirect leak of 288 byte(s) in 3 object(s) allocated from:
10
#0 0xffffab97e1f0 in __interceptor_calloc (/lib64/libasan.so.5+0xee1f0)
11
#1 0xffffab256800 in g_malloc0 (/lib64/libglib-2.0.so.0+0x56800)
12
#2 0xaaabf555db78 in ptimer_init /qemu/hw/core/ptimer.c:432
13
#3 0xaaabf5b04084 in digic_timer_init /qemu/hw/timer/digic-timer.c:142
14
#4 0xaaabf6339f6c in object_initialize_with_type /qemu/qom/object.c:515
15
#5 0xaaabf633ca04 in object_initialize_child_with_propsv /qemu/qom/object.c:564
16
#6 0xaaabf633cc08 in object_initialize_child_with_props /qemu/qom/object.c:547
17
#7 0xaaabf5b40e84 in digic_init /qemu/hw/arm/digic.c:46
18
#8 0xaaabf6339f6c in object_initialize_with_type /qemu/qom/object.c:515
19
#9 0xaaabf633a1e0 in object_new_with_type /qemu/qom/object.c:729
20
#10 0xaaabf6375e40 in qmp_device_list_properties /qemu/qom/qom-qmp-cmds.c:153
21
#11 0xaaabf653d8ec in qmp_marshal_device_list_properties /qemu/qapi/qapi-commands-qdev.c:59
22
#12 0xaaabf6587d08 in do_qmp_dispatch_bh /qemu/qapi/qmp-dispatch.c:110
23
24
Reported-by: Euler Robot <euler.robot@huawei.com>
25
Signed-off-by: Gan Qixin <ganqixin@huawei.com>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
26
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Message-id: 1524665762-31355-15-git-send-email-eric.auger@redhat.com
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
27
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
28
---
12
hw/arm/virt.c | 36 ++++++++++++++++++++++++++++++++++++
29
hw/timer/digic-timer.c | 8 ++++++++
13
1 file changed, 36 insertions(+)
30
1 file changed, 8 insertions(+)
14
31
15
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
32
diff --git a/hw/timer/digic-timer.c b/hw/timer/digic-timer.c
16
index XXXXXXX..XXXXXXX 100644
33
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/arm/virt.c
34
--- a/hw/timer/digic-timer.c
18
+++ b/hw/arm/virt.c
35
+++ b/hw/timer/digic-timer.c
19
@@ -XXX,XX +XXX,XX @@ static void virt_set_gic_version(Object *obj, const char *value, Error **errp)
36
@@ -XXX,XX +XXX,XX @@ static void digic_timer_init(Object *obj)
20
}
37
sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->iomem);
21
}
38
}
22
39
23
+static char *virt_get_iommu(Object *obj, Error **errp)
40
+static void digic_timer_finalize(Object *obj)
24
+{
41
+{
25
+ VirtMachineState *vms = VIRT_MACHINE(obj);
42
+ DigicTimerState *s = DIGIC_TIMER(obj);
26
+
43
+
27
+ switch (vms->iommu) {
44
+ ptimer_free(s->ptimer);
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
+}
45
+}
36
+
46
+
37
+static void virt_set_iommu(Object *obj, const char *value, Error **errp)
47
static void digic_timer_class_init(ObjectClass *klass, void *class_data)
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
{
48
{
54
@@ -XXX,XX +XXX,XX @@ static void virt_2_12_instance_init(Object *obj)
49
DeviceClass *dc = DEVICE_CLASS(klass);
55
NULL);
50
@@ -XXX,XX +XXX,XX @@ static const TypeInfo digic_timer_info = {
56
}
51
.parent = TYPE_SYS_BUS_DEVICE,
57
52
.instance_size = sizeof(DigicTimerState),
58
+ /* Default disallows iommu instantiation */
53
.instance_init = digic_timer_init,
59
+ vms->iommu = VIRT_IOMMU_NONE;
54
+ .instance_finalize = digic_timer_finalize,
60
+ object_property_add_str(obj, "iommu", virt_get_iommu, virt_set_iommu, NULL);
55
.class_init = digic_timer_class_init,
61
+ object_property_set_description(obj, "iommu",
56
};
62
+ "Set the IOMMU type. "
57
63
+ "Valid values are none and smmuv3",
64
+ NULL);
65
+
66
vms->memmap = a15memmap;
67
vms->irqmap = a15irqmap;
68
}
69
--
58
--
70
2.17.0
59
2.20.1
71
60
72
61
diff view generated by jsdifflib
1
From: Eric Auger <eric.auger@redhat.com>
1
From: Gan Qixin <ganqixin@huawei.com>
2
2
3
Now we have relevant helpers for queue and irq
3
When running device-introspect-test, a memory leak occurred in the a10_pit_init
4
management, let's implement MMIO write operations.
4
function, so use ptimer_free() in the finalize function to avoid it.
5
5
6
Signed-off-by: Eric Auger <eric.auger@redhat.com>
6
ASAN shows memory leak stack:
7
Signed-off-by: Prem Mallappa <prem.mallappa@broadcom.com>
7
8
Indirect leak of 288 byte(s) in 6 object(s) allocated from:
9
#0 0xffffab97e1f0 in __interceptor_calloc (/lib64/libasan.so.5+0xee1f0)
10
#1 0xffffab256800 in g_malloc0 (/lib64/libglib-2.0.so.0+0x56800)
11
#2 0xaaabf555db84 in timer_new_full /qemu/include/qemu/timer.h:523
12
#3 0xaaabf555db84 in timer_new /qemu/include/qemu/timer.h:544
13
#4 0xaaabf555db84 in timer_new_ns /qemu/include/qemu/timer.h:562
14
#5 0xaaabf555db84 in ptimer_init /qemu/hw/core/ptimer.c:433
15
#6 0xaaabf57415e8 in a10_pit_init /qemu/hw/timer/allwinner-a10-pit.c:278
16
#7 0xaaabf6339f6c in object_initialize_with_type /qemu/qom/object.c:515
17
#8 0xaaabf633ca04 in object_initialize_child_with_propsv /qemu/qom/object.c:564
18
#9 0xaaabf633cc08 in object_initialize_child_with_props /qemu/qom/object.c:547
19
#10 0xaaabf5b94680 in aw_a10_init /qemu/hw/arm/allwinner-a10.c:49
20
#11 0xaaabf6339f6c in object_initialize_with_type /qemu/qom/object.c:515
21
#12 0xaaabf633a1e0 in object_new_with_type /qemu/qom/object.c:729
22
23
Reported-by: Euler Robot <euler.robot@huawei.com>
24
Signed-off-by: Gan Qixin <ganqixin@huawei.com>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
25
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Message-id: 1524665762-31355-8-git-send-email-eric.auger@redhat.com
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
26
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
27
---
12
hw/arm/smmuv3-internal.h | 8 +-
28
hw/timer/allwinner-a10-pit.c | 11 +++++++++++
13
hw/arm/smmuv3.c | 170 +++++++++++++++++++++++++++++++++++++--
29
1 file changed, 11 insertions(+)
14
hw/arm/trace-events | 6 ++
15
3 files changed, 174 insertions(+), 10 deletions(-)
16
30
17
diff --git a/hw/arm/smmuv3-internal.h b/hw/arm/smmuv3-internal.h
31
diff --git a/hw/timer/allwinner-a10-pit.c b/hw/timer/allwinner-a10-pit.c
18
index XXXXXXX..XXXXXXX 100644
32
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/arm/smmuv3-internal.h
33
--- a/hw/timer/allwinner-a10-pit.c
20
+++ b/hw/arm/smmuv3-internal.h
34
+++ b/hw/timer/allwinner-a10-pit.c
21
@@ -XXX,XX +XXX,XX @@ REG32(CR0, 0x20)
35
@@ -XXX,XX +XXX,XX @@ static void a10_pit_init(Object *obj)
22
FIELD(CR0, EVENTQEN, 2, 1)
23
FIELD(CR0, CMDQEN, 3, 1)
24
25
+#define SMMU_CR0_RESERVED 0xFFFFFC20
26
+
27
REG32(CR0ACK, 0x24)
28
REG32(CR1, 0x28)
29
REG32(CR2, 0x2c)
30
@@ -XXX,XX +XXX,XX @@ static inline bool smmuv3_gerror_irq_enabled(SMMUv3State *s)
31
return FIELD_EX32(s->irq_ctrl, IRQ_CTRL, GERROR_IRQEN);
32
}
33
34
-/* public until callers get introduced */
35
-void smmuv3_trigger_irq(SMMUv3State *s, SMMUIrq irq, uint32_t gerror_mask);
36
-void smmuv3_write_gerrorn(SMMUv3State *s, uint32_t gerrorn);
37
-
38
/* Queue Handling */
39
40
#define Q_BASE(q) ((q)->base & SMMU_BASE_ADDR_MASK)
41
@@ -XXX,XX +XXX,XX @@ enum { /* Command completion notification */
42
addr; \
43
})
44
45
-int smmuv3_cmdq_consume(SMMUv3State *s);
46
+#define SMMU_FEATURE_2LVL_STE (1 << 0)
47
48
#endif
49
diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c
50
index XXXXXXX..XXXXXXX 100644
51
--- a/hw/arm/smmuv3.c
52
+++ b/hw/arm/smmuv3.c
53
@@ -XXX,XX +XXX,XX @@
54
* @irq: irq type
55
* @gerror_mask: mask of gerrors to toggle (relevant if @irq is GERROR)
56
*/
57
-void smmuv3_trigger_irq(SMMUv3State *s, SMMUIrq irq, uint32_t gerror_mask)
58
+static void smmuv3_trigger_irq(SMMUv3State *s, SMMUIrq irq,
59
+ uint32_t gerror_mask)
60
{
61
62
bool pulse = false;
63
@@ -XXX,XX +XXX,XX @@ void smmuv3_trigger_irq(SMMUv3State *s, SMMUIrq irq, uint32_t gerror_mask)
64
}
36
}
65
}
37
}
66
38
67
-void smmuv3_write_gerrorn(SMMUv3State *s, uint32_t new_gerrorn)
39
+static void a10_pit_finalize(Object *obj)
68
+static void smmuv3_write_gerrorn(SMMUv3State *s, uint32_t new_gerrorn)
69
{
70
uint32_t pending = s->gerror ^ s->gerrorn;
71
uint32_t toggled = s->gerrorn ^ new_gerrorn;
72
@@ -XXX,XX +XXX,XX @@ static void smmuv3_init_regs(SMMUv3State *s)
73
s->sid_split = 0;
74
}
75
76
-int smmuv3_cmdq_consume(SMMUv3State *s)
77
+static int smmuv3_cmdq_consume(SMMUv3State *s)
78
{
79
SMMUCmdError cmd_error = SMMU_CERROR_NONE;
80
SMMUQueue *q = &s->cmdq;
81
@@ -XXX,XX +XXX,XX @@ int smmuv3_cmdq_consume(SMMUv3State *s)
82
return 0;
83
}
84
85
+static MemTxResult smmu_writell(SMMUv3State *s, hwaddr offset,
86
+ uint64_t data, MemTxAttrs attrs)
87
+{
40
+{
88
+ switch (offset) {
41
+ AwA10PITState *s = AW_A10_PIT(obj);
89
+ case A_GERROR_IRQ_CFG0:
42
+ int i;
90
+ s->gerror_irq_cfg0 = data;
43
+
91
+ return MEMTX_OK;
44
+ for (i = 0; i < AW_A10_PIT_TIMER_NR; i++) {
92
+ case A_STRTAB_BASE:
45
+ ptimer_free(s->timer[i]);
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
+ }
46
+ }
118
+}
47
+}
119
+
48
+
120
+static MemTxResult smmu_writel(SMMUv3State *s, hwaddr offset,
49
static void a10_pit_class_init(ObjectClass *klass, void *data)
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
{
50
{
228
- /* not yet implemented */
51
DeviceClass *dc = DEVICE_CLASS(klass);
229
- return MEMTX_ERROR;
52
@@ -XXX,XX +XXX,XX @@ static const TypeInfo a10_pit_info = {
230
+ SMMUState *sys = opaque;
53
.parent = TYPE_SYS_BUS_DEVICE,
231
+ SMMUv3State *s = ARM_SMMUV3(sys);
54
.instance_size = sizeof(AwA10PITState),
232
+ MemTxResult r;
55
.instance_init = a10_pit_init,
233
+
56
+ .instance_finalize = a10_pit_finalize,
234
+ /* CONSTRAINED UNPREDICTABLE choice to have page0/1 be exact aliases */
57
.class_init = a10_pit_class_init,
235
+ offset &= ~0x10000;
58
};
236
+
59
237
+ switch (size) {
238
+ case 8:
239
+ r = smmu_writell(s, offset, data, attrs);
240
+ break;
241
+ case 4:
242
+ r = smmu_writel(s, offset, data, attrs);
243
+ break;
244
+ default:
245
+ r = MEMTX_ERROR;
246
+ break;
247
+ }
248
+
249
+ trace_smmuv3_write_mmio(offset, data, size, r);
250
+ return r;
251
}
252
253
static MemTxResult smmu_readll(SMMUv3State *s, hwaddr offset,
254
diff --git a/hw/arm/trace-events b/hw/arm/trace-events
255
index XXXXXXX..XXXXXXX 100644
256
--- a/hw/arm/trace-events
257
+++ b/hw/arm/trace-events
258
@@ -XXX,XX +XXX,XX @@ smmuv3_cmdq_consume(uint32_t prod, uint32_t cons, uint8_t prod_wrap, uint8_t con
259
smmuv3_cmdq_opcode(const char *opcode) "<--- %s"
260
smmuv3_cmdq_consume_out(uint32_t prod, uint32_t cons, uint8_t prod_wrap, uint8_t cons_wrap) "prod:%d, cons:%d, prod_wrap:%d, cons_wrap:%d "
261
smmuv3_cmdq_consume_error(const char *cmd_name, uint8_t cmd_error) "Error on %s command execution: %d"
262
+smmuv3_update(bool is_empty, uint32_t prod, uint32_t cons, uint8_t prod_wrap, uint8_t cons_wrap) "q empty:%d prod:%d cons:%d p.wrap:%d p.cons:%d"
263
+smmuv3_update_check_cmd(int error) "cmdq not enabled or error :0x%x"
264
+smmuv3_write_mmio(uint64_t addr, uint64_t val, unsigned size, uint32_t r) "addr: 0x%"PRIx64" val:0x%"PRIx64" size: 0x%x(%d)"
265
+smmuv3_write_mmio_idr(uint64_t addr, uint64_t val) "write to RO/Unimpl reg 0x%lx val64:0x%lx"
266
+smmuv3_write_mmio_evtq_cons_bef_clear(uint32_t prod, uint32_t cons, uint8_t prod_wrap, uint8_t cons_wrap) "Before clearing interrupt prod:0x%x cons:0x%x prod.w:%d cons.w:%d"
267
+smmuv3_write_mmio_evtq_cons_after_clear(uint32_t prod, uint32_t cons, uint8_t prod_wrap, uint8_t cons_wrap) "after clearing interrupt prod:0x%x cons:0x%x prod.w:%d cons.w:%d"
268
--
60
--
269
2.17.0
61
2.20.1
270
62
271
63
diff view generated by jsdifflib
1
From: Eric Auger <eric.auger@redhat.com>
1
From: Gan Qixin <ganqixin@huawei.com>
2
2
3
This patch implements the page table walk for VMSAv8-64.
3
When running device-introspect-test, a memory leak occurred in the
4
exynos4210_rtc_init function, so use ptimer_free() in the finalize function to
5
avoid it.
4
6
5
Signed-off-by: Eric Auger <eric.auger@redhat.com>
7
ASAN shows memory leak stack:
6
Signed-off-by: Prem Mallappa <prem.mallappa@broadcom.com>
8
7
Message-id: 1524665762-31355-4-git-send-email-eric.auger@redhat.com
9
Indirect leak of 96 byte(s) in 1 object(s) allocated from:
10
#0 0xffffab97e1f0 in __interceptor_calloc (/lib64/libasan.so.5+0xee1f0)
11
#1 0xffffab256800 in g_malloc0 (/lib64/libglib-2.0.so.0+0x56800)
12
#2 0xaaabf555db78 in ptimer_init /qemu/hw/core/ptimer.c:432
13
#3 0xaaabf57b3934 in exynos4210_rtc_init /qemu/hw/rtc/exynos4210_rtc.c:567
14
#4 0xaaabf6339f6c in object_initialize_with_type /qemu/qom/object.c:515
15
#5 0xaaabf633a1e0 in object_new_with_type /qemu/qom/object.c:729
16
#6 0xaaabf6375e40 in qmp_device_list_properties /qemu/qom/qom-qmp-cmds.c:153
17
#7 0xaaabf653d8ec in qmp_marshal_device_list_properties /qemu/qapi/qapi-commands-qdev.c:59
18
#8 0xaaabf6587d08 in do_qmp_dispatch_bh /qemu/qapi/qmp-dispatch.c:110
19
#9 0xaaabf6552708 in aio_bh_call /qemu/util/async.c:136
20
#10 0xaaabf6552708 in aio_bh_poll /qemu/util/async.c:164
21
#11 0xaaabf655f19c in aio_dispatch /qemu/util/aio-posix.c:381
22
#12 0xaaabf65523f4 in aio_ctx_dispatch /qemu/util/async.c:306
23
24
Reported-by: Euler Robot <euler.robot@huawei.com>
25
Signed-off-by: Gan Qixin <ganqixin@huawei.com>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
26
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
27
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
28
---
11
hw/arm/smmu-internal.h | 99 ++++++++++++++++
29
hw/rtc/exynos4210_rtc.c | 9 +++++++++
12
include/hw/arm/smmu-common.h | 14 +++
30
1 file changed, 9 insertions(+)
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
31
18
diff --git a/hw/arm/smmu-internal.h b/hw/arm/smmu-internal.h
32
diff --git a/hw/rtc/exynos4210_rtc.c b/hw/rtc/exynos4210_rtc.c
19
new file mode 100644
33
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX
34
--- a/hw/rtc/exynos4210_rtc.c
21
--- /dev/null
35
+++ b/hw/rtc/exynos4210_rtc.c
22
+++ b/hw/arm/smmu-internal.h
36
@@ -XXX,XX +XXX,XX @@ static void exynos4210_rtc_init(Object *obj)
23
@@ -XXX,XX +XXX,XX @@
37
sysbus_init_mmio(dev, &s->iomem);
24
+/*
38
}
25
+ * ARM SMMU support - Internal API
39
26
+ *
40
+static void exynos4210_rtc_finalize(Object *obj)
27
+ * Copyright (c) 2017 Red Hat, Inc.
41
+{
28
+ * Copyright (C) 2014-2016 Broadcom Corporation
42
+ Exynos4210RTCState *s = EXYNOS4210_RTC(obj);
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
+
43
+
44
+#ifndef HW_ARM_SMMU_INTERNAL_H
44
+ ptimer_free(s->ptimer);
45
+#define HW_ARM_SMMU_INTERNAL_H
45
+ ptimer_free(s->ptimer_1Hz);
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
+}
46
+}
108
+
47
+
109
+static inline uint64_t level_page_mask(int level, int granule_sz)
48
static void exynos4210_rtc_class_init(ObjectClass *klass, void *data)
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
{
49
{
129
return PCI_BUILD_BDF(pci_bus_num(sdev->bus), sdev->devfn);
50
DeviceClass *dc = DEVICE_CLASS(klass);
130
}
51
@@ -XXX,XX +XXX,XX @@ static const TypeInfo exynos4210_rtc_info = {
131
+
52
.parent = TYPE_SYS_BUS_DEVICE,
132
+/**
53
.instance_size = sizeof(Exynos4210RTCState),
133
+ * smmu_ptw - Perform the page table walk for a given iova / access flags
54
.instance_init = exynos4210_rtc_init,
134
+ * pair, according to @cfg translation config
55
+ .instance_finalize = exynos4210_rtc_finalize,
135
+ */
56
.class_init = exynos4210_rtc_class_init,
136
+int smmu_ptw(SMMUTransCfg *cfg, dma_addr_t iova, IOMMUAccessFlags perm,
57
};
137
+ IOMMUTLBEntry *tlbe, SMMUPTWEventInfo *info);
58
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
--
59
--
398
2.17.0
60
2.20.1
399
61
400
62
diff view generated by jsdifflib
1
From: Eric Auger <eric.auger@redhat.com>
1
From: Gan Qixin <ganqixin@huawei.com>
2
2
3
At the moment, the SMMUv3 does not support notification on
3
When running device-introspect-test, a memory leak occurred in the
4
TLB invalidation. So let's log an error as soon as such notifier
4
exynos4210_pwm_init function, so use ptimer_free() in the finalize function to
5
gets enabled.
5
avoid it.
6
6
7
Signed-off-by: Eric Auger <eric.auger@redhat.com>
7
ASAN shows memory leak stack:
8
9
Indirect leak of 240 byte(s) in 5 object(s) allocated from:
10
#0 0xffffab97e1f0 in __interceptor_calloc (/lib64/libasan.so.5+0xee1f0)
11
#1 0xffffab256800 in g_malloc0 (/lib64/libglib-2.0.so.0+0x56800)
12
#2 0xaaabf555db84 in timer_new_full /qemu/include/qemu/timer.h:523
13
#3 0xaaabf555db84 in timer_new /qemu/include/qemu/timer.h:544
14
#4 0xaaabf555db84 in timer_new_ns /qemu/include/qemu/timer.h:562
15
#5 0xaaabf555db84 in ptimer_init /qemu/hw/core/ptimer.c:433
16
#6 0xaaabf56a36cc in exynos4210_pwm_init /qemu/hw/timer/exynos4210_pwm.c:401
17
#7 0xaaabf6339f6c in object_initialize_with_type /qemu/qom/object.c:515
18
#8 0xaaabf633a1e0 in object_new_with_type /qemu/qom/object.c:729
19
#9 0xaaabf6375e40 in qmp_device_list_properties /qemu/qom/qom-qmp-cmds.c:153
20
#10 0xaaabf653d8ec in qmp_marshal_device_list_properties /qemu/qapi/qapi-commands-qdev.c:59
21
#11 0xaaabf6587d08 in do_qmp_dispatch_bh /qemu/qapi/qmp-dispatch.c:110
22
#12 0xaaabf6552708 in aio_bh_call /qemu/util/async.c:136
23
24
Reported-by: Euler Robot <euler.robot@huawei.com>
25
Signed-off-by: Gan Qixin <ganqixin@huawei.com>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
26
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Message-id: 1524665762-31355-11-git-send-email-eric.auger@redhat.com
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
27
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
28
---
12
hw/arm/smmuv3.c | 11 +++++++++++
29
hw/timer/exynos4210_pwm.c | 11 +++++++++++
13
1 file changed, 11 insertions(+)
30
1 file changed, 11 insertions(+)
14
31
15
diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c
32
diff --git a/hw/timer/exynos4210_pwm.c b/hw/timer/exynos4210_pwm.c
16
index XXXXXXX..XXXXXXX 100644
33
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/arm/smmuv3.c
34
--- a/hw/timer/exynos4210_pwm.c
18
+++ b/hw/arm/smmuv3.c
35
+++ b/hw/timer/exynos4210_pwm.c
19
@@ -XXX,XX +XXX,XX @@ static void smmuv3_class_init(ObjectClass *klass, void *data)
36
@@ -XXX,XX +XXX,XX @@ static void exynos4210_pwm_init(Object *obj)
20
dc->realize = smmu_realize;
37
sysbus_init_mmio(dev, &s->iomem);
21
}
38
}
22
39
23
+static void smmuv3_notify_flag_changed(IOMMUMemoryRegion *iommu,
40
+static void exynos4210_pwm_finalize(Object *obj)
24
+ IOMMUNotifierFlag old,
25
+ IOMMUNotifierFlag new)
26
+{
41
+{
27
+ if (old == IOMMU_NOTIFIER_NONE) {
42
+ Exynos4210PWMState *s = EXYNOS4210_PWM(obj);
28
+ warn_report("SMMUV3 does not support vhost/vfio integration yet: "
43
+ int i;
29
+ "devices of those types will not function properly");
44
+
45
+ for (i = 0; i < EXYNOS4210_PWM_TIMERS_NUM; i++) {
46
+ ptimer_free(s->timer[i].ptimer);
30
+ }
47
+ }
31
+}
48
+}
32
+
49
+
33
static void smmuv3_iommu_memory_region_class_init(ObjectClass *klass,
50
static void exynos4210_pwm_class_init(ObjectClass *klass, void *data)
34
void *data)
35
{
51
{
36
IOMMUMemoryRegionClass *imrc = IOMMU_MEMORY_REGION_CLASS(klass);
52
DeviceClass *dc = DEVICE_CLASS(klass);
37
53
@@ -XXX,XX +XXX,XX @@ static const TypeInfo exynos4210_pwm_info = {
38
imrc->translate = smmuv3_translate;
54
.parent = TYPE_SYS_BUS_DEVICE,
39
+ imrc->notify_flag_changed = smmuv3_notify_flag_changed;
55
.instance_size = sizeof(Exynos4210PWMState),
40
}
56
.instance_init = exynos4210_pwm_init,
41
57
+ .instance_finalize = exynos4210_pwm_finalize,
42
static const TypeInfo smmuv3_type_info = {
58
.class_init = exynos4210_pwm_class_init,
59
};
60
43
--
61
--
44
2.17.0
62
2.20.1
45
63
46
64
diff view generated by jsdifflib
1
From: Eric Auger <eric.auger@redhat.com>
1
From: Gan Qixin <ganqixin@huawei.com>
2
2
3
This patch implements the IOMMU Memory Region translate()
3
When running device-introspect-test, a memory leak occurred in the
4
callback. Most of the code relates to the translation
4
mss_timer_init function, so use ptimer_free() in the finalize function to avoid
5
configuration decoding and check (STE, CD).
5
it.
6
6
7
Signed-off-by: Eric Auger <eric.auger@redhat.com>
7
ASAN shows memory leak stack:
8
Signed-off-by: Prem Mallappa <prem.mallappa@broadcom.com>
8
9
Message-id: 1524665762-31355-10-git-send-email-eric.auger@redhat.com
9
Indirect leak of 192 byte(s) in 2 object(s) allocated from:
10
#0 0xffffab97e1f0 in __interceptor_calloc (/lib64/libasan.so.5+0xee1f0)
11
#1 0xffffab256800 in g_malloc0 (/lib64/libglib-2.0.so.0+0x56800)
12
#2 0xaaabf555db78 in ptimer_init /qemu/hw/core/ptimer.c:432
13
#3 0xaaabf58a0010 in mss_timer_init /qemu/hw/timer/mss-timer.c:235
14
#4 0xaaabf6339f6c in object_initialize_with_type /qemu/qom/object.c:515
15
#5 0xaaabf633ca04 in object_initialize_child_with_propsv /qemu/qom/object.c:564
16
#6 0xaaabf633cc08 in object_initialize_child_with_props /qemu/qom/object.c:547
17
#7 0xaaabf5b8316c in m2sxxx_soc_initfn /qemu/hw/arm/msf2-soc.c:70
18
#8 0xaaabf6339f6c in object_initialize_with_type /qemu/qom/object.c:515
19
#9 0xaaabf633a1e0 in object_new_with_type /qemu/qom/object.c:729
20
#10 0xaaabf6375e40 in qmp_device_list_properties /qemu/qom/qom-qmp-cmds.c:153
21
#11 0xaaabf653d8ec in qmp_marshal_device_list_properties /qemu/qapi/qapi-commands-qdev.c:59
22
#12 0xaaabf6587d08 in do_qmp_dispatch_bh /qemu/qapi/qmp-dispatch.c:110
23
24
Reported-by: Euler Robot <euler.robot@huawei.com>
25
Signed-off-by: Gan Qixin <ganqixin@huawei.com>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
26
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
27
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
28
---
13
hw/arm/smmuv3-internal.h | 160 +++++++++++++++++
29
hw/timer/mss-timer.c | 13 +++++++++++++
14
hw/arm/smmuv3.c | 358 +++++++++++++++++++++++++++++++++++++++
30
1 file changed, 13 insertions(+)
15
hw/arm/trace-events | 9 +
16
3 files changed, 527 insertions(+)
17
31
18
diff --git a/hw/arm/smmuv3-internal.h b/hw/arm/smmuv3-internal.h
32
diff --git a/hw/timer/mss-timer.c b/hw/timer/mss-timer.c
19
index XXXXXXX..XXXXXXX 100644
33
index XXXXXXX..XXXXXXX 100644
20
--- a/hw/arm/smmuv3-internal.h
34
--- a/hw/timer/mss-timer.c
21
+++ b/hw/arm/smmuv3-internal.h
35
+++ b/hw/timer/mss-timer.c
22
@@ -XXX,XX +XXX,XX @@ typedef struct SMMUEventInfo {
36
@@ -XXX,XX +XXX,XX @@ static void mss_timer_init(Object *obj)
23
37
sysbus_init_mmio(SYS_BUS_DEVICE(obj), &t->mmio);
24
void smmuv3_record_event(SMMUv3State *s, SMMUEventInfo *event);
38
}
25
39
26
+/* Configuration Data */
40
+static void mss_timer_finalize(Object *obj)
41
+{
42
+ MSSTimerState *t = MSS_TIMER(obj);
43
+ int i;
27
+
44
+
28
+/* STE Level 1 Descriptor */
45
+ for (i = 0; i < NUM_TIMERS; i++) {
29
+typedef struct STEDesc {
46
+ struct Msf2Timer *st = &t->timers[i];
30
+ uint32_t word[2];
31
+} STEDesc;
32
+
47
+
33
+/* CD Level 1 Descriptor */
48
+ ptimer_free(st->ptimer);
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
+ }
49
+ }
173
+}
50
+}
174
+
51
+
175
+static inline uint64_t l1std_l2ptr(STEDesc *desc)
52
static const VMStateDescription vmstate_timers = {
176
+{
53
.name = "mss-timer-block",
177
+ uint64_t hi, lo;
54
.version_id = 1,
178
+
55
@@ -XXX,XX +XXX,XX @@ static const TypeInfo mss_timer_info = {
179
+ hi = desc->word[1];
56
.parent = TYPE_SYS_BUS_DEVICE,
180
+ lo = desc->word[0] & ~0x1fULL;
57
.instance_size = sizeof(MSSTimerState),
181
+ return hi << 32 | lo;
58
.instance_init = mss_timer_init,
182
+}
59
+ .instance_finalize = mss_timer_finalize,
183
+
60
.class_init = mss_timer_class_init,
184
+#define L1STD_SPAN(stm) (extract32((stm)->word[0], 0, 4))
61
};
185
+
62
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
--
63
--
581
2.17.0
64
2.20.1
582
65
583
66
diff view generated by jsdifflib
1
From: Eric Auger <eric.auger@redhat.com>
1
From: Gan Qixin <ganqixin@huawei.com>
2
2
3
Let's introduce a helper function aiming at recording an
3
When running device-introspect-test, a memory leak occurred in the
4
event in the event queue.
4
mv88w8618_pit_init function, so use ptimer_free() in the finalize function to
5
avoid it.
5
6
6
Signed-off-by: Eric Auger <eric.auger@redhat.com>
7
ASAN shows memory leak stack:
8
9
Indirect leak of 192 byte(s) in 4 object(s) allocated from:
10
#0 0xffffab97e1f0 in __interceptor_calloc (/lib64/libasan.so.5+0xee1f0)
11
#1 0xffffab256800 in g_malloc0 (/lib64/libglib-2.0.so.0+0x56800)
12
#2 0xaaabf555db84 in timer_new_full /qemu/include/qemu/timer.h:523
13
#3 0xaaabf555db84 in timer_new /qemu/include/qemu/timer.h:544
14
#4 0xaaabf555db84 in timer_new_ns /qemu/include/qemu/timer.h:562
15
#5 0xaaabf555db84 in ptimer_init /qemu/hw/core/ptimer.c:433
16
#6 0xaaabf5bb2290 in mv88w8618_timer_init /qemu/hw/arm/musicpal.c:862
17
#7 0xaaabf5bb2290 in mv88w8618_pit_init /qemu/hw/arm/musicpal.c:954
18
#8 0xaaabf6339f6c in object_initialize_with_type /qemu/qom/object.c:515
19
#9 0xaaabf633a1e0 in object_new_with_type /qemu/qom/object.c:729
20
#10 0xaaabf6375e40 in qmp_device_list_properties /qemu/qom/qom-qmp-cmds.c:153
21
#11 0xaaabf5a95540 in qdev_device_help /qemu/softmmu/qdev-monitor.c:283
22
#12 0xaaabf5a96940 in qmp_device_add /qemu/softmmu/qdev-monitor.c:801
23
24
Reported-by: Euler Robot <euler.robot@huawei.com>
25
Signed-off-by: Gan Qixin <ganqixin@huawei.com>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
26
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>
27
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
28
---
11
hw/arm/smmuv3-internal.h | 148 ++++++++++++++++++++++++++++++++++++++-
29
hw/arm/musicpal.c | 12 ++++++++++++
12
hw/arm/smmuv3.c | 108 ++++++++++++++++++++++++++--
30
1 file changed, 12 insertions(+)
13
hw/arm/trace-events | 1 +
14
3 files changed, 249 insertions(+), 8 deletions(-)
15
31
16
diff --git a/hw/arm/smmuv3-internal.h b/hw/arm/smmuv3-internal.h
32
diff --git a/hw/arm/musicpal.c b/hw/arm/musicpal.c
17
index XXXXXXX..XXXXXXX 100644
33
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/arm/smmuv3-internal.h
34
--- a/hw/arm/musicpal.c
19
+++ b/hw/arm/smmuv3-internal.h
35
+++ b/hw/arm/musicpal.c
20
@@ -XXX,XX +XXX,XX @@ static inline void smmu_write_cmdq_err(SMMUv3State *s, uint32_t err_type)
36
@@ -XXX,XX +XXX,XX @@ static void mv88w8618_pit_init(Object *obj)
21
s->cmdq.cons = FIELD_DP32(s->cmdq.cons, CMDQ_CONS, ERR, err_type);
37
sysbus_init_mmio(dev, &s->iomem);
22
}
38
}
23
39
24
-void smmuv3_write_eventq(SMMUv3State *s, Evt *evt);
40
+static void mv88w8618_pit_finalize(Object *obj)
25
-
41
+{
26
/* Commands */
42
+ SysBusDevice *dev = SYS_BUS_DEVICE(obj);
27
43
+ mv88w8618_pit_state *s = MV88W8618_PIT(dev);
28
typedef enum SMMUCommandType {
44
+ int i;
29
@@ -XXX,XX +XXX,XX @@ enum { /* Command completion notification */
30
31
#define SMMU_FEATURE_2LVL_STE (1 << 0)
32
33
+/* Events */
34
+
45
+
35
+typedef enum SMMUEventType {
46
+ for (i = 0; i < 4; i++) {
36
+ SMMU_EVT_OK = 0x00,
47
+ ptimer_free(s->timer[i].ptimer);
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
+ }
48
+ }
86
+}
49
+}
87
+
50
+
88
+/* Encode an event record */
51
static const VMStateDescription mv88w8618_timer_vmsd = {
89
+typedef struct SMMUEventInfo {
52
.name = "timer",
90
+ SMMUEventType type;
53
.version_id = 1,
91
+ uint32_t sid;
54
@@ -XXX,XX +XXX,XX @@ static const TypeInfo mv88w8618_pit_info = {
92
+ bool recorded;
55
.parent = TYPE_SYS_BUS_DEVICE,
93
+ bool record_trans_faults;
56
.instance_size = sizeof(mv88w8618_pit_state),
94
+ union {
57
.instance_init = mv88w8618_pit_init,
95
+ struct {
58
+ .instance_finalize = mv88w8618_pit_finalize,
96
+ uint32_t ssid;
59
.class_init = mv88w8618_pit_class_init,
97
+ bool ssv;
60
};
98
+ dma_addr_t addr;
61
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
}
221
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
--
62
--
320
2.17.0
63
2.20.1
321
64
322
65
diff view generated by jsdifflib
1
From: Eric Auger <eric.auger@redhat.com>
1
From: Gan Qixin <ganqixin@huawei.com>
2
2
3
We introduce some helpers to handle wired IRQs and especially
3
When running device-introspect-test, a memory leak occurred in the
4
GERROR interrupt. SMMU writes GERROR register on GERROR event
4
exynos4210_mct_init function, so use ptimer_free() in the finalize function to
5
and SW acks GERROR interrupts by setting GERRORn.
5
avoid it.
6
6
7
The Wired interrupts are edge sensitive hence the pulse usage.
7
ASAN shows memory leak stack:
8
8
9
Signed-off-by: Eric Auger <eric.auger@redhat.com>
9
Indirect leak of 96 byte(s) in 1 object(s) allocated from:
10
Signed-off-by: Prem Mallappa <prem.mallappa@broadcom.com>
10
#0 0xffffab97e1f0 in __interceptor_calloc (/lib64/libasan.so.5+0xee1f0)
11
#1 0xffffab256800 in g_malloc0 (/lib64/libglib-2.0.so.0+0x56800)
12
#2 0xaaabf555db78 in ptimer_init /qemu/hw/core/ptimer.c:432
13
#3 0xaaabf56b01a0 in exynos4210_mct_init /qemu/hw/timer/exynos4210_mct.c:1505
14
#4 0xaaabf6339f6c in object_initialize_with_type /qemu/qom/object.c:515
15
#5 0xaaabf633a1e0 in object_new_with_type /qemu/qom/object.c:729
16
#6 0xaaabf6375e40 in qmp_device_list_properties /qemu/qom/qom-qmp-cmds.c:153
17
#7 0xaaabf653d8ec in qmp_marshal_device_list_properties /qemu/qapi/qapi-commands-qdev.c:59
18
#8 0xaaabf6587d08 in do_qmp_dispatch_bh /qemu/qapi/qmp-dispatch.c:110
19
#9 0xaaabf6552708 in aio_bh_call /qemu/util/async.c:136
20
#10 0xaaabf6552708 in aio_bh_poll /qemu/util/async.c:164
21
#11 0xaaabf655f19c in aio_dispatch /qemu/util/aio-posix.c:381
22
#12 0xaaabf65523f4 in aio_ctx_dispatch /qemu/util/async.c:306
23
24
Reported-by: Euler Robot <euler.robot@huawei.com>
25
Signed-off-by: Gan Qixin <ganqixin@huawei.com>
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
26
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>
27
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
28
---
15
hw/arm/smmuv3-internal.h | 14 +++++++++
29
hw/timer/exynos4210_mct.c | 14 ++++++++++++++
16
hw/arm/smmuv3.c | 64 ++++++++++++++++++++++++++++++++++++++++
30
1 file changed, 14 insertions(+)
17
hw/arm/trace-events | 3 ++
18
3 files changed, 81 insertions(+)
19
31
20
diff --git a/hw/arm/smmuv3-internal.h b/hw/arm/smmuv3-internal.h
32
diff --git a/hw/timer/exynos4210_mct.c b/hw/timer/exynos4210_mct.c
21
index XXXXXXX..XXXXXXX 100644
33
index XXXXXXX..XXXXXXX 100644
22
--- a/hw/arm/smmuv3-internal.h
34
--- a/hw/timer/exynos4210_mct.c
23
+++ b/hw/arm/smmuv3-internal.h
35
+++ b/hw/timer/exynos4210_mct.c
24
@@ -XXX,XX +XXX,XX @@ static inline uint32_t smmuv3_idreg(int regoffset)
36
@@ -XXX,XX +XXX,XX @@ static void exynos4210_mct_init(Object *obj)
25
return smmuv3_ids[regoffset / 4];
37
sysbus_init_mmio(dev, &s->iomem);
26
}
38
}
27
39
28
+static inline bool smmuv3_eventq_irq_enabled(SMMUv3State *s)
40
+static void exynos4210_mct_finalize(Object *obj)
29
+{
41
+{
30
+ return FIELD_EX32(s->irq_ctrl, IRQ_CTRL, EVENTQ_IRQEN);
42
+ int i;
31
+}
43
+ Exynos4210MCTState *s = EXYNOS4210_MCT(obj);
32
+
44
+
33
+static inline bool smmuv3_gerror_irq_enabled(SMMUv3State *s)
45
+ ptimer_free(s->g_timer.ptimer_frc);
34
+{
35
+ return FIELD_EX32(s->irq_ctrl, IRQ_CTRL, GERROR_IRQEN);
36
+}
37
+
46
+
38
+/* public until callers get introduced */
47
+ for (i = 0; i < 2; i++) {
39
+void smmuv3_trigger_irq(SMMUv3State *s, SMMUIrq irq, uint32_t gerror_mask);
48
+ ptimer_free(s->l_timer[i].tick_timer.ptimer_tick);
40
+void smmuv3_write_gerrorn(SMMUv3State *s, uint32_t gerrorn);
49
+ ptimer_free(s->l_timer[i].ptimer_frc);
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
+ }
50
+ }
93
+}
51
+}
94
+
52
+
95
+void smmuv3_write_gerrorn(SMMUv3State *s, uint32_t new_gerrorn)
53
static void exynos4210_mct_class_init(ObjectClass *klass, void *data)
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
{
54
{
117
/**
55
DeviceClass *dc = DEVICE_CLASS(klass);
118
diff --git a/hw/arm/trace-events b/hw/arm/trace-events
56
@@ -XXX,XX +XXX,XX @@ static const TypeInfo exynos4210_mct_info = {
119
index XXXXXXX..XXXXXXX 100644
57
.parent = TYPE_SYS_BUS_DEVICE,
120
--- a/hw/arm/trace-events
58
.instance_size = sizeof(Exynos4210MCTState),
121
+++ b/hw/arm/trace-events
59
.instance_init = exynos4210_mct_init,
122
@@ -XXX,XX +XXX,XX @@ smmu_get_pte(uint64_t baseaddr, int index, uint64_t pteaddr, uint64_t pte) "base
60
+ .instance_finalize = exynos4210_mct_finalize,
123
61
.class_init = exynos4210_mct_class_init,
124
#hw/arm/smmuv3.c
62
};
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)"
63
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
--
64
--
130
2.17.0
65
2.20.1
131
66
132
67
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Bin Meng <bin.meng@windriver.com>
2
2
3
Path analysis shows that size == 3 && !is_q has been eliminated.
3
U-Boot expects PMU_MISC0 register bit 7 is set (see init_bandgap()
4
in arch/arm/mach-imx/mx6/soc.c) during boot. This bit indicates the
5
bandgap has stabilized.
4
6
5
Fixes: Coverity CID1385853
7
With this change, the latest upstream U-Boot (v2021.01-rc3) for imx6
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
sabrelite board (mx6qsabrelite_defconfig), with a slight change made
9
by switching CONFIG_OF_SEPARATE to CONFIG_OF_EMBED, boots to U-Boot
10
shell on QEMU with the following command:
11
12
$ qemu-system-arm -M sabrelite -smp 4 -m 1G -kernel u-boot \
13
-display none -serial null -serial stdio
14
15
Boot log below:
16
17
U-Boot 2021.01-rc3 (Dec 12 2020 - 17:40:02 +0800)
18
19
CPU: Freescale i.MX?? rev1.0 at 792 MHz
20
Reset cause: POR
21
Model: Freescale i.MX6 Quad SABRE Lite Board
22
Board: SABRE Lite
23
I2C: ready
24
DRAM: 1 GiB
25
force_idle_bus: sda=0 scl=0 sda.gp=0x5c scl.gp=0x55
26
force_idle_bus: failed to clear bus, sda=0 scl=0
27
force_idle_bus: sda=0 scl=0 sda.gp=0x6d scl.gp=0x6c
28
force_idle_bus: failed to clear bus, sda=0 scl=0
29
force_idle_bus: sda=0 scl=0 sda.gp=0xcb scl.gp=0x5
30
force_idle_bus: failed to clear bus, sda=0 scl=0
31
MMC: FSL_SDHC: 0, FSL_SDHC: 1
32
Loading Environment from MMC... *** Warning - No block device, using default environment
33
34
In: serial
35
Out: serial
36
Err: serial
37
Net: Board Net Initialization Failed
38
No ethernet found.
39
starting USB...
40
Bus usb@2184000: usb dr_mode not found
41
USB EHCI 1.00
42
Bus usb@2184200: USB EHCI 1.00
43
scanning bus usb@2184000 for devices... 1 USB Device(s) found
44
scanning bus usb@2184200 for devices... 1 USB Device(s) found
45
scanning usb for storage devices... 0 Storage Device(s) found
46
scanning usb for ethernet devices... 0 Ethernet Device(s) found
47
Hit any key to stop autoboot: 0
48
=>
49
50
Signed-off-by: Bin Meng <bin.meng@windriver.com>
7
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
51
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
8
Message-id: 20180501180455.11214-3-richard.henderson@linaro.org
52
Message-id: 20210106063504.10841-2-bmeng.cn@gmail.com
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
53
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
54
---
11
target/arm/translate-a64.c | 6 +++++-
55
hw/misc/imx6_ccm.c | 2 +-
12
1 file changed, 5 insertions(+), 1 deletion(-)
56
1 file changed, 1 insertion(+), 1 deletion(-)
13
57
14
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
58
diff --git a/hw/misc/imx6_ccm.c b/hw/misc/imx6_ccm.c
15
index XXXXXXX..XXXXXXX 100644
59
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/translate-a64.c
60
--- a/hw/misc/imx6_ccm.c
17
+++ b/target/arm/translate-a64.c
61
+++ b/hw/misc/imx6_ccm.c
18
@@ -XXX,XX +XXX,XX @@ static void disas_simd_two_reg_misc(DisasContext *s, uint32_t insn)
62
@@ -XXX,XX +XXX,XX @@ static void imx6_ccm_reset(DeviceState *dev)
19
/* All 64-bit element operations can be shared with scalar 2misc */
63
s->analog[PMU_REG_3P0] = 0x00000F74;
20
int pass;
64
s->analog[PMU_REG_2P5] = 0x00005071;
21
65
s->analog[PMU_REG_CORE] = 0x00402010;
22
- for (pass = 0; pass < (is_q ? 2 : 1); pass++) {
66
- s->analog[PMU_MISC0] = 0x04000000;
23
+ /* Coverity claims (size == 3 && !is_q) has been eliminated
67
+ s->analog[PMU_MISC0] = 0x04000080;
24
+ * from all paths leading to here.
68
s->analog[PMU_MISC1] = 0x00000000;
25
+ */
69
s->analog[PMU_MISC2] = 0x00272727;
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
70
31
--
71
--
32
2.17.0
72
2.20.1
33
73
34
74
diff view generated by jsdifflib
1
From: Igor Mammedov <imammedo@redhat.com>
1
From: Bin Meng <bin.meng@windriver.com>
2
2
3
Even though nothing is currently broken (since all boards
3
Currently when U-Boot boots, it prints "??" for i.MX processor:
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
4
12
Ref:
5
CPU: Freescale i.MX?? rev1.0 at 792 MHz
13
"Message-ID: <CAFEAcA_NMWuA8WSs3cNeY6xX1kerO_uAcN_3=fK02BEhHJW86g@mail.gmail.com>"
14
6
15
Signed-off-by: Igor Mammedov <imammedo@redhat.com>
7
The register that was used to determine the silicon type is
16
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
undocumented in the latest IMX6DQRM (Rev. 6, 05/2020), but we
17
Message-id: 1525176522-200354-5-git-send-email-imammedo@redhat.com
9
can refer to get_cpu_rev() in arch/arm/mach-imx/mx6/soc.c in
10
the U-Boot source codes that USB_ANALOG_DIGPROG is used.
11
12
Update its reset value to indicate i.MX6Q.
13
14
Signed-off-by: Bin Meng <bin.meng@windriver.com>
15
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
16
Message-id: 20210106063504.10841-3-bmeng.cn@gmail.com
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
---
18
---
20
hw/arm/boot.c | 2 +-
19
hw/misc/imx6_ccm.c | 2 +-
21
1 file changed, 1 insertion(+), 1 deletion(-)
20
1 file changed, 1 insertion(+), 1 deletion(-)
22
21
23
diff --git a/hw/arm/boot.c b/hw/arm/boot.c
22
diff --git a/hw/misc/imx6_ccm.c b/hw/misc/imx6_ccm.c
24
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
25
--- a/hw/arm/boot.c
24
--- a/hw/misc/imx6_ccm.c
26
+++ b/hw/arm/boot.c
25
+++ b/hw/misc/imx6_ccm.c
27
@@ -XXX,XX +XXX,XX @@ static void arm_load_kernel_notify(Notifier *notifier, void *data)
26
@@ -XXX,XX +XXX,XX @@ static void imx6_ccm_reset(DeviceState *dev)
28
}
27
s->analog[USB_ANALOG_USB2_VBUS_DETECT] = 0x00000004;
29
info->is_linux = is_linux;
28
s->analog[USB_ANALOG_USB2_CHRG_DETECT] = 0x00000000;
30
29
s->analog[USB_ANALOG_USB2_MISC] = 0x00000002;
31
- for (cs = CPU(cpu); cs; cs = CPU_NEXT(cs)) {
30
- s->analog[USB_ANALOG_DIGPROG] = 0x00000000;
32
+ for (cs = first_cpu; cs; cs = CPU_NEXT(cs)) {
31
+ s->analog[USB_ANALOG_DIGPROG] = 0x00630000;
33
ARM_CPU(cs)->env.boot_info = info;
32
34
}
33
/* all PLLs need to be locked */
35
}
34
s->analog[CCM_ANALOG_PLL_ARM] |= CCM_ANALOG_PLL_LOCK;
36
--
35
--
37
2.17.0
36
2.20.1
38
37
39
38
diff view generated by jsdifflib
1
From: Patrick Oppenlander <patrick.oppenlander@gmail.com>
1
From: Bin Meng <bin.meng@windriver.com>
2
2
3
The character frontend needs to be notified that the uart receive buffer
3
At present, when booting U-Boot on QEMU sabrelite, we see:
4
is empty and ready to handle another character.
5
4
6
Previously, the uart only worked correctly when receiving one character
5
Net: Board Net Initialization Failed
7
at a time.
6
No ethernet found.
8
7
9
Signed-off-by: Patrick Oppenlander <patrick.oppenlander@gmail.com>
8
U-Boot scans PHY at address 4/5/6/7 (see board_eth_init() in the
10
Message-id: CAEg67GkRTw=cXei3o9hvpxG_L4zSrNzR0bFyAgny+sSEUb_kPw@mail.gmail.com
9
U-Boot source: board/boundary/nitrogen6x/nitrogen6x.c). On the real
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
board, the Ethernet PHY is at address 6. Adjust this by updating the
11
"fec-phy-num" property of the fsl_imx6 SoC object.
12
13
With this change, U-Boot sees the PHY but complains MAC address:
14
15
Net: using phy at 6
16
FEC [PRIME]
17
Error: FEC address not set.
18
19
This is due to U-Boot tries to read the MAC address from the fuse,
20
which QEMU does not have any valid content filled in. However this
21
does not prevent the Ethernet from working in QEMU. We just need to
22
set up the MAC address later in the U-Boot command shell, by:
23
24
=> setenv ethaddr 00:11:22:33:44:55
25
26
Signed-off-by: Bin Meng <bin.meng@windriver.com>
27
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
28
Message-id: 20210106063504.10841-4-bmeng.cn@gmail.com
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
29
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
30
---
14
hw/char/cmsdk-apb-uart.c | 1 +
31
hw/arm/sabrelite.c | 4 ++++
15
1 file changed, 1 insertion(+)
32
1 file changed, 4 insertions(+)
16
33
17
diff --git a/hw/char/cmsdk-apb-uart.c b/hw/char/cmsdk-apb-uart.c
34
diff --git a/hw/arm/sabrelite.c b/hw/arm/sabrelite.c
18
index XXXXXXX..XXXXXXX 100644
35
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/char/cmsdk-apb-uart.c
36
--- a/hw/arm/sabrelite.c
20
+++ b/hw/char/cmsdk-apb-uart.c
37
+++ b/hw/arm/sabrelite.c
21
@@ -XXX,XX +XXX,XX @@ static uint64_t uart_read(void *opaque, hwaddr offset, unsigned size)
38
@@ -XXX,XX +XXX,XX @@ static void sabrelite_init(MachineState *machine)
22
r = s->rxbuf;
39
23
s->state &= ~R_STATE_RXFULL_MASK;
40
s = FSL_IMX6(object_new(TYPE_FSL_IMX6));
24
cmsdk_apb_uart_update(s);
41
object_property_add_child(OBJECT(machine), "soc", OBJECT(s));
25
+ qemu_chr_fe_accept_input(&s->chr);
42
+
26
break;
43
+ /* Ethernet PHY address is 6 */
27
case A_STATE:
44
+ object_property_set_int(OBJECT(s), "fec-phy-num", 6, &error_fatal);
28
r = s->state;
45
+
46
qdev_realize(DEVICE(s), NULL, &error_fatal);
47
48
memory_region_add_subregion(get_system_memory(), FSL_IMX6_MMDC_ADDR,
29
--
49
--
30
2.17.0
50
2.20.1
31
51
32
52
diff view generated by jsdifflib
1
From: Eric Auger <eric.auger@redhat.com>
1
From: Bin Meng <bin.meng@windriver.com>
2
2
3
The patch introduces the smmu base device and class for the ARM
3
This adds the target guide for SABRE Lite board, and documents how
4
smmu. Devices for specific versions will be derived from this
4
to boot a Linux kernel and U-Boot bootloader.
5
base device.
6
5
7
We also introduce some important datatypes.
6
Signed-off-by: Bin Meng <bin.meng@windriver.com>
8
7
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
9
Signed-off-by: Eric Auger <eric.auger@redhat.com>
8
Message-id: 20210106063504.10841-5-bmeng.cn@gmail.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>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
10
---
15
hw/arm/Makefile.objs | 1 +
11
docs/system/arm/sabrelite.rst | 119 ++++++++++++++++++++++++++++++++++
16
include/hw/arm/smmu-common.h | 123 ++++++++++++++++++++++++++++
12
docs/system/target-arm.rst | 1 +
17
hw/arm/smmu-common.c | 81 ++++++++++++++++++
13
2 files changed, 120 insertions(+)
18
default-configs/aarch64-softmmu.mak | 1 +
14
create mode 100644 docs/system/arm/sabrelite.rst
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
15
23
diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
16
diff --git a/docs/system/arm/sabrelite.rst b/docs/system/arm/sabrelite.rst
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
17
new file mode 100644
34
index XXXXXXX..XXXXXXX
18
index XXXXXXX..XXXXXXX
35
--- /dev/null
19
--- /dev/null
36
+++ b/include/hw/arm/smmu-common.h
20
+++ b/docs/system/arm/sabrelite.rst
37
@@ -XXX,XX +XXX,XX @@
21
@@ -XXX,XX +XXX,XX @@
38
+/*
22
+Boundary Devices SABRE Lite (``sabrelite``)
39
+ * ARM SMMU Support
23
+===========================================
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
+
24
+
56
+#ifndef HW_ARM_SMMU_COMMON_H
25
+Boundary Devices SABRE Lite i.MX6 Development Board is a low-cost development
57
+#define HW_ARM_SMMU_COMMON_H
26
+platform featuring the powerful Freescale / NXP Semiconductor's i.MX 6 Quad
27
+Applications Processor.
58
+
28
+
59
+#include "hw/sysbus.h"
29
+Supported devices
60
+#include "hw/pci/pci.h"
30
+-----------------
61
+
31
+
62
+#define SMMU_PCI_BUS_MAX 256
32
+The SABRE Lite machine supports the following devices:
63
+#define SMMU_PCI_DEVFN_MAX 256
64
+
33
+
65
+#define SMMU_MAX_VA_BITS 48
34
+ * Up to 4 Cortex A9 cores
35
+ * Generic Interrupt Controller
36
+ * 1 Clock Controller Module
37
+ * 1 System Reset Controller
38
+ * 5 UARTs
39
+ * 2 EPIC timers
40
+ * 1 GPT timer
41
+ * 2 Watchdog timers
42
+ * 1 FEC Ethernet controller
43
+ * 3 I2C controllers
44
+ * 7 GPIO controllers
45
+ * 4 SDHC storage controllers
46
+ * 4 USB 2.0 host controllers
47
+ * 5 ECSPI controllers
48
+ * 1 SST 25VF016B flash
66
+
49
+
67
+/*
50
+Please note above list is a complete superset the QEMU SABRE Lite machine can
68
+ * Page table walk error types
51
+support. For a normal use case, a device tree blob that represents a real world
69
+ */
52
+SABRE Lite board, only exposes a subset of devices to the guest software.
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
+
53
+
79
+typedef struct SMMUPTWEventInfo {
54
+Boot options
80
+ SMMUPTWEventType type;
55
+------------
81
+ dma_addr_t addr; /* fetched address that induced an abort, if any */
82
+} SMMUPTWEventInfo;
83
+
56
+
84
+typedef struct SMMUTransTableInfo {
57
+The SABRE Lite machine can start using the standard -kernel functionality
85
+ bool disabled; /* is the translation table disabled? */
58
+for loading a Linux kernel, U-Boot bootloader or ELF executable.
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
+
59
+
91
+/*
60
+Running Linux kernel
92
+ * Generic structure populated by derived SMMU devices
61
+--------------------
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
+
62
+
109
+typedef struct SMMUDevice {
63
+Linux mainline v5.10 release is tested at the time of writing. To build a Linux
110
+ void *smmu;
64
+mainline kernel that can be booted by the SABRE Lite machine, simply configure
111
+ PCIBus *bus;
65
+the kernel using the imx_v6_v7_defconfig configuration:
112
+ int devfn;
113
+ IOMMUMemoryRegion iommu;
114
+ AddressSpace as;
115
+} SMMUDevice;
116
+
66
+
117
+typedef struct SMMUNotifierNode {
67
+.. code-block:: bash
118
+ SMMUDevice *sdev;
119
+ QLIST_ENTRY(SMMUNotifierNode) next;
120
+} SMMUNotifierNode;
121
+
68
+
122
+typedef struct SMMUPciBus {
69
+ $ export ARCH=arm
123
+ PCIBus *bus;
70
+ $ export CROSS_COMPILE=arm-linux-gnueabihf-
124
+ SMMUDevice *pbdev[0]; /* Parent array is sparse, so dynamically alloc */
71
+ $ make imx_v6_v7_defconfig
125
+} SMMUPciBus;
72
+ $ make
126
+
73
+
127
+typedef struct SMMUState {
74
+To boot the newly built Linux kernel in QEMU with the SABRE Lite machine, use:
128
+ /* <private> */
129
+ SysBusDevice dev;
130
+ const char *mrtypename;
131
+ MemoryRegion iomem;
132
+
75
+
133
+ GHashTable *smmu_pcibus_by_busptr;
76
+.. code-block:: bash
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
+
77
+
143
+typedef struct {
78
+ $ qemu-system-arm -M sabrelite -smp 4 -m 1G \
144
+ /* <private> */
79
+ -display none -serial null -serial stdio \
145
+ SysBusDeviceClass parent_class;
80
+ -kernel arch/arm/boot/zImage \
81
+ -dtb arch/arm/boot/dts/imx6q-sabrelite.dtb \
82
+ -initrd /path/to/rootfs.ext4 \
83
+ -append "root=/dev/ram"
146
+
84
+
147
+ /*< public >*/
85
+Running U-Boot
86
+--------------
148
+
87
+
149
+ DeviceRealize parent_realize;
88
+U-Boot mainline v2020.10 release is tested at the time of writing. To build a
89
+U-Boot mainline bootloader that can be booted by the SABRE Lite machine, use
90
+the mx6qsabrelite_defconfig with similar commands as described above for Linux:
150
+
91
+
151
+} SMMUBaseClass;
92
+.. code-block:: bash
152
+
93
+
153
+#define TYPE_ARM_SMMU "arm-smmu"
94
+ $ export CROSS_COMPILE=arm-linux-gnueabihf-
154
+#define ARM_SMMU(obj) OBJECT_CHECK(SMMUState, (obj), TYPE_ARM_SMMU)
95
+ $ make mx6qsabrelite_defconfig
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
+
96
+
160
+#endif /* HW_ARM_SMMU_COMMON */
97
+Note we need to adjust settings by:
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
+
98
+
185
+#include "qemu/osdep.h"
99
+.. code-block:: bash
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
+
100
+
194
+#include "qemu/error-report.h"
101
+ $ make menuconfig
195
+#include "hw/arm/smmu-common.h"
196
+
102
+
197
+static void smmu_base_realize(DeviceState *dev, Error **errp)
103
+then manually select the following configuration in U-Boot:
198
+{
199
+ SMMUBaseClass *sbc = ARM_SMMU_GET_CLASS(dev);
200
+ Error *local_err = NULL;
201
+
104
+
202
+ sbc->parent_realize(dev, &local_err);
105
+ Device Tree Control > Provider of DTB for DT Control > Embedded DTB
203
+ if (local_err) {
204
+ error_propagate(errp, local_err);
205
+ return;
206
+ }
207
+}
208
+
106
+
209
+static void smmu_base_reset(DeviceState *dev)
107
+To start U-Boot using the SABRE Lite machine, provide the u-boot binary to
210
+{
108
+the -kernel argument, along with an SD card image with rootfs:
211
+ /* will be filled later on */
212
+}
213
+
109
+
214
+static Property smmu_dev_properties[] = {
110
+.. code-block:: bash
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
+
111
+
220
+static void smmu_base_class_init(ObjectClass *klass, void *data)
112
+ $ qemu-system-arm -M sabrelite -smp 4 -m 1G \
221
+{
113
+ -display none -serial null -serial stdio \
222
+ DeviceClass *dc = DEVICE_CLASS(klass);
114
+ -kernel u-boot
223
+ SMMUBaseClass *sbc = ARM_SMMU_CLASS(klass);
224
+
115
+
225
+ dc->props = smmu_dev_properties;
116
+The following example shows booting Linux kernel from dhcp, and uses the
226
+ device_class_set_parent_realize(dc, smmu_base_realize,
117
+rootfs on an SD card. This requires some additional command line parameters
227
+ &sbc->parent_realize);
118
+for QEMU:
228
+ dc->reset = smmu_base_reset;
229
+}
230
+
119
+
231
+static const TypeInfo smmu_base_info = {
120
+.. code-block:: none
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
+
121
+
241
+static void smmu_base_register_types(void)
122
+ -nic user,tftp=/path/to/kernel/zImage \
242
+{
123
+ -drive file=sdcard.img,id=rootfs -device sd-card,drive=rootfs
243
+ type_register_static(&smmu_base_info);
244
+}
245
+
124
+
246
+type_init(smmu_base_register_types)
125
+The directory for the built-in TFTP server should also contain the device tree
126
+blob of the SABRE Lite board. The sample SD card image was populated with the
127
+root file system with one single partition. You may adjust the kernel "root="
128
+boot parameter accordingly.
247
+
129
+
248
diff --git a/default-configs/aarch64-softmmu.mak b/default-configs/aarch64-softmmu.mak
130
+After U-Boot boots, type the following commands in the U-Boot command shell to
131
+boot the Linux kernel:
132
+
133
+.. code-block:: none
134
+
135
+ => setenv ethaddr 00:11:22:33:44:55
136
+ => setenv bootfile zImage
137
+ => dhcp
138
+ => tftpboot 14000000 imx6q-sabrelite.dtb
139
+ => setenv bootargs root=/dev/mmcblk3p1
140
+ => bootz 12000000 - 14000000
141
diff --git a/docs/system/target-arm.rst b/docs/system/target-arm.rst
249
index XXXXXXX..XXXXXXX 100644
142
index XXXXXXX..XXXXXXX 100644
250
--- a/default-configs/aarch64-softmmu.mak
143
--- a/docs/system/target-arm.rst
251
+++ b/default-configs/aarch64-softmmu.mak
144
+++ b/docs/system/target-arm.rst
252
@@ -XXX,XX +XXX,XX @@ CONFIG_DDC=y
145
@@ -XXX,XX +XXX,XX @@ undocumented; you can get a complete list by running
253
CONFIG_DPCD=y
146
arm/versatile
254
CONFIG_XLNX_ZYNQMP=y
147
arm/vexpress
255
CONFIG_XLNX_ZYNQMP_ARM=y
148
arm/aspeed
256
+CONFIG_ARM_SMMUV3=y
149
+ arm/sabrelite
150
arm/digic
151
arm/musicpal
152
arm/gumstix
257
--
153
--
258
2.17.0
154
2.20.1
259
155
260
156
diff view generated by jsdifflib