1
target-arm queue: Eric's SMMUv3 patchset, and an array
1
The following changes since commit 8f6330a807f2642dc2a3cdf33347aa28a4c00a87:
2
of minor bugfixes and improvements from various others.
3
2
4
thanks
3
Merge tag 'pull-maintainer-updates-060324-1' of https://gitlab.com/stsquad/qemu into staging (2024-03-06 16:56:20 +0000)
5
-- PMM
6
7
The following changes since commit c8b7e627b4269a3bc3ae41d9f420547a47e6d9b9:
8
9
Merge remote-tracking branch 'remotes/ericb/tags/pull-nbd-2018-05-04' into staging (2018-05-04 14:42:46 +0100)
10
4
11
are available in the Git repository at:
5
are available in the Git repository at:
12
6
13
git://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20180504
7
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20240308
14
8
15
for you to fetch changes up to 5680740c92993e9b3f3e011f2a2c394070e33f56:
9
for you to fetch changes up to bbf6c6dbead82292a20951eb1204442a6b838de9:
16
10
17
hw/arm/virt: Introduce the iommu option (2018-05-04 18:05:52 +0100)
11
target/arm: Move v7m-related code from cpu32.c into a separate file (2024-03-08 14:45:03 +0000)
18
12
19
----------------------------------------------------------------
13
----------------------------------------------------------------
20
target-arm queue:
14
target-arm queue:
21
* Emulate the SMMUv3 (IOMMU); one will be created in the 'virt' board
15
* Implement FEAT_ECV
22
if the commandline includes "-machine iommu=smmuv3"
16
* STM32L4x5: Implement GPIO device
23
* target/arm: Implement v8M VLLDM and VLSTM
17
* Fix 32-bit SMOPA
24
* hw/arm: Don't fail qtest due to missing SD card in -nodefaults mode
18
* Refactor v7m related code from cpu32.c into its own file
25
* Some fixes to silence Coverity false-positives
19
* hw/rtc/sun4v-rtc: Relicense to GPLv2-or-later
26
* arm: boot: set boot_info starting from first_cpu
27
(fixes a technical bug not visible in practice)
28
* hw/net/smc91c111: Convert away from old_mmio
29
* hw/usb/tusb6010: Convert away from old_mmio
30
* hw/char/cmsdk-apb-uart.c: Accept more input after character read
31
* target/arm: Make MPUIR write-ignored on OMAP, StrongARM
32
* hw/arm/virt: Add linux,pci-domain property
33
20
34
----------------------------------------------------------------
21
----------------------------------------------------------------
35
Eric Auger (11):
22
Inès Varhol (3):
36
hw/arm/smmu-common: smmu base device and datatypes
23
hw/gpio: Implement STM32L4x5 GPIO
37
hw/arm/smmu-common: IOMMU memory region and address space setup
24
hw/arm: Connect STM32L4x5 GPIO to STM32L4x5 SoC
38
hw/arm/smmu-common: VMSAv8-64 page table walk
25
tests/qtest: Add STM32L4x5 GPIO QTest testcase
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
26
48
Igor Mammedov (1):
27
Peter Maydell (9):
49
arm: boot: set boot_info starting from first_cpu
28
target/arm: Move some register related defines to internals.h
29
target/arm: Timer _EL02 registers UNDEF for E2H == 0
30
target/arm: use FIELD macro for CNTHCTL bit definitions
31
target/arm: Don't allow RES0 CNTHCTL_EL2 bits to be written
32
target/arm: Implement new FEAT_ECV trap bits
33
target/arm: Define CNTPCTSS_EL0 and CNTVCTSS_EL0
34
target/arm: Implement FEAT_ECV CNTPOFF_EL2 handling
35
target/arm: Enable FEAT_ECV for 'max' CPU
36
hw/rtc/sun4v-rtc: Relicense to GPLv2-or-later
50
37
51
Jan Kiszka (1):
38
Richard Henderson (1):
52
hw/arm/virt: Add linux,pci-domain property
39
target/arm: Fix 32-bit SMOPA
53
54
Mathew Maidment (1):
55
target/arm: Correct MPUIR privilege level in register_cp_regs_for_features() conditional case
56
57
Patrick Oppenlander (1):
58
hw/char/cmsdk-apb-uart.c: Accept more input after character read
59
60
Peter Maydell (3):
61
hw/usb/tusb6010: Convert away from old_mmio
62
hw/net/smc91c111: Convert away from old_mmio
63
target/arm: Implement v8M VLLDM and VLSTM
64
65
Prem Mallappa (3):
66
hw/arm/smmuv3: Skeleton
67
hw/arm/virt: Add SMMUv3 to the virt board
68
hw/arm/virt-acpi-build: Add smmuv3 node in IORT table
69
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
40
74
Thomas Huth (1):
41
Thomas Huth (1):
75
hw/arm: Don't fail qtest due to missing SD card in -nodefaults mode
42
target/arm: Move v7m-related code from cpu32.c into a separate file
76
43
77
hw/arm/Makefile.objs | 1 +
44
MAINTAINERS | 1 +
78
hw/arm/smmu-internal.h | 99 +++
45
docs/system/arm/b-l475e-iot01a.rst | 2 +-
79
hw/arm/smmuv3-internal.h | 621 ++++++++++++++++++
46
docs/system/arm/emulation.rst | 1 +
80
include/hw/acpi/acpi-defs.h | 15 +
47
include/hw/arm/stm32l4x5_soc.h | 2 +
81
include/hw/arm/smmu-common.h | 145 +++++
48
include/hw/gpio/stm32l4x5_gpio.h | 71 +++++
82
include/hw/arm/smmuv3.h | 87 +++
49
include/hw/misc/stm32l4x5_syscfg.h | 3 +-
83
include/hw/arm/virt.h | 10 +
50
include/hw/rtc/sun4v-rtc.h | 2 +-
84
hw/arm/boot.c | 2 +-
51
target/arm/cpu-features.h | 10 +
85
hw/arm/omap1.c | 8 +-
52
target/arm/cpu.h | 129 +--------
86
hw/arm/omap2.c | 8 +-
53
target/arm/internals.h | 151 ++++++++++
87
hw/arm/pxa2xx.c | 15 +-
54
hw/arm/stm32l4x5_soc.c | 71 ++++-
88
hw/arm/smmu-common.c | 372 +++++++++++
55
hw/gpio/stm32l4x5_gpio.c | 477 ++++++++++++++++++++++++++++++++
89
hw/arm/smmuv3.c | 1191 +++++++++++++++++++++++++++++++++++
56
hw/misc/stm32l4x5_syscfg.c | 1 +
90
hw/arm/virt-acpi-build.c | 55 +-
57
hw/rtc/sun4v-rtc.c | 2 +-
91
hw/arm/virt.c | 101 ++-
58
target/arm/helper.c | 189 ++++++++++++-
92
hw/char/cmsdk-apb-uart.c | 1 +
59
target/arm/tcg/cpu-v7m.c | 290 +++++++++++++++++++
93
hw/net/smc91c111.c | 54 +-
60
target/arm/tcg/cpu32.c | 261 ------------------
94
hw/usb/tusb6010.c | 40 +-
61
target/arm/tcg/cpu64.c | 1 +
95
target/arm/helper.c | 2 +-
62
target/arm/tcg/sme_helper.c | 77 +++---
96
target/arm/kvm.c | 38 +-
63
tests/qtest/stm32l4x5_gpio-test.c | 551 +++++++++++++++++++++++++++++++++++++
97
target/arm/translate-a64.c | 12 +-
64
tests/tcg/aarch64/sme-smopa-1.c | 47 ++++
98
target/arm/translate.c | 17 +-
65
tests/tcg/aarch64/sme-smopa-2.c | 54 ++++
99
default-configs/aarch64-softmmu.mak | 1 +
66
hw/arm/Kconfig | 3 +-
100
hw/arm/trace-events | 37 ++
67
hw/gpio/Kconfig | 3 +
101
target/arm/trace-events | 3 +
68
hw/gpio/meson.build | 1 +
102
25 files changed, 2868 insertions(+), 67 deletions(-)
69
hw/gpio/trace-events | 6 +
103
create mode 100644 hw/arm/smmu-internal.h
70
target/arm/meson.build | 3 +
104
create mode 100644 hw/arm/smmuv3-internal.h
71
target/arm/tcg/meson.build | 3 +
105
create mode 100644 include/hw/arm/smmu-common.h
72
target/arm/trace-events | 1 +
106
create mode 100644 include/hw/arm/smmuv3.h
73
tests/qtest/meson.build | 3 +-
107
create mode 100644 hw/arm/smmu-common.c
74
tests/tcg/aarch64/Makefile.target | 2 +-
108
create mode 100644 hw/arm/smmuv3.c
75
31 files changed, 1962 insertions(+), 456 deletions(-)
76
create mode 100644 include/hw/gpio/stm32l4x5_gpio.h
77
create mode 100644 hw/gpio/stm32l4x5_gpio.c
78
create mode 100644 target/arm/tcg/cpu-v7m.c
79
create mode 100644 tests/qtest/stm32l4x5_gpio-test.c
80
create mode 100644 tests/tcg/aarch64/sme-smopa-1.c
81
create mode 100644 tests/tcg/aarch64/sme-smopa-2.c
109
82
diff view generated by jsdifflib
Deleted patch
1
From: Jan Kiszka <jan.kiszka@siemens.com>
2
1
3
This allows to pin the host controller in the Linux PCI domain space.
4
Linux requires that property to be available consistently or not at all,
5
in which case the domain number becomes unstable on additions/removals.
6
Adding it here won't make a difference in practice for most setups as we
7
only expose one controller.
8
9
However, enabling Jailhouse on top may introduce another controller, and
10
that one would like to have stable address as well. So the property is
11
needed for the first controller as well.
12
13
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
14
Message-id: 3301c5bc-7b47-1b0e-8ce4-30435057a276@web.de
15
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
---
18
hw/arm/virt.c | 1 +
19
1 file changed, 1 insertion(+)
20
21
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
22
index XXXXXXX..XXXXXXX 100644
23
--- a/hw/arm/virt.c
24
+++ b/hw/arm/virt.c
25
@@ -XXX,XX +XXX,XX @@ static void create_pcie(const VirtMachineState *vms, qemu_irq *pic)
26
qemu_fdt_setprop_string(vms->fdt, nodename, "device_type", "pci");
27
qemu_fdt_setprop_cell(vms->fdt, nodename, "#address-cells", 3);
28
qemu_fdt_setprop_cell(vms->fdt, nodename, "#size-cells", 2);
29
+ qemu_fdt_setprop_cell(vms->fdt, nodename, "linux,pci-domain", 0);
30
qemu_fdt_setprop_cells(vms->fdt, nodename, "bus-range", 0,
31
nr_pcie_buses - 1);
32
qemu_fdt_setprop(vms->fdt, nodename, "dma-coherent", NULL, 0);
33
--
34
2.17.0
35
36
diff view generated by jsdifflib
1
From: Eric Auger <eric.auger@redhat.com>
1
cpu.h has a lot of #defines relating to CPU register fields.
2
Most of these aren't actually used outside target/arm code,
3
so there's no point in cluttering up the cpu.h file with them.
4
Move some easy ones to internals.h.
2
5
3
ARM virt machine now exposes a new "iommu" option.
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
The SMMUv3 IOMMU is instantiated using -machine virt,iommu=smmuv3.
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20240301183219.2424889-2-peter.maydell@linaro.org
10
---
11
target/arm/cpu.h | 128 -----------------------------------------
12
target/arm/internals.h | 128 +++++++++++++++++++++++++++++++++++++++++
13
2 files changed, 128 insertions(+), 128 deletions(-)
5
14
6
Signed-off-by: Eric Auger <eric.auger@redhat.com>
15
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
7
Signed-off-by: Prem Mallappa <prem.mallappa@broadcom.com>
8
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>
11
---
12
hw/arm/virt.c | 36 ++++++++++++++++++++++++++++++++++++
13
1 file changed, 36 insertions(+)
14
15
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
16
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/arm/virt.c
17
--- a/target/arm/cpu.h
18
+++ b/hw/arm/virt.c
18
+++ b/target/arm/cpu.h
19
@@ -XXX,XX +XXX,XX @@ static void virt_set_gic_version(Object *obj, const char *value, Error **errp)
19
@@ -XXX,XX +XXX,XX @@ typedef struct ARMGenericTimer {
20
}
20
uint64_t ctl; /* Timer Control register */
21
}
21
} ARMGenericTimer;
22
22
23
+static char *virt_get_iommu(Object *obj, Error **errp)
23
-#define VTCR_NSW (1u << 29)
24
+{
24
-#define VTCR_NSA (1u << 30)
25
+ VirtMachineState *vms = VIRT_MACHINE(obj);
25
-#define VSTCR_SW VTCR_NSW
26
+
26
-#define VSTCR_SA VTCR_NSA
27
+ switch (vms->iommu) {
27
-
28
+ case VIRT_IOMMU_NONE:
28
/* Define a maximum sized vector register.
29
+ return g_strdup("none");
29
* For 32-bit, this is a 128-bit NEON/AdvSIMD register.
30
+ case VIRT_IOMMU_SMMUV3:
30
* For 64-bit, this is a 2048-bit SVE register.
31
+ return g_strdup("smmuv3");
31
@@ -XXX,XX +XXX,XX @@ void pmu_init(ARMCPU *cpu);
32
+ default:
32
#define SCTLR_SPINTMASK (1ULL << 62) /* FEAT_NMI */
33
+ g_assert_not_reached();
33
#define SCTLR_TIDCP (1ULL << 63) /* FEAT_TIDCP1 */
34
+ }
34
35
+}
35
-/* Bit definitions for CPACR (AArch32 only) */
36
+
36
-FIELD(CPACR, CP10, 20, 2)
37
+static void virt_set_iommu(Object *obj, const char *value, Error **errp)
37
-FIELD(CPACR, CP11, 22, 2)
38
+{
38
-FIELD(CPACR, TRCDIS, 28, 1) /* matches CPACR_EL1.TTA */
39
+ VirtMachineState *vms = VIRT_MACHINE(obj);
39
-FIELD(CPACR, D32DIS, 30, 1) /* up to v7; RAZ in v8 */
40
+
40
-FIELD(CPACR, ASEDIS, 31, 1)
41
+ if (!strcmp(value, "smmuv3")) {
41
-
42
+ vms->iommu = VIRT_IOMMU_SMMUV3;
42
-/* Bit definitions for CPACR_EL1 (AArch64 only) */
43
+ } else if (!strcmp(value, "none")) {
43
-FIELD(CPACR_EL1, ZEN, 16, 2)
44
+ vms->iommu = VIRT_IOMMU_NONE;
44
-FIELD(CPACR_EL1, FPEN, 20, 2)
45
+ } else {
45
-FIELD(CPACR_EL1, SMEN, 24, 2)
46
+ error_setg(errp, "Invalid iommu value");
46
-FIELD(CPACR_EL1, TTA, 28, 1) /* matches CPACR.TRCDIS */
47
+ error_append_hint(errp, "Valid values are none, smmuv3.\n");
47
-
48
+ }
48
-/* Bit definitions for HCPTR (AArch32 only) */
49
+}
49
-FIELD(HCPTR, TCP10, 10, 1)
50
+
50
-FIELD(HCPTR, TCP11, 11, 1)
51
static CpuInstanceProperties
51
-FIELD(HCPTR, TASE, 15, 1)
52
virt_cpu_index_to_props(MachineState *ms, unsigned cpu_index)
52
-FIELD(HCPTR, TTA, 20, 1)
53
{
53
-FIELD(HCPTR, TAM, 30, 1) /* matches CPTR_EL2.TAM */
54
@@ -XXX,XX +XXX,XX @@ static void virt_2_12_instance_init(Object *obj)
54
-FIELD(HCPTR, TCPAC, 31, 1) /* matches CPTR_EL2.TCPAC */
55
NULL);
55
-
56
}
56
-/* Bit definitions for CPTR_EL2 (AArch64 only) */
57
57
-FIELD(CPTR_EL2, TZ, 8, 1) /* !E2H */
58
+ /* Default disallows iommu instantiation */
58
-FIELD(CPTR_EL2, TFP, 10, 1) /* !E2H, matches HCPTR.TCP10 */
59
+ vms->iommu = VIRT_IOMMU_NONE;
59
-FIELD(CPTR_EL2, TSM, 12, 1) /* !E2H */
60
+ object_property_add_str(obj, "iommu", virt_get_iommu, virt_set_iommu, NULL);
60
-FIELD(CPTR_EL2, ZEN, 16, 2) /* E2H */
61
+ object_property_set_description(obj, "iommu",
61
-FIELD(CPTR_EL2, FPEN, 20, 2) /* E2H */
62
+ "Set the IOMMU type. "
62
-FIELD(CPTR_EL2, SMEN, 24, 2) /* E2H */
63
+ "Valid values are none and smmuv3",
63
-FIELD(CPTR_EL2, TTA, 28, 1)
64
+ NULL);
64
-FIELD(CPTR_EL2, TAM, 30, 1) /* matches HCPTR.TAM */
65
+
65
-FIELD(CPTR_EL2, TCPAC, 31, 1) /* matches HCPTR.TCPAC */
66
vms->memmap = a15memmap;
66
-
67
vms->irqmap = a15irqmap;
67
-/* Bit definitions for CPTR_EL3 (AArch64 only) */
68
}
68
-FIELD(CPTR_EL3, EZ, 8, 1)
69
-FIELD(CPTR_EL3, TFP, 10, 1)
70
-FIELD(CPTR_EL3, ESM, 12, 1)
71
-FIELD(CPTR_EL3, TTA, 20, 1)
72
-FIELD(CPTR_EL3, TAM, 30, 1)
73
-FIELD(CPTR_EL3, TCPAC, 31, 1)
74
-
75
-#define MDCR_MTPME (1U << 28)
76
-#define MDCR_TDCC (1U << 27)
77
-#define MDCR_HLP (1U << 26) /* MDCR_EL2 */
78
-#define MDCR_SCCD (1U << 23) /* MDCR_EL3 */
79
-#define MDCR_HCCD (1U << 23) /* MDCR_EL2 */
80
-#define MDCR_EPMAD (1U << 21)
81
-#define MDCR_EDAD (1U << 20)
82
-#define MDCR_TTRF (1U << 19)
83
-#define MDCR_STE (1U << 18) /* MDCR_EL3 */
84
-#define MDCR_SPME (1U << 17) /* MDCR_EL3 */
85
-#define MDCR_HPMD (1U << 17) /* MDCR_EL2 */
86
-#define MDCR_SDD (1U << 16)
87
-#define MDCR_SPD (3U << 14)
88
-#define MDCR_TDRA (1U << 11)
89
-#define MDCR_TDOSA (1U << 10)
90
-#define MDCR_TDA (1U << 9)
91
-#define MDCR_TDE (1U << 8)
92
-#define MDCR_HPME (1U << 7)
93
-#define MDCR_TPM (1U << 6)
94
-#define MDCR_TPMCR (1U << 5)
95
-#define MDCR_HPMN (0x1fU)
96
-
97
-/* Not all of the MDCR_EL3 bits are present in the 32-bit SDCR */
98
-#define SDCR_VALID_MASK (MDCR_MTPME | MDCR_TDCC | MDCR_SCCD | \
99
- MDCR_EPMAD | MDCR_EDAD | MDCR_TTRF | \
100
- MDCR_STE | MDCR_SPME | MDCR_SPD)
101
-
102
#define CPSR_M (0x1fU)
103
#define CPSR_T (1U << 5)
104
#define CPSR_F (1U << 6)
105
@@ -XXX,XX +XXX,XX @@ FIELD(CPTR_EL3, TCPAC, 31, 1)
106
#define XPSR_NZCV CPSR_NZCV
107
#define XPSR_IT CPSR_IT
108
109
-#define TTBCR_N (7U << 0) /* TTBCR.EAE==0 */
110
-#define TTBCR_T0SZ (7U << 0) /* TTBCR.EAE==1 */
111
-#define TTBCR_PD0 (1U << 4)
112
-#define TTBCR_PD1 (1U << 5)
113
-#define TTBCR_EPD0 (1U << 7)
114
-#define TTBCR_IRGN0 (3U << 8)
115
-#define TTBCR_ORGN0 (3U << 10)
116
-#define TTBCR_SH0 (3U << 12)
117
-#define TTBCR_T1SZ (3U << 16)
118
-#define TTBCR_A1 (1U << 22)
119
-#define TTBCR_EPD1 (1U << 23)
120
-#define TTBCR_IRGN1 (3U << 24)
121
-#define TTBCR_ORGN1 (3U << 26)
122
-#define TTBCR_SH1 (1U << 28)
123
-#define TTBCR_EAE (1U << 31)
124
-
125
-FIELD(VTCR, T0SZ, 0, 6)
126
-FIELD(VTCR, SL0, 6, 2)
127
-FIELD(VTCR, IRGN0, 8, 2)
128
-FIELD(VTCR, ORGN0, 10, 2)
129
-FIELD(VTCR, SH0, 12, 2)
130
-FIELD(VTCR, TG0, 14, 2)
131
-FIELD(VTCR, PS, 16, 3)
132
-FIELD(VTCR, VS, 19, 1)
133
-FIELD(VTCR, HA, 21, 1)
134
-FIELD(VTCR, HD, 22, 1)
135
-FIELD(VTCR, HWU59, 25, 1)
136
-FIELD(VTCR, HWU60, 26, 1)
137
-FIELD(VTCR, HWU61, 27, 1)
138
-FIELD(VTCR, HWU62, 28, 1)
139
-FIELD(VTCR, NSW, 29, 1)
140
-FIELD(VTCR, NSA, 30, 1)
141
-FIELD(VTCR, DS, 32, 1)
142
-FIELD(VTCR, SL2, 33, 1)
143
-
144
/* Bit definitions for ARMv8 SPSR (PSTATE) format.
145
* Only these are valid when in AArch64 mode; in
146
* AArch32 mode SPSRs are basically CPSR-format.
147
@@ -XXX,XX +XXX,XX @@ static inline void xpsr_write(CPUARMState *env, uint32_t val, uint32_t mask)
148
#define HCR_TWEDEN (1ULL << 59)
149
#define HCR_TWEDEL MAKE_64BIT_MASK(60, 4)
150
151
-#define HCRX_ENAS0 (1ULL << 0)
152
-#define HCRX_ENALS (1ULL << 1)
153
-#define HCRX_ENASR (1ULL << 2)
154
-#define HCRX_FNXS (1ULL << 3)
155
-#define HCRX_FGTNXS (1ULL << 4)
156
-#define HCRX_SMPME (1ULL << 5)
157
-#define HCRX_TALLINT (1ULL << 6)
158
-#define HCRX_VINMI (1ULL << 7)
159
-#define HCRX_VFNMI (1ULL << 8)
160
-#define HCRX_CMOW (1ULL << 9)
161
-#define HCRX_MCE2 (1ULL << 10)
162
-#define HCRX_MSCEN (1ULL << 11)
163
-
164
-#define HPFAR_NS (1ULL << 63)
165
-
166
#define SCR_NS (1ULL << 0)
167
#define SCR_IRQ (1ULL << 1)
168
#define SCR_FIQ (1ULL << 2)
169
@@ -XXX,XX +XXX,XX @@ static inline void xpsr_write(CPUARMState *env, uint32_t val, uint32_t mask)
170
#define SCR_GPF (1ULL << 48)
171
#define SCR_NSE (1ULL << 62)
172
173
-#define HSTR_TTEE (1 << 16)
174
-#define HSTR_TJDBX (1 << 17)
175
-
176
-#define CNTHCTL_CNTVMASK (1 << 18)
177
-#define CNTHCTL_CNTPMASK (1 << 19)
178
-
179
/* Return the current FPSCR value. */
180
uint32_t vfp_get_fpscr(CPUARMState *env);
181
void vfp_set_fpscr(CPUARMState *env, uint32_t val);
182
diff --git a/target/arm/internals.h b/target/arm/internals.h
183
index XXXXXXX..XXXXXXX 100644
184
--- a/target/arm/internals.h
185
+++ b/target/arm/internals.h
186
@@ -XXX,XX +XXX,XX @@ FIELD(DBGWCR, WT, 20, 1)
187
FIELD(DBGWCR, MASK, 24, 5)
188
FIELD(DBGWCR, SSCE, 29, 1)
189
190
+#define VTCR_NSW (1u << 29)
191
+#define VTCR_NSA (1u << 30)
192
+#define VSTCR_SW VTCR_NSW
193
+#define VSTCR_SA VTCR_NSA
194
+
195
+/* Bit definitions for CPACR (AArch32 only) */
196
+FIELD(CPACR, CP10, 20, 2)
197
+FIELD(CPACR, CP11, 22, 2)
198
+FIELD(CPACR, TRCDIS, 28, 1) /* matches CPACR_EL1.TTA */
199
+FIELD(CPACR, D32DIS, 30, 1) /* up to v7; RAZ in v8 */
200
+FIELD(CPACR, ASEDIS, 31, 1)
201
+
202
+/* Bit definitions for CPACR_EL1 (AArch64 only) */
203
+FIELD(CPACR_EL1, ZEN, 16, 2)
204
+FIELD(CPACR_EL1, FPEN, 20, 2)
205
+FIELD(CPACR_EL1, SMEN, 24, 2)
206
+FIELD(CPACR_EL1, TTA, 28, 1) /* matches CPACR.TRCDIS */
207
+
208
+/* Bit definitions for HCPTR (AArch32 only) */
209
+FIELD(HCPTR, TCP10, 10, 1)
210
+FIELD(HCPTR, TCP11, 11, 1)
211
+FIELD(HCPTR, TASE, 15, 1)
212
+FIELD(HCPTR, TTA, 20, 1)
213
+FIELD(HCPTR, TAM, 30, 1) /* matches CPTR_EL2.TAM */
214
+FIELD(HCPTR, TCPAC, 31, 1) /* matches CPTR_EL2.TCPAC */
215
+
216
+/* Bit definitions for CPTR_EL2 (AArch64 only) */
217
+FIELD(CPTR_EL2, TZ, 8, 1) /* !E2H */
218
+FIELD(CPTR_EL2, TFP, 10, 1) /* !E2H, matches HCPTR.TCP10 */
219
+FIELD(CPTR_EL2, TSM, 12, 1) /* !E2H */
220
+FIELD(CPTR_EL2, ZEN, 16, 2) /* E2H */
221
+FIELD(CPTR_EL2, FPEN, 20, 2) /* E2H */
222
+FIELD(CPTR_EL2, SMEN, 24, 2) /* E2H */
223
+FIELD(CPTR_EL2, TTA, 28, 1)
224
+FIELD(CPTR_EL2, TAM, 30, 1) /* matches HCPTR.TAM */
225
+FIELD(CPTR_EL2, TCPAC, 31, 1) /* matches HCPTR.TCPAC */
226
+
227
+/* Bit definitions for CPTR_EL3 (AArch64 only) */
228
+FIELD(CPTR_EL3, EZ, 8, 1)
229
+FIELD(CPTR_EL3, TFP, 10, 1)
230
+FIELD(CPTR_EL3, ESM, 12, 1)
231
+FIELD(CPTR_EL3, TTA, 20, 1)
232
+FIELD(CPTR_EL3, TAM, 30, 1)
233
+FIELD(CPTR_EL3, TCPAC, 31, 1)
234
+
235
+#define MDCR_MTPME (1U << 28)
236
+#define MDCR_TDCC (1U << 27)
237
+#define MDCR_HLP (1U << 26) /* MDCR_EL2 */
238
+#define MDCR_SCCD (1U << 23) /* MDCR_EL3 */
239
+#define MDCR_HCCD (1U << 23) /* MDCR_EL2 */
240
+#define MDCR_EPMAD (1U << 21)
241
+#define MDCR_EDAD (1U << 20)
242
+#define MDCR_TTRF (1U << 19)
243
+#define MDCR_STE (1U << 18) /* MDCR_EL3 */
244
+#define MDCR_SPME (1U << 17) /* MDCR_EL3 */
245
+#define MDCR_HPMD (1U << 17) /* MDCR_EL2 */
246
+#define MDCR_SDD (1U << 16)
247
+#define MDCR_SPD (3U << 14)
248
+#define MDCR_TDRA (1U << 11)
249
+#define MDCR_TDOSA (1U << 10)
250
+#define MDCR_TDA (1U << 9)
251
+#define MDCR_TDE (1U << 8)
252
+#define MDCR_HPME (1U << 7)
253
+#define MDCR_TPM (1U << 6)
254
+#define MDCR_TPMCR (1U << 5)
255
+#define MDCR_HPMN (0x1fU)
256
+
257
+/* Not all of the MDCR_EL3 bits are present in the 32-bit SDCR */
258
+#define SDCR_VALID_MASK (MDCR_MTPME | MDCR_TDCC | MDCR_SCCD | \
259
+ MDCR_EPMAD | MDCR_EDAD | MDCR_TTRF | \
260
+ MDCR_STE | MDCR_SPME | MDCR_SPD)
261
+
262
+#define TTBCR_N (7U << 0) /* TTBCR.EAE==0 */
263
+#define TTBCR_T0SZ (7U << 0) /* TTBCR.EAE==1 */
264
+#define TTBCR_PD0 (1U << 4)
265
+#define TTBCR_PD1 (1U << 5)
266
+#define TTBCR_EPD0 (1U << 7)
267
+#define TTBCR_IRGN0 (3U << 8)
268
+#define TTBCR_ORGN0 (3U << 10)
269
+#define TTBCR_SH0 (3U << 12)
270
+#define TTBCR_T1SZ (3U << 16)
271
+#define TTBCR_A1 (1U << 22)
272
+#define TTBCR_EPD1 (1U << 23)
273
+#define TTBCR_IRGN1 (3U << 24)
274
+#define TTBCR_ORGN1 (3U << 26)
275
+#define TTBCR_SH1 (1U << 28)
276
+#define TTBCR_EAE (1U << 31)
277
+
278
+FIELD(VTCR, T0SZ, 0, 6)
279
+FIELD(VTCR, SL0, 6, 2)
280
+FIELD(VTCR, IRGN0, 8, 2)
281
+FIELD(VTCR, ORGN0, 10, 2)
282
+FIELD(VTCR, SH0, 12, 2)
283
+FIELD(VTCR, TG0, 14, 2)
284
+FIELD(VTCR, PS, 16, 3)
285
+FIELD(VTCR, VS, 19, 1)
286
+FIELD(VTCR, HA, 21, 1)
287
+FIELD(VTCR, HD, 22, 1)
288
+FIELD(VTCR, HWU59, 25, 1)
289
+FIELD(VTCR, HWU60, 26, 1)
290
+FIELD(VTCR, HWU61, 27, 1)
291
+FIELD(VTCR, HWU62, 28, 1)
292
+FIELD(VTCR, NSW, 29, 1)
293
+FIELD(VTCR, NSA, 30, 1)
294
+FIELD(VTCR, DS, 32, 1)
295
+FIELD(VTCR, SL2, 33, 1)
296
+
297
+#define HCRX_ENAS0 (1ULL << 0)
298
+#define HCRX_ENALS (1ULL << 1)
299
+#define HCRX_ENASR (1ULL << 2)
300
+#define HCRX_FNXS (1ULL << 3)
301
+#define HCRX_FGTNXS (1ULL << 4)
302
+#define HCRX_SMPME (1ULL << 5)
303
+#define HCRX_TALLINT (1ULL << 6)
304
+#define HCRX_VINMI (1ULL << 7)
305
+#define HCRX_VFNMI (1ULL << 8)
306
+#define HCRX_CMOW (1ULL << 9)
307
+#define HCRX_MCE2 (1ULL << 10)
308
+#define HCRX_MSCEN (1ULL << 11)
309
+
310
+#define HPFAR_NS (1ULL << 63)
311
+
312
+#define HSTR_TTEE (1 << 16)
313
+#define HSTR_TJDBX (1 << 17)
314
+
315
+#define CNTHCTL_CNTVMASK (1 << 18)
316
+#define CNTHCTL_CNTPMASK (1 << 19)
317
+
318
/* We use a few fake FSR values for internal purposes in M profile.
319
* M profile cores don't have A/R format FSRs, but currently our
320
* get_phys_addr() code assumes A/R profile and reports failures via
69
--
321
--
70
2.17.0
322
2.34.1
71
323
72
324
diff view generated by jsdifflib
1
From: Mathew Maidment <mathew1800@gmail.com>
1
The timer _EL02 registers should UNDEF for invalid accesses from EL2
2
or EL3 when HCR_EL2.E2H == 0, not take a cp access trap. We were
3
delivering the exception to EL2 with the wrong syndrome.
2
4
3
The duplication of id_tlbtr_reginfo was unintentionally added within
4
3281af8114c6b8ead02f08b58e3c36895c1ea047 which should have been
5
id_mpuir_reginfo.
6
7
The effect was that for OMAP and StrongARM CPUs we would
8
incorrectly UNDEF writes to MPUIR rather than NOPing them.
9
10
Signed-off-by: Mathew Maidment <mathew1800@gmail.com>
11
Message-id: 20180501184933.37609-2-mathew1800@gmail.com
12
[PMM: tweak commit message]
13
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20240301183219.2424889-3-peter.maydell@linaro.org
15
---
8
---
16
target/arm/helper.c | 2 +-
9
target/arm/helper.c | 2 +-
17
1 file changed, 1 insertion(+), 1 deletion(-)
10
1 file changed, 1 insertion(+), 1 deletion(-)
18
11
19
diff --git a/target/arm/helper.c b/target/arm/helper.c
12
diff --git a/target/arm/helper.c b/target/arm/helper.c
20
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
21
--- a/target/arm/helper.c
14
--- a/target/arm/helper.c
22
+++ b/target/arm/helper.c
15
+++ b/target/arm/helper.c
23
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
16
@@ -XXX,XX +XXX,XX @@ static CPAccessResult e2h_access(CPUARMState *env, const ARMCPRegInfo *ri,
24
for (r = id_cp_reginfo; r->type != ARM_CP_SENTINEL; r++) {
17
return CP_ACCESS_OK;
25
r->access = PL1_RW;
18
}
26
}
19
if (!(arm_hcr_el2_eff(env) & HCR_E2H)) {
27
- id_tlbtr_reginfo.access = PL1_RW;
20
- return CP_ACCESS_TRAP;
28
+ id_mpuir_reginfo.access = PL1_RW;
21
+ return CP_ACCESS_TRAP_UNCATEGORIZED;
29
id_tlbtr_reginfo.access = PL1_RW;
22
}
30
}
23
return CP_ACCESS_OK;
31
if (arm_feature(env, ARM_FEATURE_V8)) {
24
}
32
--
25
--
33
2.17.0
26
2.34.1
34
35
diff view generated by jsdifflib
Deleted patch
1
From: Patrick Oppenlander <patrick.oppenlander@gmail.com>
2
1
3
The character frontend needs to be notified that the uart receive buffer
4
is empty and ready to handle another character.
5
6
Previously, the uart only worked correctly when receiving one character
7
at a time.
8
9
Signed-off-by: Patrick Oppenlander <patrick.oppenlander@gmail.com>
10
Message-id: CAEg67GkRTw=cXei3o9hvpxG_L4zSrNzR0bFyAgny+sSEUb_kPw@mail.gmail.com
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
14
hw/char/cmsdk-apb-uart.c | 1 +
15
1 file changed, 1 insertion(+)
16
17
diff --git a/hw/char/cmsdk-apb-uart.c b/hw/char/cmsdk-apb-uart.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/char/cmsdk-apb-uart.c
20
+++ b/hw/char/cmsdk-apb-uart.c
21
@@ -XXX,XX +XXX,XX @@ static uint64_t uart_read(void *opaque, hwaddr offset, unsigned size)
22
r = s->rxbuf;
23
s->state &= ~R_STATE_RXFULL_MASK;
24
cmsdk_apb_uart_update(s);
25
+ qemu_chr_fe_accept_input(&s->chr);
26
break;
27
case A_STATE:
28
r = s->state;
29
--
30
2.17.0
31
32
diff view generated by jsdifflib
1
From: Igor Mammedov <imammedo@redhat.com>
1
We prefer the FIELD macro over ad-hoc #defines for register bits;
2
switch CNTHCTL to that style before we add any more bits.
2
3
3
Even though nothing is currently broken (since all boards
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
use first_cpu as boot cpu), make sure that boot_info is set
5
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
5
on all CPUs.
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
If some board would like support heterogenuos setup (i.e.
7
Message-id: 20240301183219.2424889-4-peter.maydell@linaro.org
7
init boot_info on subset of CPUs) in future, it should add
8
---
8
a reasonable API to do it, instead of starting assigning
9
target/arm/internals.h | 27 +++++++++++++++++++++++++--
9
boot_info from some CPU and till the end of present CPUs
10
target/arm/helper.c | 9 ++++-----
10
list.
11
2 files changed, 29 insertions(+), 7 deletions(-)
11
12
12
Ref:
13
diff --git a/target/arm/internals.h b/target/arm/internals.h
13
"Message-ID: <CAFEAcA_NMWuA8WSs3cNeY6xX1kerO_uAcN_3=fK02BEhHJW86g@mail.gmail.com>"
14
15
Signed-off-by: Igor Mammedov <imammedo@redhat.com>
16
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
17
Message-id: 1525176522-200354-5-git-send-email-imammedo@redhat.com
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
---
20
hw/arm/boot.c | 2 +-
21
1 file changed, 1 insertion(+), 1 deletion(-)
22
23
diff --git a/hw/arm/boot.c b/hw/arm/boot.c
24
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
25
--- a/hw/arm/boot.c
15
--- a/target/arm/internals.h
26
+++ b/hw/arm/boot.c
16
+++ b/target/arm/internals.h
27
@@ -XXX,XX +XXX,XX @@ static void arm_load_kernel_notify(Notifier *notifier, void *data)
17
@@ -XXX,XX +XXX,XX @@ FIELD(VTCR, SL2, 33, 1)
18
#define HSTR_TTEE (1 << 16)
19
#define HSTR_TJDBX (1 << 17)
20
21
-#define CNTHCTL_CNTVMASK (1 << 18)
22
-#define CNTHCTL_CNTPMASK (1 << 19)
23
+/*
24
+ * Depending on the value of HCR_EL2.E2H, bits 0 and 1
25
+ * have different bit definitions, and EL1PCTEN might be
26
+ * bit 0 or bit 10. We use _E2H1 and _E2H0 suffixes to
27
+ * disambiguate if necessary.
28
+ */
29
+FIELD(CNTHCTL, EL0PCTEN_E2H1, 0, 1)
30
+FIELD(CNTHCTL, EL0VCTEN_E2H1, 1, 1)
31
+FIELD(CNTHCTL, EL1PCTEN_E2H0, 0, 1)
32
+FIELD(CNTHCTL, EL1PCEN_E2H0, 1, 1)
33
+FIELD(CNTHCTL, EVNTEN, 2, 1)
34
+FIELD(CNTHCTL, EVNTDIR, 3, 1)
35
+FIELD(CNTHCTL, EVNTI, 4, 4)
36
+FIELD(CNTHCTL, EL0VTEN, 8, 1)
37
+FIELD(CNTHCTL, EL0PTEN, 9, 1)
38
+FIELD(CNTHCTL, EL1PCTEN_E2H1, 10, 1)
39
+FIELD(CNTHCTL, EL1PTEN, 11, 1)
40
+FIELD(CNTHCTL, ECV, 12, 1)
41
+FIELD(CNTHCTL, EL1TVT, 13, 1)
42
+FIELD(CNTHCTL, EL1TVCT, 14, 1)
43
+FIELD(CNTHCTL, EL1NVPCT, 15, 1)
44
+FIELD(CNTHCTL, EL1NVVCT, 16, 1)
45
+FIELD(CNTHCTL, EVNTIS, 17, 1)
46
+FIELD(CNTHCTL, CNTVMASK, 18, 1)
47
+FIELD(CNTHCTL, CNTPMASK, 19, 1)
48
49
/* We use a few fake FSR values for internal purposes in M profile.
50
* M profile cores don't have A/R format FSRs, but currently our
51
diff --git a/target/arm/helper.c b/target/arm/helper.c
52
index XXXXXXX..XXXXXXX 100644
53
--- a/target/arm/helper.c
54
+++ b/target/arm/helper.c
55
@@ -XXX,XX +XXX,XX @@ static void gt_update_irq(ARMCPU *cpu, int timeridx)
56
* It is RES0 in Secure and NonSecure state.
57
*/
58
if ((ss == ARMSS_Root || ss == ARMSS_Realm) &&
59
- ((timeridx == GTIMER_VIRT && (cnthctl & CNTHCTL_CNTVMASK)) ||
60
- (timeridx == GTIMER_PHYS && (cnthctl & CNTHCTL_CNTPMASK)))) {
61
+ ((timeridx == GTIMER_VIRT && (cnthctl & R_CNTHCTL_CNTVMASK_MASK)) ||
62
+ (timeridx == GTIMER_PHYS && (cnthctl & R_CNTHCTL_CNTPMASK_MASK)))) {
63
irqstate = 0;
28
}
64
}
29
info->is_linux = is_linux;
65
30
66
@@ -XXX,XX +XXX,XX @@ static void gt_cnthctl_write(CPUARMState *env, const ARMCPRegInfo *ri,
31
- for (cs = CPU(cpu); cs; cs = CPU_NEXT(cs)) {
67
{
32
+ for (cs = first_cpu; cs; cs = CPU_NEXT(cs)) {
68
ARMCPU *cpu = env_archcpu(env);
33
ARM_CPU(cs)->env.boot_info = info;
69
uint32_t oldval = env->cp15.cnthctl_el2;
70
-
71
raw_write(env, ri, value);
72
73
- if ((oldval ^ value) & CNTHCTL_CNTVMASK) {
74
+ if ((oldval ^ value) & R_CNTHCTL_CNTVMASK_MASK) {
75
gt_update_irq(cpu, GTIMER_VIRT);
76
- } else if ((oldval ^ value) & CNTHCTL_CNTPMASK) {
77
+ } else if ((oldval ^ value) & R_CNTHCTL_CNTPMASK_MASK) {
78
gt_update_irq(cpu, GTIMER_PHYS);
34
}
79
}
35
}
80
}
36
--
81
--
37
2.17.0
82
2.34.1
38
83
39
84
diff view generated by jsdifflib
1
From: Prem Mallappa <prem.mallappa@broadcom.com>
1
Don't allow the guest to write CNTHCTL_EL2 bits which don't exist.
2
This is not strictly architecturally required, but it is how we've
3
tended to implement registers more recently.
2
4
3
This patch builds the smmuv3 node in the ACPI IORT table.
5
In particular, bits [19:18] are only present with FEAT_RME,
6
and bits [17:12] will only be present with FEAT_ECV.
4
7
5
The RID space of the root complex, which spans 0x0-0x10000
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
maps to streamid space 0x0-0x10000 in smmuv3, which in turn
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
maps to deviceid space 0x0-0x10000 in the ITS group.
10
Message-id: 20240301183219.2424889-5-peter.maydell@linaro.org
11
---
12
target/arm/helper.c | 18 ++++++++++++++++++
13
1 file changed, 18 insertions(+)
8
14
9
The guest must feature the IOMMU probe deferral series
15
diff --git a/target/arm/helper.c b/target/arm/helper.c
10
(https://lkml.org/lkml/2017/4/10/214) which fixes streamid
11
multiple lookup. This bug is not related to the SMMU emulation.
12
13
Signed-off-by: Prem Mallappa <prem.mallappa@broadcom.com>
14
Signed-off-by: Eric Auger <eric.auger@redhat.com>
15
Reviewed-by: Shannon Zhao <zhaoshenglong@huawei.com>
16
Message-id: 1524665762-31355-14-git-send-email-eric.auger@redhat.com
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
---
19
include/hw/acpi/acpi-defs.h | 15 ++++++++++
20
hw/arm/virt-acpi-build.c | 55 ++++++++++++++++++++++++++++++++-----
21
2 files changed, 63 insertions(+), 7 deletions(-)
22
23
diff --git a/include/hw/acpi/acpi-defs.h b/include/hw/acpi/acpi-defs.h
24
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
25
--- a/include/hw/acpi/acpi-defs.h
17
--- a/target/arm/helper.c
26
+++ b/include/hw/acpi/acpi-defs.h
18
+++ b/target/arm/helper.c
27
@@ -XXX,XX +XXX,XX @@ struct AcpiIortItsGroup {
19
@@ -XXX,XX +XXX,XX @@ static void gt_cnthctl_write(CPUARMState *env, const ARMCPRegInfo *ri,
28
} QEMU_PACKED;
20
{
29
typedef struct AcpiIortItsGroup AcpiIortItsGroup;
21
ARMCPU *cpu = env_archcpu(env);
30
22
uint32_t oldval = env->cp15.cnthctl_el2;
31
+struct AcpiIortSmmu3 {
23
+ uint32_t valid_mask =
32
+ ACPI_IORT_NODE_HEADER_DEF
24
+ R_CNTHCTL_EL0PCTEN_E2H1_MASK |
33
+ uint64_t base_address;
25
+ R_CNTHCTL_EL0VCTEN_E2H1_MASK |
34
+ uint32_t flags;
26
+ R_CNTHCTL_EVNTEN_MASK |
35
+ uint32_t reserved2;
27
+ R_CNTHCTL_EVNTDIR_MASK |
36
+ uint64_t vatos_address;
28
+ R_CNTHCTL_EVNTI_MASK |
37
+ uint32_t model;
29
+ R_CNTHCTL_EL0VTEN_MASK |
38
+ uint32_t event_gsiv;
30
+ R_CNTHCTL_EL0PTEN_MASK |
39
+ uint32_t pri_gsiv;
31
+ R_CNTHCTL_EL1PCTEN_E2H1_MASK |
40
+ uint32_t gerr_gsiv;
32
+ R_CNTHCTL_EL1PTEN_MASK;
41
+ uint32_t sync_gsiv;
42
+ AcpiIortIdMapping id_mapping_array[0];
43
+} QEMU_PACKED;
44
+typedef struct AcpiIortSmmu3 AcpiIortSmmu3;
45
+
33
+
46
struct AcpiIortRC {
34
+ if (cpu_isar_feature(aa64_rme, cpu)) {
47
ACPI_IORT_NODE_HEADER_DEF
35
+ valid_mask |= R_CNTHCTL_CNTVMASK_MASK | R_CNTHCTL_CNTPMASK_MASK;
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
+ }
36
+ }
77
+
37
+
78
iort_length = sizeof(*iort);
38
+ /* Clear RES0 bits */
79
- iort->node_count = cpu_to_le32(2); /* RC and ITS nodes */
39
+ value &= valid_mask;
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
+
40
+
91
+ /* SMMUv3 node */
41
raw_write(env, ri, value);
92
+ smmu_offset = iort->node_offset + node_size;
42
93
+ node_size = sizeof(*smmu) + sizeof(*idmap);
43
if ((oldval ^ value) & R_CNTHCTL_CNTVMASK_MASK) {
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
}
143
144
/* XSDT is pointed to by RSDP */
145
--
44
--
146
2.17.0
45
2.34.1
147
148
diff view generated by jsdifflib
1
Convert the tusb6010 device away from using the old_mmio field
1
The functionality defined by ID_AA64MMFR0_EL1.ECV == 1 is:
2
of MemoryRegionOps. This device is used only in the n800 and n810
2
* four new trap bits for various counter and timer registers
3
boards.
3
* the CNTHCTL_EL2.EVNTIS and CNTKCTL_EL1.EVNTIS bits which control
4
scaling of the event stream. This is a no-op for us, because we don't
5
implement the event stream (our WFE is a NOP): all we need to do is
6
allow CNTHCTL_EL2.ENVTIS to be read and written.
7
* extensions to PMSCR_EL1.PCT, PMSCR_EL2.PCT, TRFCR_EL1.TS and
8
TRFCR_EL2.TS: these are all no-ops for us, because we don't implement
9
FEAT_SPE or FEAT_TRF.
10
* new registers CNTPCTSS_EL0 and NCTVCTSS_EL0 which are
11
"self-sychronizing" views of the CNTPCT_EL0 and CNTVCT_EL0, meaning
12
that no barriers are needed around their accesses. For us these
13
are just the same as the normal views, because all our sysregs are
14
inherently self-sychronizing.
15
16
In this commit we implement the trap handling and permit the new
17
CNTHCTL_EL2 bits to be written.
4
18
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
20
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20180427173611.10281-2-peter.maydell@linaro.org
21
Message-id: 20240301183219.2424889-6-peter.maydell@linaro.org
8
---
22
---
9
hw/usb/tusb6010.c | 40 ++++++++++++++++++++++++++++++++++++----
23
target/arm/cpu-features.h | 5 ++++
10
1 file changed, 36 insertions(+), 4 deletions(-)
24
target/arm/helper.c | 51 +++++++++++++++++++++++++++++++++++----
25
2 files changed, 51 insertions(+), 5 deletions(-)
11
26
12
diff --git a/hw/usb/tusb6010.c b/hw/usb/tusb6010.c
27
diff --git a/target/arm/cpu-features.h b/target/arm/cpu-features.h
13
index XXXXXXX..XXXXXXX 100644
28
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/usb/tusb6010.c
29
--- a/target/arm/cpu-features.h
15
+++ b/hw/usb/tusb6010.c
30
+++ b/target/arm/cpu-features.h
16
@@ -XXX,XX +XXX,XX @@ static void tusb_async_writew(void *opaque, hwaddr addr,
31
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa64_fgt(const ARMISARegisters *id)
17
}
32
return FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, FGT) != 0;
18
}
33
}
19
34
20
+static uint64_t tusb_async_readfn(void *opaque, hwaddr addr, unsigned size)
35
+static inline bool isar_feature_aa64_ecv_traps(const ARMISARegisters *id)
21
+{
36
+{
22
+ switch (size) {
37
+ return FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, ECV) > 0;
23
+ case 1:
24
+ return tusb_async_readb(opaque, addr);
25
+ case 2:
26
+ return tusb_async_readh(opaque, addr);
27
+ case 4:
28
+ return tusb_async_readw(opaque, addr);
29
+ default:
30
+ g_assert_not_reached();
31
+ }
32
+}
38
+}
33
+
39
+
34
+static void tusb_async_writefn(void *opaque, hwaddr addr,
40
static inline bool isar_feature_aa64_vh(const ARMISARegisters *id)
35
+ uint64_t value, unsigned size)
41
{
42
return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, VH) != 0;
43
diff --git a/target/arm/helper.c b/target/arm/helper.c
44
index XXXXXXX..XXXXXXX 100644
45
--- a/target/arm/helper.c
46
+++ b/target/arm/helper.c
47
@@ -XXX,XX +XXX,XX @@ static CPAccessResult gt_counter_access(CPUARMState *env, int timeridx,
48
: !extract32(env->cp15.cnthctl_el2, 0, 1))) {
49
return CP_ACCESS_TRAP_EL2;
50
}
51
+ if (has_el2 && timeridx == GTIMER_VIRT) {
52
+ if (FIELD_EX64(env->cp15.cnthctl_el2, CNTHCTL, EL1TVCT)) {
53
+ return CP_ACCESS_TRAP_EL2;
54
+ }
55
+ }
56
break;
57
}
58
return CP_ACCESS_OK;
59
@@ -XXX,XX +XXX,XX @@ static CPAccessResult gt_timer_access(CPUARMState *env, int timeridx,
60
}
61
}
62
}
63
+ if (has_el2 && timeridx == GTIMER_VIRT) {
64
+ if (FIELD_EX64(env->cp15.cnthctl_el2, CNTHCTL, EL1TVT)) {
65
+ return CP_ACCESS_TRAP_EL2;
66
+ }
67
+ }
68
break;
69
}
70
return CP_ACCESS_OK;
71
@@ -XXX,XX +XXX,XX @@ static void gt_cnthctl_write(CPUARMState *env, const ARMCPRegInfo *ri,
72
if (cpu_isar_feature(aa64_rme, cpu)) {
73
valid_mask |= R_CNTHCTL_CNTVMASK_MASK | R_CNTHCTL_CNTPMASK_MASK;
74
}
75
+ if (cpu_isar_feature(aa64_ecv_traps, cpu)) {
76
+ valid_mask |=
77
+ R_CNTHCTL_EL1TVT_MASK |
78
+ R_CNTHCTL_EL1TVCT_MASK |
79
+ R_CNTHCTL_EL1NVPCT_MASK |
80
+ R_CNTHCTL_EL1NVVCT_MASK |
81
+ R_CNTHCTL_EVNTIS_MASK;
82
+ }
83
84
/* Clear RES0 bits */
85
value &= valid_mask;
86
@@ -XXX,XX +XXX,XX @@ static CPAccessResult e2h_access(CPUARMState *env, const ARMCPRegInfo *ri,
87
{
88
if (arm_current_el(env) == 1) {
89
/* This must be a FEAT_NV access */
90
- /* TODO: FEAT_ECV will need to check CNTHCTL_EL2 here */
91
return CP_ACCESS_OK;
92
}
93
if (!(arm_hcr_el2_eff(env) & HCR_E2H)) {
94
@@ -XXX,XX +XXX,XX @@ static CPAccessResult e2h_access(CPUARMState *env, const ARMCPRegInfo *ri,
95
return CP_ACCESS_OK;
96
}
97
98
+static CPAccessResult access_el1nvpct(CPUARMState *env, const ARMCPRegInfo *ri,
99
+ bool isread)
36
+{
100
+{
37
+ switch (size) {
101
+ if (arm_current_el(env) == 1) {
38
+ case 1:
102
+ /* This must be a FEAT_NV access with NVx == 101 */
39
+ tusb_async_writeb(opaque, addr, value);
103
+ if (FIELD_EX64(env->cp15.cnthctl_el2, CNTHCTL, EL1NVPCT)) {
40
+ break;
104
+ return CP_ACCESS_TRAP_EL2;
41
+ case 2:
105
+ }
42
+ tusb_async_writeh(opaque, addr, value);
43
+ break;
44
+ case 4:
45
+ tusb_async_writew(opaque, addr, value);
46
+ break;
47
+ default:
48
+ g_assert_not_reached();
49
+ }
106
+ }
107
+ return e2h_access(env, ri, isread);
50
+}
108
+}
51
+
109
+
52
static const MemoryRegionOps tusb_async_ops = {
110
+static CPAccessResult access_el1nvvct(CPUARMState *env, const ARMCPRegInfo *ri,
53
- .old_mmio = {
111
+ bool isread)
54
- .read = { tusb_async_readb, tusb_async_readh, tusb_async_readw, },
112
+{
55
- .write = { tusb_async_writeb, tusb_async_writeh, tusb_async_writew, },
113
+ if (arm_current_el(env) == 1) {
56
- },
114
+ /* This must be a FEAT_NV access with NVx == 101 */
57
+ .read = tusb_async_readfn,
115
+ if (FIELD_EX64(env->cp15.cnthctl_el2, CNTHCTL, EL1NVVCT)) {
58
+ .write = tusb_async_writefn,
116
+ return CP_ACCESS_TRAP_EL2;
59
+ .valid.min_access_size = 1,
117
+ }
60
+ .valid.max_access_size = 4,
118
+ }
61
.endianness = DEVICE_NATIVE_ENDIAN,
119
+ return e2h_access(env, ri, isread);
120
+}
121
+
122
/* Test if system register redirection is to occur in the current state. */
123
static bool redirect_for_e2h(CPUARMState *env)
124
{
125
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo vhe_reginfo[] = {
126
{ .name = "CNTP_CTL_EL02", .state = ARM_CP_STATE_AA64,
127
.opc0 = 3, .opc1 = 5, .crn = 14, .crm = 2, .opc2 = 1,
128
.type = ARM_CP_IO | ARM_CP_ALIAS,
129
- .access = PL2_RW, .accessfn = e2h_access,
130
+ .access = PL2_RW, .accessfn = access_el1nvpct,
131
.nv2_redirect_offset = 0x180 | NV2_REDIR_NO_NV1,
132
.fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_PHYS].ctl),
133
.writefn = gt_phys_ctl_write, .raw_writefn = raw_write },
134
{ .name = "CNTV_CTL_EL02", .state = ARM_CP_STATE_AA64,
135
.opc0 = 3, .opc1 = 5, .crn = 14, .crm = 3, .opc2 = 1,
136
.type = ARM_CP_IO | ARM_CP_ALIAS,
137
- .access = PL2_RW, .accessfn = e2h_access,
138
+ .access = PL2_RW, .accessfn = access_el1nvvct,
139
.nv2_redirect_offset = 0x170 | NV2_REDIR_NO_NV1,
140
.fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_VIRT].ctl),
141
.writefn = gt_virt_ctl_write, .raw_writefn = raw_write },
142
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo vhe_reginfo[] = {
143
.type = ARM_CP_IO | ARM_CP_ALIAS,
144
.fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_PHYS].cval),
145
.nv2_redirect_offset = 0x178 | NV2_REDIR_NO_NV1,
146
- .access = PL2_RW, .accessfn = e2h_access,
147
+ .access = PL2_RW, .accessfn = access_el1nvpct,
148
.writefn = gt_phys_cval_write, .raw_writefn = raw_write },
149
{ .name = "CNTV_CVAL_EL02", .state = ARM_CP_STATE_AA64,
150
.opc0 = 3, .opc1 = 5, .crn = 14, .crm = 3, .opc2 = 2,
151
.type = ARM_CP_IO | ARM_CP_ALIAS,
152
.nv2_redirect_offset = 0x168 | NV2_REDIR_NO_NV1,
153
.fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_VIRT].cval),
154
- .access = PL2_RW, .accessfn = e2h_access,
155
+ .access = PL2_RW, .accessfn = access_el1nvvct,
156
.writefn = gt_virt_cval_write, .raw_writefn = raw_write },
157
#endif
62
};
158
};
63
64
--
159
--
65
2.17.0
160
2.34.1
66
67
diff view generated by jsdifflib
1
From: Prem Mallappa <prem.mallappa@broadcom.com>
1
For FEAT_ECV, new registers CNTPCTSS_EL0 and CNTVCTSS_EL0 are
2
defined, which are "self-synchronized" views of the physical and
3
virtual counts as seen in the CNTPCT_EL0 and CNTVCT_EL0 registers
4
(meaning that no barriers are needed around accesses to them to
5
ensure that reads of them do not occur speculatively and out-of-order
6
with other instructions).
2
7
3
Add code to instantiate an smmuv3 in virt machine. A new iommu
8
For QEMU, all our system registers are self-synchronized, so we can
4
integer member is introduced in VirtMachineState to store the type
9
simply copy the existing implementation of CNTPCT_EL0 and CNTVCT_EL0
5
of the iommu in use.
10
to the new register encodings.
6
11
7
Signed-off-by: Prem Mallappa <prem.mallappa@broadcom.com>
12
This means we now implement all the functionality required for
8
Signed-off-by: Eric Auger <eric.auger@redhat.com>
13
ID_AA64MMFR0_EL1.ECV == 0b0001.
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
10
Message-id: 1524665762-31355-13-git-send-email-eric.auger@redhat.com
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
17
Message-id: 20240301183219.2424889-7-peter.maydell@linaro.org
12
---
18
---
13
include/hw/arm/virt.h | 10 +++++++
19
target/arm/helper.c | 43 +++++++++++++++++++++++++++++++++++++++++++
14
hw/arm/virt.c | 64 ++++++++++++++++++++++++++++++++++++++++++-
20
1 file changed, 43 insertions(+)
15
2 files changed, 73 insertions(+), 1 deletion(-)
16
21
17
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
22
diff --git a/target/arm/helper.c b/target/arm/helper.c
18
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
19
--- a/include/hw/arm/virt.h
24
--- a/target/arm/helper.c
20
+++ b/include/hw/arm/virt.h
25
+++ b/target/arm/helper.c
21
@@ -XXX,XX +XXX,XX @@
26
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo generic_timer_cp_reginfo[] = {
22
27
},
23
#define NUM_GICV2M_SPIS 64
24
#define NUM_VIRTIO_TRANSPORTS 32
25
+#define NUM_SMMU_IRQS 4
26
27
#define ARCH_GICV3_MAINT_IRQ 9
28
29
@@ -XXX,XX +XXX,XX @@ enum {
30
VIRT_GIC_V2M,
31
VIRT_GIC_ITS,
32
VIRT_GIC_REDIST,
33
+ VIRT_SMMU,
34
VIRT_UART,
35
VIRT_MMIO,
36
VIRT_RTC,
37
@@ -XXX,XX +XXX,XX @@ enum {
38
VIRT_SECURE_MEM,
39
};
28
};
40
29
41
+typedef enum VirtIOMMUType {
30
+/*
42
+ VIRT_IOMMU_NONE,
31
+ * FEAT_ECV adds extra views of CNTVCT_EL0 and CNTPCT_EL0 which
43
+ VIRT_IOMMU_SMMUV3,
32
+ * are "self-synchronizing". For QEMU all sysregs are self-synchronizing,
44
+ VIRT_IOMMU_VIRTIO,
33
+ * so our implementations here are identical to the normal registers.
45
+} VirtIOMMUType;
34
+ */
35
+static const ARMCPRegInfo gen_timer_ecv_cp_reginfo[] = {
36
+ { .name = "CNTVCTSS", .cp = 15, .crm = 14, .opc1 = 9,
37
+ .access = PL0_R, .type = ARM_CP_64BIT | ARM_CP_NO_RAW | ARM_CP_IO,
38
+ .accessfn = gt_vct_access,
39
+ .readfn = gt_virt_cnt_read, .resetfn = arm_cp_reset_ignore,
40
+ },
41
+ { .name = "CNTVCTSS_EL0", .state = ARM_CP_STATE_AA64,
42
+ .opc0 = 3, .opc1 = 3, .crn = 14, .crm = 0, .opc2 = 6,
43
+ .access = PL0_R, .type = ARM_CP_NO_RAW | ARM_CP_IO,
44
+ .accessfn = gt_vct_access, .readfn = gt_virt_cnt_read,
45
+ },
46
+ { .name = "CNTPCTSS", .cp = 15, .crm = 14, .opc1 = 8,
47
+ .access = PL0_R, .type = ARM_CP_64BIT | ARM_CP_NO_RAW | ARM_CP_IO,
48
+ .accessfn = gt_pct_access,
49
+ .readfn = gt_cnt_read, .resetfn = arm_cp_reset_ignore,
50
+ },
51
+ { .name = "CNTPCTSS_EL0", .state = ARM_CP_STATE_AA64,
52
+ .opc0 = 3, .opc1 = 3, .crn = 14, .crm = 0, .opc2 = 5,
53
+ .access = PL0_R, .type = ARM_CP_NO_RAW | ARM_CP_IO,
54
+ .accessfn = gt_pct_access, .readfn = gt_cnt_read,
55
+ },
56
+};
46
+
57
+
47
typedef struct MemMapEntry {
58
#else
48
hwaddr base;
59
49
hwaddr size;
60
/*
50
@@ -XXX,XX +XXX,XX @@ typedef struct {
61
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo generic_timer_cp_reginfo[] = {
51
bool its;
62
},
52
bool virt;
53
int32_t gic_version;
54
+ VirtIOMMUType iommu;
55
struct arm_boot_info bootinfo;
56
const MemMapEntry *memmap;
57
const int *irqmap;
58
@@ -XXX,XX +XXX,XX @@ typedef struct {
59
uint32_t clock_phandle;
60
uint32_t gic_phandle;
61
uint32_t msi_phandle;
62
+ uint32_t iommu_phandle;
63
int psci_conduit;
64
} VirtMachineState;
65
66
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
67
index XXXXXXX..XXXXXXX 100644
68
--- a/hw/arm/virt.c
69
+++ b/hw/arm/virt.c
70
@@ -XXX,XX +XXX,XX @@
71
#include "hw/smbios/smbios.h"
72
#include "qapi/visitor.h"
73
#include "standard-headers/linux/input.h"
74
+#include "hw/arm/smmuv3.h"
75
76
#define DEFINE_VIRT_MACHINE_LATEST(major, minor, latest) \
77
static void virt_##major##_##minor##_class_init(ObjectClass *oc, \
78
@@ -XXX,XX +XXX,XX @@ static const MemMapEntry a15memmap[] = {
79
[VIRT_FW_CFG] = { 0x09020000, 0x00000018 },
80
[VIRT_GPIO] = { 0x09030000, 0x00001000 },
81
[VIRT_SECURE_UART] = { 0x09040000, 0x00001000 },
82
+ [VIRT_SMMU] = { 0x09050000, 0x00020000 },
83
[VIRT_MMIO] = { 0x0a000000, 0x00000200 },
84
/* ...repeating for a total of NUM_VIRTIO_TRANSPORTS, each of that size */
85
[VIRT_PLATFORM_BUS] = { 0x0c000000, 0x02000000 },
86
@@ -XXX,XX +XXX,XX @@ static const int a15irqmap[] = {
87
[VIRT_SECURE_UART] = 8,
88
[VIRT_MMIO] = 16, /* ...to 16 + NUM_VIRTIO_TRANSPORTS - 1 */
89
[VIRT_GIC_V2M] = 48, /* ...to 48 + NUM_GICV2M_SPIS - 1 */
90
+ [VIRT_SMMU] = 74, /* ...to 74 + NUM_SMMU_IRQS - 1 */
91
[VIRT_PLATFORM_BUS] = 112, /* ...to 112 + PLATFORM_BUS_NUM_IRQS -1 */
92
};
63
};
93
64
94
@@ -XXX,XX +XXX,XX @@ static void create_pcie_irq_map(const VirtMachineState *vms,
65
+/*
95
0x7 /* PCI irq */);
66
+ * CNTVCTSS_EL0 has the same trap conditions as CNTVCT_EL0, so it also
96
}
67
+ * is exposed to userspace by Linux.
97
68
+ */
98
-static void create_pcie(const VirtMachineState *vms, qemu_irq *pic)
69
+static const ARMCPRegInfo gen_timer_ecv_cp_reginfo[] = {
99
+static void create_smmu(const VirtMachineState *vms, qemu_irq *pic,
70
+ { .name = "CNTVCTSS_EL0", .state = ARM_CP_STATE_AA64,
100
+ PCIBus *bus)
71
+ .opc0 = 3, .opc1 = 3, .crn = 14, .crm = 0, .opc2 = 6,
101
+{
72
+ .access = PL0_R, .type = ARM_CP_NO_RAW | ARM_CP_IO,
102
+ char *node;
73
+ .readfn = gt_virt_cnt_read,
103
+ const char compat[] = "arm,smmu-v3";
74
+ },
104
+ int irq = vms->irqmap[VIRT_SMMU];
75
+};
105
+ int i;
106
+ hwaddr base = vms->memmap[VIRT_SMMU].base;
107
+ hwaddr size = vms->memmap[VIRT_SMMU].size;
108
+ const char irq_names[] = "eventq\0priq\0cmdq-sync\0gerror";
109
+ DeviceState *dev;
110
+
76
+
111
+ if (vms->iommu != VIRT_IOMMU_SMMUV3 || !vms->iommu_phandle) {
77
#endif
112
+ return;
78
79
static void par_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
80
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
81
if (arm_feature(env, ARM_FEATURE_GENERIC_TIMER)) {
82
define_arm_cp_regs(cpu, generic_timer_cp_reginfo);
83
}
84
+ if (cpu_isar_feature(aa64_ecv_traps, cpu)) {
85
+ define_arm_cp_regs(cpu, gen_timer_ecv_cp_reginfo);
113
+ }
86
+ }
114
+
87
if (arm_feature(env, ARM_FEATURE_VAPA)) {
115
+ dev = qdev_create(NULL, "arm-smmuv3");
88
ARMCPRegInfo vapa_cp_reginfo[] = {
116
+
89
{ .name = "PAR", .cp = 15, .crn = 7, .crm = 4, .opc1 = 0, .opc2 = 0,
117
+ object_property_set_link(OBJECT(dev), OBJECT(bus), "primary-bus",
118
+ &error_abort);
119
+ qdev_init_nofail(dev);
120
+ sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
121
+ for (i = 0; i < NUM_SMMU_IRQS; i++) {
122
+ sysbus_connect_irq(SYS_BUS_DEVICE(dev), i, pic[irq + i]);
123
+ }
124
+
125
+ node = g_strdup_printf("/smmuv3@%" PRIx64, base);
126
+ qemu_fdt_add_subnode(vms->fdt, node);
127
+ qemu_fdt_setprop(vms->fdt, node, "compatible", compat, sizeof(compat));
128
+ qemu_fdt_setprop_sized_cells(vms->fdt, node, "reg", 2, base, 2, size);
129
+
130
+ qemu_fdt_setprop_cells(vms->fdt, node, "interrupts",
131
+ GIC_FDT_IRQ_TYPE_SPI, irq , GIC_FDT_IRQ_FLAGS_EDGE_LO_HI,
132
+ GIC_FDT_IRQ_TYPE_SPI, irq + 1, GIC_FDT_IRQ_FLAGS_EDGE_LO_HI,
133
+ GIC_FDT_IRQ_TYPE_SPI, irq + 2, GIC_FDT_IRQ_FLAGS_EDGE_LO_HI,
134
+ GIC_FDT_IRQ_TYPE_SPI, irq + 3, GIC_FDT_IRQ_FLAGS_EDGE_LO_HI);
135
+
136
+ qemu_fdt_setprop(vms->fdt, node, "interrupt-names", irq_names,
137
+ sizeof(irq_names));
138
+
139
+ qemu_fdt_setprop_cell(vms->fdt, node, "clocks", vms->clock_phandle);
140
+ qemu_fdt_setprop_string(vms->fdt, node, "clock-names", "apb_pclk");
141
+ qemu_fdt_setprop(vms->fdt, node, "dma-coherent", NULL, 0);
142
+
143
+ qemu_fdt_setprop_cell(vms->fdt, node, "#iommu-cells", 1);
144
+
145
+ qemu_fdt_setprop_cell(vms->fdt, node, "phandle", vms->iommu_phandle);
146
+ g_free(node);
147
+}
148
+
149
+static void create_pcie(VirtMachineState *vms, qemu_irq *pic)
150
{
151
hwaddr base_mmio = vms->memmap[VIRT_PCIE_MMIO].base;
152
hwaddr size_mmio = vms->memmap[VIRT_PCIE_MMIO].size;
153
@@ -XXX,XX +XXX,XX @@ static void create_pcie(const VirtMachineState *vms, qemu_irq *pic)
154
qemu_fdt_setprop_cell(vms->fdt, nodename, "#interrupt-cells", 1);
155
create_pcie_irq_map(vms, vms->gic_phandle, irq, nodename);
156
157
+ if (vms->iommu) {
158
+ vms->iommu_phandle = qemu_fdt_alloc_phandle(vms->fdt);
159
+
160
+ create_smmu(vms, pic, pci->bus);
161
+
162
+ qemu_fdt_setprop_cells(vms->fdt, nodename, "iommu-map",
163
+ 0x0, vms->iommu_phandle, 0x0, 0x10000);
164
+ }
165
+
166
g_free(nodename);
167
}
168
169
--
90
--
170
2.17.0
91
2.34.1
171
172
diff view generated by jsdifflib
1
From: Eric Auger <eric.auger@redhat.com>
1
When ID_AA64MMFR0_EL1.ECV is 0b0010, a new register CNTPOFF_EL2 is
2
implemented. This is similar to the existing CNTVOFF_EL2, except
3
that it controls a hypervisor-adjustable offset made to the physical
4
counter and timer.
2
5
3
This patch implements the IOMMU Memory Region translate()
6
Implement the handling for this register, which includes control/trap
4
callback. Most of the code relates to the translation
7
bits in SCR_EL3 and CNTHCTL_EL2.
5
configuration decoding and check (STE, CD).
6
8
7
Signed-off-by: Eric Auger <eric.auger@redhat.com>
8
Signed-off-by: Prem Mallappa <prem.mallappa@broadcom.com>
9
Message-id: 1524665762-31355-10-git-send-email-eric.auger@redhat.com
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20240301183219.2424889-8-peter.maydell@linaro.org
12
---
12
---
13
hw/arm/smmuv3-internal.h | 160 +++++++++++++++++
13
target/arm/cpu-features.h | 5 +++
14
hw/arm/smmuv3.c | 358 +++++++++++++++++++++++++++++++++++++++
14
target/arm/cpu.h | 1 +
15
hw/arm/trace-events | 9 +
15
target/arm/helper.c | 68 +++++++++++++++++++++++++++++++++++++--
16
3 files changed, 527 insertions(+)
16
target/arm/trace-events | 1 +
17
4 files changed, 73 insertions(+), 2 deletions(-)
17
18
18
diff --git a/hw/arm/smmuv3-internal.h b/hw/arm/smmuv3-internal.h
19
diff --git a/target/arm/cpu-features.h b/target/arm/cpu-features.h
19
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
20
--- a/hw/arm/smmuv3-internal.h
21
--- a/target/arm/cpu-features.h
21
+++ b/hw/arm/smmuv3-internal.h
22
+++ b/target/arm/cpu-features.h
22
@@ -XXX,XX +XXX,XX @@ typedef struct SMMUEventInfo {
23
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa64_ecv_traps(const ARMISARegisters *id)
23
24
return FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, ECV) > 0;
24
void smmuv3_record_event(SMMUv3State *s, SMMUEventInfo *event);
25
}
25
26
26
+/* Configuration Data */
27
+static inline bool isar_feature_aa64_ecv(const ARMISARegisters *id)
27
+
28
+/* STE Level 1 Descriptor */
29
+typedef struct STEDesc {
30
+ uint32_t word[2];
31
+} STEDesc;
32
+
33
+/* CD Level 1 Descriptor */
34
+typedef struct CDDesc {
35
+ uint32_t word[2];
36
+} CDDesc;
37
+
38
+/* Stream Table Entry(STE) */
39
+typedef struct STE {
40
+ uint32_t word[16];
41
+} STE;
42
+
43
+/* Context Descriptor(CD) */
44
+typedef struct CD {
45
+ uint32_t word[16];
46
+} CD;
47
+
48
+/* STE fields */
49
+
50
+#define STE_VALID(x) extract32((x)->word[0], 0, 1)
51
+
52
+#define STE_CONFIG(x) extract32((x)->word[0], 1, 3)
53
+#define STE_CFG_S1_ENABLED(config) (config & 0x1)
54
+#define STE_CFG_S2_ENABLED(config) (config & 0x2)
55
+#define STE_CFG_ABORT(config) (!(config & 0x4))
56
+#define STE_CFG_BYPASS(config) (config == 0x4)
57
+
58
+#define STE_S1FMT(x) extract32((x)->word[0], 4 , 2)
59
+#define STE_S1CDMAX(x) extract32((x)->word[1], 27, 5)
60
+#define STE_S1STALLD(x) extract32((x)->word[2], 27, 1)
61
+#define STE_EATS(x) extract32((x)->word[2], 28, 2)
62
+#define STE_STRW(x) extract32((x)->word[2], 30, 2)
63
+#define STE_S2VMID(x) extract32((x)->word[4], 0 , 16)
64
+#define STE_S2T0SZ(x) extract32((x)->word[5], 0 , 6)
65
+#define STE_S2SL0(x) extract32((x)->word[5], 6 , 2)
66
+#define STE_S2TG(x) extract32((x)->word[5], 14, 2)
67
+#define STE_S2PS(x) extract32((x)->word[5], 16, 3)
68
+#define STE_S2AA64(x) extract32((x)->word[5], 19, 1)
69
+#define STE_S2HD(x) extract32((x)->word[5], 24, 1)
70
+#define STE_S2HA(x) extract32((x)->word[5], 25, 1)
71
+#define STE_S2S(x) extract32((x)->word[5], 26, 1)
72
+#define STE_CTXPTR(x) \
73
+ ({ \
74
+ unsigned long addr; \
75
+ addr = (uint64_t)extract32((x)->word[1], 0, 16) << 32; \
76
+ addr |= (uint64_t)((x)->word[0] & 0xffffffc0); \
77
+ addr; \
78
+ })
79
+
80
+#define STE_S2TTB(x) \
81
+ ({ \
82
+ unsigned long addr; \
83
+ addr = (uint64_t)extract32((x)->word[7], 0, 16) << 32; \
84
+ addr |= (uint64_t)((x)->word[6] & 0xfffffff0); \
85
+ addr; \
86
+ })
87
+
88
+static inline int oas2bits(int oas_field)
89
+{
28
+{
90
+ switch (oas_field) {
29
+ return FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, ECV) > 1;
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
+}
30
+}
106
+
31
+
107
+static inline int pa_range(STE *ste)
32
static inline bool isar_feature_aa64_vh(const ARMISARegisters *id)
33
{
34
return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, VH) != 0;
35
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
36
index XXXXXXX..XXXXXXX 100644
37
--- a/target/arm/cpu.h
38
+++ b/target/arm/cpu.h
39
@@ -XXX,XX +XXX,XX @@ typedef struct CPUArchState {
40
uint64_t c14_cntkctl; /* Timer Control register */
41
uint64_t cnthctl_el2; /* Counter/Timer Hyp Control register */
42
uint64_t cntvoff_el2; /* Counter Virtual Offset register */
43
+ uint64_t cntpoff_el2; /* Counter Physical Offset register */
44
ARMGenericTimer c14_timer[NUM_GTIMERS];
45
uint32_t c15_cpar; /* XScale Coprocessor Access Register */
46
uint32_t c15_ticonfig; /* TI925T configuration byte. */
47
diff --git a/target/arm/helper.c b/target/arm/helper.c
48
index XXXXXXX..XXXXXXX 100644
49
--- a/target/arm/helper.c
50
+++ b/target/arm/helper.c
51
@@ -XXX,XX +XXX,XX @@ static void scr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
52
if (cpu_isar_feature(aa64_rme, cpu)) {
53
valid_mask |= SCR_NSE | SCR_GPF;
54
}
55
+ if (cpu_isar_feature(aa64_ecv, cpu)) {
56
+ valid_mask |= SCR_ECVEN;
57
+ }
58
} else {
59
valid_mask &= ~(SCR_RW | SCR_ST);
60
if (cpu_isar_feature(aa32_ras, cpu)) {
61
@@ -XXX,XX +XXX,XX @@ void gt_rme_post_el_change(ARMCPU *cpu, void *ignored)
62
gt_update_irq(cpu, GTIMER_PHYS);
63
}
64
65
+static uint64_t gt_phys_raw_cnt_offset(CPUARMState *env)
108
+{
66
+{
109
+ int oas_field = MIN(STE_S2PS(ste), SMMU_IDR5_OAS);
67
+ if ((env->cp15.scr_el3 & SCR_ECVEN) &&
110
+
68
+ FIELD_EX64(env->cp15.cnthctl_el2, CNTHCTL, ECV) &&
111
+ if (!STE_S2AA64(ste)) {
69
+ arm_is_el2_enabled(env) &&
112
+ return 40;
70
+ (arm_hcr_el2_eff(env) & (HCR_E2H | HCR_TGE)) != (HCR_E2H | HCR_TGE)) {
113
+ }
71
+ return env->cp15.cntpoff_el2;
114
+
115
+ return oas2bits(oas_field);
116
+}
117
+
118
+#define MAX_PA(ste) ((1 << pa_range(ste)) - 1)
119
+
120
+/* CD fields */
121
+
122
+#define CD_VALID(x) extract32((x)->word[0], 30, 1)
123
+#define CD_ASID(x) extract32((x)->word[1], 16, 16)
124
+#define CD_TTB(x, sel) \
125
+ ({ \
126
+ uint64_t hi, lo; \
127
+ hi = extract32((x)->word[(sel) * 2 + 3], 0, 19); \
128
+ hi <<= 32; \
129
+ lo = (x)->word[(sel) * 2 + 2] & ~0xfULL; \
130
+ hi | lo; \
131
+ })
132
+
133
+#define CD_TSZ(x, sel) extract32((x)->word[0], (16 * (sel)) + 0, 6)
134
+#define CD_TG(x, sel) extract32((x)->word[0], (16 * (sel)) + 6, 2)
135
+#define CD_EPD(x, sel) extract32((x)->word[0], (16 * (sel)) + 14, 1)
136
+#define CD_ENDI(x) extract32((x)->word[0], 15, 1)
137
+#define CD_IPS(x) extract32((x)->word[1], 0 , 3)
138
+#define CD_TBI(x) extract32((x)->word[1], 6 , 2)
139
+#define CD_HD(x) extract32((x)->word[1], 10 , 1)
140
+#define CD_HA(x) extract32((x)->word[1], 11 , 1)
141
+#define CD_S(x) extract32((x)->word[1], 12, 1)
142
+#define CD_R(x) extract32((x)->word[1], 13, 1)
143
+#define CD_A(x) extract32((x)->word[1], 14, 1)
144
+#define CD_AARCH64(x) extract32((x)->word[1], 9 , 1)
145
+
146
+#define CDM_VALID(x) ((x)->word[0] & 0x1)
147
+
148
+static inline int is_cd_valid(SMMUv3State *s, STE *ste, CD *cd)
149
+{
150
+ return CD_VALID(cd);
151
+}
152
+
153
+/**
154
+ * tg2granule - Decodes the CD translation granule size field according
155
+ * to the ttbr in use
156
+ * @bits: TG0/1 fields
157
+ * @ttbr: ttbr index in use
158
+ */
159
+static inline int tg2granule(int bits, int ttbr)
160
+{
161
+ switch (bits) {
162
+ case 0:
163
+ return ttbr ? 0 : 12;
164
+ case 1:
165
+ return ttbr ? 14 : 16;
166
+ case 2:
167
+ return ttbr ? 12 : 14;
168
+ case 3:
169
+ return ttbr ? 16 : 0;
170
+ default:
171
+ return 0;
172
+ }
173
+}
174
+
175
+static inline uint64_t l1std_l2ptr(STEDesc *desc)
176
+{
177
+ uint64_t hi, lo;
178
+
179
+ hi = desc->word[1];
180
+ lo = desc->word[0] & ~0x1fULL;
181
+ return hi << 32 | lo;
182
+}
183
+
184
+#define L1STD_SPAN(stm) (extract32((stm)->word[0], 0, 4))
185
+
186
#endif
187
diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c
188
index XXXXXXX..XXXXXXX 100644
189
--- a/hw/arm/smmuv3.c
190
+++ b/hw/arm/smmuv3.c
191
@@ -XXX,XX +XXX,XX @@ static void smmuv3_init_regs(SMMUv3State *s)
192
s->sid_split = 0;
193
}
194
195
+static int smmu_get_ste(SMMUv3State *s, dma_addr_t addr, STE *buf,
196
+ SMMUEventInfo *event)
197
+{
198
+ int ret;
199
+
200
+ trace_smmuv3_get_ste(addr);
201
+ /* TODO: guarantee 64-bit single-copy atomicity */
202
+ ret = dma_memory_read(&address_space_memory, addr,
203
+ (void *)buf, sizeof(*buf));
204
+ if (ret != MEMTX_OK) {
205
+ qemu_log_mask(LOG_GUEST_ERROR,
206
+ "Cannot fetch pte at address=0x%"PRIx64"\n", addr);
207
+ event->type = SMMU_EVT_F_STE_FETCH;
208
+ event->u.f_ste_fetch.addr = addr;
209
+ return -EINVAL;
210
+ }
211
+ return 0;
212
+
213
+}
214
+
215
+/* @ssid > 0 not supported yet */
216
+static int smmu_get_cd(SMMUv3State *s, STE *ste, uint32_t ssid,
217
+ CD *buf, SMMUEventInfo *event)
218
+{
219
+ dma_addr_t addr = STE_CTXPTR(ste);
220
+ int ret;
221
+
222
+ trace_smmuv3_get_cd(addr);
223
+ /* TODO: guarantee 64-bit single-copy atomicity */
224
+ ret = dma_memory_read(&address_space_memory, addr,
225
+ (void *)buf, sizeof(*buf));
226
+ if (ret != MEMTX_OK) {
227
+ qemu_log_mask(LOG_GUEST_ERROR,
228
+ "Cannot fetch pte at address=0x%"PRIx64"\n", addr);
229
+ event->type = SMMU_EVT_F_CD_FETCH;
230
+ event->u.f_ste_fetch.addr = addr;
231
+ return -EINVAL;
232
+ }
72
+ }
233
+ return 0;
73
+ return 0;
234
+}
74
+}
235
+
75
+
236
+/* Returns <0 if the caller has no need to continue the translation */
76
+static uint64_t gt_phys_cnt_offset(CPUARMState *env)
237
+static int decode_ste(SMMUv3State *s, SMMUTransCfg *cfg,
238
+ STE *ste, SMMUEventInfo *event)
239
+{
77
+{
240
+ uint32_t config;
78
+ if (arm_current_el(env) >= 2) {
241
+ int ret = -EINVAL;
79
+ return 0;
242
+
243
+ if (!STE_VALID(ste)) {
244
+ goto bad_ste;
245
+ }
80
+ }
246
+
81
+ return gt_phys_raw_cnt_offset(env);
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
+}
82
+}
281
+
83
+
282
+/**
84
static void gt_recalc_timer(ARMCPU *cpu, int timeridx)
283
+ * smmu_find_ste - Return the stream table entry associated
85
{
284
+ * to the sid
86
ARMGenericTimer *gt = &cpu->env.cp15.c14_timer[timeridx];
285
+ *
87
@@ -XXX,XX +XXX,XX @@ static void gt_recalc_timer(ARMCPU *cpu, int timeridx)
286
+ * @s: smmuv3 handle
88
* reset timer to when ISTATUS next has to change
287
+ * @sid: stream ID
89
*/
288
+ * @ste: returned stream table entry
90
uint64_t offset = timeridx == GTIMER_VIRT ?
289
+ * @event: handle to an event info
91
- cpu->env.cp15.cntvoff_el2 : 0;
290
+ *
92
+ cpu->env.cp15.cntvoff_el2 : gt_phys_raw_cnt_offset(&cpu->env);
291
+ * Supports linear and 2-level stream table
93
uint64_t count = gt_get_countervalue(&cpu->env);
292
+ * Return 0 on success, -EINVAL otherwise
94
/* Note that this must be unsigned 64 bit arithmetic: */
293
+ */
95
int istatus = count - offset >= gt->cval;
294
+static int smmu_find_ste(SMMUv3State *s, uint32_t sid, STE *ste,
96
@@ -XXX,XX +XXX,XX @@ static void gt_timer_reset(CPUARMState *env, const ARMCPRegInfo *ri,
295
+ SMMUEventInfo *event)
97
98
static uint64_t gt_cnt_read(CPUARMState *env, const ARMCPRegInfo *ri)
99
{
100
- return gt_get_countervalue(env);
101
+ return gt_get_countervalue(env) - gt_phys_cnt_offset(env);
102
}
103
104
static uint64_t gt_virt_cnt_offset(CPUARMState *env)
105
@@ -XXX,XX +XXX,XX @@ static uint64_t gt_tval_read(CPUARMState *env, const ARMCPRegInfo *ri,
106
case GTIMER_HYPVIRT:
107
offset = gt_virt_cnt_offset(env);
108
break;
109
+ case GTIMER_PHYS:
110
+ offset = gt_phys_cnt_offset(env);
111
+ break;
112
}
113
114
return (uint32_t)(env->cp15.c14_timer[timeridx].cval -
115
@@ -XXX,XX +XXX,XX @@ static void gt_tval_write(CPUARMState *env, const ARMCPRegInfo *ri,
116
case GTIMER_HYPVIRT:
117
offset = gt_virt_cnt_offset(env);
118
break;
119
+ case GTIMER_PHYS:
120
+ offset = gt_phys_cnt_offset(env);
121
+ break;
122
}
123
124
trace_arm_gt_tval_write(timeridx, value);
125
@@ -XXX,XX +XXX,XX @@ static void gt_cnthctl_write(CPUARMState *env, const ARMCPRegInfo *ri,
126
R_CNTHCTL_EL1NVVCT_MASK |
127
R_CNTHCTL_EVNTIS_MASK;
128
}
129
+ if (cpu_isar_feature(aa64_ecv, cpu)) {
130
+ valid_mask |= R_CNTHCTL_ECV_MASK;
131
+ }
132
133
/* Clear RES0 bits */
134
value &= valid_mask;
135
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo gen_timer_ecv_cp_reginfo[] = {
136
},
137
};
138
139
+static CPAccessResult gt_cntpoff_access(CPUARMState *env,
140
+ const ARMCPRegInfo *ri,
141
+ bool isread)
296
+{
142
+{
297
+ dma_addr_t addr;
143
+ if (arm_current_el(env) == 2 && !(env->cp15.scr_el3 & SCR_ECVEN)) {
298
+ int ret;
144
+ return CP_ACCESS_TRAP_EL3;
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
+ }
145
+ }
306
+ if (s->features & SMMU_FEATURE_2LVL_STE) {
146
+ return CP_ACCESS_OK;
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
+}
147
+}
357
+
148
+
358
+static int decode_cd(SMMUTransCfg *cfg, CD *cd, SMMUEventInfo *event)
149
+static void gt_cntpoff_write(CPUARMState *env, const ARMCPRegInfo *ri,
150
+ uint64_t value)
359
+{
151
+{
360
+ int ret = -EINVAL;
152
+ ARMCPU *cpu = env_archcpu(env);
361
+ int i;
362
+
153
+
363
+ if (!CD_VALID(cd) || !CD_AARCH64(cd)) {
154
+ trace_arm_gt_cntpoff_write(value);
364
+ goto bad_cd;
155
+ raw_write(env, ri, value);
365
+ }
156
+ gt_recalc_timer(cpu, GTIMER_PHYS);
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
+}
157
+}
424
+
158
+
425
+/**
159
+static const ARMCPRegInfo gen_timer_cntpoff_reginfo = {
426
+ * smmuv3_decode_config - Prepare the translation configuration
160
+ .name = "CNTPOFF_EL2", .state = ARM_CP_STATE_AA64,
427
+ * for the @mr iommu region
161
+ .opc0 = 3, .opc1 = 4, .crn = 14, .crm = 0, .opc2 = 6,
428
+ * @mr: iommu memory region the translation config must be prepared for
162
+ .access = PL2_RW, .type = ARM_CP_IO, .resetvalue = 0,
429
+ * @cfg: output translation configuration which is populated through
163
+ .accessfn = gt_cntpoff_access, .writefn = gt_cntpoff_write,
430
+ * the different configuration decoding steps
164
+ .nv2_redirect_offset = 0x1a8,
431
+ * @event: must be zero'ed by the caller
165
+ .fieldoffset = offsetof(CPUARMState, cp15.cntpoff_el2),
432
+ *
166
+};
433
+ * return < 0 if the translation needs to be aborted (@event is filled
167
#else
434
+ * accordingly). Return 0 otherwise.
168
435
+ */
169
/*
436
+static int smmuv3_decode_config(IOMMUMemoryRegion *mr, SMMUTransCfg *cfg,
170
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
437
+ SMMUEventInfo *event)
171
if (cpu_isar_feature(aa64_ecv_traps, cpu)) {
438
+{
172
define_arm_cp_regs(cpu, gen_timer_ecv_cp_reginfo);
439
+ SMMUDevice *sdev = container_of(mr, SMMUDevice, iommu);
173
}
440
+ uint32_t sid = smmu_get_sid(sdev);
174
+#ifndef CONFIG_USER_ONLY
441
+ SMMUv3State *s = sdev->smmu;
175
+ if (cpu_isar_feature(aa64_ecv, cpu)) {
442
+ int ret = -EINVAL;
176
+ define_one_arm_cp_reg(cpu, &gen_timer_cntpoff_reginfo);
443
+ STE ste;
444
+ CD cd;
445
+
446
+ if (smmu_find_ste(s, sid, &ste, event)) {
447
+ return ret;
448
+ }
177
+ }
449
+
178
+#endif
450
+ if (decode_ste(s, cfg, &ste, event)) {
179
if (arm_feature(env, ARM_FEATURE_VAPA)) {
451
+ return ret;
180
ARMCPRegInfo vapa_cp_reginfo[] = {
452
+ }
181
{ .name = "PAR", .cp = 15, .crn = 7, .crm = 4, .opc1 = 0, .opc2 = 0,
453
+
182
diff --git a/target/arm/trace-events b/target/arm/trace-events
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
183
index XXXXXXX..XXXXXXX 100644
565
--- a/hw/arm/trace-events
184
--- a/target/arm/trace-events
566
+++ b/hw/arm/trace-events
185
+++ b/target/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
186
@@ -XXX,XX +XXX,XX @@ arm_gt_tval_write(int timer, uint64_t value) "gt_tval_write: timer %d value 0x%"
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"
187
arm_gt_ctl_write(int timer, uint64_t value) "gt_ctl_write: timer %d value 0x%" PRIx64
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"
188
arm_gt_imask_toggle(int timer) "gt_ctl_write: timer %d IMASK toggle"
570
smmuv3_record_event(const char *type, uint32_t sid) "%s sid=%d"
189
arm_gt_cntvoff_write(uint64_t value) "gt_cntvoff_write: value 0x%" PRIx64
571
+smmuv3_find_ste(uint16_t sid, uint32_t features, uint16_t sid_split) "SID:0x%x features:0x%x, sid_split:0x%x"
190
+arm_gt_cntpoff_write(uint64_t value) "gt_cntpoff_write: value 0x%" PRIx64
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"
191
arm_gt_update_irq(int timer, int irqstate) "gt_update_irq: timer %d irqstate %d"
573
+smmuv3_get_ste(uint64_t addr) "STE addr: 0x%"PRIx64
192
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"
193
# kvm.c
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
--
194
--
581
2.17.0
195
2.34.1
582
583
diff view generated by jsdifflib
1
Convert the smc91c111 device away from using the old_mmio field of
1
Enable all FEAT_ECV features on the 'max' CPU.
2
MemoryRegionOps. This device is used by several Arm board models.
3
2
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20180427173611.10281-3-peter.maydell@linaro.org
6
Message-id: 20240301183219.2424889-9-peter.maydell@linaro.org
7
---
7
---
8
hw/net/smc91c111.c | 54 +++++++++++++++++++++-------------------------
8
docs/system/arm/emulation.rst | 1 +
9
1 file changed, 25 insertions(+), 29 deletions(-)
9
target/arm/tcg/cpu64.c | 1 +
10
2 files changed, 2 insertions(+)
10
11
11
diff --git a/hw/net/smc91c111.c b/hw/net/smc91c111.c
12
diff --git a/docs/system/arm/emulation.rst b/docs/system/arm/emulation.rst
12
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
13
--- a/hw/net/smc91c111.c
14
--- a/docs/system/arm/emulation.rst
14
+++ b/hw/net/smc91c111.c
15
+++ b/docs/system/arm/emulation.rst
15
@@ -XXX,XX +XXX,XX @@ static uint32_t smc91c111_readb(void *opaque, hwaddr offset)
16
@@ -XXX,XX +XXX,XX @@ the following architecture extensions:
16
return 0;
17
- FEAT_DotProd (Advanced SIMD dot product instructions)
17
}
18
- FEAT_DoubleFault (Double Fault Extension)
18
19
- FEAT_E0PD (Preventing EL0 access to halves of address maps)
19
-static void smc91c111_writew(void *opaque, hwaddr offset,
20
+- FEAT_ECV (Enhanced Counter Virtualization)
20
- uint32_t value)
21
- FEAT_EPAC (Enhanced pointer authentication)
21
+static uint64_t smc91c111_readfn(void *opaque, hwaddr addr, unsigned size)
22
- FEAT_ETS (Enhanced Translation Synchronization)
22
{
23
- FEAT_EVT (Enhanced Virtualization Traps)
23
- smc91c111_writeb(opaque, offset, value & 0xff);
24
diff --git a/target/arm/tcg/cpu64.c b/target/arm/tcg/cpu64.c
24
- smc91c111_writeb(opaque, offset + 1, value >> 8);
25
index XXXXXXX..XXXXXXX 100644
25
+ int i;
26
--- a/target/arm/tcg/cpu64.c
26
+ uint32_t val = 0;
27
+++ b/target/arm/tcg/cpu64.c
27
+
28
@@ -XXX,XX +XXX,XX @@ void aarch64_max_tcg_initfn(Object *obj)
28
+ for (i = 0; i < size; i++) {
29
t = FIELD_DP64(t, ID_AA64MMFR0, TGRAN64_2, 2); /* 64k stage2 supported */
29
+ val |= smc91c111_readb(opaque, addr + i) << (i * 8);
30
t = FIELD_DP64(t, ID_AA64MMFR0, TGRAN4_2, 2); /* 4k stage2 supported */
30
+ }
31
t = FIELD_DP64(t, ID_AA64MMFR0, FGT, 1); /* FEAT_FGT */
31
+ return val;
32
+ t = FIELD_DP64(t, ID_AA64MMFR0, ECV, 2); /* FEAT_ECV */
32
}
33
cpu->isar.id_aa64mmfr0 = t;
33
34
34
-static void smc91c111_writel(void *opaque, hwaddr offset,
35
t = cpu->isar.id_aa64mmfr1;
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
--
36
--
90
2.17.0
37
2.34.1
91
38
92
39
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
The (size > 3 && !is_q) condition is identical to the preceeding test
4
of bit 3 in immh; eliminate it. For the benefit of Coverity, assert
5
that size is within the bounds we expect.
6
7
Fixes: Coverity CID1385846
8
Fixes: Coverity CID1385849
9
Fixes: Coverity CID1385852
10
Fixes: Coverity CID1385857
11
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
12
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
13
Message-id: 20180501180455.11214-2-richard.henderson@linaro.org
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
---
16
target/arm/translate-a64.c | 6 +-----
17
1 file changed, 1 insertion(+), 5 deletions(-)
18
19
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
20
index XXXXXXX..XXXXXXX 100644
21
--- a/target/arm/translate-a64.c
22
+++ b/target/arm/translate-a64.c
23
@@ -XXX,XX +XXX,XX @@ static void handle_vec_simd_shri(DisasContext *s, bool is_q, bool is_u,
24
unallocated_encoding(s);
25
return;
26
}
27
-
28
- if (size > 3 && !is_q) {
29
- unallocated_encoding(s);
30
- return;
31
- }
32
+ tcg_debug_assert(size <= 3);
33
34
if (!fp_access_check(s)) {
35
return;
36
--
37
2.17.0
38
39
diff view generated by jsdifflib
1
From: Prem Mallappa <prem.mallappa@broadcom.com>
1
From: Inès Varhol <ines.varhol@telecom-paris.fr>
2
2
3
This patch implements a skeleton for the smmuv3 device.
3
Features supported :
4
Datatypes and register definitions are introduced. The MMIO
4
- the 8 STM32L4x5 GPIOs are initialized with their reset values
5
region, the interrupts and the queue are initialized.
5
(except IDR, see below)
6
- input mode : setting a pin in input mode "externally" (using input
7
irqs) results in an out irq (transmitted to SYSCFG)
8
- output mode : setting a bit in ODR sets the corresponding out irq
9
(if this line is configured in output mode)
10
- pull-up, pull-down
11
- push-pull, open-drain
6
12
7
Only the MMIO read operation is implemented here.
13
Difference with the real GPIOs :
14
- Alternate Function and Analog mode aren't implemented :
15
pins in AF/Analog behave like pins in input mode
16
- floating pins stay at their last value
17
- register IDR reset values differ from the real one :
18
values are coherent with the other registers reset values
19
and the fact that AF/Analog modes aren't implemented
20
- setting I/O output speed isn't supported
21
- locking port bits isn't supported
22
- ADC function isn't supported
23
- GPIOH has 16 pins instead of 2 pins
24
- writing to registers LCKR, AFRL, AFRH and ASCR is ineffective
8
25
9
Signed-off-by: Prem Mallappa <prem.mallappa@broadcom.com>
26
Signed-off-by: Arnaud Minier <arnaud.minier@telecom-paris.fr>
10
Signed-off-by: Eric Auger <eric.auger@redhat.com>
27
Signed-off-by: Inès Varhol <ines.varhol@telecom-paris.fr>
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
28
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
12
Message-id: 1524665762-31355-5-git-send-email-eric.auger@redhat.com
29
Acked-by: Alistair Francis <alistair.francis@wdc.com>
30
Message-id: 20240305210444.310665-2-ines.varhol@telecom-paris.fr
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
31
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
32
---
15
hw/arm/Makefile.objs | 2 +-
33
MAINTAINERS | 1 +
16
hw/arm/smmuv3-internal.h | 142 +++++++++++++++
34
docs/system/arm/b-l475e-iot01a.rst | 2 +-
17
include/hw/arm/smmuv3.h | 87 ++++++++++
35
include/hw/gpio/stm32l4x5_gpio.h | 70 +++++
18
hw/arm/smmuv3.c | 366 +++++++++++++++++++++++++++++++++++++++
36
hw/gpio/stm32l4x5_gpio.c | 477 +++++++++++++++++++++++++++++
19
hw/arm/trace-events | 3 +
37
hw/gpio/Kconfig | 3 +
20
5 files changed, 599 insertions(+), 1 deletion(-)
38
hw/gpio/meson.build | 1 +
21
create mode 100644 hw/arm/smmuv3-internal.h
39
hw/gpio/trace-events | 6 +
22
create mode 100644 include/hw/arm/smmuv3.h
40
7 files changed, 559 insertions(+), 1 deletion(-)
23
create mode 100644 hw/arm/smmuv3.c
41
create mode 100644 include/hw/gpio/stm32l4x5_gpio.h
42
create mode 100644 hw/gpio/stm32l4x5_gpio.c
24
43
25
diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
44
diff --git a/MAINTAINERS b/MAINTAINERS
26
index XXXXXXX..XXXXXXX 100644
45
index XXXXXXX..XXXXXXX 100644
27
--- a/hw/arm/Makefile.objs
46
--- a/MAINTAINERS
28
+++ b/hw/arm/Makefile.objs
47
+++ b/MAINTAINERS
29
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_MPS2) += mps2-tz.o
48
@@ -XXX,XX +XXX,XX @@ F: hw/arm/stm32l4x5_soc.c
30
obj-$(CONFIG_MSF2) += msf2-soc.o msf2-som.o
49
F: hw/misc/stm32l4x5_exti.c
31
obj-$(CONFIG_IOTKIT) += iotkit.o
50
F: hw/misc/stm32l4x5_syscfg.c
32
obj-$(CONFIG_FSL_IMX7) += fsl-imx7.o mcimx7d-sabre.o
51
F: hw/misc/stm32l4x5_rcc.c
33
-obj-$(CONFIG_ARM_SMMUV3) += smmu-common.o
52
+F: hw/gpio/stm32l4x5_gpio.c
34
+obj-$(CONFIG_ARM_SMMUV3) += smmu-common.o smmuv3.o
53
F: include/hw/*/stm32l4x5_*.h
35
diff --git a/hw/arm/smmuv3-internal.h b/hw/arm/smmuv3-internal.h
54
55
B-L475E-IOT01A IoT Node
56
diff --git a/docs/system/arm/b-l475e-iot01a.rst b/docs/system/arm/b-l475e-iot01a.rst
57
index XXXXXXX..XXXXXXX 100644
58
--- a/docs/system/arm/b-l475e-iot01a.rst
59
+++ b/docs/system/arm/b-l475e-iot01a.rst
60
@@ -XXX,XX +XXX,XX @@ Currently B-L475E-IOT01A machine's only supports the following devices:
61
- STM32L4x5 EXTI (Extended interrupts and events controller)
62
- STM32L4x5 SYSCFG (System configuration controller)
63
- STM32L4x5 RCC (Reset and clock control)
64
+- STM32L4x5 GPIOs (General-purpose I/Os)
65
66
Missing devices
67
"""""""""""""""
68
@@ -XXX,XX +XXX,XX @@ Missing devices
69
The B-L475E-IOT01A does *not* support the following devices:
70
71
- Serial ports (UART)
72
-- General-purpose I/Os (GPIO)
73
- Analog to Digital Converter (ADC)
74
- SPI controller
75
- Timer controller (TIMER)
76
diff --git a/include/hw/gpio/stm32l4x5_gpio.h b/include/hw/gpio/stm32l4x5_gpio.h
36
new file mode 100644
77
new file mode 100644
37
index XXXXXXX..XXXXXXX
78
index XXXXXXX..XXXXXXX
38
--- /dev/null
79
--- /dev/null
39
+++ b/hw/arm/smmuv3-internal.h
80
+++ b/include/hw/gpio/stm32l4x5_gpio.h
40
@@ -XXX,XX +XXX,XX @@
81
@@ -XXX,XX +XXX,XX @@
41
+/*
82
+/*
42
+ * ARM SMMUv3 support - Internal API
83
+ * STM32L4x5 GPIO (General Purpose Input/Ouput)
43
+ *
84
+ *
44
+ * Copyright (C) 2014-2016 Broadcom Corporation
85
+ * Copyright (c) 2024 Arnaud Minier <arnaud.minier@telecom-paris.fr>
45
+ * Copyright (c) 2017 Red Hat, Inc.
86
+ * Copyright (c) 2024 Inès Varhol <ines.varhol@telecom-paris.fr>
46
+ * Written by Prem Mallappa, Eric Auger
47
+ *
87
+ *
48
+ * This program is free software; you can redistribute it and/or modify
88
+ * SPDX-License-Identifier: GPL-2.0-or-later
49
+ * it under the terms of the GNU General Public License version 2 as
50
+ * published by the Free Software Foundation.
51
+ *
89
+ *
52
+ * This program is distributed in the hope that it will be useful,
90
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
53
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
91
+ * See the COPYING file in the top-level directory.
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
+ */
92
+ */
60
+
93
+
61
+#ifndef HW_ARM_SMMU_V3_INTERNAL_H
94
+/*
62
+#define HW_ARM_SMMU_V3_INTERNAL_H
95
+ * The reference used is the STMicroElectronics RM0351 Reference manual
63
+
96
+ * for STM32L4x5 and STM32L4x6 advanced Arm ® -based 32-bit MCUs.
64
+#include "hw/arm/smmu-common.h"
97
+ * https://www.st.com/en/microcontrollers-microprocessors/stm32l4x5/documentation.html
65
+
98
+ */
66
+/* MMIO Registers */
99
+
67
+
100
+#ifndef HW_STM32L4X5_GPIO_H
68
+REG32(IDR0, 0x0)
101
+#define HW_STM32L4X5_GPIO_H
69
+ FIELD(IDR0, S1P, 1 , 1)
102
+
70
+ FIELD(IDR0, TTF, 2 , 2)
103
+#include "hw/sysbus.h"
71
+ FIELD(IDR0, COHACC, 4 , 1)
104
+#include "qom/object.h"
72
+ FIELD(IDR0, ASID16, 12, 1)
105
+
73
+ FIELD(IDR0, TTENDIAN, 21, 2)
106
+#define TYPE_STM32L4X5_GPIO "stm32l4x5-gpio"
74
+ FIELD(IDR0, STALL_MODEL, 24, 2)
107
+OBJECT_DECLARE_SIMPLE_TYPE(Stm32l4x5GpioState, STM32L4X5_GPIO)
75
+ FIELD(IDR0, TERM_MODEL, 26, 1)
108
+
76
+ FIELD(IDR0, STLEVEL, 27, 2)
109
+#define GPIO_NUM_PINS 16
77
+
110
+
78
+REG32(IDR1, 0x4)
111
+struct Stm32l4x5GpioState {
79
+ FIELD(IDR1, SIDSIZE, 0 , 6)
112
+ SysBusDevice parent_obj;
80
+ FIELD(IDR1, EVENTQS, 16, 5)
113
+
81
+ FIELD(IDR1, CMDQS, 21, 5)
114
+ MemoryRegion mmio;
82
+
115
+
83
+#define SMMU_IDR1_SIDSIZE 16
116
+ /* GPIO registers */
84
+#define SMMU_CMDQS 19
117
+ uint32_t moder;
85
+#define SMMU_EVENTQS 19
118
+ uint32_t otyper;
86
+
119
+ uint32_t ospeedr;
87
+REG32(IDR2, 0x8)
120
+ uint32_t pupdr;
88
+REG32(IDR3, 0xc)
121
+ uint32_t idr;
89
+REG32(IDR4, 0x10)
122
+ uint32_t odr;
90
+REG32(IDR5, 0x14)
123
+ uint32_t lckr;
91
+ FIELD(IDR5, OAS, 0, 3);
124
+ uint32_t afrl;
92
+ FIELD(IDR5, GRAN4K, 4, 1);
125
+ uint32_t afrh;
93
+ FIELD(IDR5, GRAN16K, 5, 1);
126
+ uint32_t ascr;
94
+ FIELD(IDR5, GRAN64K, 6, 1);
127
+
95
+
128
+ /* GPIO registers reset values */
96
+#define SMMU_IDR5_OAS 4
129
+ uint32_t moder_reset;
97
+
130
+ uint32_t ospeedr_reset;
98
+REG32(IIDR, 0x1c)
131
+ uint32_t pupdr_reset;
99
+REG32(CR0, 0x20)
132
+
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
+ /*
133
+ /*
172
+ * Return the value of the Primecell/Corelink ID registers at the
134
+ * External driving of pins.
173
+ * specified offset from the first ID register.
135
+ * The pins can be set externally through the device
174
+ * These value indicate an ARM implementation of MMU600 p1
136
+ * anonymous input GPIOs lines under certain conditions.
137
+ * The pin must not be in push-pull output mode,
138
+ * and can't be set high in open-drain mode.
139
+ * Pins driven externally and configured to
140
+ * output mode will in general be "disconnected"
141
+ * (see `get_gpio_pinmask_to_disconnect()`)
175
+ */
142
+ */
176
+ static const uint8_t smmuv3_ids[] = {
143
+ uint16_t disconnected_pins;
177
+ 0x04, 0, 0, 0, 0x84, 0xB4, 0xF0, 0x10, 0x0D, 0xF0, 0x05, 0xB1
144
+ uint16_t pins_connected_high;
178
+ };
145
+
179
+ return smmuv3_ids[regoffset / 4];
146
+ char *name;
180
+}
147
+ Clock *clk;
148
+ qemu_irq pin[GPIO_NUM_PINS];
149
+};
181
+
150
+
182
+#endif
151
+#endif
183
diff --git a/include/hw/arm/smmuv3.h b/include/hw/arm/smmuv3.h
152
diff --git a/hw/gpio/stm32l4x5_gpio.c b/hw/gpio/stm32l4x5_gpio.c
184
new file mode 100644
153
new file mode 100644
185
index XXXXXXX..XXXXXXX
154
index XXXXXXX..XXXXXXX
186
--- /dev/null
155
--- /dev/null
187
+++ b/include/hw/arm/smmuv3.h
156
+++ b/hw/gpio/stm32l4x5_gpio.c
188
@@ -XXX,XX +XXX,XX @@
157
@@ -XXX,XX +XXX,XX @@
189
+/*
158
+/*
190
+ * Copyright (C) 2014-2016 Broadcom Corporation
159
+ * STM32L4x5 GPIO (General Purpose Input/Ouput)
191
+ * Copyright (c) 2017 Red Hat, Inc.
192
+ * Written by Prem Mallappa, Eric Auger
193
+ *
160
+ *
194
+ * This program is free software; you can redistribute it and/or modify
161
+ * Copyright (c) 2024 Arnaud Minier <arnaud.minier@telecom-paris.fr>
195
+ * it under the terms of the GNU General Public License version 2 as
162
+ * Copyright (c) 2024 Inès Varhol <ines.varhol@telecom-paris.fr>
196
+ * published by the Free Software Foundation.
197
+ *
163
+ *
198
+ * This program is distributed in the hope that it will be useful,
164
+ * SPDX-License-Identifier: GPL-2.0-or-later
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
+ *
165
+ *
203
+ * You should have received a copy of the GNU General Public License along
166
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
204
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
167
+ * See the COPYING file in the top-level directory.
205
+ */
168
+ */
206
+
169
+
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
+/*
170
+/*
283
+ * Copyright (C) 2014-2016 Broadcom Corporation
171
+ * The reference used is the STMicroElectronics RM0351 Reference manual
284
+ * Copyright (c) 2017 Red Hat, Inc.
172
+ * for STM32L4x5 and STM32L4x6 advanced Arm ® -based 32-bit MCUs.
285
+ * Written by Prem Mallappa, Eric Auger
173
+ * https://www.st.com/en/microcontrollers-microprocessors/stm32l4x5/documentation.html
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
+ */
174
+ */
299
+
175
+
300
+#include "qemu/osdep.h"
176
+#include "qemu/osdep.h"
301
+#include "hw/boards.h"
177
+#include "qemu/log.h"
302
+#include "sysemu/sysemu.h"
178
+#include "hw/gpio/stm32l4x5_gpio.h"
303
+#include "hw/sysbus.h"
179
+#include "hw/irq.h"
304
+#include "hw/qdev-core.h"
180
+#include "hw/qdev-clock.h"
305
+#include "hw/pci/pci.h"
181
+#include "hw/qdev-properties.h"
306
+#include "exec/address-spaces.h"
182
+#include "qapi/visitor.h"
183
+#include "qapi/error.h"
184
+#include "migration/vmstate.h"
307
+#include "trace.h"
185
+#include "trace.h"
308
+#include "qemu/log.h"
186
+
309
+#include "qemu/error-report.h"
187
+#define GPIO_MODER 0x00
310
+#include "qapi/error.h"
188
+#define GPIO_OTYPER 0x04
311
+
189
+#define GPIO_OSPEEDR 0x08
312
+#include "hw/arm/smmuv3.h"
190
+#define GPIO_PUPDR 0x0C
313
+#include "smmuv3-internal.h"
191
+#define GPIO_IDR 0x10
314
+
192
+#define GPIO_ODR 0x14
315
+static void smmuv3_init_regs(SMMUv3State *s)
193
+#define GPIO_BSRR 0x18
316
+{
194
+#define GPIO_LCKR 0x1C
317
+ /**
195
+#define GPIO_AFRL 0x20
318
+ * IDR0: stage1 only, AArch64 only, coherent access, 16b ASID,
196
+#define GPIO_AFRH 0x24
319
+ * multi-level stream table
197
+#define GPIO_BRR 0x28
198
+#define GPIO_ASCR 0x2C
199
+
200
+/* 0b11111111_11111111_00000000_00000000 */
201
+#define RESERVED_BITS_MASK 0xFFFF0000
202
+
203
+static void update_gpio_idr(Stm32l4x5GpioState *s);
204
+
205
+static bool is_pull_up(Stm32l4x5GpioState *s, unsigned pin)
206
+{
207
+ return extract32(s->pupdr, 2 * pin, 2) == 1;
208
+}
209
+
210
+static bool is_pull_down(Stm32l4x5GpioState *s, unsigned pin)
211
+{
212
+ return extract32(s->pupdr, 2 * pin, 2) == 2;
213
+}
214
+
215
+static bool is_output(Stm32l4x5GpioState *s, unsigned pin)
216
+{
217
+ return extract32(s->moder, 2 * pin, 2) == 1;
218
+}
219
+
220
+static bool is_open_drain(Stm32l4x5GpioState *s, unsigned pin)
221
+{
222
+ return extract32(s->otyper, pin, 1) == 1;
223
+}
224
+
225
+static bool is_push_pull(Stm32l4x5GpioState *s, unsigned pin)
226
+{
227
+ return extract32(s->otyper, pin, 1) == 0;
228
+}
229
+
230
+static void stm32l4x5_gpio_reset_hold(Object *obj)
231
+{
232
+ Stm32l4x5GpioState *s = STM32L4X5_GPIO(obj);
233
+
234
+ s->moder = s->moder_reset;
235
+ s->otyper = 0x00000000;
236
+ s->ospeedr = s->ospeedr_reset;
237
+ s->pupdr = s->pupdr_reset;
238
+ s->idr = 0x00000000;
239
+ s->odr = 0x00000000;
240
+ s->lckr = 0x00000000;
241
+ s->afrl = 0x00000000;
242
+ s->afrh = 0x00000000;
243
+ s->ascr = 0x00000000;
244
+
245
+ s->disconnected_pins = 0xFFFF;
246
+ s->pins_connected_high = 0x0000;
247
+ update_gpio_idr(s);
248
+}
249
+
250
+static void stm32l4x5_gpio_set(void *opaque, int line, int level)
251
+{
252
+ Stm32l4x5GpioState *s = opaque;
253
+ /*
254
+ * The pin isn't set if line is configured in output mode
255
+ * except if level is 0 and the output is open-drain.
256
+ * This way there will be no short-circuit prone situations.
320
+ */
257
+ */
321
+ s->idr[0] = FIELD_DP32(s->idr[0], IDR0, S1P, 1); /* stage 1 supported */
258
+ if (is_output(s, line) && !(is_open_drain(s, line) && (level == 0))) {
322
+ s->idr[0] = FIELD_DP32(s->idr[0], IDR0, TTF, 2); /* AArch64 PTW only */
259
+ qemu_log_mask(LOG_GUEST_ERROR, "Line %d can't be driven externally\n",
323
+ s->idr[0] = FIELD_DP32(s->idr[0], IDR0, COHACC, 1); /* IO coherent */
260
+ line);
324
+ s->idr[0] = FIELD_DP32(s->idr[0], IDR0, ASID16, 1); /* 16-bit ASID */
261
+ return;
325
+ s->idr[0] = FIELD_DP32(s->idr[0], IDR0, TTENDIAN, 2); /* little endian */
262
+ }
326
+ s->idr[0] = FIELD_DP32(s->idr[0], IDR0, STALL_MODEL, 1); /* No stall */
263
+
327
+ /* terminated transaction will always be aborted/error returned */
264
+ s->disconnected_pins &= ~(1 << line);
328
+ s->idr[0] = FIELD_DP32(s->idr[0], IDR0, TERM_MODEL, 1);
265
+ if (level) {
329
+ /* 2-level stream table supported */
266
+ s->pins_connected_high |= (1 << line);
330
+ s->idr[0] = FIELD_DP32(s->idr[0], IDR0, STLEVEL, 1);
267
+ } else {
331
+
268
+ s->pins_connected_high &= ~(1 << line);
332
+ s->idr[1] = FIELD_DP32(s->idr[1], IDR1, SIDSIZE, SMMU_IDR1_SIDSIZE);
269
+ }
333
+ s->idr[1] = FIELD_DP32(s->idr[1], IDR1, EVENTQS, SMMU_EVENTQS);
270
+ trace_stm32l4x5_gpio_pins(s->name, s->disconnected_pins,
334
+ s->idr[1] = FIELD_DP32(s->idr[1], IDR1, CMDQS, SMMU_CMDQS);
271
+ s->pins_connected_high);
335
+
272
+ update_gpio_idr(s);
336
+ /* 4K and 64K granule support */
273
+}
337
+ s->idr[5] = FIELD_DP32(s->idr[5], IDR5, GRAN4K, 1);
274
+
338
+ s->idr[5] = FIELD_DP32(s->idr[5], IDR5, GRAN64K, 1);
275
+
339
+ s->idr[5] = FIELD_DP32(s->idr[5], IDR5, OAS, SMMU_IDR5_OAS); /* 44 bits */
276
+static void update_gpio_idr(Stm32l4x5GpioState *s)
340
+
277
+{
341
+ s->cmdq.base = deposit64(s->cmdq.base, 0, 5, SMMU_CMDQS);
278
+ uint32_t new_idr_mask = 0;
342
+ s->cmdq.prod = 0;
279
+ uint32_t new_idr = s->odr;
343
+ s->cmdq.cons = 0;
280
+ uint32_t old_idr = s->idr;
344
+ s->cmdq.entry_size = sizeof(struct Cmd);
281
+ int new_pin_state, old_pin_state;
345
+ s->eventq.base = deposit64(s->eventq.base, 0, 5, SMMU_EVENTQS);
282
+
346
+ s->eventq.prod = 0;
283
+ for (int i = 0; i < GPIO_NUM_PINS; i++) {
347
+ s->eventq.cons = 0;
284
+ if (is_output(s, i)) {
348
+ s->eventq.entry_size = sizeof(struct Evt);
285
+ if (is_push_pull(s, i)) {
349
+
286
+ new_idr_mask |= (1 << i);
350
+ s->features = 0;
287
+ } else if (!(s->odr & (1 << i))) {
351
+ s->sid_split = 0;
288
+ /* open-drain ODR 0 */
352
+}
289
+ new_idr_mask |= (1 << i);
353
+
290
+ /* open-drain ODR 1 */
354
+static MemTxResult smmu_write_mmio(void *opaque, hwaddr offset, uint64_t data,
291
+ } else if (!(s->disconnected_pins & (1 << i)) &&
355
+ unsigned size, MemTxAttrs attrs)
292
+ !(s->pins_connected_high & (1 << i))) {
356
+{
293
+ /* open-drain ODR 1 with pin connected low */
357
+ /* not yet implemented */
294
+ new_idr_mask |= (1 << i);
358
+ return MEMTX_ERROR;
295
+ new_idr &= ~(1 << i);
359
+}
296
+ /* open-drain ODR 1 with unactive pin */
360
+
297
+ } else if (is_pull_up(s, i)) {
361
+static MemTxResult smmu_readll(SMMUv3State *s, hwaddr offset,
298
+ new_idr_mask |= (1 << i);
362
+ uint64_t *data, MemTxAttrs attrs)
299
+ } else if (is_pull_down(s, i)) {
363
+{
300
+ new_idr_mask |= (1 << i);
364
+ switch (offset) {
301
+ new_idr &= ~(1 << i);
365
+ case A_GERROR_IRQ_CFG0:
302
+ }
366
+ *data = s->gerror_irq_cfg0;
303
+ /*
367
+ return MEMTX_OK;
304
+ * The only case left is for open-drain ODR 1
368
+ case A_STRTAB_BASE:
305
+ * with unactive pin without pull-up or pull-down :
369
+ *data = s->strtab_base;
306
+ * the value is floating.
370
+ return MEMTX_OK;
307
+ */
371
+ case A_CMDQ_BASE:
308
+ /* input or analog mode with connected pin */
372
+ *data = s->cmdq.base;
309
+ } else if (!(s->disconnected_pins & (1 << i))) {
373
+ return MEMTX_OK;
310
+ if (s->pins_connected_high & (1 << i)) {
374
+ case A_EVENTQ_BASE:
311
+ /* pin high */
375
+ *data = s->eventq.base;
312
+ new_idr_mask |= (1 << i);
376
+ return MEMTX_OK;
313
+ new_idr |= (1 << i);
314
+ } else {
315
+ /* pin low */
316
+ new_idr_mask |= (1 << i);
317
+ new_idr &= ~(1 << i);
318
+ }
319
+ /* input or analog mode with disconnected pin */
320
+ } else {
321
+ if (is_pull_up(s, i)) {
322
+ /* pull-up */
323
+ new_idr_mask |= (1 << i);
324
+ new_idr |= (1 << i);
325
+ } else if (is_pull_down(s, i)) {
326
+ /* pull-down */
327
+ new_idr_mask |= (1 << i);
328
+ new_idr &= ~(1 << i);
329
+ }
330
+ /*
331
+ * The only case left is for a disconnected pin
332
+ * without pull-up or pull-down :
333
+ * the value is floating.
334
+ */
335
+ }
336
+ }
337
+
338
+ s->idr = (old_idr & ~new_idr_mask) | (new_idr & new_idr_mask);
339
+ trace_stm32l4x5_gpio_update_idr(s->name, old_idr, s->idr);
340
+
341
+ for (int i = 0; i < GPIO_NUM_PINS; i++) {
342
+ if (new_idr_mask & (1 << i)) {
343
+ new_pin_state = (new_idr & (1 << i)) > 0;
344
+ old_pin_state = (old_idr & (1 << i)) > 0;
345
+ if (new_pin_state > old_pin_state) {
346
+ qemu_irq_raise(s->pin[i]);
347
+ } else if (new_pin_state < old_pin_state) {
348
+ qemu_irq_lower(s->pin[i]);
349
+ }
350
+ }
351
+ }
352
+}
353
+
354
+/*
355
+ * Return mask of pins that are both configured in output
356
+ * mode and externally driven (except pins in open-drain
357
+ * mode externally set to 0).
358
+ */
359
+static uint32_t get_gpio_pinmask_to_disconnect(Stm32l4x5GpioState *s)
360
+{
361
+ uint32_t pins_to_disconnect = 0;
362
+ for (int i = 0; i < GPIO_NUM_PINS; i++) {
363
+ /* for each connected pin in output mode */
364
+ if (!(s->disconnected_pins & (1 << i)) && is_output(s, i)) {
365
+ /* if either push-pull or high level */
366
+ if (is_push_pull(s, i) || s->pins_connected_high & (1 << i)) {
367
+ pins_to_disconnect |= (1 << i);
368
+ qemu_log_mask(LOG_GUEST_ERROR,
369
+ "Line %d can't be driven externally\n",
370
+ i);
371
+ }
372
+ }
373
+ }
374
+ return pins_to_disconnect;
375
+}
376
+
377
+/*
378
+ * Set field `disconnected_pins` and call `update_gpio_idr()`
379
+ */
380
+static void disconnect_gpio_pins(Stm32l4x5GpioState *s, uint16_t lines)
381
+{
382
+ s->disconnected_pins |= lines;
383
+ trace_stm32l4x5_gpio_pins(s->name, s->disconnected_pins,
384
+ s->pins_connected_high);
385
+ update_gpio_idr(s);
386
+}
387
+
388
+static void disconnected_pins_set(Object *obj, Visitor *v,
389
+ const char *name, void *opaque, Error **errp)
390
+{
391
+ Stm32l4x5GpioState *s = STM32L4X5_GPIO(obj);
392
+ uint16_t value;
393
+ if (!visit_type_uint16(v, name, &value, errp)) {
394
+ return;
395
+ }
396
+ disconnect_gpio_pins(s, value);
397
+}
398
+
399
+static void disconnected_pins_get(Object *obj, Visitor *v,
400
+ const char *name, void *opaque, Error **errp)
401
+{
402
+ visit_type_uint16(v, name, (uint16_t *)opaque, errp);
403
+}
404
+
405
+static void clock_freq_get(Object *obj, Visitor *v,
406
+ const char *name, void *opaque, Error **errp)
407
+{
408
+ Stm32l4x5GpioState *s = STM32L4X5_GPIO(obj);
409
+ uint32_t clock_freq_hz = clock_get_hz(s->clk);
410
+ visit_type_uint32(v, name, &clock_freq_hz, errp);
411
+}
412
+
413
+static void stm32l4x5_gpio_write(void *opaque, hwaddr addr,
414
+ uint64_t val64, unsigned int size)
415
+{
416
+ Stm32l4x5GpioState *s = opaque;
417
+
418
+ uint32_t value = val64;
419
+ trace_stm32l4x5_gpio_write(s->name, addr, val64);
420
+
421
+ switch (addr) {
422
+ case GPIO_MODER:
423
+ s->moder = value;
424
+ disconnect_gpio_pins(s, get_gpio_pinmask_to_disconnect(s));
425
+ qemu_log_mask(LOG_UNIMP,
426
+ "%s: Analog and AF modes aren't supported\n\
427
+ Analog and AF mode behave like input mode\n",
428
+ __func__);
429
+ return;
430
+ case GPIO_OTYPER:
431
+ s->otyper = value & ~RESERVED_BITS_MASK;
432
+ disconnect_gpio_pins(s, get_gpio_pinmask_to_disconnect(s));
433
+ return;
434
+ case GPIO_OSPEEDR:
435
+ qemu_log_mask(LOG_UNIMP,
436
+ "%s: Changing I/O output speed isn't supported\n\
437
+ I/O speed is already maximal\n",
438
+ __func__);
439
+ s->ospeedr = value;
440
+ return;
441
+ case GPIO_PUPDR:
442
+ s->pupdr = value;
443
+ update_gpio_idr(s);
444
+ return;
445
+ case GPIO_IDR:
446
+ qemu_log_mask(LOG_UNIMP,
447
+ "%s: GPIO->IDR is read-only\n",
448
+ __func__);
449
+ return;
450
+ case GPIO_ODR:
451
+ s->odr = value & ~RESERVED_BITS_MASK;
452
+ update_gpio_idr(s);
453
+ return;
454
+ case GPIO_BSRR: {
455
+ uint32_t bits_to_reset = (value & RESERVED_BITS_MASK) >> GPIO_NUM_PINS;
456
+ uint32_t bits_to_set = value & ~RESERVED_BITS_MASK;
457
+ /* If both BSx and BRx are set, BSx has priority.*/
458
+ s->odr &= ~bits_to_reset;
459
+ s->odr |= bits_to_set;
460
+ update_gpio_idr(s);
461
+ return;
462
+ }
463
+ case GPIO_LCKR:
464
+ qemu_log_mask(LOG_UNIMP,
465
+ "%s: Locking port bits configuration isn't supported\n",
466
+ __func__);
467
+ s->lckr = value & ~RESERVED_BITS_MASK;
468
+ return;
469
+ case GPIO_AFRL:
470
+ qemu_log_mask(LOG_UNIMP,
471
+ "%s: Alternate functions aren't supported\n",
472
+ __func__);
473
+ s->afrl = value;
474
+ return;
475
+ case GPIO_AFRH:
476
+ qemu_log_mask(LOG_UNIMP,
477
+ "%s: Alternate functions aren't supported\n",
478
+ __func__);
479
+ s->afrh = value;
480
+ return;
481
+ case GPIO_BRR: {
482
+ uint32_t bits_to_reset = value & ~RESERVED_BITS_MASK;
483
+ s->odr &= ~bits_to_reset;
484
+ update_gpio_idr(s);
485
+ return;
486
+ }
487
+ case GPIO_ASCR:
488
+ qemu_log_mask(LOG_UNIMP,
489
+ "%s: ADC function isn't supported\n",
490
+ __func__);
491
+ s->ascr = value & ~RESERVED_BITS_MASK;
492
+ return;
377
+ default:
493
+ default:
378
+ *data = 0;
494
+ qemu_log_mask(LOG_GUEST_ERROR,
379
+ qemu_log_mask(LOG_UNIMP,
495
+ "%s: Bad offset 0x%" HWADDR_PRIx "\n", __func__, addr);
380
+ "%s Unexpected 64-bit access to 0x%"PRIx64" (RAZ)\n",
496
+ }
381
+ __func__, offset);
497
+}
382
+ return MEMTX_OK;
498
+
383
+ }
499
+static uint64_t stm32l4x5_gpio_read(void *opaque, hwaddr addr,
384
+}
500
+ unsigned int size)
385
+
501
+{
386
+static MemTxResult smmu_readl(SMMUv3State *s, hwaddr offset,
502
+ Stm32l4x5GpioState *s = opaque;
387
+ uint64_t *data, MemTxAttrs attrs)
503
+
388
+{
504
+ trace_stm32l4x5_gpio_read(s->name, addr);
389
+ switch (offset) {
505
+
390
+ case A_IDREGS ... A_IDREGS + 0x1f:
506
+ switch (addr) {
391
+ *data = smmuv3_idreg(offset - A_IDREGS);
507
+ case GPIO_MODER:
392
+ return MEMTX_OK;
508
+ return s->moder;
393
+ case A_IDR0 ... A_IDR5:
509
+ case GPIO_OTYPER:
394
+ *data = s->idr[(offset - A_IDR0) / 4];
510
+ return s->otyper;
395
+ return MEMTX_OK;
511
+ case GPIO_OSPEEDR:
396
+ case A_IIDR:
512
+ return s->ospeedr;
397
+ *data = s->iidr;
513
+ case GPIO_PUPDR:
398
+ return MEMTX_OK;
514
+ return s->pupdr;
399
+ case A_CR0:
515
+ case GPIO_IDR:
400
+ *data = s->cr[0];
516
+ return s->idr;
401
+ return MEMTX_OK;
517
+ case GPIO_ODR:
402
+ case A_CR0ACK:
518
+ return s->odr;
403
+ *data = s->cr0ack;
519
+ case GPIO_BSRR:
404
+ return MEMTX_OK;
520
+ return 0;
405
+ case A_CR1:
521
+ case GPIO_LCKR:
406
+ *data = s->cr[1];
522
+ return s->lckr;
407
+ return MEMTX_OK;
523
+ case GPIO_AFRL:
408
+ case A_CR2:
524
+ return s->afrl;
409
+ *data = s->cr[2];
525
+ case GPIO_AFRH:
410
+ return MEMTX_OK;
526
+ return s->afrh;
411
+ case A_STATUSR:
527
+ case GPIO_BRR:
412
+ *data = s->statusr;
528
+ return 0;
413
+ return MEMTX_OK;
529
+ case GPIO_ASCR:
414
+ case A_IRQ_CTRL:
530
+ return s->ascr;
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:
531
+ default:
470
+ *data = 0;
532
+ qemu_log_mask(LOG_GUEST_ERROR,
471
+ qemu_log_mask(LOG_UNIMP,
533
+ "%s: Bad offset 0x%" HWADDR_PRIx "\n", __func__, addr);
472
+ "%s unhandled 32-bit access at 0x%"PRIx64" (RAZ)\n",
534
+ return 0;
473
+ __func__, offset);
535
+ }
474
+ return MEMTX_OK;
536
+}
475
+ }
537
+
476
+}
538
+static const MemoryRegionOps stm32l4x5_gpio_ops = {
477
+
539
+ .read = stm32l4x5_gpio_read,
478
+static MemTxResult smmu_read_mmio(void *opaque, hwaddr offset, uint64_t *data,
540
+ .write = stm32l4x5_gpio_write,
479
+ unsigned size, MemTxAttrs attrs)
541
+ .endianness = DEVICE_NATIVE_ENDIAN,
480
+{
542
+ .impl = {
481
+ SMMUState *sys = opaque;
543
+ .min_access_size = 4,
482
+ SMMUv3State *s = ARM_SMMUV3(sys);
544
+ .max_access_size = 4,
483
+ MemTxResult r;
545
+ .unaligned = false,
484
+
546
+ },
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 = {
547
+ .valid = {
509
+ .min_access_size = 4,
548
+ .min_access_size = 4,
510
+ .max_access_size = 8,
549
+ .max_access_size = 4,
511
+ },
550
+ .unaligned = false,
512
+ .impl = {
513
+ .min_access_size = 4,
514
+ .max_access_size = 8,
515
+ },
551
+ },
516
+};
552
+};
517
+
553
+
518
+static void smmu_init_irq(SMMUv3State *s, SysBusDevice *dev)
554
+static void stm32l4x5_gpio_init(Object *obj)
519
+{
555
+{
520
+ int i;
556
+ Stm32l4x5GpioState *s = STM32L4X5_GPIO(obj);
521
+
557
+
522
+ for (i = 0; i < ARRAY_SIZE(s->irq); i++) {
558
+ memory_region_init_io(&s->mmio, obj, &stm32l4x5_gpio_ops, s,
523
+ sysbus_init_irq(dev, &s->irq[i]);
559
+ TYPE_STM32L4X5_GPIO, 0x400);
524
+ }
560
+
525
+}
561
+ sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio);
526
+
562
+
527
+static void smmu_reset(DeviceState *dev)
563
+ qdev_init_gpio_out(DEVICE(obj), s->pin, GPIO_NUM_PINS);
528
+{
564
+ qdev_init_gpio_in(DEVICE(obj), stm32l4x5_gpio_set, GPIO_NUM_PINS);
529
+ SMMUv3State *s = ARM_SMMUV3(dev);
565
+
530
+ SMMUv3Class *c = ARM_SMMUV3_GET_CLASS(s);
566
+ s->clk = qdev_init_clock_in(DEVICE(s), "clk", NULL, s, 0);
531
+
567
+
532
+ c->parent_reset(dev);
568
+ object_property_add(obj, "disconnected-pins", "uint16",
533
+
569
+ disconnected_pins_get, disconnected_pins_set,
534
+ smmuv3_init_regs(s);
570
+ NULL, &s->disconnected_pins);
535
+}
571
+ object_property_add(obj, "clock-freq-hz", "uint32",
536
+
572
+ clock_freq_get, NULL, NULL, NULL);
537
+static void smmu_realize(DeviceState *d, Error **errp)
573
+}
538
+{
574
+
539
+ SMMUState *sys = ARM_SMMU(d);
575
+static void stm32l4x5_gpio_realize(DeviceState *dev, Error **errp)
540
+ SMMUv3State *s = ARM_SMMUV3(sys);
576
+{
541
+ SMMUv3Class *c = ARM_SMMUV3_GET_CLASS(s);
577
+ Stm32l4x5GpioState *s = STM32L4X5_GPIO(dev);
542
+ SysBusDevice *dev = SYS_BUS_DEVICE(d);
578
+ if (!clock_has_source(s->clk)) {
543
+ Error *local_err = NULL;
579
+ error_setg(errp, "GPIO: clk input must be connected");
544
+
580
+ return;
545
+ c->parent_realize(d, &local_err);
581
+ }
546
+ if (local_err) {
582
+}
547
+ error_propagate(errp, local_err);
583
+
548
+ return;
584
+static const VMStateDescription vmstate_stm32l4x5_gpio = {
549
+ }
585
+ .name = TYPE_STM32L4X5_GPIO,
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,
586
+ .version_id = 1,
564
+ .minimum_version_id = 1,
587
+ .minimum_version_id = 1,
565
+ .fields = (VMStateField[]) {
588
+ .fields = (VMStateField[]){
566
+ VMSTATE_UINT64(base, SMMUQueue),
589
+ VMSTATE_UINT32(moder, Stm32l4x5GpioState),
567
+ VMSTATE_UINT32(prod, SMMUQueue),
590
+ VMSTATE_UINT32(otyper, Stm32l4x5GpioState),
568
+ VMSTATE_UINT32(cons, SMMUQueue),
591
+ VMSTATE_UINT32(ospeedr, Stm32l4x5GpioState),
569
+ VMSTATE_UINT8(log2size, SMMUQueue),
592
+ VMSTATE_UINT32(pupdr, Stm32l4x5GpioState),
593
+ VMSTATE_UINT32(idr, Stm32l4x5GpioState),
594
+ VMSTATE_UINT32(odr, Stm32l4x5GpioState),
595
+ VMSTATE_UINT32(lckr, Stm32l4x5GpioState),
596
+ VMSTATE_UINT32(afrl, Stm32l4x5GpioState),
597
+ VMSTATE_UINT32(afrh, Stm32l4x5GpioState),
598
+ VMSTATE_UINT32(ascr, Stm32l4x5GpioState),
599
+ VMSTATE_UINT16(disconnected_pins, Stm32l4x5GpioState),
600
+ VMSTATE_UINT16(pins_connected_high, Stm32l4x5GpioState),
601
+ VMSTATE_END_OF_LIST()
602
+ }
603
+};
604
+
605
+static Property stm32l4x5_gpio_properties[] = {
606
+ DEFINE_PROP_STRING("name", Stm32l4x5GpioState, name),
607
+ DEFINE_PROP_UINT32("mode-reset", Stm32l4x5GpioState, moder_reset, 0),
608
+ DEFINE_PROP_UINT32("ospeed-reset", Stm32l4x5GpioState, ospeedr_reset, 0),
609
+ DEFINE_PROP_UINT32("pupd-reset", Stm32l4x5GpioState, pupdr_reset, 0),
610
+ DEFINE_PROP_END_OF_LIST(),
611
+};
612
+
613
+static void stm32l4x5_gpio_class_init(ObjectClass *klass, void *data)
614
+{
615
+ DeviceClass *dc = DEVICE_CLASS(klass);
616
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
617
+
618
+ device_class_set_props(dc, stm32l4x5_gpio_properties);
619
+ dc->vmsd = &vmstate_stm32l4x5_gpio;
620
+ dc->realize = stm32l4x5_gpio_realize;
621
+ rc->phases.hold = stm32l4x5_gpio_reset_hold;
622
+}
623
+
624
+static const TypeInfo stm32l4x5_gpio_types[] = {
625
+ {
626
+ .name = TYPE_STM32L4X5_GPIO,
627
+ .parent = TYPE_SYS_BUS_DEVICE,
628
+ .instance_size = sizeof(Stm32l4x5GpioState),
629
+ .instance_init = stm32l4x5_gpio_init,
630
+ .class_init = stm32l4x5_gpio_class_init,
570
+ },
631
+ },
571
+};
632
+};
572
+
633
+
573
+static const VMStateDescription vmstate_smmuv3 = {
634
+DEFINE_TYPES(stm32l4x5_gpio_types)
574
+ .name = "smmuv3",
635
diff --git a/hw/gpio/Kconfig b/hw/gpio/Kconfig
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
636
index XXXXXXX..XXXXXXX 100644
650
--- a/hw/arm/trace-events
637
--- a/hw/gpio/Kconfig
651
+++ b/hw/arm/trace-events
638
+++ b/hw/gpio/Kconfig
652
@@ -XXX,XX +XXX,XX @@ smmu_ptw_invalid_pte(int stage, int level, uint64_t baseaddr, uint64_t pteaddr,
639
@@ -XXX,XX +XXX,XX @@ config GPIO_PWR
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
640
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"
641
config SIFIVE_GPIO
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
642
bool
656
+
643
+
657
+#hw/arm/smmuv3.c
644
+config STM32L4X5_GPIO
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)"
645
+ bool
646
diff --git a/hw/gpio/meson.build b/hw/gpio/meson.build
647
index XXXXXXX..XXXXXXX 100644
648
--- a/hw/gpio/meson.build
649
+++ b/hw/gpio/meson.build
650
@@ -XXX,XX +XXX,XX @@ system_ss.add(when: 'CONFIG_RASPI', if_true: files(
651
'bcm2835_gpio.c',
652
'bcm2838_gpio.c'
653
))
654
+system_ss.add(when: 'CONFIG_STM32L4X5_SOC', if_true: files('stm32l4x5_gpio.c'))
655
system_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files('aspeed_gpio.c'))
656
system_ss.add(when: 'CONFIG_SIFIVE_GPIO', if_true: files('sifive_gpio.c'))
657
diff --git a/hw/gpio/trace-events b/hw/gpio/trace-events
658
index XXXXXXX..XXXXXXX 100644
659
--- a/hw/gpio/trace-events
660
+++ b/hw/gpio/trace-events
661
@@ -XXX,XX +XXX,XX @@ sifive_gpio_update_output_irq(int64_t line, int64_t value) "line %" PRIi64 " val
662
# aspeed_gpio.c
663
aspeed_gpio_read(uint64_t offset, uint64_t value) "offset: 0x%" PRIx64 " value 0x%" PRIx64
664
aspeed_gpio_write(uint64_t offset, uint64_t value) "offset: 0x%" PRIx64 " value 0x%" PRIx64
665
+
666
+# stm32l4x5_gpio.c
667
+stm32l4x5_gpio_read(char *gpio, uint64_t addr) "GPIO%s addr: 0x%" PRIx64 " "
668
+stm32l4x5_gpio_write(char *gpio, uint64_t addr, uint64_t data) "GPIO%s addr: 0x%" PRIx64 " val: 0x%" PRIx64 ""
669
+stm32l4x5_gpio_update_idr(char *gpio, uint32_t old_idr, uint32_t new_idr) "GPIO%s from: 0x%x to: 0x%x"
670
+stm32l4x5_gpio_pins(char *gpio, uint16_t disconnected, uint16_t high) "GPIO%s disconnected pins: 0x%x levels: 0x%x"
659
--
671
--
660
2.17.0
672
2.34.1
661
673
662
674
diff view generated by jsdifflib
1
From: Eric Auger <eric.auger@redhat.com>
1
From: Inès Varhol <ines.varhol@telecom-paris.fr>
2
2
3
We introduce helpers to read/write into the command and event
3
Signed-off-by: Arnaud Minier <arnaud.minier@telecom-paris.fr>
4
circular queues.
4
Signed-off-by: Inès Varhol <ines.varhol@telecom-paris.fr>
5
5
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
6
smmuv3_write_eventq and smmuv3_cmq_consume will become static
6
Acked-by: Alistair Francis <alistair.francis@wdc.com>
7
in subsequent patches.
7
Message-id: 20240305210444.310665-3-ines.varhol@telecom-paris.fr
8
9
Invalidation commands are not yet dealt with. We do not cache
10
data that need to be invalidated. This will change with vhost
11
integration.
12
13
Signed-off-by: Eric Auger <eric.auger@redhat.com>
14
Signed-off-by: Prem Mallappa <prem.mallappa@broadcom.com>
15
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
16
Message-id: 1524665762-31355-7-git-send-email-eric.auger@redhat.com
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
---
9
---
19
hw/arm/smmuv3-internal.h | 163 +++++++++++++++++++++++++++++++++++++++
10
include/hw/arm/stm32l4x5_soc.h | 2 +
20
hw/arm/smmuv3.c | 136 ++++++++++++++++++++++++++++++++
11
include/hw/gpio/stm32l4x5_gpio.h | 1 +
21
hw/arm/trace-events | 5 ++
12
include/hw/misc/stm32l4x5_syscfg.h | 3 +-
22
3 files changed, 304 insertions(+)
13
hw/arm/stm32l4x5_soc.c | 71 +++++++++++++++++++++++-------
23
14
hw/misc/stm32l4x5_syscfg.c | 1 +
24
diff --git a/hw/arm/smmuv3-internal.h b/hw/arm/smmuv3-internal.h
15
hw/arm/Kconfig | 3 +-
25
index XXXXXXX..XXXXXXX 100644
16
6 files changed, 63 insertions(+), 18 deletions(-)
26
--- a/hw/arm/smmuv3-internal.h
17
27
+++ b/hw/arm/smmuv3-internal.h
18
diff --git a/include/hw/arm/stm32l4x5_soc.h b/include/hw/arm/stm32l4x5_soc.h
28
@@ -XXX,XX +XXX,XX @@ static inline bool smmuv3_gerror_irq_enabled(SMMUv3State *s)
19
index XXXXXXX..XXXXXXX 100644
29
void smmuv3_trigger_irq(SMMUv3State *s, SMMUIrq irq, uint32_t gerror_mask);
20
--- a/include/hw/arm/stm32l4x5_soc.h
30
void smmuv3_write_gerrorn(SMMUv3State *s, uint32_t gerrorn);
21
+++ b/include/hw/arm/stm32l4x5_soc.h
31
22
@@ -XXX,XX +XXX,XX @@
32
+/* Queue Handling */
23
#include "hw/misc/stm32l4x5_syscfg.h"
33
+
24
#include "hw/misc/stm32l4x5_exti.h"
34
+#define Q_BASE(q) ((q)->base & SMMU_BASE_ADDR_MASK)
25
#include "hw/misc/stm32l4x5_rcc.h"
35
+#define WRAP_MASK(q) (1 << (q)->log2size)
26
+#include "hw/gpio/stm32l4x5_gpio.h"
36
+#define INDEX_MASK(q) (((1 << (q)->log2size)) - 1)
27
#include "qom/object.h"
37
+#define WRAP_INDEX_MASK(q) ((1 << ((q)->log2size + 1)) - 1)
28
38
+
29
#define TYPE_STM32L4X5_SOC "stm32l4x5-soc"
39
+#define Q_CONS(q) ((q)->cons & INDEX_MASK(q))
30
@@ -XXX,XX +XXX,XX @@ struct Stm32l4x5SocState {
40
+#define Q_PROD(q) ((q)->prod & INDEX_MASK(q))
31
OrIRQState exti_or_gates[NUM_EXTI_OR_GATES];
41
+
32
Stm32l4x5SyscfgState syscfg;
42
+#define Q_CONS_ENTRY(q) (Q_BASE(q) + (q)->entry_size * Q_CONS(q))
33
Stm32l4x5RccState rcc;
43
+#define Q_PROD_ENTRY(q) (Q_BASE(q) + (q)->entry_size * Q_PROD(q))
34
+ Stm32l4x5GpioState gpio[NUM_GPIOS];
44
+
35
45
+#define Q_CONS_WRAP(q) (((q)->cons & WRAP_MASK(q)) >> (q)->log2size)
36
MemoryRegion sram1;
46
+#define Q_PROD_WRAP(q) (((q)->prod & WRAP_MASK(q)) >> (q)->log2size)
37
MemoryRegion sram2;
47
+
38
diff --git a/include/hw/gpio/stm32l4x5_gpio.h b/include/hw/gpio/stm32l4x5_gpio.h
48
+static inline bool smmuv3_q_full(SMMUQueue *q)
39
index XXXXXXX..XXXXXXX 100644
49
+{
40
--- a/include/hw/gpio/stm32l4x5_gpio.h
50
+ return ((q->cons ^ q->prod) & WRAP_INDEX_MASK(q)) == WRAP_MASK(q);
41
+++ b/include/hw/gpio/stm32l4x5_gpio.h
51
+}
42
@@ -XXX,XX +XXX,XX @@
52
+
43
#define TYPE_STM32L4X5_GPIO "stm32l4x5-gpio"
53
+static inline bool smmuv3_q_empty(SMMUQueue *q)
44
OBJECT_DECLARE_SIMPLE_TYPE(Stm32l4x5GpioState, STM32L4X5_GPIO)
54
+{
45
55
+ return (q->cons & WRAP_INDEX_MASK(q)) == (q->prod & WRAP_INDEX_MASK(q));
46
+#define NUM_GPIOS 8
56
+}
47
#define GPIO_NUM_PINS 16
57
+
48
58
+static inline void queue_prod_incr(SMMUQueue *q)
49
struct Stm32l4x5GpioState {
59
+{
50
diff --git a/include/hw/misc/stm32l4x5_syscfg.h b/include/hw/misc/stm32l4x5_syscfg.h
60
+ q->prod = (q->prod + 1) & WRAP_INDEX_MASK(q);
51
index XXXXXXX..XXXXXXX 100644
61
+}
52
--- a/include/hw/misc/stm32l4x5_syscfg.h
62
+
53
+++ b/include/hw/misc/stm32l4x5_syscfg.h
63
+static inline void queue_cons_incr(SMMUQueue *q)
54
@@ -XXX,XX +XXX,XX @@
64
+{
55
65
+ /*
56
#include "hw/sysbus.h"
66
+ * We have to use deposit for the CONS registers to preserve
57
#include "qom/object.h"
67
+ * the ERR field in the high bits.
58
+#include "hw/gpio/stm32l4x5_gpio.h"
68
+ */
59
69
+ q->cons = deposit32(q->cons, 0, q->log2size + 1, q->cons + 1);
60
#define TYPE_STM32L4X5_SYSCFG "stm32l4x5-syscfg"
70
+}
61
OBJECT_DECLARE_SIMPLE_TYPE(Stm32l4x5SyscfgState, STM32L4X5_SYSCFG)
71
+
62
72
+static inline bool smmuv3_cmdq_enabled(SMMUv3State *s)
63
-#define NUM_GPIOS 8
73
+{
64
-#define GPIO_NUM_PINS 16
74
+ return FIELD_EX32(s->cr[0], CR0, CMDQEN);
65
#define SYSCFG_NUM_EXTICR 4
75
+}
66
76
+
67
struct Stm32l4x5SyscfgState {
77
+static inline bool smmuv3_eventq_enabled(SMMUv3State *s)
68
diff --git a/hw/arm/stm32l4x5_soc.c b/hw/arm/stm32l4x5_soc.c
78
+{
69
index XXXXXXX..XXXXXXX 100644
79
+ return FIELD_EX32(s->cr[0], CR0, EVENTQEN);
70
--- a/hw/arm/stm32l4x5_soc.c
80
+}
71
+++ b/hw/arm/stm32l4x5_soc.c
81
+
72
@@ -XXX,XX +XXX,XX @@
82
+static inline void smmu_write_cmdq_err(SMMUv3State *s, uint32_t err_type)
73
#include "sysemu/sysemu.h"
83
+{
74
#include "hw/or-irq.h"
84
+ s->cmdq.cons = FIELD_DP32(s->cmdq.cons, CMDQ_CONS, ERR, err_type);
75
#include "hw/arm/stm32l4x5_soc.h"
85
+}
76
+#include "hw/gpio/stm32l4x5_gpio.h"
86
+
77
#include "hw/qdev-clock.h"
87
+void smmuv3_write_eventq(SMMUv3State *s, Evt *evt);
78
#include "hw/misc/unimp.h"
88
+
79
89
+/* Commands */
80
@@ -XXX,XX +XXX,XX @@ static const int exti_or_gate1_lines_in[EXTI_OR_GATE1_NUM_LINES_IN] = {
90
+
81
16, 35, 36, 37, 38,
91
+typedef enum SMMUCommandType {
82
};
92
+ SMMU_CMD_NONE = 0x00,
83
93
+ SMMU_CMD_PREFETCH_CONFIG ,
84
+static const struct {
94
+ SMMU_CMD_PREFETCH_ADDR,
85
+ uint32_t addr;
95
+ SMMU_CMD_CFGI_STE,
86
+ uint32_t moder_reset;
96
+ SMMU_CMD_CFGI_STE_RANGE,
87
+ uint32_t ospeedr_reset;
97
+ SMMU_CMD_CFGI_CD,
88
+ uint32_t pupdr_reset;
98
+ SMMU_CMD_CFGI_CD_ALL,
89
+} stm32l4x5_gpio_cfg[NUM_GPIOS] = {
99
+ SMMU_CMD_CFGI_ALL,
90
+ { 0x48000000, 0xABFFFFFF, 0x0C000000, 0x64000000 },
100
+ SMMU_CMD_TLBI_NH_ALL = 0x10,
91
+ { 0x48000400, 0xFFFFFEBF, 0x00000000, 0x00000100 },
101
+ SMMU_CMD_TLBI_NH_ASID,
92
+ { 0x48000800, 0xFFFFFFFF, 0x00000000, 0x00000000 },
102
+ SMMU_CMD_TLBI_NH_VA,
93
+ { 0x48000C00, 0xFFFFFFFF, 0x00000000, 0x00000000 },
103
+ SMMU_CMD_TLBI_NH_VAA,
94
+ { 0x48001000, 0xFFFFFFFF, 0x00000000, 0x00000000 },
104
+ SMMU_CMD_TLBI_EL3_ALL = 0x18,
95
+ { 0x48001400, 0xFFFFFFFF, 0x00000000, 0x00000000 },
105
+ SMMU_CMD_TLBI_EL3_VA = 0x1a,
96
+ { 0x48001800, 0xFFFFFFFF, 0x00000000, 0x00000000 },
106
+ SMMU_CMD_TLBI_EL2_ALL = 0x20,
97
+ { 0x48001C00, 0x0000000F, 0x00000000, 0x00000000 },
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
+};
98
+};
147
+
99
+
148
+static inline const char *smmu_cmd_string(SMMUCommandType type)
100
static void stm32l4x5_soc_initfn(Object *obj)
149
+{
101
{
150
+ if (type > SMMU_CMD_NONE && type < ARRAY_SIZE(cmd_stringify)) {
102
Stm32l4x5SocState *s = STM32L4X5_SOC(obj);
151
+ return cmd_stringify[type] ? cmd_stringify[type] : "UNKNOWN";
103
@@ -XXX,XX +XXX,XX @@ static void stm32l4x5_soc_initfn(Object *obj)
152
+ } else {
104
}
153
+ return "INVALID";
105
object_initialize_child(obj, "syscfg", &s->syscfg, TYPE_STM32L4X5_SYSCFG);
106
object_initialize_child(obj, "rcc", &s->rcc, TYPE_STM32L4X5_RCC);
107
+
108
+ for (unsigned i = 0; i < NUM_GPIOS; i++) {
109
+ g_autofree char *name = g_strdup_printf("gpio%c", 'a' + i);
110
+ object_initialize_child(obj, name, &s->gpio[i], TYPE_STM32L4X5_GPIO);
154
+ }
111
+ }
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
}
112
}
203
113
204
+static inline MemTxResult queue_read(SMMUQueue *q, void *data)
114
static void stm32l4x5_soc_realize(DeviceState *dev_soc, Error **errp)
205
+{
115
@@ -XXX,XX +XXX,XX @@ static void stm32l4x5_soc_realize(DeviceState *dev_soc, Error **errp)
206
+ dma_addr_t addr = Q_CONS_ENTRY(q);
116
Stm32l4x5SocState *s = STM32L4X5_SOC(dev_soc);
207
+
117
const Stm32l4x5SocClass *sc = STM32L4X5_SOC_GET_CLASS(dev_soc);
208
+ return dma_memory_read(&address_space_memory, addr, data, q->entry_size);
118
MemoryRegion *system_memory = get_system_memory();
209
+}
119
- DeviceState *armv7m;
210
+
120
+ DeviceState *armv7m, *dev;
211
+static MemTxResult queue_write(SMMUQueue *q, void *data)
121
SysBusDevice *busdev;
212
+{
122
+ uint32_t pin_index;
213
+ dma_addr_t addr = Q_PROD_ENTRY(q);
123
214
+ MemTxResult ret;
124
if (!memory_region_init_rom(&s->flash, OBJECT(dev_soc), "flash",
215
+
125
sc->flash_size, errp)) {
216
+ ret = dma_memory_write(&address_space_memory, addr, data, q->entry_size);
126
@@ -XXX,XX +XXX,XX @@ static void stm32l4x5_soc_realize(DeviceState *dev_soc, Error **errp)
217
+ if (ret != MEMTX_OK) {
127
return;
218
+ return ret;
128
}
129
130
+ /* GPIOs */
131
+ for (unsigned i = 0; i < NUM_GPIOS; i++) {
132
+ g_autofree char *name = g_strdup_printf("%c", 'A' + i);
133
+ dev = DEVICE(&s->gpio[i]);
134
+ qdev_prop_set_string(dev, "name", name);
135
+ qdev_prop_set_uint32(dev, "mode-reset",
136
+ stm32l4x5_gpio_cfg[i].moder_reset);
137
+ qdev_prop_set_uint32(dev, "ospeed-reset",
138
+ stm32l4x5_gpio_cfg[i].ospeedr_reset);
139
+ qdev_prop_set_uint32(dev, "pupd-reset",
140
+ stm32l4x5_gpio_cfg[i].pupdr_reset);
141
+ busdev = SYS_BUS_DEVICE(&s->gpio[i]);
142
+ g_free(name);
143
+ name = g_strdup_printf("gpio%c-out", 'a' + i);
144
+ qdev_connect_clock_in(DEVICE(&s->gpio[i]), "clk",
145
+ qdev_get_clock_out(DEVICE(&(s->rcc)), name));
146
+ if (!sysbus_realize(busdev, errp)) {
147
+ return;
148
+ }
149
+ sysbus_mmio_map(busdev, 0, stm32l4x5_gpio_cfg[i].addr);
219
+ }
150
+ }
220
+
151
+
221
+ queue_prod_incr(q);
152
/* System configuration controller */
222
+ return MEMTX_OK;
153
busdev = SYS_BUS_DEVICE(&s->syscfg);
223
+}
154
if (!sysbus_realize(busdev, errp)) {
224
+
155
return;
225
+void smmuv3_write_eventq(SMMUv3State *s, Evt *evt)
156
}
226
+{
157
sysbus_mmio_map(busdev, 0, SYSCFG_ADDR);
227
+ SMMUQueue *q = &s->eventq;
158
- /*
228
+
159
- * TODO: when the GPIO device is implemented, connect it
229
+ if (!smmuv3_eventq_enabled(s)) {
160
- * to SYCFG using `qdev_connect_gpio_out`, NUM_GPIOS and
230
+ return;
161
- * GPIO_NUM_PINS.
162
- */
163
+
164
+ for (unsigned i = 0; i < NUM_GPIOS; i++) {
165
+ for (unsigned j = 0; j < GPIO_NUM_PINS; j++) {
166
+ pin_index = GPIO_NUM_PINS * i + j;
167
+ qdev_connect_gpio_out(DEVICE(&s->gpio[i]), j,
168
+ qdev_get_gpio_in(DEVICE(&s->syscfg),
169
+ pin_index));
170
+ }
231
+ }
171
+ }
232
+
172
233
+ if (smmuv3_q_full(q)) {
173
/* EXTI device */
234
+ return;
174
busdev = SYS_BUS_DEVICE(&s->exti);
235
+ }
175
@@ -XXX,XX +XXX,XX @@ static void stm32l4x5_soc_realize(DeviceState *dev_soc, Error **errp)
236
+
176
}
237
+ queue_write(q, evt);
177
}
238
+
178
239
+ if (smmuv3_q_empty(q)) {
179
- for (unsigned i = 0; i < 16; i++) {
240
+ smmuv3_trigger_irq(s, SMMU_IRQ_EVTQ, 0);
180
+ for (unsigned i = 0; i < GPIO_NUM_PINS; i++) {
241
+ }
181
qdev_connect_gpio_out(DEVICE(&s->syscfg), i,
242
+}
182
qdev_get_gpio_in(DEVICE(&s->exti), i));
243
+
183
}
244
static void smmuv3_init_regs(SMMUv3State *s)
184
@@ -XXX,XX +XXX,XX @@ static void stm32l4x5_soc_realize(DeviceState *dev_soc, Error **errp)
245
{
185
/* RESERVED: 0x40024400, 0x7FDBC00 */
246
/**
186
247
@@ -XXX,XX +XXX,XX @@ static void smmuv3_init_regs(SMMUv3State *s)
187
/* AHB2 BUS */
248
s->sid_split = 0;
188
- create_unimplemented_device("GPIOA", 0x48000000, 0x400);
249
}
189
- create_unimplemented_device("GPIOB", 0x48000400, 0x400);
250
190
- create_unimplemented_device("GPIOC", 0x48000800, 0x400);
251
+int smmuv3_cmdq_consume(SMMUv3State *s)
191
- create_unimplemented_device("GPIOD", 0x48000C00, 0x400);
252
+{
192
- create_unimplemented_device("GPIOE", 0x48001000, 0x400);
253
+ SMMUCmdError cmd_error = SMMU_CERROR_NONE;
193
- create_unimplemented_device("GPIOF", 0x48001400, 0x400);
254
+ SMMUQueue *q = &s->cmdq;
194
- create_unimplemented_device("GPIOG", 0x48001800, 0x400);
255
+ SMMUCommandType type = 0;
195
- create_unimplemented_device("GPIOH", 0x48001C00, 0x400);
256
+
196
/* RESERVED: 0x48002000, 0x7FDBC00 */
257
+ if (!smmuv3_cmdq_enabled(s)) {
197
create_unimplemented_device("OTG_FS", 0x50000000, 0x40000);
258
+ return 0;
198
create_unimplemented_device("ADC", 0x50040000, 0x400);
259
+ }
199
diff --git a/hw/misc/stm32l4x5_syscfg.c b/hw/misc/stm32l4x5_syscfg.c
260
+ /*
200
index XXXXXXX..XXXXXXX 100644
261
+ * some commands depend on register values, typically CR0. In case those
201
--- a/hw/misc/stm32l4x5_syscfg.c
262
+ * register values change while handling the command, spec says it
202
+++ b/hw/misc/stm32l4x5_syscfg.c
263
+ * is UNPREDICTABLE whether the command is interpreted under the new
203
@@ -XXX,XX +XXX,XX @@
264
+ * or old value.
204
#include "hw/irq.h"
265
+ */
205
#include "migration/vmstate.h"
266
+
206
#include "hw/misc/stm32l4x5_syscfg.h"
267
+ while (!smmuv3_q_empty(q)) {
207
+#include "hw/gpio/stm32l4x5_gpio.h"
268
+ uint32_t pending = s->gerror ^ s->gerrorn;
208
269
+ Cmd cmd;
209
#define SYSCFG_MEMRMP 0x00
270
+
210
#define SYSCFG_CFGR1 0x04
271
+ trace_smmuv3_cmdq_consume(Q_PROD(q), Q_CONS(q),
211
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
272
+ Q_PROD_WRAP(q), Q_CONS_WRAP(q));
212
index XXXXXXX..XXXXXXX 100644
273
+
213
--- a/hw/arm/Kconfig
274
+ if (FIELD_EX32(pending, GERROR, CMDQ_ERR)) {
214
+++ b/hw/arm/Kconfig
275
+ break;
215
@@ -XXX,XX +XXX,XX @@ config STM32L4X5_SOC
276
+ }
216
bool
277
+
217
select ARM_V7M
278
+ if (queue_read(q, &cmd) != MEMTX_OK) {
218
select OR_IRQ
279
+ cmd_error = SMMU_CERROR_ABT;
219
- select STM32L4X5_SYSCFG
280
+ break;
220
select STM32L4X5_EXTI
281
+ }
221
+ select STM32L4X5_SYSCFG
282
+
222
select STM32L4X5_RCC
283
+ type = CMD_TYPE(&cmd);
223
+ select STM32L4X5_GPIO
284
+
224
285
+ trace_smmuv3_cmdq_opcode(smmu_cmd_string(type));
225
config XLNX_ZYNQMP_ARM
286
+
226
bool
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
--
227
--
364
2.17.0
228
2.34.1
365
229
366
230
diff view generated by jsdifflib
1
From: Eric Auger <eric.auger@redhat.com>
1
From: Inès Varhol <ines.varhol@telecom-paris.fr>
2
2
3
The patch introduces the smmu base device and class for the ARM
3
The testcase contains :
4
smmu. Devices for specific versions will be derived from this
4
- `test_idr_reset_value()` :
5
base device.
5
Checks the reset values of MODER, OTYPER, PUPDR, ODR and IDR.
6
- `test_gpio_output_mode()` :
7
Checks that writing a bit in register ODR results in the corresponding
8
pin rising or lowering, if this pin is configured in output mode.
9
- `test_gpio_input_mode()` :
10
Checks that a input pin set high or low externally results
11
in the pin rising and lowering.
12
- `test_pull_up_pull_down()` :
13
Checks that a floating pin in pull-up/down mode is actually high/down.
14
- `test_push_pull()` :
15
Checks that a pin set externally is disconnected when configured in
16
push-pull output mode, and can't be set externally while in this mode.
17
- `test_open_drain()` :
18
Checks that a pin set externally high is disconnected when configured
19
in open-drain output mode, and can't be set high while in this mode.
20
- `test_bsrr_brr()` :
21
Checks that writing to BSRR and BRR has the desired result in ODR.
22
- `test_clock_enable()` :
23
Checks that GPIO clock is at the right frequency after enabling it.
6
24
7
We also introduce some important datatypes.
25
Acked-by: Thomas Huth <thuth@redhat.com>
8
26
Signed-off-by: Arnaud Minier <arnaud.minier@telecom-paris.fr>
9
Signed-off-by: Eric Auger <eric.auger@redhat.com>
27
Signed-off-by: Inès Varhol <ines.varhol@telecom-paris.fr>
10
Signed-off-by: Prem Mallappa <prem.mallappa@broadcom.com>
28
Message-id: 20240305210444.310665-4-ines.varhol@telecom-paris.fr
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>
29
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
30
---
15
hw/arm/Makefile.objs | 1 +
31
tests/qtest/stm32l4x5_gpio-test.c | 551 ++++++++++++++++++++++++++++++
16
include/hw/arm/smmu-common.h | 123 ++++++++++++++++++++++++++++
32
tests/qtest/meson.build | 3 +-
17
hw/arm/smmu-common.c | 81 ++++++++++++++++++
33
2 files changed, 553 insertions(+), 1 deletion(-)
18
default-configs/aarch64-softmmu.mak | 1 +
34
create mode 100644 tests/qtest/stm32l4x5_gpio-test.c
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
35
23
diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
36
diff --git a/tests/qtest/stm32l4x5_gpio-test.c b/tests/qtest/stm32l4x5_gpio-test.c
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
37
new file mode 100644
34
index XXXXXXX..XXXXXXX
38
index XXXXXXX..XXXXXXX
35
--- /dev/null
39
--- /dev/null
36
+++ b/include/hw/arm/smmu-common.h
40
+++ b/tests/qtest/stm32l4x5_gpio-test.c
37
@@ -XXX,XX +XXX,XX @@
41
@@ -XXX,XX +XXX,XX @@
38
+/*
42
+/*
39
+ * ARM SMMU Support
43
+ * QTest testcase for STM32L4x5_GPIO
40
+ *
44
+ *
41
+ * Copyright (C) 2015-2016 Broadcom Corporation
45
+ * Copyright (c) 2024 Arnaud Minier <arnaud.minier@telecom-paris.fr>
42
+ * Copyright (c) 2017 Red Hat, Inc.
46
+ * Copyright (c) 2024 Inès Varhol <ines.varhol@telecom-paris.fr>
43
+ * Written by Prem Mallappa, Eric Auger
44
+ *
47
+ *
45
+ * This program is free software; you can redistribute it and/or modify
48
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
46
+ * it under the terms of the GNU General Public License version 2 as
49
+ * See the COPYING file in the top-level directory.
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
+ */
50
+ */
55
+
51
+
56
+#ifndef HW_ARM_SMMU_COMMON_H
57
+#define HW_ARM_SMMU_COMMON_H
58
+
59
+#include "hw/sysbus.h"
60
+#include "hw/pci/pci.h"
61
+
62
+#define SMMU_PCI_BUS_MAX 256
63
+#define SMMU_PCI_DEVFN_MAX 256
64
+
65
+#define SMMU_MAX_VA_BITS 48
66
+
67
+/*
68
+ * Page table walk error types
69
+ */
70
+typedef enum {
71
+ SMMU_PTW_ERR_NONE,
72
+ SMMU_PTW_ERR_WALK_EABT, /* Translation walk external abort */
73
+ SMMU_PTW_ERR_TRANSLATION, /* Translation fault */
74
+ SMMU_PTW_ERR_ADDR_SIZE, /* Address Size fault */
75
+ SMMU_PTW_ERR_ACCESS, /* Access fault */
76
+ SMMU_PTW_ERR_PERMISSION, /* Permission fault */
77
+} SMMUPTWEventType;
78
+
79
+typedef struct SMMUPTWEventInfo {
80
+ SMMUPTWEventType type;
81
+ dma_addr_t addr; /* fetched address that induced an abort, if any */
82
+} SMMUPTWEventInfo;
83
+
84
+typedef struct SMMUTransTableInfo {
85
+ bool disabled; /* is the translation table disabled? */
86
+ uint64_t ttb; /* TT base address */
87
+ uint8_t tsz; /* input range, ie. 2^(64 -tsz)*/
88
+ uint8_t granule_sz; /* granule page shift */
89
+} SMMUTransTableInfo;
90
+
91
+/*
92
+ * Generic structure populated by derived SMMU devices
93
+ * after decoding the configuration information and used as
94
+ * input to the page table walk
95
+ */
96
+typedef struct SMMUTransCfg {
97
+ int stage; /* translation stage */
98
+ bool aa64; /* arch64 or aarch32 translation table */
99
+ bool disabled; /* smmu is disabled */
100
+ bool bypassed; /* translation is bypassed */
101
+ bool aborted; /* translation is aborted */
102
+ uint64_t ttb; /* TT base address */
103
+ uint8_t oas; /* output address width */
104
+ uint8_t tbi; /* Top Byte Ignore */
105
+ uint16_t asid;
106
+ SMMUTransTableInfo tt[2];
107
+} SMMUTransCfg;
108
+
109
+typedef struct SMMUDevice {
110
+ void *smmu;
111
+ PCIBus *bus;
112
+ int devfn;
113
+ IOMMUMemoryRegion iommu;
114
+ AddressSpace as;
115
+} SMMUDevice;
116
+
117
+typedef struct SMMUNotifierNode {
118
+ SMMUDevice *sdev;
119
+ QLIST_ENTRY(SMMUNotifierNode) next;
120
+} SMMUNotifierNode;
121
+
122
+typedef struct SMMUPciBus {
123
+ PCIBus *bus;
124
+ SMMUDevice *pbdev[0]; /* Parent array is sparse, so dynamically alloc */
125
+} SMMUPciBus;
126
+
127
+typedef struct SMMUState {
128
+ /* <private> */
129
+ SysBusDevice dev;
130
+ const char *mrtypename;
131
+ MemoryRegion iomem;
132
+
133
+ GHashTable *smmu_pcibus_by_busptr;
134
+ GHashTable *configs; /* cache for configuration data */
135
+ GHashTable *iotlb;
136
+ SMMUPciBus *smmu_pcibus_by_bus_num[SMMU_PCI_BUS_MAX];
137
+ PCIBus *pci_bus;
138
+ QLIST_HEAD(, SMMUNotifierNode) notifiers_list;
139
+ uint8_t bus_num;
140
+ PCIBus *primary_bus;
141
+} SMMUState;
142
+
143
+typedef struct {
144
+ /* <private> */
145
+ SysBusDeviceClass parent_class;
146
+
147
+ /*< public >*/
148
+
149
+ DeviceRealize parent_realize;
150
+
151
+} SMMUBaseClass;
152
+
153
+#define TYPE_ARM_SMMU "arm-smmu"
154
+#define ARM_SMMU(obj) OBJECT_CHECK(SMMUState, (obj), TYPE_ARM_SMMU)
155
+#define ARM_SMMU_CLASS(klass) \
156
+ OBJECT_CLASS_CHECK(SMMUBaseClass, (klass), TYPE_ARM_SMMU)
157
+#define ARM_SMMU_GET_CLASS(obj) \
158
+ OBJECT_GET_CLASS(SMMUBaseClass, (obj), TYPE_ARM_SMMU)
159
+
160
+#endif /* HW_ARM_SMMU_COMMON */
161
diff --git a/hw/arm/smmu-common.c b/hw/arm/smmu-common.c
162
new file mode 100644
163
index XXXXXXX..XXXXXXX
164
--- /dev/null
165
+++ b/hw/arm/smmu-common.c
166
@@ -XXX,XX +XXX,XX @@
167
+/*
168
+ * Copyright (C) 2014-2016 Broadcom Corporation
169
+ * Copyright (c) 2017 Red Hat, Inc.
170
+ * Written by Prem Mallappa, Eric Auger
171
+ *
172
+ * This program is free software; you can redistribute it and/or modify
173
+ * it under the terms of the GNU General Public License version 2 as
174
+ * published by the Free Software Foundation.
175
+ *
176
+ * This program is distributed in the hope that it will be useful,
177
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
178
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
179
+ * GNU General Public License for more details.
180
+ *
181
+ * Author: Prem Mallappa <pmallapp@broadcom.com>
182
+ *
183
+ */
184
+
185
+#include "qemu/osdep.h"
52
+#include "qemu/osdep.h"
186
+#include "sysemu/sysemu.h"
53
+#include "libqtest-single.h"
187
+#include "exec/address-spaces.h"
54
+
188
+#include "trace.h"
55
+#define GPIO_BASE_ADDR 0x48000000
189
+#include "exec/target_page.h"
56
+#define GPIO_SIZE 0x400
190
+#include "qom/cpu.h"
57
+#define NUM_GPIOS 8
191
+#include "hw/qdev-properties.h"
58
+#define NUM_GPIO_PINS 16
192
+#include "qapi/error.h"
59
+
193
+
60
+#define GPIO_A 0x48000000
194
+#include "qemu/error-report.h"
61
+#define GPIO_B 0x48000400
195
+#include "hw/arm/smmu-common.h"
62
+#define GPIO_C 0x48000800
196
+
63
+#define GPIO_D 0x48000C00
197
+static void smmu_base_realize(DeviceState *dev, Error **errp)
64
+#define GPIO_E 0x48001000
198
+{
65
+#define GPIO_F 0x48001400
199
+ SMMUBaseClass *sbc = ARM_SMMU_GET_CLASS(dev);
66
+#define GPIO_G 0x48001800
200
+ Error *local_err = NULL;
67
+#define GPIO_H 0x48001C00
201
+
68
+
202
+ sbc->parent_realize(dev, &local_err);
69
+#define MODER 0x00
203
+ if (local_err) {
70
+#define OTYPER 0x04
204
+ error_propagate(errp, local_err);
71
+#define PUPDR 0x0C
205
+ return;
72
+#define IDR 0x10
73
+#define ODR 0x14
74
+#define BSRR 0x18
75
+#define BRR 0x28
76
+
77
+#define MODER_INPUT 0
78
+#define MODER_OUTPUT 1
79
+
80
+#define PUPDR_NONE 0
81
+#define PUPDR_PULLUP 1
82
+#define PUPDR_PULLDOWN 2
83
+
84
+#define OTYPER_PUSH_PULL 0
85
+#define OTYPER_OPEN_DRAIN 1
86
+
87
+const uint32_t moder_reset[NUM_GPIOS] = {
88
+ 0xABFFFFFF,
89
+ 0xFFFFFEBF,
90
+ 0xFFFFFFFF,
91
+ 0xFFFFFFFF,
92
+ 0xFFFFFFFF,
93
+ 0xFFFFFFFF,
94
+ 0xFFFFFFFF,
95
+ 0x0000000F
96
+};
97
+
98
+const uint32_t pupdr_reset[NUM_GPIOS] = {
99
+ 0x64000000,
100
+ 0x00000100,
101
+ 0x00000000,
102
+ 0x00000000,
103
+ 0x00000000,
104
+ 0x00000000,
105
+ 0x00000000,
106
+ 0x00000000
107
+};
108
+
109
+const uint32_t idr_reset[NUM_GPIOS] = {
110
+ 0x0000A000,
111
+ 0x00000010,
112
+ 0x00000000,
113
+ 0x00000000,
114
+ 0x00000000,
115
+ 0x00000000,
116
+ 0x00000000,
117
+ 0x00000000
118
+};
119
+
120
+static uint32_t gpio_readl(unsigned int gpio, unsigned int offset)
121
+{
122
+ return readl(gpio + offset);
123
+}
124
+
125
+static void gpio_writel(unsigned int gpio, unsigned int offset, uint32_t value)
126
+{
127
+ writel(gpio + offset, value);
128
+}
129
+
130
+static void gpio_set_bit(unsigned int gpio, unsigned int reg,
131
+ unsigned int pin, uint32_t value)
132
+{
133
+ uint32_t mask = 0xFFFFFFFF & ~(0x1 << pin);
134
+ gpio_writel(gpio, reg, (gpio_readl(gpio, reg) & mask) | value << pin);
135
+}
136
+
137
+static void gpio_set_2bits(unsigned int gpio, unsigned int reg,
138
+ unsigned int pin, uint32_t value)
139
+{
140
+ uint32_t offset = 2 * pin;
141
+ uint32_t mask = 0xFFFFFFFF & ~(0x3 << offset);
142
+ gpio_writel(gpio, reg, (gpio_readl(gpio, reg) & mask) | value << offset);
143
+}
144
+
145
+static unsigned int get_gpio_id(uint32_t gpio_addr)
146
+{
147
+ return (gpio_addr - GPIO_BASE_ADDR) / GPIO_SIZE;
148
+}
149
+
150
+static void gpio_set_irq(unsigned int gpio, int num, int level)
151
+{
152
+ g_autofree char *name = g_strdup_printf("/machine/soc/gpio%c",
153
+ get_gpio_id(gpio) + 'a');
154
+ qtest_set_irq_in(global_qtest, name, NULL, num, level);
155
+}
156
+
157
+static void disconnect_all_pins(unsigned int gpio)
158
+{
159
+ g_autofree char *path = g_strdup_printf("/machine/soc/gpio%c",
160
+ get_gpio_id(gpio) + 'a');
161
+ QDict *r;
162
+
163
+ r = qtest_qmp(global_qtest, "{ 'execute': 'qom-set', 'arguments': "
164
+ "{ 'path': %s, 'property': 'disconnected-pins', 'value': %d } }",
165
+ path, 0xFFFF);
166
+ g_assert_false(qdict_haskey(r, "error"));
167
+ qobject_unref(r);
168
+}
169
+
170
+static uint32_t get_disconnected_pins(unsigned int gpio)
171
+{
172
+ g_autofree char *path = g_strdup_printf("/machine/soc/gpio%c",
173
+ get_gpio_id(gpio) + 'a');
174
+ uint32_t disconnected_pins = 0;
175
+ QDict *r;
176
+
177
+ r = qtest_qmp(global_qtest, "{ 'execute': 'qom-get', 'arguments':"
178
+ " { 'path': %s, 'property': 'disconnected-pins'} }", path);
179
+ g_assert_false(qdict_haskey(r, "error"));
180
+ disconnected_pins = qdict_get_int(r, "return");
181
+ qobject_unref(r);
182
+ return disconnected_pins;
183
+}
184
+
185
+static uint32_t reset(uint32_t gpio, unsigned int offset)
186
+{
187
+ switch (offset) {
188
+ case MODER:
189
+ return moder_reset[get_gpio_id(gpio)];
190
+ case PUPDR:
191
+ return pupdr_reset[get_gpio_id(gpio)];
192
+ case IDR:
193
+ return idr_reset[get_gpio_id(gpio)];
206
+ }
194
+ }
207
+}
195
+ return 0x0;
208
+
196
+}
209
+static void smmu_base_reset(DeviceState *dev)
197
+
210
+{
198
+static void system_reset(void)
211
+ /* will be filled later on */
199
+{
212
+}
200
+ QDict *r;
213
+
201
+ r = qtest_qmp(global_qtest, "{'execute': 'system_reset'}");
214
+static Property smmu_dev_properties[] = {
202
+ g_assert_false(qdict_haskey(r, "error"));
215
+ DEFINE_PROP_UINT8("bus_num", SMMUState, bus_num, 0),
203
+ qobject_unref(r);
216
+ DEFINE_PROP_LINK("primary-bus", SMMUState, primary_bus, "PCI", PCIBus *),
204
+}
217
+ DEFINE_PROP_END_OF_LIST(),
205
+
218
+};
206
+static void test_idr_reset_value(void)
219
+
207
+{
220
+static void smmu_base_class_init(ObjectClass *klass, void *data)
208
+ /*
221
+{
209
+ * Checks that the values in MODER, OTYPER, PUPDR and ODR
222
+ DeviceClass *dc = DEVICE_CLASS(klass);
210
+ * after reset are correct, and that the value in IDR is
223
+ SMMUBaseClass *sbc = ARM_SMMU_CLASS(klass);
211
+ * coherent.
224
+
212
+ * Since AF and analog modes aren't implemented, IDR reset
225
+ dc->props = smmu_dev_properties;
213
+ * values aren't the same as with a real board.
226
+ device_class_set_parent_realize(dc, smmu_base_realize,
214
+ *
227
+ &sbc->parent_realize);
215
+ * Register IDR contains the actual values of all GPIO pins.
228
+ dc->reset = smmu_base_reset;
216
+ * Its value depends on the pins' configuration
229
+}
217
+ * (intput/output/analog : register MODER, push-pull/open-drain :
230
+
218
+ * register OTYPER, pull-up/pull-down/none : register PUPDR)
231
+static const TypeInfo smmu_base_info = {
219
+ * and on the values stored in register ODR
232
+ .name = TYPE_ARM_SMMU,
220
+ * (in case the pin is in output mode).
233
+ .parent = TYPE_SYS_BUS_DEVICE,
221
+ */
234
+ .instance_size = sizeof(SMMUState),
222
+
235
+ .class_data = NULL,
223
+ gpio_writel(GPIO_A, MODER, 0xDEADBEEF);
236
+ .class_size = sizeof(SMMUBaseClass),
224
+ gpio_writel(GPIO_A, ODR, 0xDEADBEEF);
237
+ .class_init = smmu_base_class_init,
225
+ gpio_writel(GPIO_A, OTYPER, 0xDEADBEEF);
238
+ .abstract = true,
226
+ gpio_writel(GPIO_A, PUPDR, 0xDEADBEEF);
239
+};
227
+
240
+
228
+ gpio_writel(GPIO_B, MODER, 0xDEADBEEF);
241
+static void smmu_base_register_types(void)
229
+ gpio_writel(GPIO_B, ODR, 0xDEADBEEF);
242
+{
230
+ gpio_writel(GPIO_B, OTYPER, 0xDEADBEEF);
243
+ type_register_static(&smmu_base_info);
231
+ gpio_writel(GPIO_B, PUPDR, 0xDEADBEEF);
244
+}
232
+
245
+
233
+ gpio_writel(GPIO_C, MODER, 0xDEADBEEF);
246
+type_init(smmu_base_register_types)
234
+ gpio_writel(GPIO_C, ODR, 0xDEADBEEF);
247
+
235
+ gpio_writel(GPIO_C, OTYPER, 0xDEADBEEF);
248
diff --git a/default-configs/aarch64-softmmu.mak b/default-configs/aarch64-softmmu.mak
236
+ gpio_writel(GPIO_C, PUPDR, 0xDEADBEEF);
237
+
238
+ gpio_writel(GPIO_H, MODER, 0xDEADBEEF);
239
+ gpio_writel(GPIO_H, ODR, 0xDEADBEEF);
240
+ gpio_writel(GPIO_H, OTYPER, 0xDEADBEEF);
241
+ gpio_writel(GPIO_H, PUPDR, 0xDEADBEEF);
242
+
243
+ system_reset();
244
+
245
+ uint32_t moder = gpio_readl(GPIO_A, MODER);
246
+ uint32_t odr = gpio_readl(GPIO_A, ODR);
247
+ uint32_t otyper = gpio_readl(GPIO_A, OTYPER);
248
+ uint32_t pupdr = gpio_readl(GPIO_A, PUPDR);
249
+ uint32_t idr = gpio_readl(GPIO_A, IDR);
250
+ /* 15: AF, 14: AF, 13: AF, 12: Analog ... */
251
+ /* here AF is the same as Analog and Input mode */
252
+ g_assert_cmphex(moder, ==, reset(GPIO_A, MODER));
253
+ g_assert_cmphex(odr, ==, reset(GPIO_A, ODR));
254
+ g_assert_cmphex(otyper, ==, reset(GPIO_A, OTYPER));
255
+ /* 15: pull-up, 14: pull-down, 13: pull-up, 12: neither ... */
256
+ g_assert_cmphex(pupdr, ==, reset(GPIO_A, PUPDR));
257
+ /* 15 : 1, 14: 0, 13: 1, 12 : reset value ... */
258
+ g_assert_cmphex(idr, ==, reset(GPIO_A, IDR));
259
+
260
+ moder = gpio_readl(GPIO_B, MODER);
261
+ odr = gpio_readl(GPIO_B, ODR);
262
+ otyper = gpio_readl(GPIO_B, OTYPER);
263
+ pupdr = gpio_readl(GPIO_B, PUPDR);
264
+ idr = gpio_readl(GPIO_B, IDR);
265
+ /* ... 5: Analog, 4: AF, 3: AF, 2: Analog ... */
266
+ /* here AF is the same as Analog and Input mode */
267
+ g_assert_cmphex(moder, ==, reset(GPIO_B, MODER));
268
+ g_assert_cmphex(odr, ==, reset(GPIO_B, ODR));
269
+ g_assert_cmphex(otyper, ==, reset(GPIO_B, OTYPER));
270
+ /* ... 5: neither, 4: pull-up, 3: neither ... */
271
+ g_assert_cmphex(pupdr, ==, reset(GPIO_B, PUPDR));
272
+ /* ... 5 : reset value, 4 : 1, 3 : reset value ... */
273
+ g_assert_cmphex(idr, ==, reset(GPIO_B, IDR));
274
+
275
+ moder = gpio_readl(GPIO_C, MODER);
276
+ odr = gpio_readl(GPIO_C, ODR);
277
+ otyper = gpio_readl(GPIO_C, OTYPER);
278
+ pupdr = gpio_readl(GPIO_C, PUPDR);
279
+ idr = gpio_readl(GPIO_C, IDR);
280
+ /* Analog, same as Input mode*/
281
+ g_assert_cmphex(moder, ==, reset(GPIO_C, MODER));
282
+ g_assert_cmphex(odr, ==, reset(GPIO_C, ODR));
283
+ g_assert_cmphex(otyper, ==, reset(GPIO_C, OTYPER));
284
+ /* no pull-up or pull-down */
285
+ g_assert_cmphex(pupdr, ==, reset(GPIO_C, PUPDR));
286
+ /* reset value */
287
+ g_assert_cmphex(idr, ==, reset(GPIO_C, IDR));
288
+
289
+ moder = gpio_readl(GPIO_H, MODER);
290
+ odr = gpio_readl(GPIO_H, ODR);
291
+ otyper = gpio_readl(GPIO_H, OTYPER);
292
+ pupdr = gpio_readl(GPIO_H, PUPDR);
293
+ idr = gpio_readl(GPIO_H, IDR);
294
+ /* Analog, same as Input mode */
295
+ g_assert_cmphex(moder, ==, reset(GPIO_H, MODER));
296
+ g_assert_cmphex(odr, ==, reset(GPIO_H, ODR));
297
+ g_assert_cmphex(otyper, ==, reset(GPIO_H, OTYPER));
298
+ /* no pull-up or pull-down */
299
+ g_assert_cmphex(pupdr, ==, reset(GPIO_H, PUPDR));
300
+ /* reset value */
301
+ g_assert_cmphex(idr, ==, reset(GPIO_H, IDR));
302
+}
303
+
304
+static void test_gpio_output_mode(const void *data)
305
+{
306
+ /*
307
+ * Checks that setting a bit in ODR sets the corresponding
308
+ * GPIO line high : it should set the right bit in IDR
309
+ * and send an irq to syscfg.
310
+ * Additionally, it checks that values written to ODR
311
+ * when not in output mode are stored and not discarded.
312
+ */
313
+ unsigned int pin = ((uint64_t)data) & 0xF;
314
+ uint32_t gpio = ((uint64_t)data) >> 32;
315
+ unsigned int gpio_id = get_gpio_id(gpio);
316
+
317
+ qtest_irq_intercept_in(global_qtest, "/machine/soc/syscfg");
318
+
319
+ /* Set a bit in ODR and check nothing happens */
320
+ gpio_set_bit(gpio, ODR, pin, 1);
321
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR));
322
+ g_assert_false(get_irq(gpio_id * NUM_GPIO_PINS + pin));
323
+
324
+ /* Configure the relevant line as output and check the pin is high */
325
+ gpio_set_2bits(gpio, MODER, pin, MODER_OUTPUT);
326
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) | (1 << pin));
327
+ g_assert_true(get_irq(gpio_id * NUM_GPIO_PINS + pin));
328
+
329
+ /* Reset the bit in ODR and check the pin is low */
330
+ gpio_set_bit(gpio, ODR, pin, 0);
331
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) & ~(1 << pin));
332
+ g_assert_false(get_irq(gpio_id * NUM_GPIO_PINS + pin));
333
+
334
+ /* Clean the test */
335
+ gpio_writel(gpio, ODR, reset(gpio, ODR));
336
+ gpio_writel(gpio, MODER, reset(gpio, MODER));
337
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR));
338
+ g_assert_false(get_irq(gpio_id * NUM_GPIO_PINS + pin));
339
+}
340
+
341
+static void test_gpio_input_mode(const void *data)
342
+{
343
+ /*
344
+ * Test that setting a line high/low externally sets the
345
+ * corresponding GPIO line high/low : it should set the
346
+ * right bit in IDR and send an irq to syscfg.
347
+ */
348
+ unsigned int pin = ((uint64_t)data) & 0xF;
349
+ uint32_t gpio = ((uint64_t)data) >> 32;
350
+ unsigned int gpio_id = get_gpio_id(gpio);
351
+
352
+ qtest_irq_intercept_in(global_qtest, "/machine/soc/syscfg");
353
+
354
+ /* Configure a line as input, raise it, and check that the pin is high */
355
+ gpio_set_2bits(gpio, MODER, pin, MODER_INPUT);
356
+ gpio_set_irq(gpio, pin, 1);
357
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) | (1 << pin));
358
+ g_assert_true(get_irq(gpio_id * NUM_GPIO_PINS + pin));
359
+
360
+ /* Lower the line and check that the pin is low */
361
+ gpio_set_irq(gpio, pin, 0);
362
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) & ~(1 << pin));
363
+ g_assert_false(get_irq(gpio_id * NUM_GPIO_PINS + pin));
364
+
365
+ /* Clean the test */
366
+ gpio_writel(gpio, MODER, reset(gpio, MODER));
367
+ disconnect_all_pins(gpio);
368
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR));
369
+}
370
+
371
+static void test_pull_up_pull_down(const void *data)
372
+{
373
+ /*
374
+ * Test that a floating pin with pull-up sets the pin
375
+ * high and vice-versa.
376
+ */
377
+ unsigned int pin = ((uint64_t)data) & 0xF;
378
+ uint32_t gpio = ((uint64_t)data) >> 32;
379
+ unsigned int gpio_id = get_gpio_id(gpio);
380
+
381
+ qtest_irq_intercept_in(global_qtest, "/machine/soc/syscfg");
382
+
383
+ /* Configure a line as input with pull-up, check the line is set high */
384
+ gpio_set_2bits(gpio, MODER, pin, MODER_INPUT);
385
+ gpio_set_2bits(gpio, PUPDR, pin, PUPDR_PULLUP);
386
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) | (1 << pin));
387
+ g_assert_true(get_irq(gpio_id * NUM_GPIO_PINS + pin));
388
+
389
+ /* Configure the line with pull-down, check the line is low */
390
+ gpio_set_2bits(gpio, PUPDR, pin, PUPDR_PULLDOWN);
391
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) & ~(1 << pin));
392
+ g_assert_false(get_irq(gpio_id * NUM_GPIO_PINS + pin));
393
+
394
+ /* Clean the test */
395
+ gpio_writel(gpio, MODER, reset(gpio, MODER));
396
+ gpio_writel(gpio, PUPDR, reset(gpio, PUPDR));
397
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR));
398
+}
399
+
400
+static void test_push_pull(const void *data)
401
+{
402
+ /*
403
+ * Test that configuring a line in push-pull output mode
404
+ * disconnects the pin, that the pin can't be set or reset
405
+ * externally afterwards.
406
+ */
407
+ unsigned int pin = ((uint64_t)data) & 0xF;
408
+ uint32_t gpio = ((uint64_t)data) >> 32;
409
+ uint32_t gpio2 = GPIO_BASE_ADDR + (GPIO_H - gpio);
410
+
411
+ qtest_irq_intercept_in(global_qtest, "/machine/soc/syscfg");
412
+
413
+ /* Setting a line high externally, configuring it in push-pull output */
414
+ /* And checking the pin was disconnected */
415
+ gpio_set_irq(gpio, pin, 1);
416
+ gpio_set_2bits(gpio, MODER, pin, MODER_OUTPUT);
417
+ g_assert_cmphex(get_disconnected_pins(gpio), ==, 0xFFFF);
418
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) & ~(1 << pin));
419
+
420
+ /* Setting a line low externally, configuring it in push-pull output */
421
+ /* And checking the pin was disconnected */
422
+ gpio_set_irq(gpio2, pin, 0);
423
+ gpio_set_bit(gpio2, ODR, pin, 1);
424
+ gpio_set_2bits(gpio2, MODER, pin, MODER_OUTPUT);
425
+ g_assert_cmphex(get_disconnected_pins(gpio2), ==, 0xFFFF);
426
+ g_assert_cmphex(gpio_readl(gpio2, IDR), ==, reset(gpio2, IDR) | (1 << pin));
427
+
428
+ /* Trying to set a push-pull output pin, checking it doesn't work */
429
+ gpio_set_irq(gpio, pin, 1);
430
+ g_assert_cmphex(get_disconnected_pins(gpio), ==, 0xFFFF);
431
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) & ~(1 << pin));
432
+
433
+ /* Trying to reset a push-pull output pin, checking it doesn't work */
434
+ gpio_set_irq(gpio2, pin, 0);
435
+ g_assert_cmphex(get_disconnected_pins(gpio2), ==, 0xFFFF);
436
+ g_assert_cmphex(gpio_readl(gpio2, IDR), ==, reset(gpio2, IDR) | (1 << pin));
437
+
438
+ /* Clean the test */
439
+ gpio_writel(gpio, MODER, reset(gpio, MODER));
440
+ gpio_writel(gpio2, ODR, reset(gpio2, ODR));
441
+ gpio_writel(gpio2, MODER, reset(gpio2, MODER));
442
+}
443
+
444
+static void test_open_drain(const void *data)
445
+{
446
+ /*
447
+ * Test that configuring a line in open-drain output mode
448
+ * disconnects a pin set high externally and that the pin
449
+ * can't be set high externally while configured in open-drain.
450
+ *
451
+ * However a pin set low externally shouldn't be disconnected,
452
+ * and it can be set low externally when in open-drain mode.
453
+ */
454
+ unsigned int pin = ((uint64_t)data) & 0xF;
455
+ uint32_t gpio = ((uint64_t)data) >> 32;
456
+ uint32_t gpio2 = GPIO_BASE_ADDR + (GPIO_H - gpio);
457
+
458
+ qtest_irq_intercept_in(global_qtest, "/machine/soc/syscfg");
459
+
460
+ /* Setting a line high externally, configuring it in open-drain output */
461
+ /* And checking the pin was disconnected */
462
+ gpio_set_irq(gpio, pin, 1);
463
+ gpio_set_bit(gpio, OTYPER, pin, OTYPER_OPEN_DRAIN);
464
+ gpio_set_2bits(gpio, MODER, pin, MODER_OUTPUT);
465
+ g_assert_cmphex(get_disconnected_pins(gpio), ==, 0xFFFF);
466
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) & ~(1 << pin));
467
+
468
+ /* Setting a line low externally, configuring it in open-drain output */
469
+ /* And checking the pin wasn't disconnected */
470
+ gpio_set_irq(gpio2, pin, 0);
471
+ gpio_set_bit(gpio2, ODR, pin, 1);
472
+ gpio_set_bit(gpio2, OTYPER, pin, OTYPER_OPEN_DRAIN);
473
+ gpio_set_2bits(gpio2, MODER, pin, MODER_OUTPUT);
474
+ g_assert_cmphex(get_disconnected_pins(gpio2), ==, 0xFFFF & ~(1 << pin));
475
+ g_assert_cmphex(gpio_readl(gpio2, IDR), ==,
476
+ reset(gpio2, IDR) & ~(1 << pin));
477
+
478
+ /* Trying to set a open-drain output pin, checking it doesn't work */
479
+ gpio_set_irq(gpio, pin, 1);
480
+ g_assert_cmphex(get_disconnected_pins(gpio), ==, 0xFFFF);
481
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) & ~(1 << pin));
482
+
483
+ /* Trying to reset a open-drain output pin, checking it works */
484
+ gpio_set_bit(gpio, ODR, pin, 1);
485
+ gpio_set_irq(gpio, pin, 0);
486
+ g_assert_cmphex(get_disconnected_pins(gpio2), ==, 0xFFFF & ~(1 << pin));
487
+ g_assert_cmphex(gpio_readl(gpio2, IDR), ==,
488
+ reset(gpio2, IDR) & ~(1 << pin));
489
+
490
+ /* Clean the test */
491
+ disconnect_all_pins(gpio2);
492
+ gpio_writel(gpio2, OTYPER, reset(gpio2, OTYPER));
493
+ gpio_writel(gpio2, ODR, reset(gpio2, ODR));
494
+ gpio_writel(gpio2, MODER, reset(gpio2, MODER));
495
+ g_assert_cmphex(gpio_readl(gpio2, IDR), ==, reset(gpio2, IDR));
496
+ disconnect_all_pins(gpio);
497
+ gpio_writel(gpio, OTYPER, reset(gpio, OTYPER));
498
+ gpio_writel(gpio, ODR, reset(gpio, ODR));
499
+ gpio_writel(gpio, MODER, reset(gpio, MODER));
500
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR));
501
+}
502
+
503
+static void test_bsrr_brr(const void *data)
504
+{
505
+ /*
506
+ * Test that writing a '1' in BSS and BSRR
507
+ * has the desired effect on ODR.
508
+ * In BSRR, BSx has priority over BRx.
509
+ */
510
+ unsigned int pin = ((uint64_t)data) & 0xF;
511
+ uint32_t gpio = ((uint64_t)data) >> 32;
512
+
513
+ gpio_writel(gpio, BSRR, (1 << pin));
514
+ g_assert_cmphex(gpio_readl(gpio, ODR), ==, reset(gpio, ODR) | (1 << pin));
515
+
516
+ gpio_writel(gpio, BSRR, (1 << (pin + NUM_GPIO_PINS)));
517
+ g_assert_cmphex(gpio_readl(gpio, ODR), ==, reset(gpio, ODR));
518
+
519
+ gpio_writel(gpio, BSRR, (1 << pin));
520
+ g_assert_cmphex(gpio_readl(gpio, ODR), ==, reset(gpio, ODR) | (1 << pin));
521
+
522
+ gpio_writel(gpio, BRR, (1 << pin));
523
+ g_assert_cmphex(gpio_readl(gpio, ODR), ==, reset(gpio, ODR));
524
+
525
+ /* BSx should have priority over BRx */
526
+ gpio_writel(gpio, BSRR, (1 << pin) | (1 << (pin + NUM_GPIO_PINS)));
527
+ g_assert_cmphex(gpio_readl(gpio, ODR), ==, reset(gpio, ODR) | (1 << pin));
528
+
529
+ gpio_writel(gpio, BRR, (1 << pin));
530
+ g_assert_cmphex(gpio_readl(gpio, ODR), ==, reset(gpio, ODR));
531
+
532
+ gpio_writel(gpio, ODR, reset(gpio, ODR));
533
+}
534
+
535
+int main(int argc, char **argv)
536
+{
537
+ int ret;
538
+
539
+ g_test_init(&argc, &argv, NULL);
540
+ g_test_set_nonfatal_assertions();
541
+ qtest_add_func("stm32l4x5/gpio/test_idr_reset_value",
542
+ test_idr_reset_value);
543
+ /*
544
+ * The inputs for the tests (gpio and pin) can be changed,
545
+ * but the tests don't work for pins that are high at reset
546
+ * (GPIOA15, GPIO13 and GPIOB5).
547
+ * Specifically, rising the pin then checking `get_irq()`
548
+ * is problematic since the pin was already high.
549
+ */
550
+ qtest_add_data_func("stm32l4x5/gpio/test_gpioc5_output_mode",
551
+ (void *)((uint64_t)GPIO_C << 32 | 5),
552
+ test_gpio_output_mode);
553
+ qtest_add_data_func("stm32l4x5/gpio/test_gpioh3_output_mode",
554
+ (void *)((uint64_t)GPIO_H << 32 | 3),
555
+ test_gpio_output_mode);
556
+ qtest_add_data_func("stm32l4x5/gpio/test_gpio_input_mode1",
557
+ (void *)((uint64_t)GPIO_D << 32 | 6),
558
+ test_gpio_input_mode);
559
+ qtest_add_data_func("stm32l4x5/gpio/test_gpio_input_mode2",
560
+ (void *)((uint64_t)GPIO_C << 32 | 10),
561
+ test_gpio_input_mode);
562
+ qtest_add_data_func("stm32l4x5/gpio/test_gpio_pull_up_pull_down1",
563
+ (void *)((uint64_t)GPIO_B << 32 | 5),
564
+ test_pull_up_pull_down);
565
+ qtest_add_data_func("stm32l4x5/gpio/test_gpio_pull_up_pull_down2",
566
+ (void *)((uint64_t)GPIO_F << 32 | 1),
567
+ test_pull_up_pull_down);
568
+ qtest_add_data_func("stm32l4x5/gpio/test_gpio_push_pull1",
569
+ (void *)((uint64_t)GPIO_G << 32 | 6),
570
+ test_push_pull);
571
+ qtest_add_data_func("stm32l4x5/gpio/test_gpio_push_pull2",
572
+ (void *)((uint64_t)GPIO_H << 32 | 3),
573
+ test_push_pull);
574
+ qtest_add_data_func("stm32l4x5/gpio/test_gpio_open_drain1",
575
+ (void *)((uint64_t)GPIO_C << 32 | 4),
576
+ test_open_drain);
577
+ qtest_add_data_func("stm32l4x5/gpio/test_gpio_open_drain2",
578
+ (void *)((uint64_t)GPIO_E << 32 | 11),
579
+ test_open_drain);
580
+ qtest_add_data_func("stm32l4x5/gpio/test_bsrr_brr1",
581
+ (void *)((uint64_t)GPIO_A << 32 | 12),
582
+ test_bsrr_brr);
583
+ qtest_add_data_func("stm32l4x5/gpio/test_bsrr_brr2",
584
+ (void *)((uint64_t)GPIO_D << 32 | 0),
585
+ test_bsrr_brr);
586
+
587
+ qtest_start("-machine b-l475e-iot01a");
588
+ ret = g_test_run();
589
+ qtest_end();
590
+
591
+ return ret;
592
+}
593
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
249
index XXXXXXX..XXXXXXX 100644
594
index XXXXXXX..XXXXXXX 100644
250
--- a/default-configs/aarch64-softmmu.mak
595
--- a/tests/qtest/meson.build
251
+++ b/default-configs/aarch64-softmmu.mak
596
+++ b/tests/qtest/meson.build
252
@@ -XXX,XX +XXX,XX @@ CONFIG_DDC=y
597
@@ -XXX,XX +XXX,XX @@ qtests_aspeed = \
253
CONFIG_DPCD=y
598
qtests_stm32l4x5 = \
254
CONFIG_XLNX_ZYNQMP=y
599
['stm32l4x5_exti-test',
255
CONFIG_XLNX_ZYNQMP_ARM=y
600
'stm32l4x5_syscfg-test',
256
+CONFIG_ARM_SMMUV3=y
601
- 'stm32l4x5_rcc-test']
602
+ 'stm32l4x5_rcc-test',
603
+ 'stm32l4x5_gpio-test']
604
605
qtests_arm = \
606
(config_all_devices.has_key('CONFIG_MPS2') ? ['sse-timer-test'] : []) + \
257
--
607
--
258
2.17.0
608
2.34.1
259
609
260
610
diff view generated by jsdifflib
1
From: Eric Auger <eric.auger@redhat.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
At the moment, the SMMUv3 does not support notification on
3
While the 8-bit input elements are sequential in the input vector,
4
TLB invalidation. So let's log an error as soon as such notifier
4
the 32-bit output elements are not sequential in the output matrix.
5
gets enabled.
5
Do not attempt to compute 2 32-bit outputs at the same time.
6
6
7
Signed-off-by: Eric Auger <eric.auger@redhat.com>
7
Cc: qemu-stable@nongnu.org
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Fixes: 23a5e3859f5 ("target/arm: Implement SME integer outer product")
9
Message-id: 1524665762-31355-11-git-send-email-eric.auger@redhat.com
9
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2083
10
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
12
Message-id: 20240305163931.242795-1-richard.henderson@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
14
---
12
hw/arm/smmuv3.c | 11 +++++++++++
15
target/arm/tcg/sme_helper.c | 77 ++++++++++++++++++-------------
13
1 file changed, 11 insertions(+)
16
tests/tcg/aarch64/sme-smopa-1.c | 47 +++++++++++++++++++
14
17
tests/tcg/aarch64/sme-smopa-2.c | 54 ++++++++++++++++++++++
15
diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c
18
tests/tcg/aarch64/Makefile.target | 2 +-
19
4 files changed, 147 insertions(+), 33 deletions(-)
20
create mode 100644 tests/tcg/aarch64/sme-smopa-1.c
21
create mode 100644 tests/tcg/aarch64/sme-smopa-2.c
22
23
diff --git a/target/arm/tcg/sme_helper.c b/target/arm/tcg/sme_helper.c
16
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/arm/smmuv3.c
25
--- a/target/arm/tcg/sme_helper.c
18
+++ b/hw/arm/smmuv3.c
26
+++ b/target/arm/tcg/sme_helper.c
19
@@ -XXX,XX +XXX,XX @@ static void smmuv3_class_init(ObjectClass *klass, void *data)
27
@@ -XXX,XX +XXX,XX @@ void HELPER(sme_bfmopa)(void *vza, void *vzn, void *vzm, void *vpn,
20
dc->realize = smmu_realize;
28
}
21
}
29
}
22
30
23
+static void smmuv3_notify_flag_changed(IOMMUMemoryRegion *iommu,
31
-typedef uint64_t IMOPFn(uint64_t, uint64_t, uint64_t, uint8_t, bool);
24
+ IOMMUNotifierFlag old,
32
+typedef uint32_t IMOPFn32(uint32_t, uint32_t, uint32_t, uint8_t, bool);
25
+ IOMMUNotifierFlag new)
33
+static inline void do_imopa_s(uint32_t *za, uint32_t *zn, uint32_t *zm,
34
+ uint8_t *pn, uint8_t *pm,
35
+ uint32_t desc, IMOPFn32 *fn)
26
+{
36
+{
27
+ if (old == IOMMU_NOTIFIER_NONE) {
37
+ intptr_t row, col, oprsz = simd_oprsz(desc) / 4;
28
+ warn_report("SMMUV3 does not support vhost/vfio integration yet: "
38
+ bool neg = simd_data(desc);
29
+ "devices of those types will not function properly");
39
40
-static inline void do_imopa(uint64_t *za, uint64_t *zn, uint64_t *zm,
41
- uint8_t *pn, uint8_t *pm,
42
- uint32_t desc, IMOPFn *fn)
43
+ for (row = 0; row < oprsz; ++row) {
44
+ uint8_t pa = (pn[H1(row >> 1)] >> ((row & 1) * 4)) & 0xf;
45
+ uint32_t *za_row = &za[tile_vslice_index(row)];
46
+ uint32_t n = zn[H4(row)];
47
+
48
+ for (col = 0; col < oprsz; ++col) {
49
+ uint8_t pb = pm[H1(col >> 1)] >> ((col & 1) * 4);
50
+ uint32_t *a = &za_row[H4(col)];
51
+
52
+ *a = fn(n, zm[H4(col)], *a, pa & pb, neg);
53
+ }
30
+ }
54
+ }
31
+}
55
+}
32
+
56
+
33
static void smmuv3_iommu_memory_region_class_init(ObjectClass *klass,
57
+typedef uint64_t IMOPFn64(uint64_t, uint64_t, uint64_t, uint8_t, bool);
34
void *data)
58
+static inline void do_imopa_d(uint64_t *za, uint64_t *zn, uint64_t *zm,
59
+ uint8_t *pn, uint8_t *pm,
60
+ uint32_t desc, IMOPFn64 *fn)
35
{
61
{
36
IOMMUMemoryRegionClass *imrc = IOMMU_MEMORY_REGION_CLASS(klass);
62
intptr_t row, col, oprsz = simd_oprsz(desc) / 8;
37
63
bool neg = simd_data(desc);
38
imrc->translate = smmuv3_translate;
64
@@ -XXX,XX +XXX,XX @@ static inline void do_imopa(uint64_t *za, uint64_t *zn, uint64_t *zm,
39
+ imrc->notify_flag_changed = smmuv3_notify_flag_changed;
40
}
65
}
41
66
42
static const TypeInfo smmuv3_type_info = {
67
#define DEF_IMOP_32(NAME, NTYPE, MTYPE) \
68
-static uint64_t NAME(uint64_t n, uint64_t m, uint64_t a, uint8_t p, bool neg) \
69
+static uint32_t NAME(uint32_t n, uint32_t m, uint32_t a, uint8_t p, bool neg) \
70
{ \
71
- uint32_t sum0 = 0, sum1 = 0; \
72
+ uint32_t sum = 0; \
73
/* Apply P to N as a mask, making the inactive elements 0. */ \
74
n &= expand_pred_b(p); \
75
- sum0 += (NTYPE)(n >> 0) * (MTYPE)(m >> 0); \
76
- sum0 += (NTYPE)(n >> 8) * (MTYPE)(m >> 8); \
77
- sum0 += (NTYPE)(n >> 16) * (MTYPE)(m >> 16); \
78
- sum0 += (NTYPE)(n >> 24) * (MTYPE)(m >> 24); \
79
- sum1 += (NTYPE)(n >> 32) * (MTYPE)(m >> 32); \
80
- sum1 += (NTYPE)(n >> 40) * (MTYPE)(m >> 40); \
81
- sum1 += (NTYPE)(n >> 48) * (MTYPE)(m >> 48); \
82
- sum1 += (NTYPE)(n >> 56) * (MTYPE)(m >> 56); \
83
- if (neg) { \
84
- sum0 = (uint32_t)a - sum0, sum1 = (uint32_t)(a >> 32) - sum1; \
85
- } else { \
86
- sum0 = (uint32_t)a + sum0, sum1 = (uint32_t)(a >> 32) + sum1; \
87
- } \
88
- return ((uint64_t)sum1 << 32) | sum0; \
89
+ sum += (NTYPE)(n >> 0) * (MTYPE)(m >> 0); \
90
+ sum += (NTYPE)(n >> 8) * (MTYPE)(m >> 8); \
91
+ sum += (NTYPE)(n >> 16) * (MTYPE)(m >> 16); \
92
+ sum += (NTYPE)(n >> 24) * (MTYPE)(m >> 24); \
93
+ return neg ? a - sum : a + sum; \
94
}
95
96
#define DEF_IMOP_64(NAME, NTYPE, MTYPE) \
97
@@ -XXX,XX +XXX,XX @@ DEF_IMOP_64(umopa_d, uint16_t, uint16_t)
98
DEF_IMOP_64(sumopa_d, int16_t, uint16_t)
99
DEF_IMOP_64(usmopa_d, uint16_t, int16_t)
100
101
-#define DEF_IMOPH(NAME) \
102
- void HELPER(sme_##NAME)(void *vza, void *vzn, void *vzm, void *vpn, \
103
- void *vpm, uint32_t desc) \
104
- { do_imopa(vza, vzn, vzm, vpn, vpm, desc, NAME); }
105
+#define DEF_IMOPH(NAME, S) \
106
+ void HELPER(sme_##NAME##_##S)(void *vza, void *vzn, void *vzm, \
107
+ void *vpn, void *vpm, uint32_t desc) \
108
+ { do_imopa_##S(vza, vzn, vzm, vpn, vpm, desc, NAME##_##S); }
109
110
-DEF_IMOPH(smopa_s)
111
-DEF_IMOPH(umopa_s)
112
-DEF_IMOPH(sumopa_s)
113
-DEF_IMOPH(usmopa_s)
114
-DEF_IMOPH(smopa_d)
115
-DEF_IMOPH(umopa_d)
116
-DEF_IMOPH(sumopa_d)
117
-DEF_IMOPH(usmopa_d)
118
+DEF_IMOPH(smopa, s)
119
+DEF_IMOPH(umopa, s)
120
+DEF_IMOPH(sumopa, s)
121
+DEF_IMOPH(usmopa, s)
122
+
123
+DEF_IMOPH(smopa, d)
124
+DEF_IMOPH(umopa, d)
125
+DEF_IMOPH(sumopa, d)
126
+DEF_IMOPH(usmopa, d)
127
diff --git a/tests/tcg/aarch64/sme-smopa-1.c b/tests/tcg/aarch64/sme-smopa-1.c
128
new file mode 100644
129
index XXXXXXX..XXXXXXX
130
--- /dev/null
131
+++ b/tests/tcg/aarch64/sme-smopa-1.c
132
@@ -XXX,XX +XXX,XX @@
133
+#include <stdio.h>
134
+#include <string.h>
135
+
136
+int main()
137
+{
138
+ static const int cmp[4][4] = {
139
+ { 110, 134, 158, 182 },
140
+ { 390, 478, 566, 654 },
141
+ { 670, 822, 974, 1126 },
142
+ { 950, 1166, 1382, 1598 }
143
+ };
144
+ int dst[4][4];
145
+ int *tmp = &dst[0][0];
146
+
147
+ asm volatile(
148
+ ".arch armv8-r+sme\n\t"
149
+ "smstart\n\t"
150
+ "index z0.b, #0, #1\n\t"
151
+ "movprfx z1, z0\n\t"
152
+ "add z1.b, z1.b, #16\n\t"
153
+ "ptrue p0.b\n\t"
154
+ "smopa za0.s, p0/m, p0/m, z0.b, z1.b\n\t"
155
+ "ptrue p0.s, vl4\n\t"
156
+ "mov w12, #0\n\t"
157
+ "st1w { za0h.s[w12, #0] }, p0, [%0]\n\t"
158
+ "add %0, %0, #16\n\t"
159
+ "st1w { za0h.s[w12, #1] }, p0, [%0]\n\t"
160
+ "add %0, %0, #16\n\t"
161
+ "st1w { za0h.s[w12, #2] }, p0, [%0]\n\t"
162
+ "add %0, %0, #16\n\t"
163
+ "st1w { za0h.s[w12, #3] }, p0, [%0]\n\t"
164
+ "smstop"
165
+ : "+r"(tmp) : : "memory");
166
+
167
+ if (memcmp(cmp, dst, sizeof(dst)) == 0) {
168
+ return 0;
169
+ }
170
+
171
+ /* See above for correct results. */
172
+ for (int i = 0; i < 4; ++i) {
173
+ for (int j = 0; j < 4; ++j) {
174
+ printf("%6d", dst[i][j]);
175
+ }
176
+ printf("\n");
177
+ }
178
+ return 1;
179
+}
180
diff --git a/tests/tcg/aarch64/sme-smopa-2.c b/tests/tcg/aarch64/sme-smopa-2.c
181
new file mode 100644
182
index XXXXXXX..XXXXXXX
183
--- /dev/null
184
+++ b/tests/tcg/aarch64/sme-smopa-2.c
185
@@ -XXX,XX +XXX,XX @@
186
+#include <stdio.h>
187
+#include <string.h>
188
+
189
+int main()
190
+{
191
+ static const long cmp[4][4] = {
192
+ { 110, 134, 158, 182 },
193
+ { 390, 478, 566, 654 },
194
+ { 670, 822, 974, 1126 },
195
+ { 950, 1166, 1382, 1598 }
196
+ };
197
+ long dst[4][4];
198
+ long *tmp = &dst[0][0];
199
+ long svl;
200
+
201
+ /* Validate that we have a wide enough vector for 4 elements. */
202
+ asm(".arch armv8-r+sme-i64\n\trdsvl %0, #1" : "=r"(svl));
203
+ if (svl < 32) {
204
+ return 0;
205
+ }
206
+
207
+ asm volatile(
208
+ "smstart\n\t"
209
+ "index z0.h, #0, #1\n\t"
210
+ "movprfx z1, z0\n\t"
211
+ "add z1.h, z1.h, #16\n\t"
212
+ "ptrue p0.b\n\t"
213
+ "smopa za0.d, p0/m, p0/m, z0.h, z1.h\n\t"
214
+ "ptrue p0.d, vl4\n\t"
215
+ "mov w12, #0\n\t"
216
+ "st1d { za0h.d[w12, #0] }, p0, [%0]\n\t"
217
+ "add %0, %0, #32\n\t"
218
+ "st1d { za0h.d[w12, #1] }, p0, [%0]\n\t"
219
+ "mov w12, #2\n\t"
220
+ "add %0, %0, #32\n\t"
221
+ "st1d { za0h.d[w12, #0] }, p0, [%0]\n\t"
222
+ "add %0, %0, #32\n\t"
223
+ "st1d { za0h.d[w12, #1] }, p0, [%0]\n\t"
224
+ "smstop"
225
+ : "+r"(tmp) : : "memory");
226
+
227
+ if (memcmp(cmp, dst, sizeof(dst)) == 0) {
228
+ return 0;
229
+ }
230
+
231
+ /* See above for correct results. */
232
+ for (int i = 0; i < 4; ++i) {
233
+ for (int j = 0; j < 4; ++j) {
234
+ printf("%6ld", dst[i][j]);
235
+ }
236
+ printf("\n");
237
+ }
238
+ return 1;
239
+}
240
diff --git a/tests/tcg/aarch64/Makefile.target b/tests/tcg/aarch64/Makefile.target
241
index XXXXXXX..XXXXXXX 100644
242
--- a/tests/tcg/aarch64/Makefile.target
243
+++ b/tests/tcg/aarch64/Makefile.target
244
@@ -XXX,XX +XXX,XX @@ endif
245
246
# SME Tests
247
ifneq ($(CROSS_AS_HAS_ARMV9_SME),)
248
-AARCH64_TESTS += sme-outprod1
249
+AARCH64_TESTS += sme-outprod1 sme-smopa-1 sme-smopa-2
250
endif
251
252
# System Registers Tests
43
--
253
--
44
2.17.0
254
2.34.1
45
255
46
256
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
The sun4v RTC device model added under commit a0e893039cf2ce0 in 2016
2
was unfortunately added with a license of GPL-v3-or-later, which is
3
not compatible with other QEMU code which has a GPL-v2-only license.
2
4
3
Path analysis shows that size == 3 && !is_q has been eliminated.
5
Relicense the code in the .c and the .h file to GPL-v2-or-later,
6
to make it compatible with the rest of QEMU.
4
7
5
Fixes: Coverity CID1385853
8
Cc: qemu-stable@nongnu.org
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
10
Signed-off-by: Paolo Bonzini (for Red Hat) <pbonzini@redhat.com>
8
Message-id: 20180501180455.11214-3-richard.henderson@linaro.org
11
Signed-off-by: Artyom Tarasenko <atar4qemu@gmail.com>
12
Signed-off-by: Markus Armbruster <armbru@redhat.com>
13
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
14
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
15
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
16
Acked-by: Alex Bennée <alex.bennee@linaro.org>
17
Message-id: 20240223161300.938542-1-peter.maydell@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
19
---
11
target/arm/translate-a64.c | 6 +++++-
20
include/hw/rtc/sun4v-rtc.h | 2 +-
12
1 file changed, 5 insertions(+), 1 deletion(-)
21
hw/rtc/sun4v-rtc.c | 2 +-
22
2 files changed, 2 insertions(+), 2 deletions(-)
13
23
14
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
24
diff --git a/include/hw/rtc/sun4v-rtc.h b/include/hw/rtc/sun4v-rtc.h
15
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/translate-a64.c
26
--- a/include/hw/rtc/sun4v-rtc.h
17
+++ b/target/arm/translate-a64.c
27
+++ b/include/hw/rtc/sun4v-rtc.h
18
@@ -XXX,XX +XXX,XX @@ static void disas_simd_two_reg_misc(DisasContext *s, uint32_t insn)
28
@@ -XXX,XX +XXX,XX @@
19
/* All 64-bit element operations can be shared with scalar 2misc */
29
*
20
int pass;
30
* Copyright (c) 2016 Artyom Tarasenko
21
31
*
22
- for (pass = 0; pass < (is_q ? 2 : 1); pass++) {
32
- * This code is licensed under the GNU GPL v3 or (at your option) any later
23
+ /* Coverity claims (size == 3 && !is_q) has been eliminated
33
+ * This code is licensed under the GNU GPL v2 or (at your option) any later
24
+ * from all paths leading to here.
34
* version.
25
+ */
35
*/
26
+ tcg_debug_assert(is_q);
36
27
+ for (pass = 0; pass < 2; pass++) {
37
diff --git a/hw/rtc/sun4v-rtc.c b/hw/rtc/sun4v-rtc.c
28
TCGv_i64 tcg_op = tcg_temp_new_i64();
38
index XXXXXXX..XXXXXXX 100644
29
TCGv_i64 tcg_res = tcg_temp_new_i64();
39
--- a/hw/rtc/sun4v-rtc.c
40
+++ b/hw/rtc/sun4v-rtc.c
41
@@ -XXX,XX +XXX,XX @@
42
*
43
* Copyright (c) 2016 Artyom Tarasenko
44
*
45
- * This code is licensed under the GNU GPL v3 or (at your option) any later
46
+ * This code is licensed under the GNU GPL v2 or (at your option) any later
47
* version.
48
*/
30
49
31
--
50
--
32
2.17.0
51
2.34.1
33
52
34
53
diff view generated by jsdifflib
Deleted patch
1
From: Thomas Huth <thuth@redhat.com>
2
1
3
When running omap1/2 or pxa2xx based ARM machines with -nodefaults,
4
they bail out immediately complaining about a "missing SecureDigital
5
device". That's not how the "default" devices in vl.c are meant to
6
work - it should be possible for a board to also start up without
7
default devices. So let's turn the error message and exit() into
8
a warning instead.
9
10
Signed-off-by: Thomas Huth <thuth@redhat.com>
11
Message-id: 1525326811-3233-1-git-send-email-thuth@redhat.com
12
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
13
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
---
16
hw/arm/omap1.c | 8 ++++----
17
hw/arm/omap2.c | 8 ++++----
18
hw/arm/pxa2xx.c | 15 +++++++--------
19
3 files changed, 15 insertions(+), 16 deletions(-)
20
21
diff --git a/hw/arm/omap1.c b/hw/arm/omap1.c
22
index XXXXXXX..XXXXXXX 100644
23
--- a/hw/arm/omap1.c
24
+++ b/hw/arm/omap1.c
25
@@ -XXX,XX +XXX,XX @@
26
#include "hw/arm/soc_dma.h"
27
#include "sysemu/block-backend.h"
28
#include "sysemu/blockdev.h"
29
+#include "sysemu/qtest.h"
30
#include "qemu/range.h"
31
#include "hw/sysbus.h"
32
#include "qemu/cutils.h"
33
@@ -XXX,XX +XXX,XX @@ struct omap_mpu_state_s *omap310_mpu_init(MemoryRegion *system_memory,
34
omap_findclk(s, "dpll3"));
35
36
dinfo = drive_get(IF_SD, 0, 0);
37
- if (!dinfo) {
38
- error_report("missing SecureDigital device");
39
- exit(1);
40
+ if (!dinfo && !qtest_enabled()) {
41
+ warn_report("missing SecureDigital device");
42
}
43
s->mmc = omap_mmc_init(0xfffb7800, system_memory,
44
- blk_by_legacy_dinfo(dinfo),
45
+ dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
46
qdev_get_gpio_in(s->ih[1], OMAP_INT_OQN),
47
&s->drq[OMAP_DMA_MMC_TX],
48
omap_findclk(s, "mmc_ck"));
49
diff --git a/hw/arm/omap2.c b/hw/arm/omap2.c
50
index XXXXXXX..XXXXXXX 100644
51
--- a/hw/arm/omap2.c
52
+++ b/hw/arm/omap2.c
53
@@ -XXX,XX +XXX,XX @@
54
#include "cpu.h"
55
#include "sysemu/block-backend.h"
56
#include "sysemu/blockdev.h"
57
+#include "sysemu/qtest.h"
58
#include "hw/boards.h"
59
#include "hw/hw.h"
60
#include "hw/arm/arm.h"
61
@@ -XXX,XX +XXX,XX @@ struct omap_mpu_state_s *omap2420_mpu_init(MemoryRegion *sysmem,
62
s->drq[OMAP24XX_DMA_GPMC]);
63
64
dinfo = drive_get(IF_SD, 0, 0);
65
- if (!dinfo) {
66
- error_report("missing SecureDigital device");
67
- exit(1);
68
+ if (!dinfo && !qtest_enabled()) {
69
+ warn_report("missing SecureDigital device");
70
}
71
s->mmc = omap2_mmc_init(omap_l4tao(s->l4, 9),
72
- blk_by_legacy_dinfo(dinfo),
73
+ dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
74
qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_MMC_IRQ),
75
&s->drq[OMAP24XX_DMA_MMC1_TX],
76
omap_findclk(s, "mmc_fclk"), omap_findclk(s, "mmc_iclk"));
77
diff --git a/hw/arm/pxa2xx.c b/hw/arm/pxa2xx.c
78
index XXXXXXX..XXXXXXX 100644
79
--- a/hw/arm/pxa2xx.c
80
+++ b/hw/arm/pxa2xx.c
81
@@ -XXX,XX +XXX,XX @@
82
#include "chardev/char-fe.h"
83
#include "sysemu/block-backend.h"
84
#include "sysemu/blockdev.h"
85
+#include "sysemu/qtest.h"
86
#include "qemu/cutils.h"
87
88
static struct {
89
@@ -XXX,XX +XXX,XX @@ PXA2xxState *pxa270_init(MemoryRegion *address_space,
90
s->gpio = pxa2xx_gpio_init(0x40e00000, s->cpu, s->pic, 121);
91
92
dinfo = drive_get(IF_SD, 0, 0);
93
- if (!dinfo) {
94
- error_report("missing SecureDigital device");
95
- exit(1);
96
+ if (!dinfo && !qtest_enabled()) {
97
+ warn_report("missing SecureDigital device");
98
}
99
s->mmc = pxa2xx_mmci_init(address_space, 0x41100000,
100
- blk_by_legacy_dinfo(dinfo),
101
+ dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
102
qdev_get_gpio_in(s->pic, PXA2XX_PIC_MMC),
103
qdev_get_gpio_in(s->dma, PXA2XX_RX_RQ_MMCI),
104
qdev_get_gpio_in(s->dma, PXA2XX_TX_RQ_MMCI));
105
@@ -XXX,XX +XXX,XX @@ PXA2xxState *pxa255_init(MemoryRegion *address_space, unsigned int sdram_size)
106
s->gpio = pxa2xx_gpio_init(0x40e00000, s->cpu, s->pic, 85);
107
108
dinfo = drive_get(IF_SD, 0, 0);
109
- if (!dinfo) {
110
- error_report("missing SecureDigital device");
111
- exit(1);
112
+ if (!dinfo && !qtest_enabled()) {
113
+ warn_report("missing SecureDigital device");
114
}
115
s->mmc = pxa2xx_mmci_init(address_space, 0x41100000,
116
- blk_by_legacy_dinfo(dinfo),
117
+ dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
118
qdev_get_gpio_in(s->pic, PXA2XX_PIC_MMC),
119
qdev_get_gpio_in(s->dma, PXA2XX_RX_RQ_MMCI),
120
qdev_get_gpio_in(s->dma, PXA2XX_TX_RQ_MMCI));
121
--
122
2.17.0
123
124
diff view generated by jsdifflib
Deleted patch
1
For v8M the instructions VLLDM and VLSTM support lazy saving
2
and restoring of the secure floating-point registers. Even
3
if the floating point extension is not implemented, these
4
instructions must act as NOPs in Secure state, so they can
5
be used as part of the secure-to-nonsecure call sequence.
6
1
7
Fixes: https://bugs.launchpad.net/qemu/+bug/1768295
8
Cc: qemu-stable@nongnu.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20180503105730.5958-1-peter.maydell@linaro.org
12
---
13
target/arm/translate.c | 17 ++++++++++++++++-
14
1 file changed, 16 insertions(+), 1 deletion(-)
15
16
diff --git a/target/arm/translate.c b/target/arm/translate.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/translate.c
19
+++ b/target/arm/translate.c
20
@@ -XXX,XX +XXX,XX @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
21
/* Coprocessor. */
22
if (arm_dc_feature(s, ARM_FEATURE_M)) {
23
/* We don't currently implement M profile FP support,
24
- * so this entire space should give a NOCP fault.
25
+ * so this entire space should give a NOCP fault, with
26
+ * the exception of the v8M VLLDM and VLSTM insns, which
27
+ * must be NOPs in Secure state and UNDEF in Nonsecure state.
28
*/
29
+ if (arm_dc_feature(s, ARM_FEATURE_V8) &&
30
+ (insn & 0xffa00f00) == 0xec200a00) {
31
+ /* 0b1110_1100_0x1x_xxxx_xxxx_1010_xxxx_xxxx
32
+ * - VLLDM, VLSTM
33
+ * We choose to UNDEF if the RAZ bits are non-zero.
34
+ */
35
+ if (!s->v8m_secure || (insn & 0x0040f0ff)) {
36
+ goto illegal_op;
37
+ }
38
+ /* Just NOP since FP support is not implemented */
39
+ break;
40
+ }
41
+ /* All other insns: NOCP */
42
gen_exception_insn(s, 4, EXCP_NOCP, syn_uncategorized(),
43
default_exception_el(s));
44
break;
45
--
46
2.17.0
47
48
diff view generated by jsdifflib
Deleted patch
1
From: Eric Auger <eric.auger@redhat.com>
2
1
3
We set up the infrastructure to enumerate all the PCI devices
4
attached to the SMMU and create an associated IOMMU memory
5
region and address space.
6
7
Those info are stored in SMMUDevice objects. The devices are
8
grouped according to the PCIBus they belong to. A hash table
9
indexed by the PCIBus pointer is used. Also an array indexed by
10
the bus number allows to find the list of SMMUDevices.
11
12
Signed-off-by: Eric Auger <eric.auger@redhat.com>
13
Signed-off-by: Prem Mallappa <prem.mallappa@broadcom.com>
14
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
15
Message-id: 1524665762-31355-3-git-send-email-eric.auger@redhat.com
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
---
18
include/hw/arm/smmu-common.h | 8 +++++
19
hw/arm/smmu-common.c | 69 ++++++++++++++++++++++++++++++++++++
20
hw/arm/trace-events | 3 ++
21
3 files changed, 80 insertions(+)
22
23
diff --git a/include/hw/arm/smmu-common.h b/include/hw/arm/smmu-common.h
24
index XXXXXXX..XXXXXXX 100644
25
--- a/include/hw/arm/smmu-common.h
26
+++ b/include/hw/arm/smmu-common.h
27
@@ -XXX,XX +XXX,XX @@ typedef struct {
28
#define ARM_SMMU_GET_CLASS(obj) \
29
OBJECT_GET_CLASS(SMMUBaseClass, (obj), TYPE_ARM_SMMU)
30
31
+/* Return the SMMUPciBus handle associated to a PCI bus number */
32
+SMMUPciBus *smmu_find_smmu_pcibus(SMMUState *s, uint8_t bus_num);
33
+
34
+/* Return the stream ID of an SMMU device */
35
+static inline uint16_t smmu_get_sid(SMMUDevice *sdev)
36
+{
37
+ return PCI_BUILD_BDF(pci_bus_num(sdev->bus), sdev->devfn);
38
+}
39
#endif /* HW_ARM_SMMU_COMMON */
40
diff --git a/hw/arm/smmu-common.c b/hw/arm/smmu-common.c
41
index XXXXXXX..XXXXXXX 100644
42
--- a/hw/arm/smmu-common.c
43
+++ b/hw/arm/smmu-common.c
44
@@ -XXX,XX +XXX,XX @@
45
#include "qemu/error-report.h"
46
#include "hw/arm/smmu-common.h"
47
48
+/**
49
+ * The bus number is used for lookup when SID based invalidation occurs.
50
+ * In that case we lazily populate the SMMUPciBus array from the bus hash
51
+ * table. At the time the SMMUPciBus is created (smmu_find_add_as), the bus
52
+ * numbers may not be always initialized yet.
53
+ */
54
+SMMUPciBus *smmu_find_smmu_pcibus(SMMUState *s, uint8_t bus_num)
55
+{
56
+ SMMUPciBus *smmu_pci_bus = s->smmu_pcibus_by_bus_num[bus_num];
57
+
58
+ if (!smmu_pci_bus) {
59
+ GHashTableIter iter;
60
+
61
+ g_hash_table_iter_init(&iter, s->smmu_pcibus_by_busptr);
62
+ while (g_hash_table_iter_next(&iter, NULL, (void **)&smmu_pci_bus)) {
63
+ if (pci_bus_num(smmu_pci_bus->bus) == bus_num) {
64
+ s->smmu_pcibus_by_bus_num[bus_num] = smmu_pci_bus;
65
+ return smmu_pci_bus;
66
+ }
67
+ }
68
+ }
69
+ return smmu_pci_bus;
70
+}
71
+
72
+static AddressSpace *smmu_find_add_as(PCIBus *bus, void *opaque, int devfn)
73
+{
74
+ SMMUState *s = opaque;
75
+ SMMUPciBus *sbus = g_hash_table_lookup(s->smmu_pcibus_by_busptr, bus);
76
+ SMMUDevice *sdev;
77
+
78
+ if (!sbus) {
79
+ sbus = g_malloc0(sizeof(SMMUPciBus) +
80
+ sizeof(SMMUDevice *) * SMMU_PCI_DEVFN_MAX);
81
+ sbus->bus = bus;
82
+ g_hash_table_insert(s->smmu_pcibus_by_busptr, bus, sbus);
83
+ }
84
+
85
+ sdev = sbus->pbdev[devfn];
86
+ if (!sdev) {
87
+ char *name = g_strdup_printf("%s-%d-%d",
88
+ s->mrtypename,
89
+ pci_bus_num(bus), devfn);
90
+ sdev = sbus->pbdev[devfn] = g_new0(SMMUDevice, 1);
91
+
92
+ sdev->smmu = s;
93
+ sdev->bus = bus;
94
+ sdev->devfn = devfn;
95
+
96
+ memory_region_init_iommu(&sdev->iommu, sizeof(sdev->iommu),
97
+ s->mrtypename,
98
+ OBJECT(s), name, 1ULL << SMMU_MAX_VA_BITS);
99
+ address_space_init(&sdev->as,
100
+ MEMORY_REGION(&sdev->iommu), name);
101
+ trace_smmu_add_mr(name);
102
+ g_free(name);
103
+ }
104
+
105
+ return &sdev->as;
106
+}
107
+
108
static void smmu_base_realize(DeviceState *dev, Error **errp)
109
{
110
+ SMMUState *s = ARM_SMMU(dev);
111
SMMUBaseClass *sbc = ARM_SMMU_GET_CLASS(dev);
112
Error *local_err = NULL;
113
114
@@ -XXX,XX +XXX,XX @@ static void smmu_base_realize(DeviceState *dev, Error **errp)
115
error_propagate(errp, local_err);
116
return;
117
}
118
+
119
+ s->smmu_pcibus_by_busptr = g_hash_table_new(NULL, NULL);
120
+
121
+ if (s->primary_bus) {
122
+ pci_setup_iommu(s->primary_bus, smmu_find_add_as, s);
123
+ } else {
124
+ error_setg(errp, "SMMU is not attached to any PCI bus!");
125
+ }
126
}
127
128
static void smmu_base_reset(DeviceState *dev)
129
diff --git a/hw/arm/trace-events b/hw/arm/trace-events
130
index XXXXXXX..XXXXXXX 100644
131
--- a/hw/arm/trace-events
132
+++ b/hw/arm/trace-events
133
@@ -XXX,XX +XXX,XX @@
134
135
# hw/arm/virt-acpi-build.c
136
virt_acpi_setup(void) "No fw cfg or ACPI disabled. Bailing out."
137
+
138
+# hw/arm/smmu-common.c
139
+smmu_add_mr(const char *name) "%s"
140
\ No newline at end of file
141
--
142
2.17.0
143
144
diff view generated by jsdifflib
1
From: Eric Auger <eric.auger@redhat.com>
1
From: Thomas Huth <thuth@redhat.com>
2
2
3
This patch implements the page table walk for VMSAv8-64.
3
Move the code to a separate file so that we do not have to compile
4
it anymore if CONFIG_ARM_V7M is not set.
4
5
5
Signed-off-by: Eric Auger <eric.auger@redhat.com>
6
Signed-off-by: Thomas Huth <thuth@redhat.com>
6
Signed-off-by: Prem Mallappa <prem.mallappa@broadcom.com>
7
Message-id: 20240308141051.536599-2-thuth@redhat.com
7
Message-id: 1524665762-31355-4-git-send-email-eric.auger@redhat.com
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
10
---
11
hw/arm/smmu-internal.h | 99 ++++++++++++++++
11
target/arm/tcg/cpu-v7m.c | 290 +++++++++++++++++++++++++++++++++++++
12
include/hw/arm/smmu-common.h | 14 +++
12
target/arm/tcg/cpu32.c | 261 ---------------------------------
13
hw/arm/smmu-common.c | 222 +++++++++++++++++++++++++++++++++++
13
target/arm/meson.build | 3 +
14
hw/arm/trace-events | 9 +-
14
target/arm/tcg/meson.build | 3 +
15
4 files changed, 343 insertions(+), 1 deletion(-)
15
4 files changed, 296 insertions(+), 261 deletions(-)
16
create mode 100644 hw/arm/smmu-internal.h
16
create mode 100644 target/arm/tcg/cpu-v7m.c
17
17
18
diff --git a/hw/arm/smmu-internal.h b/hw/arm/smmu-internal.h
18
diff --git a/target/arm/tcg/cpu-v7m.c b/target/arm/tcg/cpu-v7m.c
19
new file mode 100644
19
new file mode 100644
20
index XXXXXXX..XXXXXXX
20
index XXXXXXX..XXXXXXX
21
--- /dev/null
21
--- /dev/null
22
+++ b/hw/arm/smmu-internal.h
22
+++ b/target/arm/tcg/cpu-v7m.c
23
@@ -XXX,XX +XXX,XX @@
23
@@ -XXX,XX +XXX,XX @@
24
+/*
24
+/*
25
+ * ARM SMMU support - Internal API
25
+ * QEMU ARMv7-M TCG-only CPUs.
26
+ *
26
+ *
27
+ * Copyright (c) 2017 Red Hat, Inc.
27
+ * Copyright (c) 2012 SUSE LINUX Products GmbH
28
+ * Copyright (C) 2014-2016 Broadcom Corporation
29
+ * Written by Prem Mallappa, Eric Auger
30
+ *
28
+ *
31
+ * This program is free software; you can redistribute it and/or modify
29
+ * This code is licensed under the GNU GPL v2 or later.
32
+ * it under the terms of the GNU General Public License version 2 as
33
+ * published by the Free Software Foundation.
34
+ *
30
+ *
35
+ * This program is distributed in the hope that it will be useful,
31
+ * SPDX-License-Identifier: GPL-2.0-or-later
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
+ */
32
+ */
43
+
33
+
44
+#ifndef HW_ARM_SMMU_INTERNAL_H
34
+#include "qemu/osdep.h"
45
+#define HW_ARM_SMMU_INTERNAL_H
35
+#include "cpu.h"
46
+
36
+#include "hw/core/tcg-cpu-ops.h"
47
+#define TBI0(tbi) ((tbi) & 0x1)
37
+#include "internals.h"
48
+#define TBI1(tbi) ((tbi) & 0x2 >> 1)
38
+
49
+
39
+#if !defined(CONFIG_USER_ONLY)
50
+/* PTE Manipulation */
40
+
51
+
41
+#include "hw/intc/armv7m_nvic.h"
52
+#define ARM_LPAE_PTE_TYPE_SHIFT 0
42
+
53
+#define ARM_LPAE_PTE_TYPE_MASK 0x3
43
+static bool arm_v7m_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
54
+
44
+{
55
+#define ARM_LPAE_PTE_TYPE_BLOCK 1
45
+ CPUClass *cc = CPU_GET_CLASS(cs);
56
+#define ARM_LPAE_PTE_TYPE_TABLE 3
46
+ ARMCPU *cpu = ARM_CPU(cs);
57
+
47
+ CPUARMState *env = &cpu->env;
58
+#define ARM_LPAE_L3_PTE_TYPE_RESERVED 1
48
+ bool ret = false;
59
+#define ARM_LPAE_L3_PTE_TYPE_PAGE 3
49
+
60
+
50
+ /*
61
+#define ARM_LPAE_PTE_VALID (1 << 0)
51
+ * ARMv7-M interrupt masking works differently than -A or -R.
62
+
52
+ * There is no FIQ/IRQ distinction. Instead of I and F bits
63
+#define PTE_ADDRESS(pte, shift) \
53
+ * masking FIQ and IRQ interrupts, an exception is taken only
64
+ (extract64(pte, shift, 47 - shift + 1) << shift)
54
+ * if it is higher priority than the current execution priority
65
+
55
+ * (which depends on state like BASEPRI, FAULTMASK and the
66
+#define is_invalid_pte(pte) (!(pte & ARM_LPAE_PTE_VALID))
56
+ * currently active exception).
67
+
57
+ */
68
+#define is_reserved_pte(pte, level) \
58
+ if (interrupt_request & CPU_INTERRUPT_HARD
69
+ ((level == 3) && \
59
+ && (armv7m_nvic_can_take_pending_exception(env->nvic))) {
70
+ ((pte & ARM_LPAE_PTE_TYPE_MASK) == ARM_LPAE_L3_PTE_TYPE_RESERVED))
60
+ cs->exception_index = EXCP_IRQ;
71
+
61
+ cc->tcg_ops->do_interrupt(cs);
72
+#define is_block_pte(pte, level) \
62
+ ret = true;
73
+ ((level < 3) && \
63
+ }
74
+ ((pte & ARM_LPAE_PTE_TYPE_MASK) == ARM_LPAE_PTE_TYPE_BLOCK))
64
+ return ret;
75
+
65
+}
76
+#define is_table_pte(pte, level) \
66
+
77
+ ((level < 3) && \
67
+#endif /* !CONFIG_USER_ONLY */
78
+ ((pte & ARM_LPAE_PTE_TYPE_MASK) == ARM_LPAE_PTE_TYPE_TABLE))
68
+
79
+
69
+static void cortex_m0_initfn(Object *obj)
80
+#define is_page_pte(pte, level) \
70
+{
81
+ ((level == 3) && \
71
+ ARMCPU *cpu = ARM_CPU(obj);
82
+ ((pte & ARM_LPAE_PTE_TYPE_MASK) == ARM_LPAE_L3_PTE_TYPE_PAGE))
72
+ set_feature(&cpu->env, ARM_FEATURE_V6);
83
+
73
+ set_feature(&cpu->env, ARM_FEATURE_M);
84
+/* access permissions */
74
+
85
+
75
+ cpu->midr = 0x410cc200;
86
+#define PTE_AP(pte) \
76
+
87
+ (extract64(pte, 6, 2))
77
+ /*
88
+
78
+ * These ID register values are not guest visible, because
89
+#define PTE_APTABLE(pte) \
79
+ * we do not implement the Main Extension. They must be set
90
+ (extract64(pte, 61, 2))
80
+ * to values corresponding to the Cortex-M0's implemented
91
+
81
+ * features, because QEMU generally controls its emulation
92
+/*
82
+ * by looking at ID register fields. We use the same values as
93
+ * TODO: At the moment all transactions are considered as privileged (EL1)
83
+ * for the M3.
94
+ * as IOMMU translation callback does not pass user/priv attributes.
84
+ */
95
+ */
85
+ cpu->isar.id_pfr0 = 0x00000030;
96
+#define is_permission_fault(ap, perm) \
86
+ cpu->isar.id_pfr1 = 0x00000200;
97
+ (((perm) & IOMMU_WO) && ((ap) & 0x2))
87
+ cpu->isar.id_dfr0 = 0x00100000;
98
+
88
+ cpu->id_afr0 = 0x00000000;
99
+#define PTE_AP_TO_PERM(ap) \
89
+ cpu->isar.id_mmfr0 = 0x00000030;
100
+ (IOMMU_ACCESS_FLAG(true, !((ap) & 0x2)))
90
+ cpu->isar.id_mmfr1 = 0x00000000;
101
+
91
+ cpu->isar.id_mmfr2 = 0x00000000;
102
+/* Level Indexing */
92
+ cpu->isar.id_mmfr3 = 0x00000000;
103
+
93
+ cpu->isar.id_isar0 = 0x01141110;
104
+static inline int level_shift(int level, int granule_sz)
94
+ cpu->isar.id_isar1 = 0x02111000;
105
+{
95
+ cpu->isar.id_isar2 = 0x21112231;
106
+ return granule_sz + (3 - level) * (granule_sz - 3);
96
+ cpu->isar.id_isar3 = 0x01111110;
107
+}
97
+ cpu->isar.id_isar4 = 0x01310102;
108
+
98
+ cpu->isar.id_isar5 = 0x00000000;
109
+static inline uint64_t level_page_mask(int level, int granule_sz)
99
+ cpu->isar.id_isar6 = 0x00000000;
110
+{
100
+}
111
+ return ~(MAKE_64BIT_MASK(0, level_shift(level, granule_sz)));
101
+
112
+}
102
+static void cortex_m3_initfn(Object *obj)
113
+
103
+{
114
+static inline
104
+ ARMCPU *cpu = ARM_CPU(obj);
115
+uint64_t iova_level_offset(uint64_t iova, int inputsize,
105
+ set_feature(&cpu->env, ARM_FEATURE_V7);
116
+ int level, int gsz)
106
+ set_feature(&cpu->env, ARM_FEATURE_M);
117
+{
107
+ set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
118
+ return ((iova & MAKE_64BIT_MASK(0, inputsize)) >> level_shift(level, gsz)) &
108
+ cpu->midr = 0x410fc231;
119
+ MAKE_64BIT_MASK(0, gsz - 3);
109
+ cpu->pmsav7_dregion = 8;
120
+}
110
+ cpu->isar.id_pfr0 = 0x00000030;
121
+
111
+ cpu->isar.id_pfr1 = 0x00000200;
122
+#endif
112
+ cpu->isar.id_dfr0 = 0x00100000;
123
diff --git a/include/hw/arm/smmu-common.h b/include/hw/arm/smmu-common.h
113
+ cpu->id_afr0 = 0x00000000;
114
+ cpu->isar.id_mmfr0 = 0x00000030;
115
+ cpu->isar.id_mmfr1 = 0x00000000;
116
+ cpu->isar.id_mmfr2 = 0x00000000;
117
+ cpu->isar.id_mmfr3 = 0x00000000;
118
+ cpu->isar.id_isar0 = 0x01141110;
119
+ cpu->isar.id_isar1 = 0x02111000;
120
+ cpu->isar.id_isar2 = 0x21112231;
121
+ cpu->isar.id_isar3 = 0x01111110;
122
+ cpu->isar.id_isar4 = 0x01310102;
123
+ cpu->isar.id_isar5 = 0x00000000;
124
+ cpu->isar.id_isar6 = 0x00000000;
125
+}
126
+
127
+static void cortex_m4_initfn(Object *obj)
128
+{
129
+ ARMCPU *cpu = ARM_CPU(obj);
130
+
131
+ set_feature(&cpu->env, ARM_FEATURE_V7);
132
+ set_feature(&cpu->env, ARM_FEATURE_M);
133
+ set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
134
+ set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP);
135
+ cpu->midr = 0x410fc240; /* r0p0 */
136
+ cpu->pmsav7_dregion = 8;
137
+ cpu->isar.mvfr0 = 0x10110021;
138
+ cpu->isar.mvfr1 = 0x11000011;
139
+ cpu->isar.mvfr2 = 0x00000000;
140
+ cpu->isar.id_pfr0 = 0x00000030;
141
+ cpu->isar.id_pfr1 = 0x00000200;
142
+ cpu->isar.id_dfr0 = 0x00100000;
143
+ cpu->id_afr0 = 0x00000000;
144
+ cpu->isar.id_mmfr0 = 0x00000030;
145
+ cpu->isar.id_mmfr1 = 0x00000000;
146
+ cpu->isar.id_mmfr2 = 0x00000000;
147
+ cpu->isar.id_mmfr3 = 0x00000000;
148
+ cpu->isar.id_isar0 = 0x01141110;
149
+ cpu->isar.id_isar1 = 0x02111000;
150
+ cpu->isar.id_isar2 = 0x21112231;
151
+ cpu->isar.id_isar3 = 0x01111110;
152
+ cpu->isar.id_isar4 = 0x01310102;
153
+ cpu->isar.id_isar5 = 0x00000000;
154
+ cpu->isar.id_isar6 = 0x00000000;
155
+}
156
+
157
+static void cortex_m7_initfn(Object *obj)
158
+{
159
+ ARMCPU *cpu = ARM_CPU(obj);
160
+
161
+ set_feature(&cpu->env, ARM_FEATURE_V7);
162
+ set_feature(&cpu->env, ARM_FEATURE_M);
163
+ set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
164
+ set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP);
165
+ cpu->midr = 0x411fc272; /* r1p2 */
166
+ cpu->pmsav7_dregion = 8;
167
+ cpu->isar.mvfr0 = 0x10110221;
168
+ cpu->isar.mvfr1 = 0x12000011;
169
+ cpu->isar.mvfr2 = 0x00000040;
170
+ cpu->isar.id_pfr0 = 0x00000030;
171
+ cpu->isar.id_pfr1 = 0x00000200;
172
+ cpu->isar.id_dfr0 = 0x00100000;
173
+ cpu->id_afr0 = 0x00000000;
174
+ cpu->isar.id_mmfr0 = 0x00100030;
175
+ cpu->isar.id_mmfr1 = 0x00000000;
176
+ cpu->isar.id_mmfr2 = 0x01000000;
177
+ cpu->isar.id_mmfr3 = 0x00000000;
178
+ cpu->isar.id_isar0 = 0x01101110;
179
+ cpu->isar.id_isar1 = 0x02112000;
180
+ cpu->isar.id_isar2 = 0x20232231;
181
+ cpu->isar.id_isar3 = 0x01111131;
182
+ cpu->isar.id_isar4 = 0x01310132;
183
+ cpu->isar.id_isar5 = 0x00000000;
184
+ cpu->isar.id_isar6 = 0x00000000;
185
+}
186
+
187
+static void cortex_m33_initfn(Object *obj)
188
+{
189
+ ARMCPU *cpu = ARM_CPU(obj);
190
+
191
+ set_feature(&cpu->env, ARM_FEATURE_V8);
192
+ set_feature(&cpu->env, ARM_FEATURE_M);
193
+ set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
194
+ set_feature(&cpu->env, ARM_FEATURE_M_SECURITY);
195
+ set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP);
196
+ cpu->midr = 0x410fd213; /* r0p3 */
197
+ cpu->pmsav7_dregion = 16;
198
+ cpu->sau_sregion = 8;
199
+ cpu->isar.mvfr0 = 0x10110021;
200
+ cpu->isar.mvfr1 = 0x11000011;
201
+ cpu->isar.mvfr2 = 0x00000040;
202
+ cpu->isar.id_pfr0 = 0x00000030;
203
+ cpu->isar.id_pfr1 = 0x00000210;
204
+ cpu->isar.id_dfr0 = 0x00200000;
205
+ cpu->id_afr0 = 0x00000000;
206
+ cpu->isar.id_mmfr0 = 0x00101F40;
207
+ cpu->isar.id_mmfr1 = 0x00000000;
208
+ cpu->isar.id_mmfr2 = 0x01000000;
209
+ cpu->isar.id_mmfr3 = 0x00000000;
210
+ cpu->isar.id_isar0 = 0x01101110;
211
+ cpu->isar.id_isar1 = 0x02212000;
212
+ cpu->isar.id_isar2 = 0x20232232;
213
+ cpu->isar.id_isar3 = 0x01111131;
214
+ cpu->isar.id_isar4 = 0x01310132;
215
+ cpu->isar.id_isar5 = 0x00000000;
216
+ cpu->isar.id_isar6 = 0x00000000;
217
+ cpu->clidr = 0x00000000;
218
+ cpu->ctr = 0x8000c000;
219
+}
220
+
221
+static void cortex_m55_initfn(Object *obj)
222
+{
223
+ ARMCPU *cpu = ARM_CPU(obj);
224
+
225
+ set_feature(&cpu->env, ARM_FEATURE_V8);
226
+ set_feature(&cpu->env, ARM_FEATURE_V8_1M);
227
+ set_feature(&cpu->env, ARM_FEATURE_M);
228
+ set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
229
+ set_feature(&cpu->env, ARM_FEATURE_M_SECURITY);
230
+ set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP);
231
+ cpu->midr = 0x410fd221; /* r0p1 */
232
+ cpu->revidr = 0;
233
+ cpu->pmsav7_dregion = 16;
234
+ cpu->sau_sregion = 8;
235
+ /* These are the MVFR* values for the FPU + full MVE configuration */
236
+ cpu->isar.mvfr0 = 0x10110221;
237
+ cpu->isar.mvfr1 = 0x12100211;
238
+ cpu->isar.mvfr2 = 0x00000040;
239
+ cpu->isar.id_pfr0 = 0x20000030;
240
+ cpu->isar.id_pfr1 = 0x00000230;
241
+ cpu->isar.id_dfr0 = 0x10200000;
242
+ cpu->id_afr0 = 0x00000000;
243
+ cpu->isar.id_mmfr0 = 0x00111040;
244
+ cpu->isar.id_mmfr1 = 0x00000000;
245
+ cpu->isar.id_mmfr2 = 0x01000000;
246
+ cpu->isar.id_mmfr3 = 0x00000011;
247
+ cpu->isar.id_isar0 = 0x01103110;
248
+ cpu->isar.id_isar1 = 0x02212000;
249
+ cpu->isar.id_isar2 = 0x20232232;
250
+ cpu->isar.id_isar3 = 0x01111131;
251
+ cpu->isar.id_isar4 = 0x01310132;
252
+ cpu->isar.id_isar5 = 0x00000000;
253
+ cpu->isar.id_isar6 = 0x00000000;
254
+ cpu->clidr = 0x00000000; /* caches not implemented */
255
+ cpu->ctr = 0x8303c003;
256
+}
257
+
258
+static const TCGCPUOps arm_v7m_tcg_ops = {
259
+ .initialize = arm_translate_init,
260
+ .synchronize_from_tb = arm_cpu_synchronize_from_tb,
261
+ .debug_excp_handler = arm_debug_excp_handler,
262
+ .restore_state_to_opc = arm_restore_state_to_opc,
263
+
264
+#ifdef CONFIG_USER_ONLY
265
+ .record_sigsegv = arm_cpu_record_sigsegv,
266
+ .record_sigbus = arm_cpu_record_sigbus,
267
+#else
268
+ .tlb_fill = arm_cpu_tlb_fill,
269
+ .cpu_exec_interrupt = arm_v7m_cpu_exec_interrupt,
270
+ .do_interrupt = arm_v7m_cpu_do_interrupt,
271
+ .do_transaction_failed = arm_cpu_do_transaction_failed,
272
+ .do_unaligned_access = arm_cpu_do_unaligned_access,
273
+ .adjust_watchpoint_address = arm_adjust_watchpoint_address,
274
+ .debug_check_watchpoint = arm_debug_check_watchpoint,
275
+ .debug_check_breakpoint = arm_debug_check_breakpoint,
276
+#endif /* !CONFIG_USER_ONLY */
277
+};
278
+
279
+static void arm_v7m_class_init(ObjectClass *oc, void *data)
280
+{
281
+ ARMCPUClass *acc = ARM_CPU_CLASS(oc);
282
+ CPUClass *cc = CPU_CLASS(oc);
283
+
284
+ acc->info = data;
285
+ cc->tcg_ops = &arm_v7m_tcg_ops;
286
+ cc->gdb_core_xml_file = "arm-m-profile.xml";
287
+}
288
+
289
+static const ARMCPUInfo arm_v7m_cpus[] = {
290
+ { .name = "cortex-m0", .initfn = cortex_m0_initfn,
291
+ .class_init = arm_v7m_class_init },
292
+ { .name = "cortex-m3", .initfn = cortex_m3_initfn,
293
+ .class_init = arm_v7m_class_init },
294
+ { .name = "cortex-m4", .initfn = cortex_m4_initfn,
295
+ .class_init = arm_v7m_class_init },
296
+ { .name = "cortex-m7", .initfn = cortex_m7_initfn,
297
+ .class_init = arm_v7m_class_init },
298
+ { .name = "cortex-m33", .initfn = cortex_m33_initfn,
299
+ .class_init = arm_v7m_class_init },
300
+ { .name = "cortex-m55", .initfn = cortex_m55_initfn,
301
+ .class_init = arm_v7m_class_init },
302
+};
303
+
304
+static void arm_v7m_cpu_register_types(void)
305
+{
306
+ size_t i;
307
+
308
+ for (i = 0; i < ARRAY_SIZE(arm_v7m_cpus); ++i) {
309
+ arm_cpu_register(&arm_v7m_cpus[i]);
310
+ }
311
+}
312
+
313
+type_init(arm_v7m_cpu_register_types)
314
diff --git a/target/arm/tcg/cpu32.c b/target/arm/tcg/cpu32.c
124
index XXXXXXX..XXXXXXX 100644
315
index XXXXXXX..XXXXXXX 100644
125
--- a/include/hw/arm/smmu-common.h
316
--- a/target/arm/tcg/cpu32.c
126
+++ b/include/hw/arm/smmu-common.h
317
+++ b/target/arm/tcg/cpu32.c
127
@@ -XXX,XX +XXX,XX @@ static inline uint16_t smmu_get_sid(SMMUDevice *sdev)
318
@@ -XXX,XX +XXX,XX @@
319
#include "hw/boards.h"
320
#endif
321
#include "cpregs.h"
322
-#if !defined(CONFIG_USER_ONLY) && defined(CONFIG_TCG)
323
-#include "hw/intc/armv7m_nvic.h"
324
-#endif
325
326
327
/* Share AArch32 -cpu max features with AArch64. */
328
@@ -XXX,XX +XXX,XX @@ void aa32_max_features(ARMCPU *cpu)
329
/* CPU models. These are not needed for the AArch64 linux-user build. */
330
#if !defined(CONFIG_USER_ONLY) || !defined(TARGET_AARCH64)
331
332
-#if !defined(CONFIG_USER_ONLY)
333
-static bool arm_v7m_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
334
-{
335
- CPUClass *cc = CPU_GET_CLASS(cs);
336
- ARMCPU *cpu = ARM_CPU(cs);
337
- CPUARMState *env = &cpu->env;
338
- bool ret = false;
339
-
340
- /*
341
- * ARMv7-M interrupt masking works differently than -A or -R.
342
- * There is no FIQ/IRQ distinction. Instead of I and F bits
343
- * masking FIQ and IRQ interrupts, an exception is taken only
344
- * if it is higher priority than the current execution priority
345
- * (which depends on state like BASEPRI, FAULTMASK and the
346
- * currently active exception).
347
- */
348
- if (interrupt_request & CPU_INTERRUPT_HARD
349
- && (armv7m_nvic_can_take_pending_exception(env->nvic))) {
350
- cs->exception_index = EXCP_IRQ;
351
- cc->tcg_ops->do_interrupt(cs);
352
- ret = true;
353
- }
354
- return ret;
355
-}
356
-#endif /* !CONFIG_USER_ONLY */
357
-
358
static void arm926_initfn(Object *obj)
128
{
359
{
129
return PCI_BUILD_BDF(pci_bus_num(sdev->bus), sdev->devfn);
360
ARMCPU *cpu = ARM_CPU(obj);
361
@@ -XXX,XX +XXX,XX @@ static void cortex_a15_initfn(Object *obj)
362
define_arm_cp_regs(cpu, cortexa15_cp_reginfo);
130
}
363
}
131
+
364
132
+/**
365
-static void cortex_m0_initfn(Object *obj)
133
+ * smmu_ptw - Perform the page table walk for a given iova / access flags
366
-{
134
+ * pair, according to @cfg translation config
367
- ARMCPU *cpu = ARM_CPU(obj);
135
+ */
368
- set_feature(&cpu->env, ARM_FEATURE_V6);
136
+int smmu_ptw(SMMUTransCfg *cfg, dma_addr_t iova, IOMMUAccessFlags perm,
369
- set_feature(&cpu->env, ARM_FEATURE_M);
137
+ IOMMUTLBEntry *tlbe, SMMUPTWEventInfo *info);
370
-
138
+
371
- cpu->midr = 0x410cc200;
139
+/**
372
-
140
+ * select_tt - compute which translation table shall be used according to
373
- /*
141
+ * the input iova and translation config and return the TT specific info
374
- * These ID register values are not guest visible, because
142
+ */
375
- * we do not implement the Main Extension. They must be set
143
+SMMUTransTableInfo *select_tt(SMMUTransCfg *cfg, dma_addr_t iova);
376
- * to values corresponding to the Cortex-M0's implemented
144
+
377
- * features, because QEMU generally controls its emulation
145
#endif /* HW_ARM_SMMU_COMMON */
378
- * by looking at ID register fields. We use the same values as
146
diff --git a/hw/arm/smmu-common.c b/hw/arm/smmu-common.c
379
- * for the M3.
380
- */
381
- cpu->isar.id_pfr0 = 0x00000030;
382
- cpu->isar.id_pfr1 = 0x00000200;
383
- cpu->isar.id_dfr0 = 0x00100000;
384
- cpu->id_afr0 = 0x00000000;
385
- cpu->isar.id_mmfr0 = 0x00000030;
386
- cpu->isar.id_mmfr1 = 0x00000000;
387
- cpu->isar.id_mmfr2 = 0x00000000;
388
- cpu->isar.id_mmfr3 = 0x00000000;
389
- cpu->isar.id_isar0 = 0x01141110;
390
- cpu->isar.id_isar1 = 0x02111000;
391
- cpu->isar.id_isar2 = 0x21112231;
392
- cpu->isar.id_isar3 = 0x01111110;
393
- cpu->isar.id_isar4 = 0x01310102;
394
- cpu->isar.id_isar5 = 0x00000000;
395
- cpu->isar.id_isar6 = 0x00000000;
396
-}
397
-
398
-static void cortex_m3_initfn(Object *obj)
399
-{
400
- ARMCPU *cpu = ARM_CPU(obj);
401
- set_feature(&cpu->env, ARM_FEATURE_V7);
402
- set_feature(&cpu->env, ARM_FEATURE_M);
403
- set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
404
- cpu->midr = 0x410fc231;
405
- cpu->pmsav7_dregion = 8;
406
- cpu->isar.id_pfr0 = 0x00000030;
407
- cpu->isar.id_pfr1 = 0x00000200;
408
- cpu->isar.id_dfr0 = 0x00100000;
409
- cpu->id_afr0 = 0x00000000;
410
- cpu->isar.id_mmfr0 = 0x00000030;
411
- cpu->isar.id_mmfr1 = 0x00000000;
412
- cpu->isar.id_mmfr2 = 0x00000000;
413
- cpu->isar.id_mmfr3 = 0x00000000;
414
- cpu->isar.id_isar0 = 0x01141110;
415
- cpu->isar.id_isar1 = 0x02111000;
416
- cpu->isar.id_isar2 = 0x21112231;
417
- cpu->isar.id_isar3 = 0x01111110;
418
- cpu->isar.id_isar4 = 0x01310102;
419
- cpu->isar.id_isar5 = 0x00000000;
420
- cpu->isar.id_isar6 = 0x00000000;
421
-}
422
-
423
-static void cortex_m4_initfn(Object *obj)
424
-{
425
- ARMCPU *cpu = ARM_CPU(obj);
426
-
427
- set_feature(&cpu->env, ARM_FEATURE_V7);
428
- set_feature(&cpu->env, ARM_FEATURE_M);
429
- set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
430
- set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP);
431
- cpu->midr = 0x410fc240; /* r0p0 */
432
- cpu->pmsav7_dregion = 8;
433
- cpu->isar.mvfr0 = 0x10110021;
434
- cpu->isar.mvfr1 = 0x11000011;
435
- cpu->isar.mvfr2 = 0x00000000;
436
- cpu->isar.id_pfr0 = 0x00000030;
437
- cpu->isar.id_pfr1 = 0x00000200;
438
- cpu->isar.id_dfr0 = 0x00100000;
439
- cpu->id_afr0 = 0x00000000;
440
- cpu->isar.id_mmfr0 = 0x00000030;
441
- cpu->isar.id_mmfr1 = 0x00000000;
442
- cpu->isar.id_mmfr2 = 0x00000000;
443
- cpu->isar.id_mmfr3 = 0x00000000;
444
- cpu->isar.id_isar0 = 0x01141110;
445
- cpu->isar.id_isar1 = 0x02111000;
446
- cpu->isar.id_isar2 = 0x21112231;
447
- cpu->isar.id_isar3 = 0x01111110;
448
- cpu->isar.id_isar4 = 0x01310102;
449
- cpu->isar.id_isar5 = 0x00000000;
450
- cpu->isar.id_isar6 = 0x00000000;
451
-}
452
-
453
-static void cortex_m7_initfn(Object *obj)
454
-{
455
- ARMCPU *cpu = ARM_CPU(obj);
456
-
457
- set_feature(&cpu->env, ARM_FEATURE_V7);
458
- set_feature(&cpu->env, ARM_FEATURE_M);
459
- set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
460
- set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP);
461
- cpu->midr = 0x411fc272; /* r1p2 */
462
- cpu->pmsav7_dregion = 8;
463
- cpu->isar.mvfr0 = 0x10110221;
464
- cpu->isar.mvfr1 = 0x12000011;
465
- cpu->isar.mvfr2 = 0x00000040;
466
- cpu->isar.id_pfr0 = 0x00000030;
467
- cpu->isar.id_pfr1 = 0x00000200;
468
- cpu->isar.id_dfr0 = 0x00100000;
469
- cpu->id_afr0 = 0x00000000;
470
- cpu->isar.id_mmfr0 = 0x00100030;
471
- cpu->isar.id_mmfr1 = 0x00000000;
472
- cpu->isar.id_mmfr2 = 0x01000000;
473
- cpu->isar.id_mmfr3 = 0x00000000;
474
- cpu->isar.id_isar0 = 0x01101110;
475
- cpu->isar.id_isar1 = 0x02112000;
476
- cpu->isar.id_isar2 = 0x20232231;
477
- cpu->isar.id_isar3 = 0x01111131;
478
- cpu->isar.id_isar4 = 0x01310132;
479
- cpu->isar.id_isar5 = 0x00000000;
480
- cpu->isar.id_isar6 = 0x00000000;
481
-}
482
-
483
-static void cortex_m33_initfn(Object *obj)
484
-{
485
- ARMCPU *cpu = ARM_CPU(obj);
486
-
487
- set_feature(&cpu->env, ARM_FEATURE_V8);
488
- set_feature(&cpu->env, ARM_FEATURE_M);
489
- set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
490
- set_feature(&cpu->env, ARM_FEATURE_M_SECURITY);
491
- set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP);
492
- cpu->midr = 0x410fd213; /* r0p3 */
493
- cpu->pmsav7_dregion = 16;
494
- cpu->sau_sregion = 8;
495
- cpu->isar.mvfr0 = 0x10110021;
496
- cpu->isar.mvfr1 = 0x11000011;
497
- cpu->isar.mvfr2 = 0x00000040;
498
- cpu->isar.id_pfr0 = 0x00000030;
499
- cpu->isar.id_pfr1 = 0x00000210;
500
- cpu->isar.id_dfr0 = 0x00200000;
501
- cpu->id_afr0 = 0x00000000;
502
- cpu->isar.id_mmfr0 = 0x00101F40;
503
- cpu->isar.id_mmfr1 = 0x00000000;
504
- cpu->isar.id_mmfr2 = 0x01000000;
505
- cpu->isar.id_mmfr3 = 0x00000000;
506
- cpu->isar.id_isar0 = 0x01101110;
507
- cpu->isar.id_isar1 = 0x02212000;
508
- cpu->isar.id_isar2 = 0x20232232;
509
- cpu->isar.id_isar3 = 0x01111131;
510
- cpu->isar.id_isar4 = 0x01310132;
511
- cpu->isar.id_isar5 = 0x00000000;
512
- cpu->isar.id_isar6 = 0x00000000;
513
- cpu->clidr = 0x00000000;
514
- cpu->ctr = 0x8000c000;
515
-}
516
-
517
-static void cortex_m55_initfn(Object *obj)
518
-{
519
- ARMCPU *cpu = ARM_CPU(obj);
520
-
521
- set_feature(&cpu->env, ARM_FEATURE_V8);
522
- set_feature(&cpu->env, ARM_FEATURE_V8_1M);
523
- set_feature(&cpu->env, ARM_FEATURE_M);
524
- set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
525
- set_feature(&cpu->env, ARM_FEATURE_M_SECURITY);
526
- set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP);
527
- cpu->midr = 0x410fd221; /* r0p1 */
528
- cpu->revidr = 0;
529
- cpu->pmsav7_dregion = 16;
530
- cpu->sau_sregion = 8;
531
- /* These are the MVFR* values for the FPU + full MVE configuration */
532
- cpu->isar.mvfr0 = 0x10110221;
533
- cpu->isar.mvfr1 = 0x12100211;
534
- cpu->isar.mvfr2 = 0x00000040;
535
- cpu->isar.id_pfr0 = 0x20000030;
536
- cpu->isar.id_pfr1 = 0x00000230;
537
- cpu->isar.id_dfr0 = 0x10200000;
538
- cpu->id_afr0 = 0x00000000;
539
- cpu->isar.id_mmfr0 = 0x00111040;
540
- cpu->isar.id_mmfr1 = 0x00000000;
541
- cpu->isar.id_mmfr2 = 0x01000000;
542
- cpu->isar.id_mmfr3 = 0x00000011;
543
- cpu->isar.id_isar0 = 0x01103110;
544
- cpu->isar.id_isar1 = 0x02212000;
545
- cpu->isar.id_isar2 = 0x20232232;
546
- cpu->isar.id_isar3 = 0x01111131;
547
- cpu->isar.id_isar4 = 0x01310132;
548
- cpu->isar.id_isar5 = 0x00000000;
549
- cpu->isar.id_isar6 = 0x00000000;
550
- cpu->clidr = 0x00000000; /* caches not implemented */
551
- cpu->ctr = 0x8303c003;
552
-}
553
-
554
static const ARMCPRegInfo cortexr5_cp_reginfo[] = {
555
/* Dummy the TCM region regs for the moment */
556
{ .name = "ATCM", .cp = 15, .opc1 = 0, .crn = 9, .crm = 1, .opc2 = 0,
557
@@ -XXX,XX +XXX,XX @@ static void pxa270c5_initfn(Object *obj)
558
cpu->reset_sctlr = 0x00000078;
559
}
560
561
-static const TCGCPUOps arm_v7m_tcg_ops = {
562
- .initialize = arm_translate_init,
563
- .synchronize_from_tb = arm_cpu_synchronize_from_tb,
564
- .debug_excp_handler = arm_debug_excp_handler,
565
- .restore_state_to_opc = arm_restore_state_to_opc,
566
-
567
-#ifdef CONFIG_USER_ONLY
568
- .record_sigsegv = arm_cpu_record_sigsegv,
569
- .record_sigbus = arm_cpu_record_sigbus,
570
-#else
571
- .tlb_fill = arm_cpu_tlb_fill,
572
- .cpu_exec_interrupt = arm_v7m_cpu_exec_interrupt,
573
- .do_interrupt = arm_v7m_cpu_do_interrupt,
574
- .do_transaction_failed = arm_cpu_do_transaction_failed,
575
- .do_unaligned_access = arm_cpu_do_unaligned_access,
576
- .adjust_watchpoint_address = arm_adjust_watchpoint_address,
577
- .debug_check_watchpoint = arm_debug_check_watchpoint,
578
- .debug_check_breakpoint = arm_debug_check_breakpoint,
579
-#endif /* !CONFIG_USER_ONLY */
580
-};
581
-
582
-static void arm_v7m_class_init(ObjectClass *oc, void *data)
583
-{
584
- ARMCPUClass *acc = ARM_CPU_CLASS(oc);
585
- CPUClass *cc = CPU_CLASS(oc);
586
-
587
- acc->info = data;
588
- cc->tcg_ops = &arm_v7m_tcg_ops;
589
- cc->gdb_core_xml_file = "arm-m-profile.xml";
590
-}
591
-
592
#ifndef TARGET_AARCH64
593
/*
594
* -cpu max: a CPU with as many features enabled as our emulation supports.
595
@@ -XXX,XX +XXX,XX @@ static const ARMCPUInfo arm_tcg_cpus[] = {
596
{ .name = "cortex-a8", .initfn = cortex_a8_initfn },
597
{ .name = "cortex-a9", .initfn = cortex_a9_initfn },
598
{ .name = "cortex-a15", .initfn = cortex_a15_initfn },
599
- { .name = "cortex-m0", .initfn = cortex_m0_initfn,
600
- .class_init = arm_v7m_class_init },
601
- { .name = "cortex-m3", .initfn = cortex_m3_initfn,
602
- .class_init = arm_v7m_class_init },
603
- { .name = "cortex-m4", .initfn = cortex_m4_initfn,
604
- .class_init = arm_v7m_class_init },
605
- { .name = "cortex-m7", .initfn = cortex_m7_initfn,
606
- .class_init = arm_v7m_class_init },
607
- { .name = "cortex-m33", .initfn = cortex_m33_initfn,
608
- .class_init = arm_v7m_class_init },
609
- { .name = "cortex-m55", .initfn = cortex_m55_initfn,
610
- .class_init = arm_v7m_class_init },
611
{ .name = "cortex-r5", .initfn = cortex_r5_initfn },
612
{ .name = "cortex-r5f", .initfn = cortex_r5f_initfn },
613
{ .name = "cortex-r52", .initfn = cortex_r52_initfn },
614
diff --git a/target/arm/meson.build b/target/arm/meson.build
147
index XXXXXXX..XXXXXXX 100644
615
index XXXXXXX..XXXXXXX 100644
148
--- a/hw/arm/smmu-common.c
616
--- a/target/arm/meson.build
149
+++ b/hw/arm/smmu-common.c
617
+++ b/target/arm/meson.build
150
@@ -XXX,XX +XXX,XX @@
618
@@ -XXX,XX +XXX,XX @@ arm_system_ss.add(files(
151
619
'ptw.c',
152
#include "qemu/error-report.h"
620
))
153
#include "hw/arm/smmu-common.h"
621
154
+#include "smmu-internal.h"
622
+arm_user_ss = ss.source_set()
155
+
623
+
156
+/* VMSAv8-64 Translation */
624
subdir('hvf')
157
+
625
158
+/**
626
if 'CONFIG_TCG' in config_all_accel
159
+ * get_pte - Get the content of a page table entry located at
627
@@ -XXX,XX +XXX,XX @@ endif
160
+ * @base_addr[@index]
628
161
+ */
629
target_arch += {'arm': arm_ss}
162
+static int get_pte(dma_addr_t baseaddr, uint32_t index, uint64_t *pte,
630
target_system_arch += {'arm': arm_system_ss}
163
+ SMMUPTWEventInfo *info)
631
+target_user_arch += {'arm': arm_user_ss}
164
+{
632
diff --git a/target/arm/tcg/meson.build b/target/arm/tcg/meson.build
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
633
index XXXXXXX..XXXXXXX 100644
381
--- a/hw/arm/trace-events
634
--- a/target/arm/tcg/meson.build
382
+++ b/hw/arm/trace-events
635
+++ b/target/arm/tcg/meson.build
383
@@ -XXX,XX +XXX,XX @@
636
@@ -XXX,XX +XXX,XX @@ arm_ss.add(when: 'TARGET_AARCH64', if_true: files(
384
virt_acpi_setup(void) "No fw cfg or ACPI disabled. Bailing out."
637
arm_system_ss.add(files(
385
638
'psci.c',
386
# hw/arm/smmu-common.c
639
))
387
-smmu_add_mr(const char *name) "%s"
640
+
388
\ No newline at end of file
641
+arm_system_ss.add(when: 'CONFIG_ARM_V7M', if_true: files('cpu-v7m.c'))
389
+smmu_add_mr(const char *name) "%s"
642
+arm_user_ss.add(when: 'TARGET_AARCH64', if_false: files('cpu-v7m.c'))
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
--
643
--
398
2.17.0
644
2.34.1
399
400
diff view generated by jsdifflib
Deleted patch
1
From: Eric Auger <eric.auger@redhat.com>
2
1
3
We introduce some helpers to handle wired IRQs and especially
4
GERROR interrupt. SMMU writes GERROR register on GERROR event
5
and SW acks GERROR interrupts by setting GERRORn.
6
7
The Wired interrupts are edge sensitive hence the pulse usage.
8
9
Signed-off-by: Eric Auger <eric.auger@redhat.com>
10
Signed-off-by: Prem Mallappa <prem.mallappa@broadcom.com>
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
Message-id: 1524665762-31355-6-git-send-email-eric.auger@redhat.com
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
15
hw/arm/smmuv3-internal.h | 14 +++++++++
16
hw/arm/smmuv3.c | 64 ++++++++++++++++++++++++++++++++++++++++
17
hw/arm/trace-events | 3 ++
18
3 files changed, 81 insertions(+)
19
20
diff --git a/hw/arm/smmuv3-internal.h b/hw/arm/smmuv3-internal.h
21
index XXXXXXX..XXXXXXX 100644
22
--- a/hw/arm/smmuv3-internal.h
23
+++ b/hw/arm/smmuv3-internal.h
24
@@ -XXX,XX +XXX,XX @@ static inline uint32_t smmuv3_idreg(int regoffset)
25
return smmuv3_ids[regoffset / 4];
26
}
27
28
+static inline bool smmuv3_eventq_irq_enabled(SMMUv3State *s)
29
+{
30
+ return FIELD_EX32(s->irq_ctrl, IRQ_CTRL, EVENTQ_IRQEN);
31
+}
32
+
33
+static inline bool smmuv3_gerror_irq_enabled(SMMUv3State *s)
34
+{
35
+ return FIELD_EX32(s->irq_ctrl, IRQ_CTRL, GERROR_IRQEN);
36
+}
37
+
38
+/* public until callers get introduced */
39
+void smmuv3_trigger_irq(SMMUv3State *s, SMMUIrq irq, uint32_t gerror_mask);
40
+void smmuv3_write_gerrorn(SMMUv3State *s, uint32_t gerrorn);
41
+
42
#endif
43
diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c
44
index XXXXXXX..XXXXXXX 100644
45
--- a/hw/arm/smmuv3.c
46
+++ b/hw/arm/smmuv3.c
47
@@ -XXX,XX +XXX,XX @@
48
#include "hw/arm/smmuv3.h"
49
#include "smmuv3-internal.h"
50
51
+/**
52
+ * smmuv3_trigger_irq - pulse @irq if enabled and update
53
+ * GERROR register in case of GERROR interrupt
54
+ *
55
+ * @irq: irq type
56
+ * @gerror_mask: mask of gerrors to toggle (relevant if @irq is GERROR)
57
+ */
58
+void smmuv3_trigger_irq(SMMUv3State *s, SMMUIrq irq, uint32_t gerror_mask)
59
+{
60
+
61
+ bool pulse = false;
62
+
63
+ switch (irq) {
64
+ case SMMU_IRQ_EVTQ:
65
+ pulse = smmuv3_eventq_irq_enabled(s);
66
+ break;
67
+ case SMMU_IRQ_PRIQ:
68
+ qemu_log_mask(LOG_UNIMP, "PRI not yet supported\n");
69
+ break;
70
+ case SMMU_IRQ_CMD_SYNC:
71
+ pulse = true;
72
+ break;
73
+ case SMMU_IRQ_GERROR:
74
+ {
75
+ uint32_t pending = s->gerror ^ s->gerrorn;
76
+ uint32_t new_gerrors = ~pending & gerror_mask;
77
+
78
+ if (!new_gerrors) {
79
+ /* only toggle non pending errors */
80
+ return;
81
+ }
82
+ s->gerror ^= new_gerrors;
83
+ trace_smmuv3_write_gerror(new_gerrors, s->gerror);
84
+
85
+ pulse = smmuv3_gerror_irq_enabled(s);
86
+ break;
87
+ }
88
+ }
89
+ if (pulse) {
90
+ trace_smmuv3_trigger_irq(irq);
91
+ qemu_irq_pulse(s->irq[irq]);
92
+ }
93
+}
94
+
95
+void smmuv3_write_gerrorn(SMMUv3State *s, uint32_t new_gerrorn)
96
+{
97
+ uint32_t pending = s->gerror ^ s->gerrorn;
98
+ uint32_t toggled = s->gerrorn ^ new_gerrorn;
99
+
100
+ if (toggled & ~pending) {
101
+ qemu_log_mask(LOG_GUEST_ERROR,
102
+ "guest toggles non pending errors = 0x%x\n",
103
+ toggled & ~pending);
104
+ }
105
+
106
+ /*
107
+ * We do not raise any error in case guest toggles bits corresponding
108
+ * to not active IRQs (CONSTRAINED UNPREDICTABLE)
109
+ */
110
+ s->gerrorn = new_gerrorn;
111
+
112
+ trace_smmuv3_write_gerrorn(toggled & pending, s->gerrorn);
113
+}
114
+
115
static void smmuv3_init_regs(SMMUv3State *s)
116
{
117
/**
118
diff --git a/hw/arm/trace-events b/hw/arm/trace-events
119
index XXXXXXX..XXXXXXX 100644
120
--- a/hw/arm/trace-events
121
+++ b/hw/arm/trace-events
122
@@ -XXX,XX +XXX,XX @@ smmu_get_pte(uint64_t baseaddr, int index, uint64_t pteaddr, uint64_t pte) "base
123
124
#hw/arm/smmuv3.c
125
smmuv3_read_mmio(uint64_t addr, uint64_t val, unsigned size, uint32_t r) "addr: 0x%"PRIx64" val:0x%"PRIx64" size: 0x%x(%d)"
126
+smmuv3_trigger_irq(int irq) "irq=%d"
127
+smmuv3_write_gerror(uint32_t toggled, uint32_t gerror) "toggled=0x%x, new GERROR=0x%x"
128
+smmuv3_write_gerrorn(uint32_t acked, uint32_t gerrorn) "acked=0x%x, new GERRORN=0x%x"
129
--
130
2.17.0
131
132
diff view generated by jsdifflib
Deleted patch
1
From: Eric Auger <eric.auger@redhat.com>
2
1
3
Now we have relevant helpers for queue and irq
4
management, let's implement MMIO write operations.
5
6
Signed-off-by: Eric Auger <eric.auger@redhat.com>
7
Signed-off-by: Prem Mallappa <prem.mallappa@broadcom.com>
8
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>
11
---
12
hw/arm/smmuv3-internal.h | 8 +-
13
hw/arm/smmuv3.c | 170 +++++++++++++++++++++++++++++++++++++--
14
hw/arm/trace-events | 6 ++
15
3 files changed, 174 insertions(+), 10 deletions(-)
16
17
diff --git a/hw/arm/smmuv3-internal.h b/hw/arm/smmuv3-internal.h
18
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/arm/smmuv3-internal.h
20
+++ b/hw/arm/smmuv3-internal.h
21
@@ -XXX,XX +XXX,XX @@ REG32(CR0, 0x20)
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
}
65
}
66
67
-void smmuv3_write_gerrorn(SMMUv3State *s, uint32_t new_gerrorn)
68
+static void smmuv3_write_gerrorn(SMMUv3State *s, uint32_t new_gerrorn)
69
{
70
uint32_t pending = s->gerror ^ s->gerrorn;
71
uint32_t toggled = s->gerrorn ^ new_gerrorn;
72
@@ -XXX,XX +XXX,XX @@ static void smmuv3_init_regs(SMMUv3State *s)
73
s->sid_split = 0;
74
}
75
76
-int smmuv3_cmdq_consume(SMMUv3State *s)
77
+static int smmuv3_cmdq_consume(SMMUv3State *s)
78
{
79
SMMUCmdError cmd_error = SMMU_CERROR_NONE;
80
SMMUQueue *q = &s->cmdq;
81
@@ -XXX,XX +XXX,XX @@ int smmuv3_cmdq_consume(SMMUv3State *s)
82
return 0;
83
}
84
85
+static MemTxResult smmu_writell(SMMUv3State *s, hwaddr offset,
86
+ uint64_t data, MemTxAttrs attrs)
87
+{
88
+ switch (offset) {
89
+ case A_GERROR_IRQ_CFG0:
90
+ s->gerror_irq_cfg0 = data;
91
+ return MEMTX_OK;
92
+ case A_STRTAB_BASE:
93
+ s->strtab_base = data;
94
+ return MEMTX_OK;
95
+ case A_CMDQ_BASE:
96
+ s->cmdq.base = data;
97
+ s->cmdq.log2size = extract64(s->cmdq.base, 0, 5);
98
+ if (s->cmdq.log2size > SMMU_CMDQS) {
99
+ s->cmdq.log2size = SMMU_CMDQS;
100
+ }
101
+ return MEMTX_OK;
102
+ case A_EVENTQ_BASE:
103
+ s->eventq.base = data;
104
+ s->eventq.log2size = extract64(s->eventq.base, 0, 5);
105
+ if (s->eventq.log2size > SMMU_EVENTQS) {
106
+ s->eventq.log2size = SMMU_EVENTQS;
107
+ }
108
+ return MEMTX_OK;
109
+ case A_EVENTQ_IRQ_CFG0:
110
+ s->eventq_irq_cfg0 = data;
111
+ return MEMTX_OK;
112
+ default:
113
+ qemu_log_mask(LOG_UNIMP,
114
+ "%s Unexpected 64-bit access to 0x%"PRIx64" (WI)\n",
115
+ __func__, offset);
116
+ return MEMTX_OK;
117
+ }
118
+}
119
+
120
+static MemTxResult smmu_writel(SMMUv3State *s, hwaddr offset,
121
+ uint64_t data, MemTxAttrs attrs)
122
+{
123
+ switch (offset) {
124
+ case A_CR0:
125
+ s->cr[0] = data;
126
+ s->cr0ack = data & ~SMMU_CR0_RESERVED;
127
+ /* in case the command queue has been enabled */
128
+ smmuv3_cmdq_consume(s);
129
+ return MEMTX_OK;
130
+ case A_CR1:
131
+ s->cr[1] = data;
132
+ return MEMTX_OK;
133
+ case A_CR2:
134
+ s->cr[2] = data;
135
+ return MEMTX_OK;
136
+ case A_IRQ_CTRL:
137
+ s->irq_ctrl = data;
138
+ return MEMTX_OK;
139
+ case A_GERRORN:
140
+ smmuv3_write_gerrorn(s, data);
141
+ /*
142
+ * By acknowledging the CMDQ_ERR, SW may notify cmds can
143
+ * be processed again
144
+ */
145
+ smmuv3_cmdq_consume(s);
146
+ return MEMTX_OK;
147
+ case A_GERROR_IRQ_CFG0: /* 64b */
148
+ s->gerror_irq_cfg0 = deposit64(s->gerror_irq_cfg0, 0, 32, data);
149
+ return MEMTX_OK;
150
+ case A_GERROR_IRQ_CFG0 + 4:
151
+ s->gerror_irq_cfg0 = deposit64(s->gerror_irq_cfg0, 32, 32, data);
152
+ return MEMTX_OK;
153
+ case A_GERROR_IRQ_CFG1:
154
+ s->gerror_irq_cfg1 = data;
155
+ return MEMTX_OK;
156
+ case A_GERROR_IRQ_CFG2:
157
+ s->gerror_irq_cfg2 = data;
158
+ return MEMTX_OK;
159
+ case A_STRTAB_BASE: /* 64b */
160
+ s->strtab_base = deposit64(s->strtab_base, 0, 32, data);
161
+ return MEMTX_OK;
162
+ case A_STRTAB_BASE + 4:
163
+ s->strtab_base = deposit64(s->strtab_base, 32, 32, data);
164
+ return MEMTX_OK;
165
+ case A_STRTAB_BASE_CFG:
166
+ s->strtab_base_cfg = data;
167
+ if (FIELD_EX32(data, STRTAB_BASE_CFG, FMT) == 1) {
168
+ s->sid_split = FIELD_EX32(data, STRTAB_BASE_CFG, SPLIT);
169
+ s->features |= SMMU_FEATURE_2LVL_STE;
170
+ }
171
+ return MEMTX_OK;
172
+ case A_CMDQ_BASE: /* 64b */
173
+ s->cmdq.base = deposit64(s->cmdq.base, 0, 32, data);
174
+ s->cmdq.log2size = extract64(s->cmdq.base, 0, 5);
175
+ if (s->cmdq.log2size > SMMU_CMDQS) {
176
+ s->cmdq.log2size = SMMU_CMDQS;
177
+ }
178
+ return MEMTX_OK;
179
+ case A_CMDQ_BASE + 4: /* 64b */
180
+ s->cmdq.base = deposit64(s->cmdq.base, 32, 32, data);
181
+ return MEMTX_OK;
182
+ case A_CMDQ_PROD:
183
+ s->cmdq.prod = data;
184
+ smmuv3_cmdq_consume(s);
185
+ return MEMTX_OK;
186
+ case A_CMDQ_CONS:
187
+ s->cmdq.cons = data;
188
+ return MEMTX_OK;
189
+ case A_EVENTQ_BASE: /* 64b */
190
+ s->eventq.base = deposit64(s->eventq.base, 0, 32, data);
191
+ s->eventq.log2size = extract64(s->eventq.base, 0, 5);
192
+ if (s->eventq.log2size > SMMU_EVENTQS) {
193
+ s->eventq.log2size = SMMU_EVENTQS;
194
+ }
195
+ return MEMTX_OK;
196
+ case A_EVENTQ_BASE + 4:
197
+ s->eventq.base = deposit64(s->eventq.base, 32, 32, data);
198
+ return MEMTX_OK;
199
+ case A_EVENTQ_PROD:
200
+ s->eventq.prod = data;
201
+ return MEMTX_OK;
202
+ case A_EVENTQ_CONS:
203
+ s->eventq.cons = data;
204
+ return MEMTX_OK;
205
+ case A_EVENTQ_IRQ_CFG0: /* 64b */
206
+ s->eventq_irq_cfg0 = deposit64(s->eventq_irq_cfg0, 0, 32, data);
207
+ return MEMTX_OK;
208
+ case A_EVENTQ_IRQ_CFG0 + 4:
209
+ s->eventq_irq_cfg0 = deposit64(s->eventq_irq_cfg0, 32, 32, data);
210
+ return MEMTX_OK;
211
+ case A_EVENTQ_IRQ_CFG1:
212
+ s->eventq_irq_cfg1 = data;
213
+ return MEMTX_OK;
214
+ case A_EVENTQ_IRQ_CFG2:
215
+ s->eventq_irq_cfg2 = data;
216
+ return MEMTX_OK;
217
+ default:
218
+ qemu_log_mask(LOG_UNIMP,
219
+ "%s Unexpected 32-bit access to 0x%"PRIx64" (WI)\n",
220
+ __func__, offset);
221
+ return MEMTX_OK;
222
+ }
223
+}
224
+
225
static MemTxResult smmu_write_mmio(void *opaque, hwaddr offset, uint64_t data,
226
unsigned size, MemTxAttrs attrs)
227
{
228
- /* not yet implemented */
229
- return MEMTX_ERROR;
230
+ SMMUState *sys = opaque;
231
+ SMMUv3State *s = ARM_SMMUV3(sys);
232
+ MemTxResult r;
233
+
234
+ /* CONSTRAINED UNPREDICTABLE choice to have page0/1 be exact aliases */
235
+ offset &= ~0x10000;
236
+
237
+ switch (size) {
238
+ case 8:
239
+ r = smmu_writell(s, offset, data, attrs);
240
+ break;
241
+ case 4:
242
+ r = smmu_writel(s, offset, data, attrs);
243
+ break;
244
+ default:
245
+ r = MEMTX_ERROR;
246
+ break;
247
+ }
248
+
249
+ trace_smmuv3_write_mmio(offset, data, size, r);
250
+ return r;
251
}
252
253
static MemTxResult smmu_readll(SMMUv3State *s, hwaddr offset,
254
diff --git a/hw/arm/trace-events b/hw/arm/trace-events
255
index XXXXXXX..XXXXXXX 100644
256
--- a/hw/arm/trace-events
257
+++ b/hw/arm/trace-events
258
@@ -XXX,XX +XXX,XX @@ smmuv3_cmdq_consume(uint32_t prod, uint32_t cons, uint8_t prod_wrap, uint8_t con
259
smmuv3_cmdq_opcode(const char *opcode) "<--- %s"
260
smmuv3_cmdq_consume_out(uint32_t prod, uint32_t cons, uint8_t prod_wrap, uint8_t cons_wrap) "prod:%d, cons:%d, prod_wrap:%d, cons_wrap:%d "
261
smmuv3_cmdq_consume_error(const char *cmd_name, uint8_t cmd_error) "Error on %s command execution: %d"
262
+smmuv3_update(bool is_empty, uint32_t prod, uint32_t cons, uint8_t prod_wrap, uint8_t cons_wrap) "q empty:%d prod:%d cons:%d p.wrap:%d p.cons:%d"
263
+smmuv3_update_check_cmd(int error) "cmdq not enabled or error :0x%x"
264
+smmuv3_write_mmio(uint64_t addr, uint64_t val, unsigned size, uint32_t r) "addr: 0x%"PRIx64" val:0x%"PRIx64" size: 0x%x(%d)"
265
+smmuv3_write_mmio_idr(uint64_t addr, uint64_t val) "write to RO/Unimpl reg 0x%lx val64:0x%lx"
266
+smmuv3_write_mmio_evtq_cons_bef_clear(uint32_t prod, uint32_t cons, uint8_t prod_wrap, uint8_t cons_wrap) "Before clearing interrupt prod:0x%x cons:0x%x prod.w:%d cons.w:%d"
267
+smmuv3_write_mmio_evtq_cons_after_clear(uint32_t prod, uint32_t cons, uint8_t prod_wrap, uint8_t cons_wrap) "after clearing interrupt prod:0x%x cons:0x%x prod.w:%d cons.w:%d"
268
--
269
2.17.0
270
271
diff view generated by jsdifflib
Deleted patch
1
From: Eric Auger <eric.auger@redhat.com>
2
1
3
Let's introduce a helper function aiming at recording an
4
event in the event queue.
5
6
Signed-off-by: Eric Auger <eric.auger@redhat.com>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Message-id: 1524665762-31355-9-git-send-email-eric.auger@redhat.com
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
hw/arm/smmuv3-internal.h | 148 ++++++++++++++++++++++++++++++++++++++-
12
hw/arm/smmuv3.c | 108 ++++++++++++++++++++++++++--
13
hw/arm/trace-events | 1 +
14
3 files changed, 249 insertions(+), 8 deletions(-)
15
16
diff --git a/hw/arm/smmuv3-internal.h b/hw/arm/smmuv3-internal.h
17
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/arm/smmuv3-internal.h
19
+++ b/hw/arm/smmuv3-internal.h
20
@@ -XXX,XX +XXX,XX @@ static inline void smmu_write_cmdq_err(SMMUv3State *s, uint32_t err_type)
21
s->cmdq.cons = FIELD_DP32(s->cmdq.cons, CMDQ_CONS, ERR, err_type);
22
}
23
24
-void smmuv3_write_eventq(SMMUv3State *s, Evt *evt);
25
-
26
/* Commands */
27
28
typedef enum SMMUCommandType {
29
@@ -XXX,XX +XXX,XX @@ enum { /* Command completion notification */
30
31
#define SMMU_FEATURE_2LVL_STE (1 << 0)
32
33
+/* Events */
34
+
35
+typedef enum SMMUEventType {
36
+ SMMU_EVT_OK = 0x00,
37
+ SMMU_EVT_F_UUT ,
38
+ SMMU_EVT_C_BAD_STREAMID ,
39
+ SMMU_EVT_F_STE_FETCH ,
40
+ SMMU_EVT_C_BAD_STE ,
41
+ SMMU_EVT_F_BAD_ATS_TREQ ,
42
+ SMMU_EVT_F_STREAM_DISABLED ,
43
+ SMMU_EVT_F_TRANS_FORBIDDEN ,
44
+ SMMU_EVT_C_BAD_SUBSTREAMID ,
45
+ SMMU_EVT_F_CD_FETCH ,
46
+ SMMU_EVT_C_BAD_CD ,
47
+ SMMU_EVT_F_WALK_EABT ,
48
+ SMMU_EVT_F_TRANSLATION = 0x10,
49
+ SMMU_EVT_F_ADDR_SIZE ,
50
+ SMMU_EVT_F_ACCESS ,
51
+ SMMU_EVT_F_PERMISSION ,
52
+ SMMU_EVT_F_TLB_CONFLICT = 0x20,
53
+ SMMU_EVT_F_CFG_CONFLICT ,
54
+ SMMU_EVT_E_PAGE_REQ = 0x24,
55
+} SMMUEventType;
56
+
57
+static const char *event_stringify[] = {
58
+ [SMMU_EVT_OK] = "SMMU_EVT_OK",
59
+ [SMMU_EVT_F_UUT] = "SMMU_EVT_F_UUT",
60
+ [SMMU_EVT_C_BAD_STREAMID] = "SMMU_EVT_C_BAD_STREAMID",
61
+ [SMMU_EVT_F_STE_FETCH] = "SMMU_EVT_F_STE_FETCH",
62
+ [SMMU_EVT_C_BAD_STE] = "SMMU_EVT_C_BAD_STE",
63
+ [SMMU_EVT_F_BAD_ATS_TREQ] = "SMMU_EVT_F_BAD_ATS_TREQ",
64
+ [SMMU_EVT_F_STREAM_DISABLED] = "SMMU_EVT_F_STREAM_DISABLED",
65
+ [SMMU_EVT_F_TRANS_FORBIDDEN] = "SMMU_EVT_F_TRANS_FORBIDDEN",
66
+ [SMMU_EVT_C_BAD_SUBSTREAMID] = "SMMU_EVT_C_BAD_SUBSTREAMID",
67
+ [SMMU_EVT_F_CD_FETCH] = "SMMU_EVT_F_CD_FETCH",
68
+ [SMMU_EVT_C_BAD_CD] = "SMMU_EVT_C_BAD_CD",
69
+ [SMMU_EVT_F_WALK_EABT] = "SMMU_EVT_F_WALK_EABT",
70
+ [SMMU_EVT_F_TRANSLATION] = "SMMU_EVT_F_TRANSLATION",
71
+ [SMMU_EVT_F_ADDR_SIZE] = "SMMU_EVT_F_ADDR_SIZE",
72
+ [SMMU_EVT_F_ACCESS] = "SMMU_EVT_F_ACCESS",
73
+ [SMMU_EVT_F_PERMISSION] = "SMMU_EVT_F_PERMISSION",
74
+ [SMMU_EVT_F_TLB_CONFLICT] = "SMMU_EVT_F_TLB_CONFLICT",
75
+ [SMMU_EVT_F_CFG_CONFLICT] = "SMMU_EVT_F_CFG_CONFLICT",
76
+ [SMMU_EVT_E_PAGE_REQ] = "SMMU_EVT_E_PAGE_REQ",
77
+};
78
+
79
+static inline const char *smmu_event_string(SMMUEventType type)
80
+{
81
+ if (type < ARRAY_SIZE(event_stringify)) {
82
+ return event_stringify[type] ? event_stringify[type] : "UNKNOWN";
83
+ } else {
84
+ return "INVALID";
85
+ }
86
+}
87
+
88
+/* Encode an event record */
89
+typedef struct SMMUEventInfo {
90
+ SMMUEventType type;
91
+ uint32_t sid;
92
+ bool recorded;
93
+ bool record_trans_faults;
94
+ union {
95
+ struct {
96
+ uint32_t ssid;
97
+ bool ssv;
98
+ dma_addr_t addr;
99
+ bool rnw;
100
+ bool pnu;
101
+ bool ind;
102
+ } f_uut;
103
+ struct SSIDInfo {
104
+ uint32_t ssid;
105
+ bool ssv;
106
+ } c_bad_streamid;
107
+ struct SSIDAddrInfo {
108
+ uint32_t ssid;
109
+ bool ssv;
110
+ dma_addr_t addr;
111
+ } f_ste_fetch;
112
+ struct SSIDInfo c_bad_ste;
113
+ struct {
114
+ dma_addr_t addr;
115
+ bool rnw;
116
+ } f_transl_forbidden;
117
+ struct {
118
+ uint32_t ssid;
119
+ } c_bad_substream;
120
+ struct SSIDAddrInfo f_cd_fetch;
121
+ struct SSIDInfo c_bad_cd;
122
+ struct FullInfo {
123
+ bool stall;
124
+ uint16_t stag;
125
+ uint32_t ssid;
126
+ bool ssv;
127
+ bool s2;
128
+ dma_addr_t addr;
129
+ bool rnw;
130
+ bool pnu;
131
+ bool ind;
132
+ uint8_t class;
133
+ dma_addr_t addr2;
134
+ } f_walk_eabt;
135
+ struct FullInfo f_translation;
136
+ struct FullInfo f_addr_size;
137
+ struct FullInfo f_access;
138
+ struct FullInfo f_permission;
139
+ struct SSIDInfo f_cfg_conflict;
140
+ /**
141
+ * not supported yet:
142
+ * F_BAD_ATS_TREQ
143
+ * F_BAD_ATS_TREQ
144
+ * F_TLB_CONFLICT
145
+ * E_PAGE_REQUEST
146
+ * IMPDEF_EVENTn
147
+ */
148
+ } u;
149
+} SMMUEventInfo;
150
+
151
+/* EVTQ fields */
152
+
153
+#define EVT_Q_OVERFLOW (1 << 31)
154
+
155
+#define EVT_SET_TYPE(x, v) deposit32((x)->word[0], 0 , 8 , v)
156
+#define EVT_SET_SSV(x, v) deposit32((x)->word[0], 11, 1 , v)
157
+#define EVT_SET_SSID(x, v) deposit32((x)->word[0], 12, 20, v)
158
+#define EVT_SET_SID(x, v) ((x)->word[1] = v)
159
+#define EVT_SET_STAG(x, v) deposit32((x)->word[2], 0 , 16, v)
160
+#define EVT_SET_STALL(x, v) deposit32((x)->word[2], 31, 1 , v)
161
+#define EVT_SET_PNU(x, v) deposit32((x)->word[3], 1 , 1 , v)
162
+#define EVT_SET_IND(x, v) deposit32((x)->word[3], 2 , 1 , v)
163
+#define EVT_SET_RNW(x, v) deposit32((x)->word[3], 3 , 1 , v)
164
+#define EVT_SET_S2(x, v) deposit32((x)->word[3], 7 , 1 , v)
165
+#define EVT_SET_CLASS(x, v) deposit32((x)->word[3], 8 , 2 , v)
166
+#define EVT_SET_ADDR(x, addr) \
167
+ do { \
168
+ (x)->word[5] = (uint32_t)(addr >> 32); \
169
+ (x)->word[4] = (uint32_t)(addr & 0xffffffff); \
170
+ } while (0)
171
+#define EVT_SET_ADDR2(x, addr) \
172
+ do { \
173
+ deposit32((x)->word[7], 3, 29, addr >> 16); \
174
+ deposit32((x)->word[7], 0, 16, addr & 0xffff);\
175
+ } while (0)
176
+
177
+void smmuv3_record_event(SMMUv3State *s, SMMUEventInfo *event);
178
+
179
#endif
180
diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c
181
index XXXXXXX..XXXXXXX 100644
182
--- a/hw/arm/smmuv3.c
183
+++ b/hw/arm/smmuv3.c
184
@@ -XXX,XX +XXX,XX @@ static MemTxResult queue_write(SMMUQueue *q, void *data)
185
return MEMTX_OK;
186
}
187
188
-void smmuv3_write_eventq(SMMUv3State *s, Evt *evt)
189
+static MemTxResult smmuv3_write_eventq(SMMUv3State *s, Evt *evt)
190
{
191
SMMUQueue *q = &s->eventq;
192
+ MemTxResult r;
193
+
194
+ if (!smmuv3_eventq_enabled(s)) {
195
+ return MEMTX_ERROR;
196
+ }
197
+
198
+ if (smmuv3_q_full(q)) {
199
+ return MEMTX_ERROR;
200
+ }
201
+
202
+ r = queue_write(q, evt);
203
+ if (r != MEMTX_OK) {
204
+ return r;
205
+ }
206
+
207
+ if (smmuv3_q_empty(q)) {
208
+ smmuv3_trigger_irq(s, SMMU_IRQ_EVTQ, 0);
209
+ }
210
+ return MEMTX_OK;
211
+}
212
+
213
+void smmuv3_record_event(SMMUv3State *s, SMMUEventInfo *info)
214
+{
215
+ Evt evt;
216
+ MemTxResult r;
217
218
if (!smmuv3_eventq_enabled(s)) {
219
return;
220
}
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
--
320
2.17.0
321
322
diff view generated by jsdifflib
Deleted patch
1
From: Eric Auger <eric.auger@redhat.com>
2
1
3
In case the MSI is translated by an IOMMU we need to fixup the
4
MSI route with the translated address.
5
6
Signed-off-by: Eric Auger <eric.auger@redhat.com>
7
Signed-off-by: Bharat Bhushan <Bharat.Bhushan@nxp.com>
8
Message-id: 1524665762-31355-12-git-send-email-eric.auger@redhat.com
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
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
18
--- a/target/arm/kvm.c
19
+++ b/target/arm/kvm.c
20
@@ -XXX,XX +XXX,XX @@
21
#include "sysemu/kvm.h"
22
#include "kvm_arm.h"
23
#include "cpu.h"
24
+#include "trace.h"
25
#include "internals.h"
26
#include "hw/arm/arm.h"
27
+#include "hw/pci/pci.h"
28
#include "exec/memattrs.h"
29
#include "exec/address-spaces.h"
30
#include "hw/boards.h"
31
@@ -XXX,XX +XXX,XX @@ int kvm_arm_vgic_probe(void)
32
int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route,
33
uint64_t address, uint32_t data, PCIDevice *dev)
34
{
35
- return 0;
36
+ AddressSpace *as = pci_device_iommu_address_space(dev);
37
+ hwaddr xlat, len, doorbell_gpa;
38
+ MemoryRegionSection mrs;
39
+ MemoryRegion *mr;
40
+ int ret = 1;
41
+
42
+ if (as == &address_space_memory) {
43
+ return 0;
44
+ }
45
+
46
+ /* MSI doorbell address is translated by an IOMMU */
47
+
48
+ rcu_read_lock();
49
+ mr = address_space_translate(as, address, &xlat, &len, true);
50
+ if (!mr) {
51
+ goto unlock;
52
+ }
53
+ mrs = memory_region_find(mr, xlat, 1);
54
+ if (!mrs.mr) {
55
+ goto unlock;
56
+ }
57
+
58
+ doorbell_gpa = mrs.offset_within_address_space;
59
+ memory_region_unref(mrs.mr);
60
+
61
+ route->u.msi.address_lo = doorbell_gpa;
62
+ route->u.msi.address_hi = doorbell_gpa >> 32;
63
+
64
+ trace_kvm_arm_fixup_msi_route(address, doorbell_gpa);
65
+
66
+ ret = 0;
67
+
68
+unlock:
69
+ rcu_read_unlock();
70
+ return ret;
71
}
72
73
int kvm_arch_add_msi_route_post(struct kvm_irq_routing_entry *route,
74
diff --git a/target/arm/trace-events b/target/arm/trace-events
75
index XXXXXXX..XXXXXXX 100644
76
--- a/target/arm/trace-events
77
+++ b/target/arm/trace-events
78
@@ -XXX,XX +XXX,XX @@ arm_gt_tval_write(int timer, uint64_t value) "gt_tval_write: timer %d value 0x%"
79
arm_gt_ctl_write(int timer, uint64_t value) "gt_ctl_write: timer %d value 0x%" PRIx64
80
arm_gt_imask_toggle(int timer, int irqstate) "gt_ctl_write: timer %d IMASK toggle, new irqstate %d"
81
arm_gt_cntvoff_write(uint64_t value) "gt_cntvoff_write: value 0x%" PRIx64
82
+
83
+# target/arm/kvm.c
84
+kvm_arm_fixup_msi_route(uint64_t iova, uint64_t gpa) "MSI iova = 0x%"PRIx64" is translated into 0x%"PRIx64
85
--
86
2.17.0
87
88
diff view generated by jsdifflib