1
arm queue: big stuff here is my MVE codegen optimisation,
1
First arm pullreq for 7.1. The bulk of this is the qemu_split_irq
2
and Alex's Apple Silicon hvf support.
2
removal.
3
3
4
I have enough stuff in my to-review queue that I expect to do another
5
pullreq early next week, but 31 patches is enough to not hang on to.
6
7
thanks
4
-- PMM
8
-- PMM
5
9
6
The following changes since commit 7adb961995a3744f51396502b33ad04a56a317c3:
10
The following changes since commit 9c125d17e9402c232c46610802e5931b3639d77b:
7
11
8
Merge remote-tracking branch 'remotes/dgilbert-gitlab/tags/pull-virtiofs-20210916' into staging (2021-09-19 18:53:29 +0100)
12
Merge tag 'pull-tcg-20220420' of https://gitlab.com/rth7680/qemu into staging (2022-04-20 16:43:11 -0700)
9
13
10
are available in the Git repository at:
14
are available in the Git repository at:
11
15
12
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20210920
16
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20220421
13
17
14
for you to fetch changes up to 1dc5a60bfe406bc1122d68cbdefda38d23134b27:
18
for you to fetch changes up to 5b415dd61bdbf61fb4be0e9f1a7172b8bce682c6:
15
19
16
target/arm: Optimize MVE 1op-immediate insns (2021-09-20 14:18:01 +0100)
20
hw/arm: Use bit fields for NPCM7XX PWRON STRAPs (2022-04-21 11:37:05 +0100)
17
21
18
----------------------------------------------------------------
22
----------------------------------------------------------------
19
target-arm queue:
23
target-arm queue:
20
* Optimize codegen for MVE when predication not active
24
* hw/arm/virt: Check for attempt to use TrustZone with KVM or HVF
21
* hvf: Add Apple Silicon support
25
* versal: Add the Cortex-R5s in the Real-Time Processing Unit (RPU) subsystem
22
* hw/intc: Set GIC maintenance interrupt level to only 0 or 1
26
* versal: model enough of the Clock/Reset Low-power domain (CRL) to allow control of the Cortex-R5s
23
* Fix mishandling of MVE FPSCR.LTPSIZE reset for usermode emulator
27
* xlnx-zynqmp: Connect 4 TTC timers
24
* elf2dmp: Fix coverity nits
28
* exynos4210: Refactor GIC/combiner code to stop using qemu_split_irq
29
* realview: replace 'qemu_split_irq' with 'TYPE_SPLIT_IRQ'
30
* stellaris: replace 'qemu_split_irq' with 'TYPE_SPLIT_IRQ'
31
* hw/core/irq: remove unused 'qemu_irq_split' function
32
* npcm7xx: use symbolic constants for PWRON STRAP bit fields
33
* virt: document impact of gic-version on max CPUs
25
34
26
----------------------------------------------------------------
35
----------------------------------------------------------------
27
Alexander Graf (7):
36
Edgar E. Iglesias (6):
28
arm: Move PMC register definitions to internals.h
37
timer: cadence_ttc: Break out header file to allow embedding
29
hvf: Add execute to dirty log permission bitmap
38
hw/arm/xlnx-zynqmp: Connect 4 TTC timers
30
hvf: Introduce hvf_arch_init() callback
39
hw/arm: versal: Create an APU CPU Cluster
31
hvf: Add Apple Silicon support
40
hw/arm: versal: Add the Cortex-R5Fs
32
hvf: arm: Implement PSCI handling
41
hw/misc: Add a model of the Xilinx Versal CRL
33
arm: Add Hypervisor.framework build target
42
hw/arm: versal: Connect the CRL
34
hvf: arm: Add rudimentary PMC support
35
43
36
Peter Collingbourne (1):
44
Hao Wu (2):
37
arm/hvf: Add a WFI handler
45
hw/misc: Add PWRON STRAP bit fields in GCR module
46
hw/arm: Use bit fields for NPCM7XX PWRON STRAPs
38
47
39
Peter Maydell (18):
48
Heinrich Schuchardt (1):
40
elf2dmp: Check curl_easy_setopt() return value
49
hw/arm/virt: impact of gic-version on max CPUs
41
elf2dmp: Fail cleanly if PDB file specifies zero block_size
42
target/arm: Don't skip M-profile reset entirely in user mode
43
target/arm: Always clear exclusive monitor on reset
44
target/arm: Consolidate ifdef blocks in reset
45
hvf: arm: Implement -cpu host
46
target/arm: Avoid goto_tb if we're trying to exit to the main loop
47
target/arm: Enforce that FPDSCR.LTPSIZE is 4 on inbound migration
48
target/arm: Add TB flag for "MVE insns not predicated"
49
target/arm: Optimize MVE logic ops
50
target/arm: Optimize MVE arithmetic ops
51
target/arm: Optimize MVE VNEG, VABS
52
target/arm: Optimize MVE VDUP
53
target/arm: Optimize MVE VMVN
54
target/arm: Optimize MVE VSHL, VSHR immediate forms
55
target/arm: Optimize MVE VSHLL and VMOVL
56
target/arm: Optimize MVE VSLI and VSRI
57
target/arm: Optimize MVE 1op-immediate insns
58
50
59
Shashi Mallela (1):
51
Peter Maydell (19):
60
hw/intc: Set GIC maintenance interrupt level to only 0 or 1
52
hw/arm/virt: Check for attempt to use TrustZone with KVM or HVF
53
hw/arm/exynos4210: Use TYPE_OR_IRQ instead of custom OR-gate device
54
hw/intc/exynos4210_gic: Remove unused TYPE_EXYNOS4210_IRQ_GATE
55
hw/arm/exynos4210: Put a9mpcore device into state struct
56
hw/arm/exynos4210: Drop int_gic_irq[] from Exynos4210Irq struct
57
hw/arm/exynos4210: Coalesce board_irqs and irq_table
58
hw/arm/exynos4210: Fix code style nit in combiner_grp_to_gic_id[]
59
hw/arm/exynos4210: Move exynos4210_init_board_irqs() into exynos4210.c
60
hw/arm/exynos4210: Put external GIC into state struct
61
hw/arm/exynos4210: Drop ext_gic_irq[] from Exynos4210Irq struct
62
hw/arm/exynos4210: Move exynos4210_combiner_get_gpioin() into exynos4210.c
63
hw/arm/exynos4210: Delete unused macro definitions
64
hw/arm/exynos4210: Use TYPE_SPLIT_IRQ in exynos4210_init_board_irqs()
65
hw/arm/exynos4210: Fill in irq_table[] for internal-combiner-only IRQ lines
66
hw/arm/exynos4210: Connect MCT_G0 and MCT_G1 to both combiners
67
hw/arm/exynos4210: Don't connect multiple lines to external GIC inputs
68
hw/arm/exynos4210: Fold combiner splits into exynos4210_init_board_irqs()
69
hw/arm/exynos4210: Put combiners into state struct
70
hw/arm/exynos4210: Drop Exynos4210Irq struct
61
71
62
meson.build | 8 +
72
Zongyuan Li (3):
63
include/sysemu/hvf_int.h | 12 +-
73
hw/arm/realview: replace 'qemu_split_irq' with 'TYPE_SPLIT_IRQ'
64
target/arm/cpu.h | 6 +-
74
hw/arm/stellaris: replace 'qemu_split_irq' with 'TYPE_SPLIT_IRQ'
65
target/arm/hvf_arm.h | 18 +
75
hw/core/irq: remove unused 'qemu_irq_split' function
66
target/arm/internals.h | 44 ++
67
target/arm/kvm_arm.h | 2 -
68
target/arm/translate.h | 2 +
69
accel/hvf/hvf-accel-ops.c | 21 +-
70
contrib/elf2dmp/download.c | 22 +-
71
contrib/elf2dmp/pdb.c | 4 +
72
hw/intc/arm_gicv3_cpuif.c | 5 +-
73
target/arm/cpu.c | 56 +-
74
target/arm/helper.c | 77 ++-
75
target/arm/hvf/hvf.c | 1278 +++++++++++++++++++++++++++++++++++++++++
76
target/arm/machine.c | 13 +
77
target/arm/translate-m-nocp.c | 8 +-
78
target/arm/translate-mve.c | 310 +++++++---
79
target/arm/translate-vfp.c | 33 +-
80
target/arm/translate.c | 42 +-
81
target/i386/hvf/hvf.c | 10 +
82
MAINTAINERS | 5 +
83
target/arm/hvf/meson.build | 3 +
84
target/arm/hvf/trace-events | 11 +
85
target/arm/meson.build | 2 +
86
24 files changed, 1824 insertions(+), 168 deletions(-)
87
create mode 100644 target/arm/hvf_arm.h
88
create mode 100644 target/arm/hvf/hvf.c
89
create mode 100644 target/arm/hvf/meson.build
90
create mode 100644 target/arm/hvf/trace-events
91
76
77
docs/system/arm/virt.rst | 4 +-
78
include/hw/arm/exynos4210.h | 50 ++--
79
include/hw/arm/xlnx-versal.h | 16 ++
80
include/hw/arm/xlnx-zynqmp.h | 4 +
81
include/hw/intc/exynos4210_combiner.h | 57 +++++
82
include/hw/intc/exynos4210_gic.h | 43 ++++
83
include/hw/irq.h | 5 -
84
include/hw/misc/npcm7xx_gcr.h | 30 +++
85
include/hw/misc/xlnx-versal-crl.h | 235 +++++++++++++++++++
86
include/hw/timer/cadence_ttc.h | 54 +++++
87
hw/arm/exynos4210.c | 430 ++++++++++++++++++++++++++++++----
88
hw/arm/npcm7xx_boards.c | 24 +-
89
hw/arm/realview.c | 33 ++-
90
hw/arm/stellaris.c | 15 +-
91
hw/arm/virt.c | 7 +
92
hw/arm/xlnx-versal-virt.c | 6 +-
93
hw/arm/xlnx-versal.c | 99 +++++++-
94
hw/arm/xlnx-zynqmp.c | 22 ++
95
hw/core/irq.c | 15 --
96
hw/intc/exynos4210_combiner.c | 108 +--------
97
hw/intc/exynos4210_gic.c | 344 +--------------------------
98
hw/misc/xlnx-versal-crl.c | 421 +++++++++++++++++++++++++++++++++
99
hw/timer/cadence_ttc.c | 32 +--
100
MAINTAINERS | 2 +-
101
hw/misc/meson.build | 1 +
102
25 files changed, 1457 insertions(+), 600 deletions(-)
103
create mode 100644 include/hw/intc/exynos4210_combiner.h
104
create mode 100644 include/hw/intc/exynos4210_gic.h
105
create mode 100644 include/hw/misc/xlnx-versal-crl.h
106
create mode 100644 include/hw/timer/cadence_ttc.h
107
create mode 100644 hw/misc/xlnx-versal-crl.c
diff view generated by jsdifflib
1
Coverity points out that if the PDB file we're trying to read
1
It's not possible to provide the guest with the Security extensions
2
has a header specifying a block_size of zero then we will
2
(TrustZone) when using KVM or HVF, because the hardware
3
end up trying to divide by zero in pdb_ds_read_file().
3
virtualization extensions don't permit running EL3 guest code.
4
Check for this and fail cleanly instead.
4
However, we weren't checking for this combination, with the result
5
that QEMU would assert if you tried it:
5
6
6
Fixes: Coverity CID 1458869
7
$ qemu-system-aarch64 -enable-kvm -machine virt,secure=on -cpu host -display none
8
Unexpected error in object_property_find_err() at ../../qom/object.c:1304:
9
qemu-system-aarch64: Property 'host-arm-cpu.secure-memory' not found
10
Aborted
11
12
Check for this combination of options and report an error, in the
13
same way we already do for attempts to give a KVM or HVF guest the
14
Virtualization or MTE extensions. Now we will report:
15
16
qemu-system-aarch64: mach-virt: KVM does not support providing Security extensions (TrustZone) to the guest CPU
17
18
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/961
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Viktor Prutyanov <viktor.prutyanov@phystech.edu>
20
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
21
Message-id: 20220404155301.566542-1-peter.maydell@linaro.org
10
Tested-by: Viktor Prutyanov <viktor.prutyanov@phystech.edu>
11
Message-id: 20210910170656.366592-3-philmd@redhat.com
12
Message-Id: <20210901143910.17112-3-peter.maydell@linaro.org>
13
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
14
---
22
---
15
contrib/elf2dmp/pdb.c | 4 ++++
23
hw/arm/virt.c | 7 +++++++
16
1 file changed, 4 insertions(+)
24
1 file changed, 7 insertions(+)
17
25
18
diff --git a/contrib/elf2dmp/pdb.c b/contrib/elf2dmp/pdb.c
26
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
19
index XXXXXXX..XXXXXXX 100644
27
index XXXXXXX..XXXXXXX 100644
20
--- a/contrib/elf2dmp/pdb.c
28
--- a/hw/arm/virt.c
21
+++ b/contrib/elf2dmp/pdb.c
29
+++ b/hw/arm/virt.c
22
@@ -XXX,XX +XXX,XX @@ out_symbols:
30
@@ -XXX,XX +XXX,XX @@ static void machvirt_init(MachineState *machine)
23
31
exit(1);
24
static int pdb_reader_ds_init(struct pdb_reader *r, PDB_DS_HEADER *hdr)
32
}
25
{
33
26
+ if (hdr->block_size == 0) {
34
+ if (vms->secure && (kvm_enabled() || hvf_enabled())) {
27
+ return 1;
35
+ error_report("mach-virt: %s does not support providing "
36
+ "Security extensions (TrustZone) to the guest CPU",
37
+ kvm_enabled() ? "KVM" : "HVF");
38
+ exit(1);
28
+ }
39
+ }
29
+
40
+
30
memset(r->file_used, 0, sizeof(r->file_used));
41
if (vms->virt && (kvm_enabled() || hvf_enabled())) {
31
r->ds.header = hdr;
42
error_report("mach-virt: %s does not support providing "
32
r->ds.toc = pdb_ds_read(hdr, (uint32_t *)((uint8_t *)hdr +
43
"Virtualization extensions to the guest CPU",
33
--
44
--
34
2.20.1
45
2.25.1
35
36
diff view generated by jsdifflib
1
From: Alexander Graf <agraf@csgraf.de>
1
From: "Edgar E. Iglesias" <edgar.iglesias@amd.com>
2
2
3
Now that we have all logic in place that we need to handle Hypervisor.framework
3
Break out header file to allow embedding of the the TTC.
4
on Apple Silicon systems, let's add CONFIG_HVF for aarch64 as well so that we
5
can build it.
6
4
7
Signed-off-by: Alexander Graf <agraf@csgraf.de>
5
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>
8
Reviewed-by: Roman Bolshakov <r.bolshakov@yadro.com>
6
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
9
Tested-by: Roman Bolshakov <r.bolshakov@yadro.com> (x86 only)
7
Reviewed-by: Luc Michel <luc@lmichel.fr>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Francisco Iglesias <frasse.iglesias@gmail.com>
11
Reviewed-by: Sergio Lopez <slp@redhat.com>
9
Message-id: 20220331222017.2914409-2-edgar.iglesias@gmail.com
12
Message-id: 20210916155404.86958-9-agraf@csgraf.de
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
11
---
15
meson.build | 7 +++++++
12
include/hw/timer/cadence_ttc.h | 54 ++++++++++++++++++++++++++++++++++
16
target/arm/hvf/meson.build | 3 +++
13
hw/timer/cadence_ttc.c | 32 ++------------------
17
target/arm/meson.build | 2 ++
14
2 files changed, 56 insertions(+), 30 deletions(-)
18
3 files changed, 12 insertions(+)
15
create mode 100644 include/hw/timer/cadence_ttc.h
19
create mode 100644 target/arm/hvf/meson.build
20
16
21
diff --git a/meson.build b/meson.build
17
diff --git a/include/hw/timer/cadence_ttc.h b/include/hw/timer/cadence_ttc.h
22
index XXXXXXX..XXXXXXX 100644
23
--- a/meson.build
24
+++ b/meson.build
25
@@ -XXX,XX +XXX,XX @@ else
26
endif
27
28
accelerator_targets = { 'CONFIG_KVM': kvm_targets }
29
+
30
+if cpu in ['aarch64']
31
+ accelerator_targets += {
32
+ 'CONFIG_HVF': ['aarch64-softmmu']
33
+ }
34
+endif
35
+
36
if cpu in ['x86', 'x86_64', 'arm', 'aarch64']
37
# i386 emulator provides xenpv machine type for multiple architectures
38
accelerator_targets += {
39
diff --git a/target/arm/hvf/meson.build b/target/arm/hvf/meson.build
40
new file mode 100644
18
new file mode 100644
41
index XXXXXXX..XXXXXXX
19
index XXXXXXX..XXXXXXX
42
--- /dev/null
20
--- /dev/null
43
+++ b/target/arm/hvf/meson.build
21
+++ b/include/hw/timer/cadence_ttc.h
44
@@ -XXX,XX +XXX,XX @@
22
@@ -XXX,XX +XXX,XX @@
45
+arm_softmmu_ss.add(when: [hvf, 'CONFIG_HVF'], if_true: files(
23
+/*
46
+ 'hvf.c',
24
+ * Xilinx Zynq cadence TTC model
47
+))
25
+ *
48
diff --git a/target/arm/meson.build b/target/arm/meson.build
26
+ * Copyright (c) 2011 Xilinx Inc.
27
+ * Copyright (c) 2012 Peter A.G. Crosthwaite (peter.crosthwaite@petalogix.com)
28
+ * Copyright (c) 2012 PetaLogix Pty Ltd.
29
+ * Written By Haibing Ma
30
+ * M. Habib
31
+ *
32
+ * This program is free software; you can redistribute it and/or
33
+ * modify it under the terms of the GNU General Public License
34
+ * as published by the Free Software Foundation; either version
35
+ * 2 of the License, or (at your option) any later version.
36
+ *
37
+ * You should have received a copy of the GNU General Public License along
38
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
39
+ */
40
+#ifndef HW_TIMER_CADENCE_TTC_H
41
+#define HW_TIMER_CADENCE_TTC_H
42
+
43
+#include "hw/sysbus.h"
44
+#include "qemu/timer.h"
45
+
46
+typedef struct {
47
+ QEMUTimer *timer;
48
+ int freq;
49
+
50
+ uint32_t reg_clock;
51
+ uint32_t reg_count;
52
+ uint32_t reg_value;
53
+ uint16_t reg_interval;
54
+ uint16_t reg_match[3];
55
+ uint32_t reg_intr;
56
+ uint32_t reg_intr_en;
57
+ uint32_t reg_event_ctrl;
58
+ uint32_t reg_event;
59
+
60
+ uint64_t cpu_time;
61
+ unsigned int cpu_time_valid;
62
+
63
+ qemu_irq irq;
64
+} CadenceTimerState;
65
+
66
+#define TYPE_CADENCE_TTC "cadence_ttc"
67
+OBJECT_DECLARE_SIMPLE_TYPE(CadenceTTCState, CADENCE_TTC)
68
+
69
+struct CadenceTTCState {
70
+ SysBusDevice parent_obj;
71
+
72
+ MemoryRegion iomem;
73
+ CadenceTimerState timer[3];
74
+};
75
+
76
+#endif
77
diff --git a/hw/timer/cadence_ttc.c b/hw/timer/cadence_ttc.c
49
index XXXXXXX..XXXXXXX 100644
78
index XXXXXXX..XXXXXXX 100644
50
--- a/target/arm/meson.build
79
--- a/hw/timer/cadence_ttc.c
51
+++ b/target/arm/meson.build
80
+++ b/hw/timer/cadence_ttc.c
52
@@ -XXX,XX +XXX,XX @@ arm_softmmu_ss.add(files(
81
@@ -XXX,XX +XXX,XX @@
53
'psci.c',
82
#include "qemu/timer.h"
54
))
83
#include "qom/object.h"
55
84
56
+subdir('hvf')
85
+#include "hw/timer/cadence_ttc.h"
57
+
86
+
58
target_arch += {'arm': arm_ss}
87
#ifdef CADENCE_TTC_ERR_DEBUG
59
target_softmmu_arch += {'arm': arm_softmmu_ss}
88
#define DB_PRINT(...) do { \
89
fprintf(stderr, ": %s: ", __func__); \
90
@@ -XXX,XX +XXX,XX @@
91
#define CLOCK_CTRL_PS_EN 0x00000001
92
#define CLOCK_CTRL_PS_V 0x0000001e
93
94
-typedef struct {
95
- QEMUTimer *timer;
96
- int freq;
97
-
98
- uint32_t reg_clock;
99
- uint32_t reg_count;
100
- uint32_t reg_value;
101
- uint16_t reg_interval;
102
- uint16_t reg_match[3];
103
- uint32_t reg_intr;
104
- uint32_t reg_intr_en;
105
- uint32_t reg_event_ctrl;
106
- uint32_t reg_event;
107
-
108
- uint64_t cpu_time;
109
- unsigned int cpu_time_valid;
110
-
111
- qemu_irq irq;
112
-} CadenceTimerState;
113
-
114
-#define TYPE_CADENCE_TTC "cadence_ttc"
115
-OBJECT_DECLARE_SIMPLE_TYPE(CadenceTTCState, CADENCE_TTC)
116
-
117
-struct CadenceTTCState {
118
- SysBusDevice parent_obj;
119
-
120
- MemoryRegion iomem;
121
- CadenceTimerState timer[3];
122
-};
123
-
124
static void cadence_timer_update(CadenceTimerState *s)
125
{
126
qemu_set_irq(s->irq, !!(s->reg_intr & s->reg_intr_en));
60
--
127
--
61
2.20.1
128
2.25.1
62
63
diff view generated by jsdifflib
1
From: Alexander Graf <agraf@csgraf.de>
1
From: "Edgar E. Iglesias" <edgar.iglesias@amd.com>
2
2
3
We can expose cycle counters on the PMU easily. To be as compatible as
3
Connect the 4 TTC timers on the ZynqMP.
4
possible, let's do so, but make sure we don't expose any other architectural
5
counters that we can not model yet.
6
4
7
This allows OSs to work that require PMU support.
5
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>
8
6
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
9
Signed-off-by: Alexander Graf <agraf@csgraf.de>
7
Reviewed-by: Luc Michel <luc@lmichel.fr>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Francisco Iglesias <frasse.iglesias@gmail.com>
11
Message-id: 20210916155404.86958-10-agraf@csgraf.de
9
Message-id: 20220331222017.2914409-3-edgar.iglesias@gmail.com
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
11
---
14
target/arm/hvf/hvf.c | 179 +++++++++++++++++++++++++++++++++++++++++++
12
include/hw/arm/xlnx-zynqmp.h | 4 ++++
15
1 file changed, 179 insertions(+)
13
hw/arm/xlnx-zynqmp.c | 22 ++++++++++++++++++++++
14
2 files changed, 26 insertions(+)
16
15
17
diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c
16
diff --git a/include/hw/arm/xlnx-zynqmp.h b/include/hw/arm/xlnx-zynqmp.h
18
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/hvf/hvf.c
18
--- a/include/hw/arm/xlnx-zynqmp.h
20
+++ b/target/arm/hvf/hvf.c
19
+++ b/include/hw/arm/xlnx-zynqmp.h
21
@@ -XXX,XX +XXX,XX @@
20
@@ -XXX,XX +XXX,XX @@
22
#define SYSREG_OSLSR_EL1 SYSREG(2, 0, 1, 1, 4)
21
#include "hw/or-irq.h"
23
#define SYSREG_OSDLR_EL1 SYSREG(2, 0, 1, 3, 4)
22
#include "hw/misc/xlnx-zynqmp-apu-ctrl.h"
24
#define SYSREG_CNTPCT_EL0 SYSREG(3, 3, 14, 0, 1)
23
#include "hw/misc/xlnx-zynqmp-crf.h"
25
+#define SYSREG_PMCR_EL0 SYSREG(3, 3, 9, 12, 0)
24
+#include "hw/timer/cadence_ttc.h"
26
+#define SYSREG_PMUSERENR_EL0 SYSREG(3, 3, 9, 14, 0)
25
27
+#define SYSREG_PMCNTENSET_EL0 SYSREG(3, 3, 9, 12, 1)
26
#define TYPE_XLNX_ZYNQMP "xlnx-zynqmp"
28
+#define SYSREG_PMCNTENCLR_EL0 SYSREG(3, 3, 9, 12, 2)
27
OBJECT_DECLARE_SIMPLE_TYPE(XlnxZynqMPState, XLNX_ZYNQMP)
29
+#define SYSREG_PMINTENCLR_EL1 SYSREG(3, 0, 9, 14, 2)
28
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_SIMPLE_TYPE(XlnxZynqMPState, XLNX_ZYNQMP)
30
+#define SYSREG_PMOVSCLR_EL0 SYSREG(3, 3, 9, 12, 3)
29
#define XLNX_ZYNQMP_MAX_RAM_SIZE (XLNX_ZYNQMP_MAX_LOW_RAM_SIZE + \
31
+#define SYSREG_PMSWINC_EL0 SYSREG(3, 3, 9, 12, 4)
30
XLNX_ZYNQMP_MAX_HIGH_RAM_SIZE)
32
+#define SYSREG_PMSELR_EL0 SYSREG(3, 3, 9, 12, 5)
31
33
+#define SYSREG_PMCEID0_EL0 SYSREG(3, 3, 9, 12, 6)
32
+#define XLNX_ZYNQMP_NUM_TTC 4
34
+#define SYSREG_PMCEID1_EL0 SYSREG(3, 3, 9, 12, 7)
33
+
35
+#define SYSREG_PMCCNTR_EL0 SYSREG(3, 3, 9, 13, 0)
34
/*
36
+#define SYSREG_PMCCFILTR_EL0 SYSREG(3, 3, 14, 15, 7)
35
* Unimplemented mmio regions needed to boot some images.
37
36
*/
38
#define WFX_IS_WFE (1 << 0)
37
@@ -XXX,XX +XXX,XX @@ struct XlnxZynqMPState {
39
38
qemu_or_irq qspi_irq_orgate;
40
@@ -XXX,XX +XXX,XX @@ static int hvf_sysreg_read(CPUState *cpu, uint32_t reg, uint32_t rt)
39
XlnxZynqMPAPUCtrl apu_ctrl;
41
val = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) /
40
XlnxZynqMPCRF crf;
42
gt_cntfrq_period_ns(arm_cpu);
41
+ CadenceTTCState ttc[XLNX_ZYNQMP_NUM_TTC];
43
break;
42
44
+ case SYSREG_PMCR_EL0:
43
char *boot_cpu;
45
+ val = env->cp15.c9_pmcr;
44
ARMCPU *boot_cpu_ptr;
46
+ break;
45
diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c
47
+ case SYSREG_PMCCNTR_EL0:
46
index XXXXXXX..XXXXXXX 100644
48
+ pmu_op_start(env);
47
--- a/hw/arm/xlnx-zynqmp.c
49
+ val = env->cp15.c15_ccnt;
48
+++ b/hw/arm/xlnx-zynqmp.c
50
+ pmu_op_finish(env);
49
@@ -XXX,XX +XXX,XX @@
51
+ break;
50
#define APU_ADDR 0xfd5c0000
52
+ case SYSREG_PMCNTENCLR_EL0:
51
#define APU_IRQ 153
53
+ val = env->cp15.c9_pmcnten;
52
54
+ break;
53
+#define TTC0_ADDR 0xFF110000
55
+ case SYSREG_PMOVSCLR_EL0:
54
+#define TTC0_IRQ 36
56
+ val = env->cp15.c9_pmovsr;
55
+
57
+ break;
56
#define IPI_ADDR 0xFF300000
58
+ case SYSREG_PMSELR_EL0:
57
#define IPI_IRQ 64
59
+ val = env->cp15.c9_pmselr;
58
60
+ break;
59
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_create_crf(XlnxZynqMPState *s, qemu_irq *gic)
61
+ case SYSREG_PMINTENCLR_EL1:
60
sysbus_connect_irq(sbd, 0, gic[CRF_IRQ]);
62
+ val = env->cp15.c9_pminten;
63
+ break;
64
+ case SYSREG_PMCCFILTR_EL0:
65
+ val = env->cp15.pmccfiltr_el0;
66
+ break;
67
+ case SYSREG_PMCNTENSET_EL0:
68
+ val = env->cp15.c9_pmcnten;
69
+ break;
70
+ case SYSREG_PMUSERENR_EL0:
71
+ val = env->cp15.c9_pmuserenr;
72
+ break;
73
+ case SYSREG_PMCEID0_EL0:
74
+ case SYSREG_PMCEID1_EL0:
75
+ /* We can't really count anything yet, declare all events invalid */
76
+ val = 0;
77
+ break;
78
case SYSREG_OSLSR_EL1:
79
val = env->cp15.oslsr_el1;
80
break;
81
@@ -XXX,XX +XXX,XX @@ static int hvf_sysreg_read(CPUState *cpu, uint32_t reg, uint32_t rt)
82
return 0;
83
}
61
}
84
62
85
+static void pmu_update_irq(CPUARMState *env)
63
+static void xlnx_zynqmp_create_ttc(XlnxZynqMPState *s, qemu_irq *gic)
86
+{
64
+{
87
+ ARMCPU *cpu = env_archcpu(env);
65
+ SysBusDevice *sbd;
88
+ qemu_set_irq(cpu->pmu_interrupt, (env->cp15.c9_pmcr & PMCRE) &&
66
+ int i, irq;
89
+ (env->cp15.c9_pminten & env->cp15.c9_pmovsr));
90
+}
91
+
67
+
92
+static bool pmu_event_supported(uint16_t number)
68
+ for (i = 0; i < XLNX_ZYNQMP_NUM_TTC; i++) {
93
+{
69
+ object_initialize_child(OBJECT(s), "ttc[*]", &s->ttc[i],
94
+ return false;
70
+ TYPE_CADENCE_TTC);
95
+}
71
+ sbd = SYS_BUS_DEVICE(&s->ttc[i]);
96
+
72
+
97
+/* Returns true if the counter (pass 31 for PMCCNTR) should count events using
73
+ sysbus_realize(sbd, &error_fatal);
98
+ * the current EL, security state, and register configuration.
74
+ sysbus_mmio_map(sbd, 0, TTC0_ADDR + i * 0x10000);
99
+ */
75
+ for (irq = 0; irq < 3; irq++) {
100
+static bool pmu_counter_enabled(CPUARMState *env, uint8_t counter)
76
+ sysbus_connect_irq(sbd, irq, gic[TTC0_IRQ + i * 3 + irq]);
101
+{
102
+ uint64_t filter;
103
+ bool enabled, filtered = true;
104
+ int el = arm_current_el(env);
105
+
106
+ enabled = (env->cp15.c9_pmcr & PMCRE) &&
107
+ (env->cp15.c9_pmcnten & (1 << counter));
108
+
109
+ if (counter == 31) {
110
+ filter = env->cp15.pmccfiltr_el0;
111
+ } else {
112
+ filter = env->cp15.c14_pmevtyper[counter];
113
+ }
114
+
115
+ if (el == 0) {
116
+ filtered = filter & PMXEVTYPER_U;
117
+ } else if (el == 1) {
118
+ filtered = filter & PMXEVTYPER_P;
119
+ }
120
+
121
+ if (counter != 31) {
122
+ /*
123
+ * If not checking PMCCNTR, ensure the counter is setup to an event we
124
+ * support
125
+ */
126
+ uint16_t event = filter & PMXEVTYPER_EVTCOUNT;
127
+ if (!pmu_event_supported(event)) {
128
+ return false;
129
+ }
130
+ }
131
+
132
+ return enabled && !filtered;
133
+}
134
+
135
+static void pmswinc_write(CPUARMState *env, uint64_t value)
136
+{
137
+ unsigned int i;
138
+ for (i = 0; i < pmu_num_counters(env); i++) {
139
+ /* Increment a counter's count iff: */
140
+ if ((value & (1 << i)) && /* counter's bit is set */
141
+ /* counter is enabled and not filtered */
142
+ pmu_counter_enabled(env, i) &&
143
+ /* counter is SW_INCR */
144
+ (env->cp15.c14_pmevtyper[i] & PMXEVTYPER_EVTCOUNT) == 0x0) {
145
+ /*
146
+ * Detect if this write causes an overflow since we can't predict
147
+ * PMSWINC overflows like we can for other events
148
+ */
149
+ uint32_t new_pmswinc = env->cp15.c14_pmevcntr[i] + 1;
150
+
151
+ if (env->cp15.c14_pmevcntr[i] & ~new_pmswinc & INT32_MIN) {
152
+ env->cp15.c9_pmovsr |= (1 << i);
153
+ pmu_update_irq(env);
154
+ }
155
+
156
+ env->cp15.c14_pmevcntr[i] = new_pmswinc;
157
+ }
77
+ }
158
+ }
78
+ }
159
+}
79
+}
160
+
80
+
161
static int hvf_sysreg_write(CPUState *cpu, uint32_t reg, uint64_t val)
81
static void xlnx_zynqmp_create_unimp_mmio(XlnxZynqMPState *s)
162
{
82
{
163
ARMCPU *arm_cpu = ARM_CPU(cpu);
83
static const struct UnimpInfo {
164
@@ -XXX,XX +XXX,XX @@ static int hvf_sysreg_write(CPUState *cpu, uint32_t reg, uint64_t val)
84
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
165
val);
85
xlnx_zynqmp_create_efuse(s, gic_spi);
166
86
xlnx_zynqmp_create_apu_ctrl(s, gic_spi);
167
switch (reg) {
87
xlnx_zynqmp_create_crf(s, gic_spi);
168
+ case SYSREG_PMCCNTR_EL0:
88
+ xlnx_zynqmp_create_ttc(s, gic_spi);
169
+ pmu_op_start(env);
89
xlnx_zynqmp_create_unimp_mmio(s);
170
+ env->cp15.c15_ccnt = val;
90
171
+ pmu_op_finish(env);
91
for (i = 0; i < XLNX_ZYNQMP_NUM_GDMA_CH; i++) {
172
+ break;
173
+ case SYSREG_PMCR_EL0:
174
+ pmu_op_start(env);
175
+
176
+ if (val & PMCRC) {
177
+ /* The counter has been reset */
178
+ env->cp15.c15_ccnt = 0;
179
+ }
180
+
181
+ if (val & PMCRP) {
182
+ unsigned int i;
183
+ for (i = 0; i < pmu_num_counters(env); i++) {
184
+ env->cp15.c14_pmevcntr[i] = 0;
185
+ }
186
+ }
187
+
188
+ env->cp15.c9_pmcr &= ~PMCR_WRITEABLE_MASK;
189
+ env->cp15.c9_pmcr |= (val & PMCR_WRITEABLE_MASK);
190
+
191
+ pmu_op_finish(env);
192
+ break;
193
+ case SYSREG_PMUSERENR_EL0:
194
+ env->cp15.c9_pmuserenr = val & 0xf;
195
+ break;
196
+ case SYSREG_PMCNTENSET_EL0:
197
+ env->cp15.c9_pmcnten |= (val & pmu_counter_mask(env));
198
+ break;
199
+ case SYSREG_PMCNTENCLR_EL0:
200
+ env->cp15.c9_pmcnten &= ~(val & pmu_counter_mask(env));
201
+ break;
202
+ case SYSREG_PMINTENCLR_EL1:
203
+ pmu_op_start(env);
204
+ env->cp15.c9_pminten |= val;
205
+ pmu_op_finish(env);
206
+ break;
207
+ case SYSREG_PMOVSCLR_EL0:
208
+ pmu_op_start(env);
209
+ env->cp15.c9_pmovsr &= ~val;
210
+ pmu_op_finish(env);
211
+ break;
212
+ case SYSREG_PMSWINC_EL0:
213
+ pmu_op_start(env);
214
+ pmswinc_write(env, val);
215
+ pmu_op_finish(env);
216
+ break;
217
+ case SYSREG_PMSELR_EL0:
218
+ env->cp15.c9_pmselr = val & 0x1f;
219
+ break;
220
+ case SYSREG_PMCCFILTR_EL0:
221
+ pmu_op_start(env);
222
+ env->cp15.pmccfiltr_el0 = val & PMCCFILTR_EL0;
223
+ pmu_op_finish(env);
224
+ break;
225
case SYSREG_OSLAR_EL1:
226
env->cp15.oslsr_el1 = val & 1;
227
break;
228
--
92
--
229
2.20.1
93
2.25.1
230
231
diff view generated by jsdifflib
New patch
1
From: "Edgar E. Iglesias" <edgar.iglesias@amd.com>
1
2
3
Create an APU CPU Cluster. This is in preparation to add the RPU.
4
5
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>
6
Reviewed-by: Francisco Iglesias <francisco.iglesias@amd.com>
7
Message-id: 20220406174303.2022038-2-edgar.iglesias@xilinx.com
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
include/hw/arm/xlnx-versal.h | 2 ++
11
hw/arm/xlnx-versal.c | 9 ++++++++-
12
2 files changed, 10 insertions(+), 1 deletion(-)
13
14
diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
15
index XXXXXXX..XXXXXXX 100644
16
--- a/include/hw/arm/xlnx-versal.h
17
+++ b/include/hw/arm/xlnx-versal.h
18
@@ -XXX,XX +XXX,XX @@
19
20
#include "hw/sysbus.h"
21
#include "hw/arm/boot.h"
22
+#include "hw/cpu/cluster.h"
23
#include "hw/or-irq.h"
24
#include "hw/sd/sdhci.h"
25
#include "hw/intc/arm_gicv3.h"
26
@@ -XXX,XX +XXX,XX @@ struct Versal {
27
struct {
28
struct {
29
MemoryRegion mr;
30
+ CPUClusterState cluster;
31
ARMCPU cpu[XLNX_VERSAL_NR_ACPUS];
32
GICv3State gic;
33
} apu;
34
diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
35
index XXXXXXX..XXXXXXX 100644
36
--- a/hw/arm/xlnx-versal.c
37
+++ b/hw/arm/xlnx-versal.c
38
@@ -XXX,XX +XXX,XX @@ static void versal_create_apu_cpus(Versal *s)
39
{
40
int i;
41
42
+ object_initialize_child(OBJECT(s), "apu-cluster", &s->fpd.apu.cluster,
43
+ TYPE_CPU_CLUSTER);
44
+ qdev_prop_set_uint32(DEVICE(&s->fpd.apu.cluster), "cluster-id", 0);
45
+
46
for (i = 0; i < ARRAY_SIZE(s->fpd.apu.cpu); i++) {
47
Object *obj;
48
49
- object_initialize_child(OBJECT(s), "apu-cpu[*]", &s->fpd.apu.cpu[i],
50
+ object_initialize_child(OBJECT(&s->fpd.apu.cluster),
51
+ "apu-cpu[*]", &s->fpd.apu.cpu[i],
52
XLNX_VERSAL_ACPU_TYPE);
53
obj = OBJECT(&s->fpd.apu.cpu[i]);
54
if (i) {
55
@@ -XXX,XX +XXX,XX @@ static void versal_create_apu_cpus(Versal *s)
56
&error_abort);
57
qdev_realize(DEVICE(obj), NULL, &error_fatal);
58
}
59
+
60
+ qdev_realize(DEVICE(&s->fpd.apu.cluster), NULL, &error_fatal);
61
}
62
63
static void versal_create_apu_gic(Versal *s, qemu_irq *pic)
64
--
65
2.25.1
diff view generated by jsdifflib
1
From: Alexander Graf <agraf@csgraf.de>
1
From: "Edgar E. Iglesias" <edgar.iglesias@amd.com>
2
2
3
We need to handle PSCI calls. Most of the TCG code works for us,
3
Add the Cortex-R5Fs of the Versal RPU (Real-time Processing Unit)
4
but we can simplify it to only handle aa64 mode and we need to
4
subsystem.
5
handle SUSPEND differently.
6
5
7
This patch takes the TCG code as template and duplicates it in HVF.
6
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>
8
7
Reviewed-by: Francisco Iglesias <francisco.iglesias@amd.com>
9
To tell the guest that we support PSCI 0.2 now, update the check in
8
Message-id: 20220406174303.2022038-3-edgar.iglesias@xilinx.com
10
arm_cpu_initfn() as well.
11
12
Signed-off-by: Alexander Graf <agraf@csgraf.de>
13
Reviewed-by: Sergio Lopez <slp@redhat.com>
14
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
15
Message-id: 20210916155404.86958-8-agraf@csgraf.de
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
---
10
---
18
target/arm/cpu.c | 4 +-
11
include/hw/arm/xlnx-versal.h | 10 ++++++++++
19
target/arm/hvf/hvf.c | 141 ++++++++++++++++++++++++++++++++++--
12
hw/arm/xlnx-versal-virt.c | 6 +++---
20
target/arm/hvf/trace-events | 1 +
13
hw/arm/xlnx-versal.c | 36 ++++++++++++++++++++++++++++++++++++
21
3 files changed, 139 insertions(+), 7 deletions(-)
14
3 files changed, 49 insertions(+), 3 deletions(-)
22
15
23
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
16
diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
24
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
25
--- a/target/arm/cpu.c
18
--- a/include/hw/arm/xlnx-versal.h
26
+++ b/target/arm/cpu.c
19
+++ b/include/hw/arm/xlnx-versal.h
27
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_initfn(Object *obj)
20
@@ -XXX,XX +XXX,XX @@
28
cpu->psci_version = 1; /* By default assume PSCI v0.1 */
21
OBJECT_DECLARE_SIMPLE_TYPE(Versal, XLNX_VERSAL)
29
cpu->kvm_target = QEMU_KVM_ARM_TARGET_NONE;
22
30
23
#define XLNX_VERSAL_NR_ACPUS 2
31
- if (tcg_enabled()) {
24
+#define XLNX_VERSAL_NR_RCPUS 2
32
- cpu->psci_version = 2; /* TCG implements PSCI 0.2 */
25
#define XLNX_VERSAL_NR_UARTS 2
33
+ if (tcg_enabled() || hvf_enabled()) {
26
#define XLNX_VERSAL_NR_GEMS 2
34
+ cpu->psci_version = 2; /* TCG and HVF implement PSCI 0.2 */
27
#define XLNX_VERSAL_NR_ADMAS 8
28
@@ -XXX,XX +XXX,XX @@ struct Versal {
29
VersalUsb2 usb;
30
} iou;
31
32
+ /* Real-time Processing Unit. */
33
+ struct {
34
+ MemoryRegion mr;
35
+ MemoryRegion mr_ps_alias;
36
+
37
+ CPUClusterState cluster;
38
+ ARMCPU cpu[XLNX_VERSAL_NR_RCPUS];
39
+ } rpu;
40
+
41
struct {
42
qemu_or_irq irq_orgate;
43
XlnxXramCtrl ctrl[XLNX_VERSAL_NR_XRAM];
44
diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c
45
index XXXXXXX..XXXXXXX 100644
46
--- a/hw/arm/xlnx-versal-virt.c
47
+++ b/hw/arm/xlnx-versal-virt.c
48
@@ -XXX,XX +XXX,XX @@ static void versal_virt_machine_class_init(ObjectClass *oc, void *data)
49
50
mc->desc = "Xilinx Versal Virtual development board";
51
mc->init = versal_virt_init;
52
- mc->min_cpus = XLNX_VERSAL_NR_ACPUS;
53
- mc->max_cpus = XLNX_VERSAL_NR_ACPUS;
54
- mc->default_cpus = XLNX_VERSAL_NR_ACPUS;
55
+ mc->min_cpus = XLNX_VERSAL_NR_ACPUS + XLNX_VERSAL_NR_RCPUS;
56
+ mc->max_cpus = XLNX_VERSAL_NR_ACPUS + XLNX_VERSAL_NR_RCPUS;
57
+ mc->default_cpus = XLNX_VERSAL_NR_ACPUS + XLNX_VERSAL_NR_RCPUS;
58
mc->no_cdrom = true;
59
mc->default_ram_id = "ddr";
60
}
61
diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
62
index XXXXXXX..XXXXXXX 100644
63
--- a/hw/arm/xlnx-versal.c
64
+++ b/hw/arm/xlnx-versal.c
65
@@ -XXX,XX +XXX,XX @@
66
#include "hw/sysbus.h"
67
68
#define XLNX_VERSAL_ACPU_TYPE ARM_CPU_TYPE_NAME("cortex-a72")
69
+#define XLNX_VERSAL_RCPU_TYPE ARM_CPU_TYPE_NAME("cortex-r5f")
70
#define GEM_REVISION 0x40070106
71
72
#define VERSAL_NUM_PMC_APB_IRQS 3
73
@@ -XXX,XX +XXX,XX @@ static void versal_create_apu_gic(Versal *s, qemu_irq *pic)
35
}
74
}
36
}
75
}
37
76
38
diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c
77
+static void versal_create_rpu_cpus(Versal *s)
39
index XXXXXXX..XXXXXXX 100644
78
+{
40
--- a/target/arm/hvf/hvf.c
79
+ int i;
41
+++ b/target/arm/hvf/hvf.c
42
@@ -XXX,XX +XXX,XX @@
43
#include "hw/irq.h"
44
#include "qemu/main-loop.h"
45
#include "sysemu/cpus.h"
46
+#include "arm-powerctl.h"
47
#include "target/arm/cpu.h"
48
#include "target/arm/internals.h"
49
#include "trace/trace-target_arm_hvf.h"
50
@@ -XXX,XX +XXX,XX @@
51
#define TMR_CTL_IMASK (1 << 1)
52
#define TMR_CTL_ISTATUS (1 << 2)
53
54
+static void hvf_wfi(CPUState *cpu);
55
+
80
+
56
typedef struct HVFVTimer {
81
+ object_initialize_child(OBJECT(s), "rpu-cluster", &s->lpd.rpu.cluster,
57
/* Vtimer value during migration and paused state */
82
+ TYPE_CPU_CLUSTER);
58
uint64_t vtimer_val;
83
+ qdev_prop_set_uint32(DEVICE(&s->lpd.rpu.cluster), "cluster-id", 1);
59
@@ -XXX,XX +XXX,XX @@ static void hvf_raise_exception(CPUState *cpu, uint32_t excp,
84
+
60
arm_cpu_do_interrupt(cpu);
85
+ for (i = 0; i < ARRAY_SIZE(s->lpd.rpu.cpu); i++) {
61
}
86
+ Object *obj;
62
87
+
63
+static void hvf_psci_cpu_off(ARMCPU *arm_cpu)
88
+ object_initialize_child(OBJECT(&s->lpd.rpu.cluster),
64
+{
89
+ "rpu-cpu[*]", &s->lpd.rpu.cpu[i],
65
+ int32_t ret = arm_set_cpu_off(arm_cpu->mp_affinity);
90
+ XLNX_VERSAL_RCPU_TYPE);
66
+ assert(ret == QEMU_ARM_POWERCTL_RET_SUCCESS);
91
+ obj = OBJECT(&s->lpd.rpu.cpu[i]);
92
+ object_property_set_bool(obj, "start-powered-off", true,
93
+ &error_abort);
94
+
95
+ object_property_set_int(obj, "mp-affinity", 0x100 | i, &error_abort);
96
+ object_property_set_int(obj, "core-count", ARRAY_SIZE(s->lpd.rpu.cpu),
97
+ &error_abort);
98
+ object_property_set_link(obj, "memory", OBJECT(&s->lpd.rpu.mr),
99
+ &error_abort);
100
+ qdev_realize(DEVICE(obj), NULL, &error_fatal);
101
+ }
102
+
103
+ qdev_realize(DEVICE(&s->lpd.rpu.cluster), NULL, &error_fatal);
67
+}
104
+}
68
+
105
+
69
+/*
106
static void versal_create_uarts(Versal *s, qemu_irq *pic)
70
+ * Handle a PSCI call.
71
+ *
72
+ * Returns 0 on success
73
+ * -1 when the PSCI call is unknown,
74
+ */
75
+static bool hvf_handle_psci_call(CPUState *cpu)
76
+{
77
+ ARMCPU *arm_cpu = ARM_CPU(cpu);
78
+ CPUARMState *env = &arm_cpu->env;
79
+ uint64_t param[4] = {
80
+ env->xregs[0],
81
+ env->xregs[1],
82
+ env->xregs[2],
83
+ env->xregs[3]
84
+ };
85
+ uint64_t context_id, mpidr;
86
+ bool target_aarch64 = true;
87
+ CPUState *target_cpu_state;
88
+ ARMCPU *target_cpu;
89
+ target_ulong entry;
90
+ int target_el = 1;
91
+ int32_t ret = 0;
92
+
93
+ trace_hvf_psci_call(param[0], param[1], param[2], param[3],
94
+ arm_cpu->mp_affinity);
95
+
96
+ switch (param[0]) {
97
+ case QEMU_PSCI_0_2_FN_PSCI_VERSION:
98
+ ret = QEMU_PSCI_0_2_RET_VERSION_0_2;
99
+ break;
100
+ case QEMU_PSCI_0_2_FN_MIGRATE_INFO_TYPE:
101
+ ret = QEMU_PSCI_0_2_RET_TOS_MIGRATION_NOT_REQUIRED; /* No trusted OS */
102
+ break;
103
+ case QEMU_PSCI_0_2_FN_AFFINITY_INFO:
104
+ case QEMU_PSCI_0_2_FN64_AFFINITY_INFO:
105
+ mpidr = param[1];
106
+
107
+ switch (param[2]) {
108
+ case 0:
109
+ target_cpu_state = arm_get_cpu_by_id(mpidr);
110
+ if (!target_cpu_state) {
111
+ ret = QEMU_PSCI_RET_INVALID_PARAMS;
112
+ break;
113
+ }
114
+ target_cpu = ARM_CPU(target_cpu_state);
115
+
116
+ ret = target_cpu->power_state;
117
+ break;
118
+ default:
119
+ /* Everything above affinity level 0 is always on. */
120
+ ret = 0;
121
+ }
122
+ break;
123
+ case QEMU_PSCI_0_2_FN_SYSTEM_RESET:
124
+ qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
125
+ /*
126
+ * QEMU reset and shutdown are async requests, but PSCI
127
+ * mandates that we never return from the reset/shutdown
128
+ * call, so power the CPU off now so it doesn't execute
129
+ * anything further.
130
+ */
131
+ hvf_psci_cpu_off(arm_cpu);
132
+ break;
133
+ case QEMU_PSCI_0_2_FN_SYSTEM_OFF:
134
+ qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
135
+ hvf_psci_cpu_off(arm_cpu);
136
+ break;
137
+ case QEMU_PSCI_0_1_FN_CPU_ON:
138
+ case QEMU_PSCI_0_2_FN_CPU_ON:
139
+ case QEMU_PSCI_0_2_FN64_CPU_ON:
140
+ mpidr = param[1];
141
+ entry = param[2];
142
+ context_id = param[3];
143
+ ret = arm_set_cpu_on(mpidr, entry, context_id,
144
+ target_el, target_aarch64);
145
+ break;
146
+ case QEMU_PSCI_0_1_FN_CPU_OFF:
147
+ case QEMU_PSCI_0_2_FN_CPU_OFF:
148
+ hvf_psci_cpu_off(arm_cpu);
149
+ break;
150
+ case QEMU_PSCI_0_1_FN_CPU_SUSPEND:
151
+ case QEMU_PSCI_0_2_FN_CPU_SUSPEND:
152
+ case QEMU_PSCI_0_2_FN64_CPU_SUSPEND:
153
+ /* Affinity levels are not supported in QEMU */
154
+ if (param[1] & 0xfffe0000) {
155
+ ret = QEMU_PSCI_RET_INVALID_PARAMS;
156
+ break;
157
+ }
158
+ /* Powerdown is not supported, we always go into WFI */
159
+ env->xregs[0] = 0;
160
+ hvf_wfi(cpu);
161
+ break;
162
+ case QEMU_PSCI_0_1_FN_MIGRATE:
163
+ case QEMU_PSCI_0_2_FN_MIGRATE:
164
+ ret = QEMU_PSCI_RET_NOT_SUPPORTED;
165
+ break;
166
+ default:
167
+ return false;
168
+ }
169
+
170
+ env->xregs[0] = ret;
171
+ return true;
172
+}
173
+
174
static int hvf_sysreg_read(CPUState *cpu, uint32_t reg, uint32_t rt)
175
{
107
{
176
ARMCPU *arm_cpu = ARM_CPU(cpu);
108
int i;
177
@@ -XXX,XX +XXX,XX @@ int hvf_vcpu_exec(CPUState *cpu)
109
@@ -XXX,XX +XXX,XX @@ static void versal_realize(DeviceState *dev, Error **errp)
178
break;
110
179
case EC_AA64_HVC:
111
versal_create_apu_cpus(s);
180
cpu_synchronize_state(cpu);
112
versal_create_apu_gic(s, pic);
181
- trace_hvf_unknown_hvc(env->xregs[0]);
113
+ versal_create_rpu_cpus(s);
182
- /* SMCCC 1.3 section 5.2 says every unknown SMCCC call returns -1 */
114
versal_create_uarts(s, pic);
183
- env->xregs[0] = -1;
115
versal_create_usbs(s, pic);
184
+ if (arm_cpu->psci_conduit == QEMU_PSCI_CONDUIT_HVC) {
116
versal_create_gems(s, pic);
185
+ if (!hvf_handle_psci_call(cpu)) {
117
@@ -XXX,XX +XXX,XX @@ static void versal_realize(DeviceState *dev, Error **errp)
186
+ trace_hvf_unknown_hvc(env->xregs[0]);
118
187
+ /* SMCCC 1.3 section 5.2 says every unknown SMCCC call returns -1 */
119
memory_region_add_subregion_overlap(&s->mr_ps, MM_OCM, &s->lpd.mr_ocm, 0);
188
+ env->xregs[0] = -1;
120
memory_region_add_subregion_overlap(&s->fpd.apu.mr, 0, &s->mr_ps, 0);
189
+ }
121
+ memory_region_add_subregion_overlap(&s->lpd.rpu.mr, 0,
190
+ } else {
122
+ &s->lpd.rpu.mr_ps_alias, 0);
191
+ trace_hvf_unknown_hvc(env->xregs[0]);
123
}
192
+ hvf_raise_exception(cpu, EXCP_UDEF, syn_uncategorized());
124
193
+ }
125
static void versal_init(Object *obj)
194
break;
126
@@ -XXX,XX +XXX,XX @@ static void versal_init(Object *obj)
195
case EC_AA64_SMC:
127
Versal *s = XLNX_VERSAL(obj);
196
cpu_synchronize_state(cpu);
128
197
- trace_hvf_unknown_smc(env->xregs[0]);
129
memory_region_init(&s->fpd.apu.mr, obj, "mr-apu", UINT64_MAX);
198
- hvf_raise_exception(cpu, EXCP_UDEF, syn_uncategorized());
130
+ memory_region_init(&s->lpd.rpu.mr, obj, "mr-rpu", UINT64_MAX);
199
+ if (arm_cpu->psci_conduit == QEMU_PSCI_CONDUIT_SMC) {
131
memory_region_init(&s->mr_ps, obj, "mr-ps-switch", UINT64_MAX);
200
+ advance_pc = true;
132
+ memory_region_init_alias(&s->lpd.rpu.mr_ps_alias, OBJECT(s),
201
+
133
+ "mr-rpu-ps-alias", &s->mr_ps, 0, UINT64_MAX);
202
+ if (!hvf_handle_psci_call(cpu)) {
134
}
203
+ trace_hvf_unknown_smc(env->xregs[0]);
135
204
+ /* SMCCC 1.3 section 5.2 says every unknown SMCCC call returns -1 */
136
static Property versal_properties[] = {
205
+ env->xregs[0] = -1;
206
+ }
207
+ } else {
208
+ trace_hvf_unknown_smc(env->xregs[0]);
209
+ hvf_raise_exception(cpu, EXCP_UDEF, syn_uncategorized());
210
+ }
211
break;
212
default:
213
cpu_synchronize_state(cpu);
214
diff --git a/target/arm/hvf/trace-events b/target/arm/hvf/trace-events
215
index XXXXXXX..XXXXXXX 100644
216
--- a/target/arm/hvf/trace-events
217
+++ b/target/arm/hvf/trace-events
218
@@ -XXX,XX +XXX,XX @@ hvf_sysreg_write(uint32_t reg, uint32_t op0, uint32_t op1, uint32_t crn, uint32_
219
hvf_unknown_hvc(uint64_t x0) "unknown HVC! 0x%016"PRIx64
220
hvf_unknown_smc(uint64_t x0) "unknown SMC! 0x%016"PRIx64
221
hvf_exit(uint64_t syndrome, uint32_t ec, uint64_t pc) "exit: 0x%"PRIx64" [ec=0x%x pc=0x%"PRIx64"]"
222
+hvf_psci_call(uint64_t x0, uint64_t x1, uint64_t x2, uint64_t x3, uint32_t cpuid) "PSCI Call x0=0x%016"PRIx64" x1=0x%016"PRIx64" x2=0x%016"PRIx64" x3=0x%016"PRIx64" cpu=0x%x"
223
--
137
--
224
2.20.1
138
2.25.1
225
226
diff view generated by jsdifflib
1
From: Alexander Graf <agraf@csgraf.de>
1
From: "Edgar E. Iglesias" <edgar.iglesias@amd.com>
2
2
3
With Apple Silicon available to the masses, it's a good time to add support
3
Add a model of the Xilinx Versal CRL.
4
for driving its virtualization extensions from QEMU.
5
4
6
This patch adds all necessary architecture specific code to get basic VMs
5
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>
7
working, including save/restore.
6
Reviewed-by: Frederic Konrad <fkonrad@amd.com>
8
7
Reviewed-by: Francisco Iglesias <francisco.iglesias@amd.com>
9
Known limitations:
8
Message-id: 20220406174303.2022038-4-edgar.iglesias@xilinx.com
10
11
- WFI handling is missing (follows in later patch)
12
- No watchpoint/breakpoint support
13
14
Signed-off-by: Alexander Graf <agraf@csgraf.de>
15
Reviewed-by: Roman Bolshakov <r.bolshakov@yadro.com>
16
Reviewed-by: Sergio Lopez <slp@redhat.com>
17
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
18
Message-id: 20210916155404.86958-5-agraf@csgraf.de
19
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
20
---
10
---
21
meson.build | 1 +
11
include/hw/misc/xlnx-versal-crl.h | 235 +++++++++++++++++
22
include/sysemu/hvf_int.h | 10 +-
12
hw/misc/xlnx-versal-crl.c | 421 ++++++++++++++++++++++++++++++
23
accel/hvf/hvf-accel-ops.c | 9 +
13
hw/misc/meson.build | 1 +
24
target/arm/hvf/hvf.c | 794 ++++++++++++++++++++++++++++++++++++
14
3 files changed, 657 insertions(+)
25
target/i386/hvf/hvf.c | 5 +
15
create mode 100644 include/hw/misc/xlnx-versal-crl.h
26
MAINTAINERS | 5 +
16
create mode 100644 hw/misc/xlnx-versal-crl.c
27
target/arm/hvf/trace-events | 10 +
28
7 files changed, 833 insertions(+), 1 deletion(-)
29
create mode 100644 target/arm/hvf/hvf.c
30
create mode 100644 target/arm/hvf/trace-events
31
17
32
diff --git a/meson.build b/meson.build
18
diff --git a/include/hw/misc/xlnx-versal-crl.h b/include/hw/misc/xlnx-versal-crl.h
33
index XXXXXXX..XXXXXXX 100644
34
--- a/meson.build
35
+++ b/meson.build
36
@@ -XXX,XX +XXX,XX @@ if have_system or have_user
37
'accel/tcg',
38
'hw/core',
39
'target/arm',
40
+ 'target/arm/hvf',
41
'target/hppa',
42
'target/i386',
43
'target/i386/kvm',
44
diff --git a/include/sysemu/hvf_int.h b/include/sysemu/hvf_int.h
45
index XXXXXXX..XXXXXXX 100644
46
--- a/include/sysemu/hvf_int.h
47
+++ b/include/sysemu/hvf_int.h
48
@@ -XXX,XX +XXX,XX @@
49
#ifndef HVF_INT_H
50
#define HVF_INT_H
51
52
+#ifdef __aarch64__
53
+#include <Hypervisor/Hypervisor.h>
54
+#else
55
#include <Hypervisor/hv.h>
56
+#endif
57
58
/* hvf_slot flags */
59
#define HVF_SLOT_LOG (1 << 0)
60
@@ -XXX,XX +XXX,XX @@ struct HVFState {
61
int num_slots;
62
63
hvf_vcpu_caps *hvf_caps;
64
+ uint64_t vtimer_offset;
65
};
66
extern HVFState *hvf_state;
67
68
struct hvf_vcpu_state {
69
- int fd;
70
+ uint64_t fd;
71
+ void *exit;
72
+ bool vtimer_masked;
73
};
74
75
void assert_hvf_ok(hv_return_t ret);
76
@@ -XXX,XX +XXX,XX @@ int hvf_vcpu_exec(CPUState *);
77
hvf_slot *hvf_find_overlap_slot(uint64_t, uint64_t);
78
int hvf_put_registers(CPUState *);
79
int hvf_get_registers(CPUState *);
80
+void hvf_kick_vcpu_thread(CPUState *cpu);
81
82
#endif
83
diff --git a/accel/hvf/hvf-accel-ops.c b/accel/hvf/hvf-accel-ops.c
84
index XXXXXXX..XXXXXXX 100644
85
--- a/accel/hvf/hvf-accel-ops.c
86
+++ b/accel/hvf/hvf-accel-ops.c
87
@@ -XXX,XX +XXX,XX @@
88
89
HVFState *hvf_state;
90
91
+#ifdef __aarch64__
92
+#define HV_VM_DEFAULT NULL
93
+#endif
94
+
95
/* Memory slots */
96
97
hvf_slot *hvf_find_overlap_slot(uint64_t start, uint64_t size)
98
@@ -XXX,XX +XXX,XX @@ static int hvf_init_vcpu(CPUState *cpu)
99
pthread_sigmask(SIG_BLOCK, NULL, &set);
100
sigdelset(&set, SIG_IPI);
101
102
+#ifdef __aarch64__
103
+ r = hv_vcpu_create(&cpu->hvf->fd, (hv_vcpu_exit_t **)&cpu->hvf->exit, NULL);
104
+#else
105
r = hv_vcpu_create((hv_vcpuid_t *)&cpu->hvf->fd, HV_VCPU_DEFAULT);
106
+#endif
107
cpu->vcpu_dirty = 1;
108
assert_hvf_ok(r);
109
110
@@ -XXX,XX +XXX,XX @@ static void hvf_accel_ops_class_init(ObjectClass *oc, void *data)
111
AccelOpsClass *ops = ACCEL_OPS_CLASS(oc);
112
113
ops->create_vcpu_thread = hvf_start_vcpu_thread;
114
+ ops->kick_vcpu_thread = hvf_kick_vcpu_thread;
115
116
ops->synchronize_post_reset = hvf_cpu_synchronize_post_reset;
117
ops->synchronize_post_init = hvf_cpu_synchronize_post_init;
118
diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c
119
new file mode 100644
19
new file mode 100644
120
index XXXXXXX..XXXXXXX
20
index XXXXXXX..XXXXXXX
121
--- /dev/null
21
--- /dev/null
122
+++ b/target/arm/hvf/hvf.c
22
+++ b/include/hw/misc/xlnx-versal-crl.h
123
@@ -XXX,XX +XXX,XX @@
23
@@ -XXX,XX +XXX,XX @@
124
+/*
24
+/*
125
+ * QEMU Hypervisor.framework support for Apple Silicon
25
+ * QEMU model of the Clock-Reset-LPD (CRL).
126
+
127
+ * Copyright 2020 Alexander Graf <agraf@csgraf.de>
128
+ *
26
+ *
129
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
27
+ * Copyright (c) 2022 Xilinx Inc.
130
+ * See the COPYING file in the top-level directory.
28
+ * SPDX-License-Identifier: GPL-2.0-or-later
131
+ *
29
+ *
30
+ * Written by Edgar E. Iglesias <edgar.iglesias@xilinx.com>
132
+ */
31
+ */
32
+#ifndef HW_MISC_XLNX_VERSAL_CRL_H
33
+#define HW_MISC_XLNX_VERSAL_CRL_H
34
+
35
+#include "hw/sysbus.h"
36
+#include "hw/register.h"
37
+#include "target/arm/cpu.h"
38
+
39
+#define TYPE_XLNX_VERSAL_CRL "xlnx,versal-crl"
40
+OBJECT_DECLARE_SIMPLE_TYPE(XlnxVersalCRL, XLNX_VERSAL_CRL)
41
+
42
+REG32(ERR_CTRL, 0x0)
43
+ FIELD(ERR_CTRL, SLVERR_ENABLE, 0, 1)
44
+REG32(IR_STATUS, 0x4)
45
+ FIELD(IR_STATUS, ADDR_DECODE_ERR, 0, 1)
46
+REG32(IR_MASK, 0x8)
47
+ FIELD(IR_MASK, ADDR_DECODE_ERR, 0, 1)
48
+REG32(IR_ENABLE, 0xc)
49
+ FIELD(IR_ENABLE, ADDR_DECODE_ERR, 0, 1)
50
+REG32(IR_DISABLE, 0x10)
51
+ FIELD(IR_DISABLE, ADDR_DECODE_ERR, 0, 1)
52
+REG32(WPROT, 0x1c)
53
+ FIELD(WPROT, ACTIVE, 0, 1)
54
+REG32(PLL_CLK_OTHER_DMN, 0x20)
55
+ FIELD(PLL_CLK_OTHER_DMN, APLL_BYPASS, 0, 1)
56
+REG32(RPLL_CTRL, 0x40)
57
+ FIELD(RPLL_CTRL, POST_SRC, 24, 3)
58
+ FIELD(RPLL_CTRL, PRE_SRC, 20, 3)
59
+ FIELD(RPLL_CTRL, CLKOUTDIV, 16, 2)
60
+ FIELD(RPLL_CTRL, FBDIV, 8, 8)
61
+ FIELD(RPLL_CTRL, BYPASS, 3, 1)
62
+ FIELD(RPLL_CTRL, RESET, 0, 1)
63
+REG32(RPLL_CFG, 0x44)
64
+ FIELD(RPLL_CFG, LOCK_DLY, 25, 7)
65
+ FIELD(RPLL_CFG, LOCK_CNT, 13, 10)
66
+ FIELD(RPLL_CFG, LFHF, 10, 2)
67
+ FIELD(RPLL_CFG, CP, 5, 4)
68
+ FIELD(RPLL_CFG, RES, 0, 4)
69
+REG32(RPLL_FRAC_CFG, 0x48)
70
+ FIELD(RPLL_FRAC_CFG, ENABLED, 31, 1)
71
+ FIELD(RPLL_FRAC_CFG, SEED, 22, 3)
72
+ FIELD(RPLL_FRAC_CFG, ALGRTHM, 19, 1)
73
+ FIELD(RPLL_FRAC_CFG, ORDER, 18, 1)
74
+ FIELD(RPLL_FRAC_CFG, DATA, 0, 16)
75
+REG32(PLL_STATUS, 0x50)
76
+ FIELD(PLL_STATUS, RPLL_STABLE, 2, 1)
77
+ FIELD(PLL_STATUS, RPLL_LOCK, 0, 1)
78
+REG32(RPLL_TO_XPD_CTRL, 0x100)
79
+ FIELD(RPLL_TO_XPD_CTRL, CLKACT, 25, 1)
80
+ FIELD(RPLL_TO_XPD_CTRL, DIVISOR0, 8, 10)
81
+REG32(LPD_TOP_SWITCH_CTRL, 0x104)
82
+ FIELD(LPD_TOP_SWITCH_CTRL, CLKACT_ADMA, 26, 1)
83
+ FIELD(LPD_TOP_SWITCH_CTRL, CLKACT, 25, 1)
84
+ FIELD(LPD_TOP_SWITCH_CTRL, DIVISOR0, 8, 10)
85
+ FIELD(LPD_TOP_SWITCH_CTRL, SRCSEL, 0, 3)
86
+REG32(LPD_LSBUS_CTRL, 0x108)
87
+ FIELD(LPD_LSBUS_CTRL, CLKACT, 25, 1)
88
+ FIELD(LPD_LSBUS_CTRL, DIVISOR0, 8, 10)
89
+ FIELD(LPD_LSBUS_CTRL, SRCSEL, 0, 3)
90
+REG32(CPU_R5_CTRL, 0x10c)
91
+ FIELD(CPU_R5_CTRL, CLKACT_OCM2, 28, 1)
92
+ FIELD(CPU_R5_CTRL, CLKACT_OCM, 27, 1)
93
+ FIELD(CPU_R5_CTRL, CLKACT_CORE, 26, 1)
94
+ FIELD(CPU_R5_CTRL, CLKACT, 25, 1)
95
+ FIELD(CPU_R5_CTRL, DIVISOR0, 8, 10)
96
+ FIELD(CPU_R5_CTRL, SRCSEL, 0, 3)
97
+REG32(IOU_SWITCH_CTRL, 0x114)
98
+ FIELD(IOU_SWITCH_CTRL, CLKACT, 25, 1)
99
+ FIELD(IOU_SWITCH_CTRL, DIVISOR0, 8, 10)
100
+ FIELD(IOU_SWITCH_CTRL, SRCSEL, 0, 3)
101
+REG32(GEM0_REF_CTRL, 0x118)
102
+ FIELD(GEM0_REF_CTRL, CLKACT_RX, 27, 1)
103
+ FIELD(GEM0_REF_CTRL, CLKACT_TX, 26, 1)
104
+ FIELD(GEM0_REF_CTRL, CLKACT, 25, 1)
105
+ FIELD(GEM0_REF_CTRL, DIVISOR0, 8, 10)
106
+ FIELD(GEM0_REF_CTRL, SRCSEL, 0, 3)
107
+REG32(GEM1_REF_CTRL, 0x11c)
108
+ FIELD(GEM1_REF_CTRL, CLKACT_RX, 27, 1)
109
+ FIELD(GEM1_REF_CTRL, CLKACT_TX, 26, 1)
110
+ FIELD(GEM1_REF_CTRL, CLKACT, 25, 1)
111
+ FIELD(GEM1_REF_CTRL, DIVISOR0, 8, 10)
112
+ FIELD(GEM1_REF_CTRL, SRCSEL, 0, 3)
113
+REG32(GEM_TSU_REF_CTRL, 0x120)
114
+ FIELD(GEM_TSU_REF_CTRL, CLKACT, 25, 1)
115
+ FIELD(GEM_TSU_REF_CTRL, DIVISOR0, 8, 10)
116
+ FIELD(GEM_TSU_REF_CTRL, SRCSEL, 0, 3)
117
+REG32(USB0_BUS_REF_CTRL, 0x124)
118
+ FIELD(USB0_BUS_REF_CTRL, CLKACT, 25, 1)
119
+ FIELD(USB0_BUS_REF_CTRL, DIVISOR0, 8, 10)
120
+ FIELD(USB0_BUS_REF_CTRL, SRCSEL, 0, 3)
121
+REG32(UART0_REF_CTRL, 0x128)
122
+ FIELD(UART0_REF_CTRL, CLKACT, 25, 1)
123
+ FIELD(UART0_REF_CTRL, DIVISOR0, 8, 10)
124
+ FIELD(UART0_REF_CTRL, SRCSEL, 0, 3)
125
+REG32(UART1_REF_CTRL, 0x12c)
126
+ FIELD(UART1_REF_CTRL, CLKACT, 25, 1)
127
+ FIELD(UART1_REF_CTRL, DIVISOR0, 8, 10)
128
+ FIELD(UART1_REF_CTRL, SRCSEL, 0, 3)
129
+REG32(SPI0_REF_CTRL, 0x130)
130
+ FIELD(SPI0_REF_CTRL, CLKACT, 25, 1)
131
+ FIELD(SPI0_REF_CTRL, DIVISOR0, 8, 10)
132
+ FIELD(SPI0_REF_CTRL, SRCSEL, 0, 3)
133
+REG32(SPI1_REF_CTRL, 0x134)
134
+ FIELD(SPI1_REF_CTRL, CLKACT, 25, 1)
135
+ FIELD(SPI1_REF_CTRL, DIVISOR0, 8, 10)
136
+ FIELD(SPI1_REF_CTRL, SRCSEL, 0, 3)
137
+REG32(CAN0_REF_CTRL, 0x138)
138
+ FIELD(CAN0_REF_CTRL, CLKACT, 25, 1)
139
+ FIELD(CAN0_REF_CTRL, DIVISOR0, 8, 10)
140
+ FIELD(CAN0_REF_CTRL, SRCSEL, 0, 3)
141
+REG32(CAN1_REF_CTRL, 0x13c)
142
+ FIELD(CAN1_REF_CTRL, CLKACT, 25, 1)
143
+ FIELD(CAN1_REF_CTRL, DIVISOR0, 8, 10)
144
+ FIELD(CAN1_REF_CTRL, SRCSEL, 0, 3)
145
+REG32(I2C0_REF_CTRL, 0x140)
146
+ FIELD(I2C0_REF_CTRL, CLKACT, 25, 1)
147
+ FIELD(I2C0_REF_CTRL, DIVISOR0, 8, 10)
148
+ FIELD(I2C0_REF_CTRL, SRCSEL, 0, 3)
149
+REG32(I2C1_REF_CTRL, 0x144)
150
+ FIELD(I2C1_REF_CTRL, CLKACT, 25, 1)
151
+ FIELD(I2C1_REF_CTRL, DIVISOR0, 8, 10)
152
+ FIELD(I2C1_REF_CTRL, SRCSEL, 0, 3)
153
+REG32(DBG_LPD_CTRL, 0x148)
154
+ FIELD(DBG_LPD_CTRL, CLKACT, 25, 1)
155
+ FIELD(DBG_LPD_CTRL, DIVISOR0, 8, 10)
156
+ FIELD(DBG_LPD_CTRL, SRCSEL, 0, 3)
157
+REG32(TIMESTAMP_REF_CTRL, 0x14c)
158
+ FIELD(TIMESTAMP_REF_CTRL, CLKACT, 25, 1)
159
+ FIELD(TIMESTAMP_REF_CTRL, DIVISOR0, 8, 10)
160
+ FIELD(TIMESTAMP_REF_CTRL, SRCSEL, 0, 3)
161
+REG32(CRL_SAFETY_CHK, 0x150)
162
+REG32(PSM_REF_CTRL, 0x154)
163
+ FIELD(PSM_REF_CTRL, DIVISOR0, 8, 10)
164
+ FIELD(PSM_REF_CTRL, SRCSEL, 0, 3)
165
+REG32(DBG_TSTMP_CTRL, 0x158)
166
+ FIELD(DBG_TSTMP_CTRL, CLKACT, 25, 1)
167
+ FIELD(DBG_TSTMP_CTRL, DIVISOR0, 8, 10)
168
+ FIELD(DBG_TSTMP_CTRL, SRCSEL, 0, 3)
169
+REG32(CPM_TOPSW_REF_CTRL, 0x15c)
170
+ FIELD(CPM_TOPSW_REF_CTRL, CLKACT, 25, 1)
171
+ FIELD(CPM_TOPSW_REF_CTRL, DIVISOR0, 8, 10)
172
+ FIELD(CPM_TOPSW_REF_CTRL, SRCSEL, 0, 3)
173
+REG32(USB3_DUAL_REF_CTRL, 0x160)
174
+ FIELD(USB3_DUAL_REF_CTRL, CLKACT, 25, 1)
175
+ FIELD(USB3_DUAL_REF_CTRL, DIVISOR0, 8, 10)
176
+ FIELD(USB3_DUAL_REF_CTRL, SRCSEL, 0, 3)
177
+REG32(RST_CPU_R5, 0x300)
178
+ FIELD(RST_CPU_R5, RESET_PGE, 4, 1)
179
+ FIELD(RST_CPU_R5, RESET_AMBA, 2, 1)
180
+ FIELD(RST_CPU_R5, RESET_CPU1, 1, 1)
181
+ FIELD(RST_CPU_R5, RESET_CPU0, 0, 1)
182
+REG32(RST_ADMA, 0x304)
183
+ FIELD(RST_ADMA, RESET, 0, 1)
184
+REG32(RST_GEM0, 0x308)
185
+ FIELD(RST_GEM0, RESET, 0, 1)
186
+REG32(RST_GEM1, 0x30c)
187
+ FIELD(RST_GEM1, RESET, 0, 1)
188
+REG32(RST_SPARE, 0x310)
189
+ FIELD(RST_SPARE, RESET, 0, 1)
190
+REG32(RST_USB0, 0x314)
191
+ FIELD(RST_USB0, RESET, 0, 1)
192
+REG32(RST_UART0, 0x318)
193
+ FIELD(RST_UART0, RESET, 0, 1)
194
+REG32(RST_UART1, 0x31c)
195
+ FIELD(RST_UART1, RESET, 0, 1)
196
+REG32(RST_SPI0, 0x320)
197
+ FIELD(RST_SPI0, RESET, 0, 1)
198
+REG32(RST_SPI1, 0x324)
199
+ FIELD(RST_SPI1, RESET, 0, 1)
200
+REG32(RST_CAN0, 0x328)
201
+ FIELD(RST_CAN0, RESET, 0, 1)
202
+REG32(RST_CAN1, 0x32c)
203
+ FIELD(RST_CAN1, RESET, 0, 1)
204
+REG32(RST_I2C0, 0x330)
205
+ FIELD(RST_I2C0, RESET, 0, 1)
206
+REG32(RST_I2C1, 0x334)
207
+ FIELD(RST_I2C1, RESET, 0, 1)
208
+REG32(RST_DBG_LPD, 0x338)
209
+ FIELD(RST_DBG_LPD, RPU_DBG1_RESET, 5, 1)
210
+ FIELD(RST_DBG_LPD, RPU_DBG0_RESET, 4, 1)
211
+ FIELD(RST_DBG_LPD, RESET_HSDP, 1, 1)
212
+ FIELD(RST_DBG_LPD, RESET, 0, 1)
213
+REG32(RST_GPIO, 0x33c)
214
+ FIELD(RST_GPIO, RESET, 0, 1)
215
+REG32(RST_TTC, 0x344)
216
+ FIELD(RST_TTC, TTC3_RESET, 3, 1)
217
+ FIELD(RST_TTC, TTC2_RESET, 2, 1)
218
+ FIELD(RST_TTC, TTC1_RESET, 1, 1)
219
+ FIELD(RST_TTC, TTC0_RESET, 0, 1)
220
+REG32(RST_TIMESTAMP, 0x348)
221
+ FIELD(RST_TIMESTAMP, RESET, 0, 1)
222
+REG32(RST_SWDT, 0x34c)
223
+ FIELD(RST_SWDT, RESET, 0, 1)
224
+REG32(RST_OCM, 0x350)
225
+ FIELD(RST_OCM, RESET, 0, 1)
226
+REG32(RST_IPI, 0x354)
227
+ FIELD(RST_IPI, RESET, 0, 1)
228
+REG32(RST_SYSMON, 0x358)
229
+ FIELD(RST_SYSMON, SEQ_RST, 1, 1)
230
+ FIELD(RST_SYSMON, CFG_RST, 0, 1)
231
+REG32(RST_FPD, 0x360)
232
+ FIELD(RST_FPD, SRST, 1, 1)
233
+ FIELD(RST_FPD, POR, 0, 1)
234
+REG32(PSM_RST_MODE, 0x370)
235
+ FIELD(PSM_RST_MODE, WAKEUP, 2, 1)
236
+ FIELD(PSM_RST_MODE, RST_MODE, 0, 2)
237
+
238
+#define CRL_R_MAX (R_PSM_RST_MODE + 1)
239
+
240
+#define RPU_MAX_CPU 2
241
+
242
+struct XlnxVersalCRL {
243
+ SysBusDevice parent_obj;
244
+ qemu_irq irq;
245
+
246
+ struct {
247
+ ARMCPU *cpu_r5[RPU_MAX_CPU];
248
+ DeviceState *adma[8];
249
+ DeviceState *uart[2];
250
+ DeviceState *gem[2];
251
+ DeviceState *usb;
252
+ } cfg;
253
+
254
+ RegisterInfoArray *reg_array;
255
+ uint32_t regs[CRL_R_MAX];
256
+ RegisterInfo regs_info[CRL_R_MAX];
257
+};
258
+#endif
259
diff --git a/hw/misc/xlnx-versal-crl.c b/hw/misc/xlnx-versal-crl.c
260
new file mode 100644
261
index XXXXXXX..XXXXXXX
262
--- /dev/null
263
+++ b/hw/misc/xlnx-versal-crl.c
264
@@ -XXX,XX +XXX,XX @@
265
+/*
266
+ * QEMU model of the Clock-Reset-LPD (CRL).
267
+ *
268
+ * Copyright (c) 2022 Advanced Micro Devices, Inc.
269
+ * SPDX-License-Identifier: GPL-2.0-or-later
270
+ *
271
+ * Written by Edgar E. Iglesias <edgar.iglesias@amd.com>
272
+ */
133
+
273
+
134
+#include "qemu/osdep.h"
274
+#include "qemu/osdep.h"
135
+#include "qemu-common.h"
275
+#include "qapi/error.h"
136
+#include "qemu/error-report.h"
276
+#include "qemu/log.h"
137
+
277
+#include "qemu/bitops.h"
138
+#include "sysemu/runstate.h"
278
+#include "migration/vmstate.h"
139
+#include "sysemu/hvf.h"
279
+#include "hw/qdev-properties.h"
140
+#include "sysemu/hvf_int.h"
280
+#include "hw/sysbus.h"
141
+#include "sysemu/hw_accel.h"
142
+
143
+#include <mach/mach_time.h>
144
+
145
+#include "exec/address-spaces.h"
146
+#include "hw/irq.h"
281
+#include "hw/irq.h"
147
+#include "qemu/main-loop.h"
282
+#include "hw/register.h"
148
+#include "sysemu/cpus.h"
283
+#include "hw/resettable.h"
149
+#include "target/arm/cpu.h"
284
+
150
+#include "target/arm/internals.h"
285
+#include "target/arm/arm-powerctl.h"
151
+#include "trace/trace-target_arm_hvf.h"
286
+#include "hw/misc/xlnx-versal-crl.h"
152
+#include "migration/vmstate.h"
287
+
153
+
288
+#ifndef XLNX_VERSAL_CRL_ERR_DEBUG
154
+#define HVF_SYSREG(crn, crm, op0, op1, op2) \
289
+#define XLNX_VERSAL_CRL_ERR_DEBUG 0
155
+ ENCODE_AA64_CP_REG(CP_REG_ARM64_SYSREG_CP, crn, crm, op0, op1, op2)
290
+#endif
156
+#define PL1_WRITE_MASK 0x4
291
+
157
+
292
+static void crl_update_irq(XlnxVersalCRL *s)
158
+#define SYSREG(op0, op1, crn, crm, op2) \
293
+{
159
+ ((op0 << 20) | (op2 << 17) | (op1 << 14) | (crn << 10) | (crm << 1))
294
+ bool pending = s->regs[R_IR_STATUS] & ~s->regs[R_IR_MASK];
160
+#define SYSREG_MASK SYSREG(0x3, 0x7, 0xf, 0xf, 0x7)
295
+ qemu_set_irq(s->irq, pending);
161
+#define SYSREG_OSLAR_EL1 SYSREG(2, 0, 1, 0, 4)
296
+}
162
+#define SYSREG_OSLSR_EL1 SYSREG(2, 0, 1, 1, 4)
297
+
163
+#define SYSREG_OSDLR_EL1 SYSREG(2, 0, 1, 3, 4)
298
+static void crl_status_postw(RegisterInfo *reg, uint64_t val64)
164
+#define SYSREG_CNTPCT_EL0 SYSREG(3, 3, 14, 0, 1)
299
+{
165
+
300
+ XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque);
166
+#define WFX_IS_WFE (1 << 0)
301
+ crl_update_irq(s);
167
+
302
+}
168
+#define TMR_CTL_ENABLE (1 << 0)
303
+
169
+#define TMR_CTL_IMASK (1 << 1)
304
+static uint64_t crl_enable_prew(RegisterInfo *reg, uint64_t val64)
170
+#define TMR_CTL_ISTATUS (1 << 2)
305
+{
171
+
306
+ XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque);
172
+typedef struct HVFVTimer {
307
+ uint32_t val = val64;
173
+ /* Vtimer value during migration and paused state */
308
+
174
+ uint64_t vtimer_val;
309
+ s->regs[R_IR_MASK] &= ~val;
175
+} HVFVTimer;
310
+ crl_update_irq(s);
176
+
311
+ return 0;
177
+static HVFVTimer vtimer;
312
+}
178
+
313
+
179
+struct hvf_reg_match {
314
+static uint64_t crl_disable_prew(RegisterInfo *reg, uint64_t val64)
180
+ int reg;
315
+{
181
+ uint64_t offset;
316
+ XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque);
317
+ uint32_t val = val64;
318
+
319
+ s->regs[R_IR_MASK] |= val;
320
+ crl_update_irq(s);
321
+ return 0;
322
+}
323
+
324
+static void crl_reset_dev(XlnxVersalCRL *s, DeviceState *dev,
325
+ bool rst_old, bool rst_new)
326
+{
327
+ device_cold_reset(dev);
328
+}
329
+
330
+static void crl_reset_cpu(XlnxVersalCRL *s, ARMCPU *armcpu,
331
+ bool rst_old, bool rst_new)
332
+{
333
+ if (rst_new) {
334
+ arm_set_cpu_off(armcpu->mp_affinity);
335
+ } else {
336
+ arm_set_cpu_on_and_reset(armcpu->mp_affinity);
337
+ }
338
+}
339
+
340
+#define REGFIELD_RESET(type, s, reg, f, new_val, dev) { \
341
+ bool old_f = ARRAY_FIELD_EX32((s)->regs, reg, f); \
342
+ bool new_f = FIELD_EX32(new_val, reg, f); \
343
+ \
344
+ /* Detect edges. */ \
345
+ if (dev && old_f != new_f) { \
346
+ crl_reset_ ## type(s, dev, old_f, new_f); \
347
+ } \
348
+}
349
+
350
+static uint64_t crl_rst_r5_prew(RegisterInfo *reg, uint64_t val64)
351
+{
352
+ XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque);
353
+
354
+ REGFIELD_RESET(cpu, s, RST_CPU_R5, RESET_CPU0, val64, s->cfg.cpu_r5[0]);
355
+ REGFIELD_RESET(cpu, s, RST_CPU_R5, RESET_CPU1, val64, s->cfg.cpu_r5[1]);
356
+ return val64;
357
+}
358
+
359
+static uint64_t crl_rst_adma_prew(RegisterInfo *reg, uint64_t val64)
360
+{
361
+ XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque);
362
+ int i;
363
+
364
+ /* A single register fans out to all ADMA reset inputs. */
365
+ for (i = 0; i < ARRAY_SIZE(s->cfg.adma); i++) {
366
+ REGFIELD_RESET(dev, s, RST_ADMA, RESET, val64, s->cfg.adma[i]);
367
+ }
368
+ return val64;
369
+}
370
+
371
+static uint64_t crl_rst_uart0_prew(RegisterInfo *reg, uint64_t val64)
372
+{
373
+ XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque);
374
+
375
+ REGFIELD_RESET(dev, s, RST_UART0, RESET, val64, s->cfg.uart[0]);
376
+ return val64;
377
+}
378
+
379
+static uint64_t crl_rst_uart1_prew(RegisterInfo *reg, uint64_t val64)
380
+{
381
+ XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque);
382
+
383
+ REGFIELD_RESET(dev, s, RST_UART1, RESET, val64, s->cfg.uart[1]);
384
+ return val64;
385
+}
386
+
387
+static uint64_t crl_rst_gem0_prew(RegisterInfo *reg, uint64_t val64)
388
+{
389
+ XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque);
390
+
391
+ REGFIELD_RESET(dev, s, RST_GEM0, RESET, val64, s->cfg.gem[0]);
392
+ return val64;
393
+}
394
+
395
+static uint64_t crl_rst_gem1_prew(RegisterInfo *reg, uint64_t val64)
396
+{
397
+ XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque);
398
+
399
+ REGFIELD_RESET(dev, s, RST_GEM1, RESET, val64, s->cfg.gem[1]);
400
+ return val64;
401
+}
402
+
403
+static uint64_t crl_rst_usb_prew(RegisterInfo *reg, uint64_t val64)
404
+{
405
+ XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque);
406
+
407
+ REGFIELD_RESET(dev, s, RST_USB0, RESET, val64, s->cfg.usb);
408
+ return val64;
409
+}
410
+
411
+static const RegisterAccessInfo crl_regs_info[] = {
412
+ { .name = "ERR_CTRL", .addr = A_ERR_CTRL,
413
+ },{ .name = "IR_STATUS", .addr = A_IR_STATUS,
414
+ .w1c = 0x1,
415
+ .post_write = crl_status_postw,
416
+ },{ .name = "IR_MASK", .addr = A_IR_MASK,
417
+ .reset = 0x1,
418
+ .ro = 0x1,
419
+ },{ .name = "IR_ENABLE", .addr = A_IR_ENABLE,
420
+ .pre_write = crl_enable_prew,
421
+ },{ .name = "IR_DISABLE", .addr = A_IR_DISABLE,
422
+ .pre_write = crl_disable_prew,
423
+ },{ .name = "WPROT", .addr = A_WPROT,
424
+ },{ .name = "PLL_CLK_OTHER_DMN", .addr = A_PLL_CLK_OTHER_DMN,
425
+ .reset = 0x1,
426
+ .rsvd = 0xe,
427
+ },{ .name = "RPLL_CTRL", .addr = A_RPLL_CTRL,
428
+ .reset = 0x24809,
429
+ .rsvd = 0xf88c00f6,
430
+ },{ .name = "RPLL_CFG", .addr = A_RPLL_CFG,
431
+ .reset = 0x2000000,
432
+ .rsvd = 0x1801210,
433
+ },{ .name = "RPLL_FRAC_CFG", .addr = A_RPLL_FRAC_CFG,
434
+ .rsvd = 0x7e330000,
435
+ },{ .name = "PLL_STATUS", .addr = A_PLL_STATUS,
436
+ .reset = R_PLL_STATUS_RPLL_STABLE_MASK |
437
+ R_PLL_STATUS_RPLL_LOCK_MASK,
438
+ .rsvd = 0xfa,
439
+ .ro = 0x5,
440
+ },{ .name = "RPLL_TO_XPD_CTRL", .addr = A_RPLL_TO_XPD_CTRL,
441
+ .reset = 0x2000100,
442
+ .rsvd = 0xfdfc00ff,
443
+ },{ .name = "LPD_TOP_SWITCH_CTRL", .addr = A_LPD_TOP_SWITCH_CTRL,
444
+ .reset = 0x6000300,
445
+ .rsvd = 0xf9fc00f8,
446
+ },{ .name = "LPD_LSBUS_CTRL", .addr = A_LPD_LSBUS_CTRL,
447
+ .reset = 0x2000800,
448
+ .rsvd = 0xfdfc00f8,
449
+ },{ .name = "CPU_R5_CTRL", .addr = A_CPU_R5_CTRL,
450
+ .reset = 0xe000300,
451
+ .rsvd = 0xe1fc00f8,
452
+ },{ .name = "IOU_SWITCH_CTRL", .addr = A_IOU_SWITCH_CTRL,
453
+ .reset = 0x2000500,
454
+ .rsvd = 0xfdfc00f8,
455
+ },{ .name = "GEM0_REF_CTRL", .addr = A_GEM0_REF_CTRL,
456
+ .reset = 0xe000a00,
457
+ .rsvd = 0xf1fc00f8,
458
+ },{ .name = "GEM1_REF_CTRL", .addr = A_GEM1_REF_CTRL,
459
+ .reset = 0xe000a00,
460
+ .rsvd = 0xf1fc00f8,
461
+ },{ .name = "GEM_TSU_REF_CTRL", .addr = A_GEM_TSU_REF_CTRL,
462
+ .reset = 0x300,
463
+ .rsvd = 0xfdfc00f8,
464
+ },{ .name = "USB0_BUS_REF_CTRL", .addr = A_USB0_BUS_REF_CTRL,
465
+ .reset = 0x2001900,
466
+ .rsvd = 0xfdfc00f8,
467
+ },{ .name = "UART0_REF_CTRL", .addr = A_UART0_REF_CTRL,
468
+ .reset = 0xc00,
469
+ .rsvd = 0xfdfc00f8,
470
+ },{ .name = "UART1_REF_CTRL", .addr = A_UART1_REF_CTRL,
471
+ .reset = 0xc00,
472
+ .rsvd = 0xfdfc00f8,
473
+ },{ .name = "SPI0_REF_CTRL", .addr = A_SPI0_REF_CTRL,
474
+ .reset = 0x600,
475
+ .rsvd = 0xfdfc00f8,
476
+ },{ .name = "SPI1_REF_CTRL", .addr = A_SPI1_REF_CTRL,
477
+ .reset = 0x600,
478
+ .rsvd = 0xfdfc00f8,
479
+ },{ .name = "CAN0_REF_CTRL", .addr = A_CAN0_REF_CTRL,
480
+ .reset = 0xc00,
481
+ .rsvd = 0xfdfc00f8,
482
+ },{ .name = "CAN1_REF_CTRL", .addr = A_CAN1_REF_CTRL,
483
+ .reset = 0xc00,
484
+ .rsvd = 0xfdfc00f8,
485
+ },{ .name = "I2C0_REF_CTRL", .addr = A_I2C0_REF_CTRL,
486
+ .reset = 0xc00,
487
+ .rsvd = 0xfdfc00f8,
488
+ },{ .name = "I2C1_REF_CTRL", .addr = A_I2C1_REF_CTRL,
489
+ .reset = 0xc00,
490
+ .rsvd = 0xfdfc00f8,
491
+ },{ .name = "DBG_LPD_CTRL", .addr = A_DBG_LPD_CTRL,
492
+ .reset = 0x300,
493
+ .rsvd = 0xfdfc00f8,
494
+ },{ .name = "TIMESTAMP_REF_CTRL", .addr = A_TIMESTAMP_REF_CTRL,
495
+ .reset = 0x2000c00,
496
+ .rsvd = 0xfdfc00f8,
497
+ },{ .name = "CRL_SAFETY_CHK", .addr = A_CRL_SAFETY_CHK,
498
+ },{ .name = "PSM_REF_CTRL", .addr = A_PSM_REF_CTRL,
499
+ .reset = 0xf04,
500
+ .rsvd = 0xfffc00f8,
501
+ },{ .name = "DBG_TSTMP_CTRL", .addr = A_DBG_TSTMP_CTRL,
502
+ .reset = 0x300,
503
+ .rsvd = 0xfdfc00f8,
504
+ },{ .name = "CPM_TOPSW_REF_CTRL", .addr = A_CPM_TOPSW_REF_CTRL,
505
+ .reset = 0x300,
506
+ .rsvd = 0xfdfc00f8,
507
+ },{ .name = "USB3_DUAL_REF_CTRL", .addr = A_USB3_DUAL_REF_CTRL,
508
+ .reset = 0x3c00,
509
+ .rsvd = 0xfdfc00f8,
510
+ },{ .name = "RST_CPU_R5", .addr = A_RST_CPU_R5,
511
+ .reset = 0x17,
512
+ .rsvd = 0x8,
513
+ .pre_write = crl_rst_r5_prew,
514
+ },{ .name = "RST_ADMA", .addr = A_RST_ADMA,
515
+ .reset = 0x1,
516
+ .pre_write = crl_rst_adma_prew,
517
+ },{ .name = "RST_GEM0", .addr = A_RST_GEM0,
518
+ .reset = 0x1,
519
+ .pre_write = crl_rst_gem0_prew,
520
+ },{ .name = "RST_GEM1", .addr = A_RST_GEM1,
521
+ .reset = 0x1,
522
+ .pre_write = crl_rst_gem1_prew,
523
+ },{ .name = "RST_SPARE", .addr = A_RST_SPARE,
524
+ .reset = 0x1,
525
+ },{ .name = "RST_USB0", .addr = A_RST_USB0,
526
+ .reset = 0x1,
527
+ .pre_write = crl_rst_usb_prew,
528
+ },{ .name = "RST_UART0", .addr = A_RST_UART0,
529
+ .reset = 0x1,
530
+ .pre_write = crl_rst_uart0_prew,
531
+ },{ .name = "RST_UART1", .addr = A_RST_UART1,
532
+ .reset = 0x1,
533
+ .pre_write = crl_rst_uart1_prew,
534
+ },{ .name = "RST_SPI0", .addr = A_RST_SPI0,
535
+ .reset = 0x1,
536
+ },{ .name = "RST_SPI1", .addr = A_RST_SPI1,
537
+ .reset = 0x1,
538
+ },{ .name = "RST_CAN0", .addr = A_RST_CAN0,
539
+ .reset = 0x1,
540
+ },{ .name = "RST_CAN1", .addr = A_RST_CAN1,
541
+ .reset = 0x1,
542
+ },{ .name = "RST_I2C0", .addr = A_RST_I2C0,
543
+ .reset = 0x1,
544
+ },{ .name = "RST_I2C1", .addr = A_RST_I2C1,
545
+ .reset = 0x1,
546
+ },{ .name = "RST_DBG_LPD", .addr = A_RST_DBG_LPD,
547
+ .reset = 0x33,
548
+ .rsvd = 0xcc,
549
+ },{ .name = "RST_GPIO", .addr = A_RST_GPIO,
550
+ .reset = 0x1,
551
+ },{ .name = "RST_TTC", .addr = A_RST_TTC,
552
+ .reset = 0xf,
553
+ },{ .name = "RST_TIMESTAMP", .addr = A_RST_TIMESTAMP,
554
+ .reset = 0x1,
555
+ },{ .name = "RST_SWDT", .addr = A_RST_SWDT,
556
+ .reset = 0x1,
557
+ },{ .name = "RST_OCM", .addr = A_RST_OCM,
558
+ },{ .name = "RST_IPI", .addr = A_RST_IPI,
559
+ },{ .name = "RST_FPD", .addr = A_RST_FPD,
560
+ .reset = 0x3,
561
+ },{ .name = "PSM_RST_MODE", .addr = A_PSM_RST_MODE,
562
+ .reset = 0x1,
563
+ .rsvd = 0xf8,
564
+ }
182
+};
565
+};
183
+
566
+
184
+static const struct hvf_reg_match hvf_reg_match[] = {
567
+static void crl_reset_enter(Object *obj, ResetType type)
185
+ { HV_REG_X0, offsetof(CPUARMState, xregs[0]) },
568
+{
186
+ { HV_REG_X1, offsetof(CPUARMState, xregs[1]) },
569
+ XlnxVersalCRL *s = XLNX_VERSAL_CRL(obj);
187
+ { HV_REG_X2, offsetof(CPUARMState, xregs[2]) },
570
+ unsigned int i;
188
+ { HV_REG_X3, offsetof(CPUARMState, xregs[3]) },
571
+
189
+ { HV_REG_X4, offsetof(CPUARMState, xregs[4]) },
572
+ for (i = 0; i < ARRAY_SIZE(s->regs_info); ++i) {
190
+ { HV_REG_X5, offsetof(CPUARMState, xregs[5]) },
573
+ register_reset(&s->regs_info[i]);
191
+ { HV_REG_X6, offsetof(CPUARMState, xregs[6]) },
574
+ }
192
+ { HV_REG_X7, offsetof(CPUARMState, xregs[7]) },
575
+}
193
+ { HV_REG_X8, offsetof(CPUARMState, xregs[8]) },
576
+
194
+ { HV_REG_X9, offsetof(CPUARMState, xregs[9]) },
577
+static void crl_reset_hold(Object *obj)
195
+ { HV_REG_X10, offsetof(CPUARMState, xregs[10]) },
578
+{
196
+ { HV_REG_X11, offsetof(CPUARMState, xregs[11]) },
579
+ XlnxVersalCRL *s = XLNX_VERSAL_CRL(obj);
197
+ { HV_REG_X12, offsetof(CPUARMState, xregs[12]) },
580
+
198
+ { HV_REG_X13, offsetof(CPUARMState, xregs[13]) },
581
+ crl_update_irq(s);
199
+ { HV_REG_X14, offsetof(CPUARMState, xregs[14]) },
582
+}
200
+ { HV_REG_X15, offsetof(CPUARMState, xregs[15]) },
583
+
201
+ { HV_REG_X16, offsetof(CPUARMState, xregs[16]) },
584
+static const MemoryRegionOps crl_ops = {
202
+ { HV_REG_X17, offsetof(CPUARMState, xregs[17]) },
585
+ .read = register_read_memory,
203
+ { HV_REG_X18, offsetof(CPUARMState, xregs[18]) },
586
+ .write = register_write_memory,
204
+ { HV_REG_X19, offsetof(CPUARMState, xregs[19]) },
587
+ .endianness = DEVICE_LITTLE_ENDIAN,
205
+ { HV_REG_X20, offsetof(CPUARMState, xregs[20]) },
588
+ .valid = {
206
+ { HV_REG_X21, offsetof(CPUARMState, xregs[21]) },
589
+ .min_access_size = 4,
207
+ { HV_REG_X22, offsetof(CPUARMState, xregs[22]) },
590
+ .max_access_size = 4,
208
+ { HV_REG_X23, offsetof(CPUARMState, xregs[23]) },
591
+ },
209
+ { HV_REG_X24, offsetof(CPUARMState, xregs[24]) },
210
+ { HV_REG_X25, offsetof(CPUARMState, xregs[25]) },
211
+ { HV_REG_X26, offsetof(CPUARMState, xregs[26]) },
212
+ { HV_REG_X27, offsetof(CPUARMState, xregs[27]) },
213
+ { HV_REG_X28, offsetof(CPUARMState, xregs[28]) },
214
+ { HV_REG_X29, offsetof(CPUARMState, xregs[29]) },
215
+ { HV_REG_X30, offsetof(CPUARMState, xregs[30]) },
216
+ { HV_REG_PC, offsetof(CPUARMState, pc) },
217
+};
592
+};
218
+
593
+
219
+static const struct hvf_reg_match hvf_fpreg_match[] = {
594
+static void crl_init(Object *obj)
220
+ { HV_SIMD_FP_REG_Q0, offsetof(CPUARMState, vfp.zregs[0]) },
595
+{
221
+ { HV_SIMD_FP_REG_Q1, offsetof(CPUARMState, vfp.zregs[1]) },
596
+ XlnxVersalCRL *s = XLNX_VERSAL_CRL(obj);
222
+ { HV_SIMD_FP_REG_Q2, offsetof(CPUARMState, vfp.zregs[2]) },
597
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
223
+ { HV_SIMD_FP_REG_Q3, offsetof(CPUARMState, vfp.zregs[3]) },
224
+ { HV_SIMD_FP_REG_Q4, offsetof(CPUARMState, vfp.zregs[4]) },
225
+ { HV_SIMD_FP_REG_Q5, offsetof(CPUARMState, vfp.zregs[5]) },
226
+ { HV_SIMD_FP_REG_Q6, offsetof(CPUARMState, vfp.zregs[6]) },
227
+ { HV_SIMD_FP_REG_Q7, offsetof(CPUARMState, vfp.zregs[7]) },
228
+ { HV_SIMD_FP_REG_Q8, offsetof(CPUARMState, vfp.zregs[8]) },
229
+ { HV_SIMD_FP_REG_Q9, offsetof(CPUARMState, vfp.zregs[9]) },
230
+ { HV_SIMD_FP_REG_Q10, offsetof(CPUARMState, vfp.zregs[10]) },
231
+ { HV_SIMD_FP_REG_Q11, offsetof(CPUARMState, vfp.zregs[11]) },
232
+ { HV_SIMD_FP_REG_Q12, offsetof(CPUARMState, vfp.zregs[12]) },
233
+ { HV_SIMD_FP_REG_Q13, offsetof(CPUARMState, vfp.zregs[13]) },
234
+ { HV_SIMD_FP_REG_Q14, offsetof(CPUARMState, vfp.zregs[14]) },
235
+ { HV_SIMD_FP_REG_Q15, offsetof(CPUARMState, vfp.zregs[15]) },
236
+ { HV_SIMD_FP_REG_Q16, offsetof(CPUARMState, vfp.zregs[16]) },
237
+ { HV_SIMD_FP_REG_Q17, offsetof(CPUARMState, vfp.zregs[17]) },
238
+ { HV_SIMD_FP_REG_Q18, offsetof(CPUARMState, vfp.zregs[18]) },
239
+ { HV_SIMD_FP_REG_Q19, offsetof(CPUARMState, vfp.zregs[19]) },
240
+ { HV_SIMD_FP_REG_Q20, offsetof(CPUARMState, vfp.zregs[20]) },
241
+ { HV_SIMD_FP_REG_Q21, offsetof(CPUARMState, vfp.zregs[21]) },
242
+ { HV_SIMD_FP_REG_Q22, offsetof(CPUARMState, vfp.zregs[22]) },
243
+ { HV_SIMD_FP_REG_Q23, offsetof(CPUARMState, vfp.zregs[23]) },
244
+ { HV_SIMD_FP_REG_Q24, offsetof(CPUARMState, vfp.zregs[24]) },
245
+ { HV_SIMD_FP_REG_Q25, offsetof(CPUARMState, vfp.zregs[25]) },
246
+ { HV_SIMD_FP_REG_Q26, offsetof(CPUARMState, vfp.zregs[26]) },
247
+ { HV_SIMD_FP_REG_Q27, offsetof(CPUARMState, vfp.zregs[27]) },
248
+ { HV_SIMD_FP_REG_Q28, offsetof(CPUARMState, vfp.zregs[28]) },
249
+ { HV_SIMD_FP_REG_Q29, offsetof(CPUARMState, vfp.zregs[29]) },
250
+ { HV_SIMD_FP_REG_Q30, offsetof(CPUARMState, vfp.zregs[30]) },
251
+ { HV_SIMD_FP_REG_Q31, offsetof(CPUARMState, vfp.zregs[31]) },
252
+};
253
+
254
+struct hvf_sreg_match {
255
+ int reg;
256
+ uint32_t key;
257
+ uint32_t cp_idx;
258
+};
259
+
260
+static struct hvf_sreg_match hvf_sreg_match[] = {
261
+ { HV_SYS_REG_DBGBVR0_EL1, HVF_SYSREG(0, 0, 14, 0, 4) },
262
+ { HV_SYS_REG_DBGBCR0_EL1, HVF_SYSREG(0, 0, 14, 0, 5) },
263
+ { HV_SYS_REG_DBGWVR0_EL1, HVF_SYSREG(0, 0, 14, 0, 6) },
264
+ { HV_SYS_REG_DBGWCR0_EL1, HVF_SYSREG(0, 0, 14, 0, 7) },
265
+
266
+ { HV_SYS_REG_DBGBVR1_EL1, HVF_SYSREG(0, 1, 14, 0, 4) },
267
+ { HV_SYS_REG_DBGBCR1_EL1, HVF_SYSREG(0, 1, 14, 0, 5) },
268
+ { HV_SYS_REG_DBGWVR1_EL1, HVF_SYSREG(0, 1, 14, 0, 6) },
269
+ { HV_SYS_REG_DBGWCR1_EL1, HVF_SYSREG(0, 1, 14, 0, 7) },
270
+
271
+ { HV_SYS_REG_DBGBVR2_EL1, HVF_SYSREG(0, 2, 14, 0, 4) },
272
+ { HV_SYS_REG_DBGBCR2_EL1, HVF_SYSREG(0, 2, 14, 0, 5) },
273
+ { HV_SYS_REG_DBGWVR2_EL1, HVF_SYSREG(0, 2, 14, 0, 6) },
274
+ { HV_SYS_REG_DBGWCR2_EL1, HVF_SYSREG(0, 2, 14, 0, 7) },
275
+
276
+ { HV_SYS_REG_DBGBVR3_EL1, HVF_SYSREG(0, 3, 14, 0, 4) },
277
+ { HV_SYS_REG_DBGBCR3_EL1, HVF_SYSREG(0, 3, 14, 0, 5) },
278
+ { HV_SYS_REG_DBGWVR3_EL1, HVF_SYSREG(0, 3, 14, 0, 6) },
279
+ { HV_SYS_REG_DBGWCR3_EL1, HVF_SYSREG(0, 3, 14, 0, 7) },
280
+
281
+ { HV_SYS_REG_DBGBVR4_EL1, HVF_SYSREG(0, 4, 14, 0, 4) },
282
+ { HV_SYS_REG_DBGBCR4_EL1, HVF_SYSREG(0, 4, 14, 0, 5) },
283
+ { HV_SYS_REG_DBGWVR4_EL1, HVF_SYSREG(0, 4, 14, 0, 6) },
284
+ { HV_SYS_REG_DBGWCR4_EL1, HVF_SYSREG(0, 4, 14, 0, 7) },
285
+
286
+ { HV_SYS_REG_DBGBVR5_EL1, HVF_SYSREG(0, 5, 14, 0, 4) },
287
+ { HV_SYS_REG_DBGBCR5_EL1, HVF_SYSREG(0, 5, 14, 0, 5) },
288
+ { HV_SYS_REG_DBGWVR5_EL1, HVF_SYSREG(0, 5, 14, 0, 6) },
289
+ { HV_SYS_REG_DBGWCR5_EL1, HVF_SYSREG(0, 5, 14, 0, 7) },
290
+
291
+ { HV_SYS_REG_DBGBVR6_EL1, HVF_SYSREG(0, 6, 14, 0, 4) },
292
+ { HV_SYS_REG_DBGBCR6_EL1, HVF_SYSREG(0, 6, 14, 0, 5) },
293
+ { HV_SYS_REG_DBGWVR6_EL1, HVF_SYSREG(0, 6, 14, 0, 6) },
294
+ { HV_SYS_REG_DBGWCR6_EL1, HVF_SYSREG(0, 6, 14, 0, 7) },
295
+
296
+ { HV_SYS_REG_DBGBVR7_EL1, HVF_SYSREG(0, 7, 14, 0, 4) },
297
+ { HV_SYS_REG_DBGBCR7_EL1, HVF_SYSREG(0, 7, 14, 0, 5) },
298
+ { HV_SYS_REG_DBGWVR7_EL1, HVF_SYSREG(0, 7, 14, 0, 6) },
299
+ { HV_SYS_REG_DBGWCR7_EL1, HVF_SYSREG(0, 7, 14, 0, 7) },
300
+
301
+ { HV_SYS_REG_DBGBVR8_EL1, HVF_SYSREG(0, 8, 14, 0, 4) },
302
+ { HV_SYS_REG_DBGBCR8_EL1, HVF_SYSREG(0, 8, 14, 0, 5) },
303
+ { HV_SYS_REG_DBGWVR8_EL1, HVF_SYSREG(0, 8, 14, 0, 6) },
304
+ { HV_SYS_REG_DBGWCR8_EL1, HVF_SYSREG(0, 8, 14, 0, 7) },
305
+
306
+ { HV_SYS_REG_DBGBVR9_EL1, HVF_SYSREG(0, 9, 14, 0, 4) },
307
+ { HV_SYS_REG_DBGBCR9_EL1, HVF_SYSREG(0, 9, 14, 0, 5) },
308
+ { HV_SYS_REG_DBGWVR9_EL1, HVF_SYSREG(0, 9, 14, 0, 6) },
309
+ { HV_SYS_REG_DBGWCR9_EL1, HVF_SYSREG(0, 9, 14, 0, 7) },
310
+
311
+ { HV_SYS_REG_DBGBVR10_EL1, HVF_SYSREG(0, 10, 14, 0, 4) },
312
+ { HV_SYS_REG_DBGBCR10_EL1, HVF_SYSREG(0, 10, 14, 0, 5) },
313
+ { HV_SYS_REG_DBGWVR10_EL1, HVF_SYSREG(0, 10, 14, 0, 6) },
314
+ { HV_SYS_REG_DBGWCR10_EL1, HVF_SYSREG(0, 10, 14, 0, 7) },
315
+
316
+ { HV_SYS_REG_DBGBVR11_EL1, HVF_SYSREG(0, 11, 14, 0, 4) },
317
+ { HV_SYS_REG_DBGBCR11_EL1, HVF_SYSREG(0, 11, 14, 0, 5) },
318
+ { HV_SYS_REG_DBGWVR11_EL1, HVF_SYSREG(0, 11, 14, 0, 6) },
319
+ { HV_SYS_REG_DBGWCR11_EL1, HVF_SYSREG(0, 11, 14, 0, 7) },
320
+
321
+ { HV_SYS_REG_DBGBVR12_EL1, HVF_SYSREG(0, 12, 14, 0, 4) },
322
+ { HV_SYS_REG_DBGBCR12_EL1, HVF_SYSREG(0, 12, 14, 0, 5) },
323
+ { HV_SYS_REG_DBGWVR12_EL1, HVF_SYSREG(0, 12, 14, 0, 6) },
324
+ { HV_SYS_REG_DBGWCR12_EL1, HVF_SYSREG(0, 12, 14, 0, 7) },
325
+
326
+ { HV_SYS_REG_DBGBVR13_EL1, HVF_SYSREG(0, 13, 14, 0, 4) },
327
+ { HV_SYS_REG_DBGBCR13_EL1, HVF_SYSREG(0, 13, 14, 0, 5) },
328
+ { HV_SYS_REG_DBGWVR13_EL1, HVF_SYSREG(0, 13, 14, 0, 6) },
329
+ { HV_SYS_REG_DBGWCR13_EL1, HVF_SYSREG(0, 13, 14, 0, 7) },
330
+
331
+ { HV_SYS_REG_DBGBVR14_EL1, HVF_SYSREG(0, 14, 14, 0, 4) },
332
+ { HV_SYS_REG_DBGBCR14_EL1, HVF_SYSREG(0, 14, 14, 0, 5) },
333
+ { HV_SYS_REG_DBGWVR14_EL1, HVF_SYSREG(0, 14, 14, 0, 6) },
334
+ { HV_SYS_REG_DBGWCR14_EL1, HVF_SYSREG(0, 14, 14, 0, 7) },
335
+
336
+ { HV_SYS_REG_DBGBVR15_EL1, HVF_SYSREG(0, 15, 14, 0, 4) },
337
+ { HV_SYS_REG_DBGBCR15_EL1, HVF_SYSREG(0, 15, 14, 0, 5) },
338
+ { HV_SYS_REG_DBGWVR15_EL1, HVF_SYSREG(0, 15, 14, 0, 6) },
339
+ { HV_SYS_REG_DBGWCR15_EL1, HVF_SYSREG(0, 15, 14, 0, 7) },
340
+
341
+#ifdef SYNC_NO_RAW_REGS
342
+ /*
343
+ * The registers below are manually synced on init because they are
344
+ * marked as NO_RAW. We still list them to make number space sync easier.
345
+ */
346
+ { HV_SYS_REG_MDCCINT_EL1, HVF_SYSREG(0, 2, 2, 0, 0) },
347
+ { HV_SYS_REG_MIDR_EL1, HVF_SYSREG(0, 0, 3, 0, 0) },
348
+ { HV_SYS_REG_MPIDR_EL1, HVF_SYSREG(0, 0, 3, 0, 5) },
349
+ { HV_SYS_REG_ID_AA64PFR0_EL1, HVF_SYSREG(0, 4, 3, 0, 0) },
350
+#endif
351
+ { HV_SYS_REG_ID_AA64PFR1_EL1, HVF_SYSREG(0, 4, 3, 0, 2) },
352
+ { HV_SYS_REG_ID_AA64DFR0_EL1, HVF_SYSREG(0, 5, 3, 0, 0) },
353
+ { HV_SYS_REG_ID_AA64DFR1_EL1, HVF_SYSREG(0, 5, 3, 0, 1) },
354
+ { HV_SYS_REG_ID_AA64ISAR0_EL1, HVF_SYSREG(0, 6, 3, 0, 0) },
355
+ { HV_SYS_REG_ID_AA64ISAR1_EL1, HVF_SYSREG(0, 6, 3, 0, 1) },
356
+#ifdef SYNC_NO_MMFR0
357
+ /* We keep the hardware MMFR0 around. HW limits are there anyway */
358
+ { HV_SYS_REG_ID_AA64MMFR0_EL1, HVF_SYSREG(0, 7, 3, 0, 0) },
359
+#endif
360
+ { HV_SYS_REG_ID_AA64MMFR1_EL1, HVF_SYSREG(0, 7, 3, 0, 1) },
361
+ { HV_SYS_REG_ID_AA64MMFR2_EL1, HVF_SYSREG(0, 7, 3, 0, 2) },
362
+
363
+ { HV_SYS_REG_MDSCR_EL1, HVF_SYSREG(0, 2, 2, 0, 2) },
364
+ { HV_SYS_REG_SCTLR_EL1, HVF_SYSREG(1, 0, 3, 0, 0) },
365
+ { HV_SYS_REG_CPACR_EL1, HVF_SYSREG(1, 0, 3, 0, 2) },
366
+ { HV_SYS_REG_TTBR0_EL1, HVF_SYSREG(2, 0, 3, 0, 0) },
367
+ { HV_SYS_REG_TTBR1_EL1, HVF_SYSREG(2, 0, 3, 0, 1) },
368
+ { HV_SYS_REG_TCR_EL1, HVF_SYSREG(2, 0, 3, 0, 2) },
369
+
370
+ { HV_SYS_REG_APIAKEYLO_EL1, HVF_SYSREG(2, 1, 3, 0, 0) },
371
+ { HV_SYS_REG_APIAKEYHI_EL1, HVF_SYSREG(2, 1, 3, 0, 1) },
372
+ { HV_SYS_REG_APIBKEYLO_EL1, HVF_SYSREG(2, 1, 3, 0, 2) },
373
+ { HV_SYS_REG_APIBKEYHI_EL1, HVF_SYSREG(2, 1, 3, 0, 3) },
374
+ { HV_SYS_REG_APDAKEYLO_EL1, HVF_SYSREG(2, 2, 3, 0, 0) },
375
+ { HV_SYS_REG_APDAKEYHI_EL1, HVF_SYSREG(2, 2, 3, 0, 1) },
376
+ { HV_SYS_REG_APDBKEYLO_EL1, HVF_SYSREG(2, 2, 3, 0, 2) },
377
+ { HV_SYS_REG_APDBKEYHI_EL1, HVF_SYSREG(2, 2, 3, 0, 3) },
378
+ { HV_SYS_REG_APGAKEYLO_EL1, HVF_SYSREG(2, 3, 3, 0, 0) },
379
+ { HV_SYS_REG_APGAKEYHI_EL1, HVF_SYSREG(2, 3, 3, 0, 1) },
380
+
381
+ { HV_SYS_REG_SPSR_EL1, HVF_SYSREG(4, 0, 3, 0, 0) },
382
+ { HV_SYS_REG_ELR_EL1, HVF_SYSREG(4, 0, 3, 0, 1) },
383
+ { HV_SYS_REG_SP_EL0, HVF_SYSREG(4, 1, 3, 0, 0) },
384
+ { HV_SYS_REG_AFSR0_EL1, HVF_SYSREG(5, 1, 3, 0, 0) },
385
+ { HV_SYS_REG_AFSR1_EL1, HVF_SYSREG(5, 1, 3, 0, 1) },
386
+ { HV_SYS_REG_ESR_EL1, HVF_SYSREG(5, 2, 3, 0, 0) },
387
+ { HV_SYS_REG_FAR_EL1, HVF_SYSREG(6, 0, 3, 0, 0) },
388
+ { HV_SYS_REG_PAR_EL1, HVF_SYSREG(7, 4, 3, 0, 0) },
389
+ { HV_SYS_REG_MAIR_EL1, HVF_SYSREG(10, 2, 3, 0, 0) },
390
+ { HV_SYS_REG_AMAIR_EL1, HVF_SYSREG(10, 3, 3, 0, 0) },
391
+ { HV_SYS_REG_VBAR_EL1, HVF_SYSREG(12, 0, 3, 0, 0) },
392
+ { HV_SYS_REG_CONTEXTIDR_EL1, HVF_SYSREG(13, 0, 3, 0, 1) },
393
+ { HV_SYS_REG_TPIDR_EL1, HVF_SYSREG(13, 0, 3, 0, 4) },
394
+ { HV_SYS_REG_CNTKCTL_EL1, HVF_SYSREG(14, 1, 3, 0, 0) },
395
+ { HV_SYS_REG_CSSELR_EL1, HVF_SYSREG(0, 0, 3, 2, 0) },
396
+ { HV_SYS_REG_TPIDR_EL0, HVF_SYSREG(13, 0, 3, 3, 2) },
397
+ { HV_SYS_REG_TPIDRRO_EL0, HVF_SYSREG(13, 0, 3, 3, 3) },
398
+ { HV_SYS_REG_CNTV_CTL_EL0, HVF_SYSREG(14, 3, 3, 3, 1) },
399
+ { HV_SYS_REG_CNTV_CVAL_EL0, HVF_SYSREG(14, 3, 3, 3, 2) },
400
+ { HV_SYS_REG_SP_EL1, HVF_SYSREG(4, 1, 3, 4, 0) },
401
+};
402
+
403
+int hvf_get_registers(CPUState *cpu)
404
+{
405
+ ARMCPU *arm_cpu = ARM_CPU(cpu);
406
+ CPUARMState *env = &arm_cpu->env;
407
+ hv_return_t ret;
408
+ uint64_t val;
409
+ hv_simd_fp_uchar16_t fpval;
410
+ int i;
598
+ int i;
411
+
599
+
412
+ for (i = 0; i < ARRAY_SIZE(hvf_reg_match); i++) {
600
+ s->reg_array =
413
+ ret = hv_vcpu_get_reg(cpu->hvf->fd, hvf_reg_match[i].reg, &val);
601
+ register_init_block32(DEVICE(obj), crl_regs_info,
414
+ *(uint64_t *)((void *)env + hvf_reg_match[i].offset) = val;
602
+ ARRAY_SIZE(crl_regs_info),
415
+ assert_hvf_ok(ret);
603
+ s->regs_info, s->regs,
416
+ }
604
+ &crl_ops,
417
+
605
+ XLNX_VERSAL_CRL_ERR_DEBUG,
418
+ for (i = 0; i < ARRAY_SIZE(hvf_fpreg_match); i++) {
606
+ CRL_R_MAX * 4);
419
+ ret = hv_vcpu_get_simd_fp_reg(cpu->hvf->fd, hvf_fpreg_match[i].reg,
607
+ sysbus_init_mmio(sbd, &s->reg_array->mem);
420
+ &fpval);
608
+ sysbus_init_irq(sbd, &s->irq);
421
+ memcpy((void *)env + hvf_fpreg_match[i].offset, &fpval, sizeof(fpval));
609
+
422
+ assert_hvf_ok(ret);
610
+ for (i = 0; i < ARRAY_SIZE(s->cfg.cpu_r5); ++i) {
423
+ }
611
+ object_property_add_link(obj, "cpu_r5[*]", TYPE_ARM_CPU,
424
+
612
+ (Object **)&s->cfg.cpu_r5[i],
425
+ val = 0;
613
+ qdev_prop_allow_set_link_before_realize,
426
+ ret = hv_vcpu_get_reg(cpu->hvf->fd, HV_REG_FPCR, &val);
614
+ OBJ_PROP_LINK_STRONG);
427
+ assert_hvf_ok(ret);
615
+ }
428
+ vfp_set_fpcr(env, val);
616
+
429
+
617
+ for (i = 0; i < ARRAY_SIZE(s->cfg.adma); ++i) {
430
+ val = 0;
618
+ object_property_add_link(obj, "adma[*]", TYPE_DEVICE,
431
+ ret = hv_vcpu_get_reg(cpu->hvf->fd, HV_REG_FPSR, &val);
619
+ (Object **)&s->cfg.adma[i],
432
+ assert_hvf_ok(ret);
620
+ qdev_prop_allow_set_link_before_realize,
433
+ vfp_set_fpsr(env, val);
621
+ OBJ_PROP_LINK_STRONG);
434
+
622
+ }
435
+ ret = hv_vcpu_get_reg(cpu->hvf->fd, HV_REG_CPSR, &val);
623
+
436
+ assert_hvf_ok(ret);
624
+ for (i = 0; i < ARRAY_SIZE(s->cfg.uart); ++i) {
437
+ pstate_write(env, val);
625
+ object_property_add_link(obj, "uart[*]", TYPE_DEVICE,
438
+
626
+ (Object **)&s->cfg.uart[i],
439
+ for (i = 0; i < ARRAY_SIZE(hvf_sreg_match); i++) {
627
+ qdev_prop_allow_set_link_before_realize,
440
+ if (hvf_sreg_match[i].cp_idx == -1) {
628
+ OBJ_PROP_LINK_STRONG);
441
+ continue;
629
+ }
442
+ }
630
+
443
+
631
+ for (i = 0; i < ARRAY_SIZE(s->cfg.gem); ++i) {
444
+ ret = hv_vcpu_get_sys_reg(cpu->hvf->fd, hvf_sreg_match[i].reg, &val);
632
+ object_property_add_link(obj, "gem[*]", TYPE_DEVICE,
445
+ assert_hvf_ok(ret);
633
+ (Object **)&s->cfg.gem[i],
446
+
634
+ qdev_prop_allow_set_link_before_realize,
447
+ arm_cpu->cpreg_values[hvf_sreg_match[i].cp_idx] = val;
635
+ OBJ_PROP_LINK_STRONG);
448
+ }
636
+ }
449
+ assert(write_list_to_cpustate(arm_cpu));
637
+
450
+
638
+ object_property_add_link(obj, "usb", TYPE_DEVICE,
451
+ aarch64_restore_sp(env, arm_current_el(env));
639
+ (Object **)&s->cfg.gem[i],
452
+
640
+ qdev_prop_allow_set_link_before_realize,
453
+ return 0;
641
+ OBJ_PROP_LINK_STRONG);
454
+}
642
+}
455
+
643
+
456
+int hvf_put_registers(CPUState *cpu)
644
+static void crl_finalize(Object *obj)
457
+{
645
+{
458
+ ARMCPU *arm_cpu = ARM_CPU(cpu);
646
+ XlnxVersalCRL *s = XLNX_VERSAL_CRL(obj);
459
+ CPUARMState *env = &arm_cpu->env;
647
+ register_finalize_block(s->reg_array);
460
+ hv_return_t ret;
648
+}
461
+ uint64_t val;
649
+
462
+ hv_simd_fp_uchar16_t fpval;
650
+static const VMStateDescription vmstate_crl = {
463
+ int i;
651
+ .name = TYPE_XLNX_VERSAL_CRL,
464
+
465
+ for (i = 0; i < ARRAY_SIZE(hvf_reg_match); i++) {
466
+ val = *(uint64_t *)((void *)env + hvf_reg_match[i].offset);
467
+ ret = hv_vcpu_set_reg(cpu->hvf->fd, hvf_reg_match[i].reg, val);
468
+ assert_hvf_ok(ret);
469
+ }
470
+
471
+ for (i = 0; i < ARRAY_SIZE(hvf_fpreg_match); i++) {
472
+ memcpy(&fpval, (void *)env + hvf_fpreg_match[i].offset, sizeof(fpval));
473
+ ret = hv_vcpu_set_simd_fp_reg(cpu->hvf->fd, hvf_fpreg_match[i].reg,
474
+ fpval);
475
+ assert_hvf_ok(ret);
476
+ }
477
+
478
+ ret = hv_vcpu_set_reg(cpu->hvf->fd, HV_REG_FPCR, vfp_get_fpcr(env));
479
+ assert_hvf_ok(ret);
480
+
481
+ ret = hv_vcpu_set_reg(cpu->hvf->fd, HV_REG_FPSR, vfp_get_fpsr(env));
482
+ assert_hvf_ok(ret);
483
+
484
+ ret = hv_vcpu_set_reg(cpu->hvf->fd, HV_REG_CPSR, pstate_read(env));
485
+ assert_hvf_ok(ret);
486
+
487
+ aarch64_save_sp(env, arm_current_el(env));
488
+
489
+ assert(write_cpustate_to_list(arm_cpu, false));
490
+ for (i = 0; i < ARRAY_SIZE(hvf_sreg_match); i++) {
491
+ if (hvf_sreg_match[i].cp_idx == -1) {
492
+ continue;
493
+ }
494
+
495
+ val = arm_cpu->cpreg_values[hvf_sreg_match[i].cp_idx];
496
+ ret = hv_vcpu_set_sys_reg(cpu->hvf->fd, hvf_sreg_match[i].reg, val);
497
+ assert_hvf_ok(ret);
498
+ }
499
+
500
+ ret = hv_vcpu_set_vtimer_offset(cpu->hvf->fd, hvf_state->vtimer_offset);
501
+ assert_hvf_ok(ret);
502
+
503
+ return 0;
504
+}
505
+
506
+static void flush_cpu_state(CPUState *cpu)
507
+{
508
+ if (cpu->vcpu_dirty) {
509
+ hvf_put_registers(cpu);
510
+ cpu->vcpu_dirty = false;
511
+ }
512
+}
513
+
514
+static void hvf_set_reg(CPUState *cpu, int rt, uint64_t val)
515
+{
516
+ hv_return_t r;
517
+
518
+ flush_cpu_state(cpu);
519
+
520
+ if (rt < 31) {
521
+ r = hv_vcpu_set_reg(cpu->hvf->fd, HV_REG_X0 + rt, val);
522
+ assert_hvf_ok(r);
523
+ }
524
+}
525
+
526
+static uint64_t hvf_get_reg(CPUState *cpu, int rt)
527
+{
528
+ uint64_t val = 0;
529
+ hv_return_t r;
530
+
531
+ flush_cpu_state(cpu);
532
+
533
+ if (rt < 31) {
534
+ r = hv_vcpu_get_reg(cpu->hvf->fd, HV_REG_X0 + rt, &val);
535
+ assert_hvf_ok(r);
536
+ }
537
+
538
+ return val;
539
+}
540
+
541
+void hvf_arch_vcpu_destroy(CPUState *cpu)
542
+{
543
+}
544
+
545
+int hvf_arch_init_vcpu(CPUState *cpu)
546
+{
547
+ ARMCPU *arm_cpu = ARM_CPU(cpu);
548
+ CPUARMState *env = &arm_cpu->env;
549
+ uint32_t sregs_match_len = ARRAY_SIZE(hvf_sreg_match);
550
+ uint32_t sregs_cnt = 0;
551
+ uint64_t pfr;
552
+ hv_return_t ret;
553
+ int i;
554
+
555
+ env->aarch64 = 1;
556
+ asm volatile("mrs %0, cntfrq_el0" : "=r"(arm_cpu->gt_cntfrq_hz));
557
+
558
+ /* Allocate enough space for our sysreg sync */
559
+ arm_cpu->cpreg_indexes = g_renew(uint64_t, arm_cpu->cpreg_indexes,
560
+ sregs_match_len);
561
+ arm_cpu->cpreg_values = g_renew(uint64_t, arm_cpu->cpreg_values,
562
+ sregs_match_len);
563
+ arm_cpu->cpreg_vmstate_indexes = g_renew(uint64_t,
564
+ arm_cpu->cpreg_vmstate_indexes,
565
+ sregs_match_len);
566
+ arm_cpu->cpreg_vmstate_values = g_renew(uint64_t,
567
+ arm_cpu->cpreg_vmstate_values,
568
+ sregs_match_len);
569
+
570
+ memset(arm_cpu->cpreg_values, 0, sregs_match_len * sizeof(uint64_t));
571
+
572
+ /* Populate cp list for all known sysregs */
573
+ for (i = 0; i < sregs_match_len; i++) {
574
+ const ARMCPRegInfo *ri;
575
+ uint32_t key = hvf_sreg_match[i].key;
576
+
577
+ ri = get_arm_cp_reginfo(arm_cpu->cp_regs, key);
578
+ if (ri) {
579
+ assert(!(ri->type & ARM_CP_NO_RAW));
580
+ hvf_sreg_match[i].cp_idx = sregs_cnt;
581
+ arm_cpu->cpreg_indexes[sregs_cnt++] = cpreg_to_kvm_id(key);
582
+ } else {
583
+ hvf_sreg_match[i].cp_idx = -1;
584
+ }
585
+ }
586
+ arm_cpu->cpreg_array_len = sregs_cnt;
587
+ arm_cpu->cpreg_vmstate_array_len = sregs_cnt;
588
+
589
+ assert(write_cpustate_to_list(arm_cpu, false));
590
+
591
+ /* Set CP_NO_RAW system registers on init */
592
+ ret = hv_vcpu_set_sys_reg(cpu->hvf->fd, HV_SYS_REG_MIDR_EL1,
593
+ arm_cpu->midr);
594
+ assert_hvf_ok(ret);
595
+
596
+ ret = hv_vcpu_set_sys_reg(cpu->hvf->fd, HV_SYS_REG_MPIDR_EL1,
597
+ arm_cpu->mp_affinity);
598
+ assert_hvf_ok(ret);
599
+
600
+ ret = hv_vcpu_get_sys_reg(cpu->hvf->fd, HV_SYS_REG_ID_AA64PFR0_EL1, &pfr);
601
+ assert_hvf_ok(ret);
602
+ pfr |= env->gicv3state ? (1 << 24) : 0;
603
+ ret = hv_vcpu_set_sys_reg(cpu->hvf->fd, HV_SYS_REG_ID_AA64PFR0_EL1, pfr);
604
+ assert_hvf_ok(ret);
605
+
606
+ /* We're limited to underlying hardware caps, override internal versions */
607
+ ret = hv_vcpu_get_sys_reg(cpu->hvf->fd, HV_SYS_REG_ID_AA64MMFR0_EL1,
608
+ &arm_cpu->isar.id_aa64mmfr0);
609
+ assert_hvf_ok(ret);
610
+
611
+ return 0;
612
+}
613
+
614
+void hvf_kick_vcpu_thread(CPUState *cpu)
615
+{
616
+ hv_vcpus_exit(&cpu->hvf->fd, 1);
617
+}
618
+
619
+static void hvf_raise_exception(CPUState *cpu, uint32_t excp,
620
+ uint32_t syndrome)
621
+{
622
+ ARMCPU *arm_cpu = ARM_CPU(cpu);
623
+ CPUARMState *env = &arm_cpu->env;
624
+
625
+ cpu->exception_index = excp;
626
+ env->exception.target_el = 1;
627
+ env->exception.syndrome = syndrome;
628
+
629
+ arm_cpu_do_interrupt(cpu);
630
+}
631
+
632
+static int hvf_sysreg_read(CPUState *cpu, uint32_t reg, uint32_t rt)
633
+{
634
+ ARMCPU *arm_cpu = ARM_CPU(cpu);
635
+ CPUARMState *env = &arm_cpu->env;
636
+ uint64_t val = 0;
637
+
638
+ switch (reg) {
639
+ case SYSREG_CNTPCT_EL0:
640
+ val = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) /
641
+ gt_cntfrq_period_ns(arm_cpu);
642
+ break;
643
+ case SYSREG_OSLSR_EL1:
644
+ val = env->cp15.oslsr_el1;
645
+ break;
646
+ case SYSREG_OSDLR_EL1:
647
+ /* Dummy register */
648
+ break;
649
+ default:
650
+ cpu_synchronize_state(cpu);
651
+ trace_hvf_unhandled_sysreg_read(env->pc, reg,
652
+ (reg >> 20) & 0x3,
653
+ (reg >> 14) & 0x7,
654
+ (reg >> 10) & 0xf,
655
+ (reg >> 1) & 0xf,
656
+ (reg >> 17) & 0x7);
657
+ hvf_raise_exception(cpu, EXCP_UDEF, syn_uncategorized());
658
+ return 1;
659
+ }
660
+
661
+ trace_hvf_sysreg_read(reg,
662
+ (reg >> 20) & 0x3,
663
+ (reg >> 14) & 0x7,
664
+ (reg >> 10) & 0xf,
665
+ (reg >> 1) & 0xf,
666
+ (reg >> 17) & 0x7,
667
+ val);
668
+ hvf_set_reg(cpu, rt, val);
669
+
670
+ return 0;
671
+}
672
+
673
+static int hvf_sysreg_write(CPUState *cpu, uint32_t reg, uint64_t val)
674
+{
675
+ ARMCPU *arm_cpu = ARM_CPU(cpu);
676
+ CPUARMState *env = &arm_cpu->env;
677
+
678
+ trace_hvf_sysreg_write(reg,
679
+ (reg >> 20) & 0x3,
680
+ (reg >> 14) & 0x7,
681
+ (reg >> 10) & 0xf,
682
+ (reg >> 1) & 0xf,
683
+ (reg >> 17) & 0x7,
684
+ val);
685
+
686
+ switch (reg) {
687
+ case SYSREG_OSLAR_EL1:
688
+ env->cp15.oslsr_el1 = val & 1;
689
+ break;
690
+ case SYSREG_OSDLR_EL1:
691
+ /* Dummy register */
692
+ break;
693
+ default:
694
+ cpu_synchronize_state(cpu);
695
+ trace_hvf_unhandled_sysreg_write(env->pc, reg,
696
+ (reg >> 20) & 0x3,
697
+ (reg >> 14) & 0x7,
698
+ (reg >> 10) & 0xf,
699
+ (reg >> 1) & 0xf,
700
+ (reg >> 17) & 0x7);
701
+ hvf_raise_exception(cpu, EXCP_UDEF, syn_uncategorized());
702
+ return 1;
703
+ }
704
+
705
+ return 0;
706
+}
707
+
708
+static int hvf_inject_interrupts(CPUState *cpu)
709
+{
710
+ if (cpu->interrupt_request & CPU_INTERRUPT_FIQ) {
711
+ trace_hvf_inject_fiq();
712
+ hv_vcpu_set_pending_interrupt(cpu->hvf->fd, HV_INTERRUPT_TYPE_FIQ,
713
+ true);
714
+ }
715
+
716
+ if (cpu->interrupt_request & CPU_INTERRUPT_HARD) {
717
+ trace_hvf_inject_irq();
718
+ hv_vcpu_set_pending_interrupt(cpu->hvf->fd, HV_INTERRUPT_TYPE_IRQ,
719
+ true);
720
+ }
721
+
722
+ return 0;
723
+}
724
+
725
+static uint64_t hvf_vtimer_val_raw(void)
726
+{
727
+ /*
728
+ * mach_absolute_time() returns the vtimer value without the VM
729
+ * offset that we define. Add our own offset on top.
730
+ */
731
+ return mach_absolute_time() - hvf_state->vtimer_offset;
732
+}
733
+
734
+static void hvf_sync_vtimer(CPUState *cpu)
735
+{
736
+ ARMCPU *arm_cpu = ARM_CPU(cpu);
737
+ hv_return_t r;
738
+ uint64_t ctl;
739
+ bool irq_state;
740
+
741
+ if (!cpu->hvf->vtimer_masked) {
742
+ /* We will get notified on vtimer changes by hvf, nothing to do */
743
+ return;
744
+ }
745
+
746
+ r = hv_vcpu_get_sys_reg(cpu->hvf->fd, HV_SYS_REG_CNTV_CTL_EL0, &ctl);
747
+ assert_hvf_ok(r);
748
+
749
+ irq_state = (ctl & (TMR_CTL_ENABLE | TMR_CTL_IMASK | TMR_CTL_ISTATUS)) ==
750
+ (TMR_CTL_ENABLE | TMR_CTL_ISTATUS);
751
+ qemu_set_irq(arm_cpu->gt_timer_outputs[GTIMER_VIRT], irq_state);
752
+
753
+ if (!irq_state) {
754
+ /* Timer no longer asserting, we can unmask it */
755
+ hv_vcpu_set_vtimer_mask(cpu->hvf->fd, false);
756
+ cpu->hvf->vtimer_masked = false;
757
+ }
758
+}
759
+
760
+int hvf_vcpu_exec(CPUState *cpu)
761
+{
762
+ ARMCPU *arm_cpu = ARM_CPU(cpu);
763
+ CPUARMState *env = &arm_cpu->env;
764
+ hv_vcpu_exit_t *hvf_exit = cpu->hvf->exit;
765
+ hv_return_t r;
766
+ bool advance_pc = false;
767
+
768
+ if (hvf_inject_interrupts(cpu)) {
769
+ return EXCP_INTERRUPT;
770
+ }
771
+
772
+ if (cpu->halted) {
773
+ return EXCP_HLT;
774
+ }
775
+
776
+ flush_cpu_state(cpu);
777
+
778
+ qemu_mutex_unlock_iothread();
779
+ assert_hvf_ok(hv_vcpu_run(cpu->hvf->fd));
780
+
781
+ /* handle VMEXIT */
782
+ uint64_t exit_reason = hvf_exit->reason;
783
+ uint64_t syndrome = hvf_exit->exception.syndrome;
784
+ uint32_t ec = syn_get_ec(syndrome);
785
+
786
+ qemu_mutex_lock_iothread();
787
+ switch (exit_reason) {
788
+ case HV_EXIT_REASON_EXCEPTION:
789
+ /* This is the main one, handle below. */
790
+ break;
791
+ case HV_EXIT_REASON_VTIMER_ACTIVATED:
792
+ qemu_set_irq(arm_cpu->gt_timer_outputs[GTIMER_VIRT], 1);
793
+ cpu->hvf->vtimer_masked = true;
794
+ return 0;
795
+ case HV_EXIT_REASON_CANCELED:
796
+ /* we got kicked, no exit to process */
797
+ return 0;
798
+ default:
799
+ assert(0);
800
+ }
801
+
802
+ hvf_sync_vtimer(cpu);
803
+
804
+ switch (ec) {
805
+ case EC_DATAABORT: {
806
+ bool isv = syndrome & ARM_EL_ISV;
807
+ bool iswrite = (syndrome >> 6) & 1;
808
+ bool s1ptw = (syndrome >> 7) & 1;
809
+ uint32_t sas = (syndrome >> 22) & 3;
810
+ uint32_t len = 1 << sas;
811
+ uint32_t srt = (syndrome >> 16) & 0x1f;
812
+ uint64_t val = 0;
813
+
814
+ trace_hvf_data_abort(env->pc, hvf_exit->exception.virtual_address,
815
+ hvf_exit->exception.physical_address, isv,
816
+ iswrite, s1ptw, len, srt);
817
+
818
+ assert(isv);
819
+
820
+ if (iswrite) {
821
+ val = hvf_get_reg(cpu, srt);
822
+ address_space_write(&address_space_memory,
823
+ hvf_exit->exception.physical_address,
824
+ MEMTXATTRS_UNSPECIFIED, &val, len);
825
+ } else {
826
+ address_space_read(&address_space_memory,
827
+ hvf_exit->exception.physical_address,
828
+ MEMTXATTRS_UNSPECIFIED, &val, len);
829
+ hvf_set_reg(cpu, srt, val);
830
+ }
831
+
832
+ advance_pc = true;
833
+ break;
834
+ }
835
+ case EC_SYSTEMREGISTERTRAP: {
836
+ bool isread = (syndrome >> 0) & 1;
837
+ uint32_t rt = (syndrome >> 5) & 0x1f;
838
+ uint32_t reg = syndrome & SYSREG_MASK;
839
+ uint64_t val;
840
+ int ret = 0;
841
+
842
+ if (isread) {
843
+ ret = hvf_sysreg_read(cpu, reg, rt);
844
+ } else {
845
+ val = hvf_get_reg(cpu, rt);
846
+ ret = hvf_sysreg_write(cpu, reg, val);
847
+ }
848
+
849
+ advance_pc = !ret;
850
+ break;
851
+ }
852
+ case EC_WFX_TRAP:
853
+ advance_pc = true;
854
+ break;
855
+ case EC_AA64_HVC:
856
+ cpu_synchronize_state(cpu);
857
+ trace_hvf_unknown_hvc(env->xregs[0]);
858
+ /* SMCCC 1.3 section 5.2 says every unknown SMCCC call returns -1 */
859
+ env->xregs[0] = -1;
860
+ break;
861
+ case EC_AA64_SMC:
862
+ cpu_synchronize_state(cpu);
863
+ trace_hvf_unknown_smc(env->xregs[0]);
864
+ hvf_raise_exception(cpu, EXCP_UDEF, syn_uncategorized());
865
+ break;
866
+ default:
867
+ cpu_synchronize_state(cpu);
868
+ trace_hvf_exit(syndrome, ec, env->pc);
869
+ error_report("0x%llx: unhandled exception ec=0x%x", env->pc, ec);
870
+ }
871
+
872
+ if (advance_pc) {
873
+ uint64_t pc;
874
+
875
+ flush_cpu_state(cpu);
876
+
877
+ r = hv_vcpu_get_reg(cpu->hvf->fd, HV_REG_PC, &pc);
878
+ assert_hvf_ok(r);
879
+ pc += 4;
880
+ r = hv_vcpu_set_reg(cpu->hvf->fd, HV_REG_PC, pc);
881
+ assert_hvf_ok(r);
882
+ }
883
+
884
+ return 0;
885
+}
886
+
887
+static const VMStateDescription vmstate_hvf_vtimer = {
888
+ .name = "hvf-vtimer",
889
+ .version_id = 1,
652
+ .version_id = 1,
890
+ .minimum_version_id = 1,
653
+ .minimum_version_id = 1,
891
+ .fields = (VMStateField[]) {
654
+ .fields = (VMStateField[]) {
892
+ VMSTATE_UINT64(vtimer_val, HVFVTimer),
655
+ VMSTATE_UINT32_ARRAY(regs, XlnxVersalCRL, CRL_R_MAX),
893
+ VMSTATE_END_OF_LIST()
656
+ VMSTATE_END_OF_LIST(),
894
+ },
657
+ }
895
+};
658
+};
896
+
659
+
897
+static void hvf_vm_state_change(void *opaque, bool running, RunState state)
660
+static void crl_class_init(ObjectClass *klass, void *data)
898
+{
661
+{
899
+ HVFVTimer *s = opaque;
662
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
900
+
663
+ DeviceClass *dc = DEVICE_CLASS(klass);
901
+ if (running) {
664
+
902
+ /* Update vtimer offset on all CPUs */
665
+ dc->vmsd = &vmstate_crl;
903
+ hvf_state->vtimer_offset = mach_absolute_time() - s->vtimer_val;
666
+
904
+ cpu_synchronize_all_states();
667
+ rc->phases.enter = crl_reset_enter;
905
+ } else {
668
+ rc->phases.hold = crl_reset_hold;
906
+ /* Remember vtimer value on every pause */
669
+}
907
+ s->vtimer_val = hvf_vtimer_val_raw();
670
+
908
+ }
671
+static const TypeInfo crl_info = {
909
+}
672
+ .name = TYPE_XLNX_VERSAL_CRL,
910
+
673
+ .parent = TYPE_SYS_BUS_DEVICE,
911
+int hvf_arch_init(void)
674
+ .instance_size = sizeof(XlnxVersalCRL),
912
+{
675
+ .class_init = crl_class_init,
913
+ hvf_state->vtimer_offset = mach_absolute_time();
676
+ .instance_init = crl_init,
914
+ vmstate_register(NULL, 0, &vmstate_hvf_vtimer, &vtimer);
677
+ .instance_finalize = crl_finalize,
915
+ qemu_add_vm_change_state_handler(hvf_vm_state_change, &vtimer);
678
+};
916
+ return 0;
679
+
917
+}
680
+static void crl_register_types(void)
918
diff --git a/target/i386/hvf/hvf.c b/target/i386/hvf/hvf.c
681
+{
682
+ type_register_static(&crl_info);
683
+}
684
+
685
+type_init(crl_register_types)
686
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
919
index XXXXXXX..XXXXXXX 100644
687
index XXXXXXX..XXXXXXX 100644
920
--- a/target/i386/hvf/hvf.c
688
--- a/hw/misc/meson.build
921
+++ b/target/i386/hvf/hvf.c
689
+++ b/hw/misc/meson.build
922
@@ -XXX,XX +XXX,XX @@ static inline bool apic_bus_freq_is_known(CPUX86State *env)
690
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_SLAVIO', if_true: files('slavio_misc.c'))
923
return env->apic_bus_freq != 0;
691
softmmu_ss.add(when: 'CONFIG_ZYNQ', if_true: files('zynq_slcr.c'))
924
}
692
specific_ss.add(when: 'CONFIG_XLNX_ZYNQMP_ARM', if_true: files('xlnx-zynqmp-crf.c'))
925
693
specific_ss.add(when: 'CONFIG_XLNX_ZYNQMP_ARM', if_true: files('xlnx-zynqmp-apu-ctrl.c'))
926
+void hvf_kick_vcpu_thread(CPUState *cpu)
694
+specific_ss.add(when: 'CONFIG_XLNX_VERSAL', if_true: files('xlnx-versal-crl.c'))
927
+{
695
softmmu_ss.add(when: 'CONFIG_XLNX_VERSAL', if_true: files(
928
+ cpus_kick_thread(cpu);
696
'xlnx-versal-xramc.c',
929
+}
697
'xlnx-versal-pmc-iou-slcr.c',
930
+
931
int hvf_arch_init(void)
932
{
933
return 0;
934
diff --git a/MAINTAINERS b/MAINTAINERS
935
index XXXXXXX..XXXXXXX 100644
936
--- a/MAINTAINERS
937
+++ b/MAINTAINERS
938
@@ -XXX,XX +XXX,XX @@ F: accel/accel-*.c
939
F: accel/Makefile.objs
940
F: accel/stubs/Makefile.objs
941
942
+Apple Silicon HVF CPUs
943
+M: Alexander Graf <agraf@csgraf.de>
944
+S: Maintained
945
+F: target/arm/hvf/
946
+
947
X86 HVF CPUs
948
M: Cameron Esfahani <dirty@apple.com>
949
M: Roman Bolshakov <r.bolshakov@yadro.com>
950
diff --git a/target/arm/hvf/trace-events b/target/arm/hvf/trace-events
951
new file mode 100644
952
index XXXXXXX..XXXXXXX
953
--- /dev/null
954
+++ b/target/arm/hvf/trace-events
955
@@ -XXX,XX +XXX,XX @@
956
+hvf_unhandled_sysreg_read(uint64_t pc, uint32_t reg, uint32_t op0, uint32_t op1, uint32_t crn, uint32_t crm, uint32_t op2) "unhandled sysreg read at pc=0x%"PRIx64": 0x%08x (op0=%d op1=%d crn=%d crm=%d op2=%d)"
957
+hvf_unhandled_sysreg_write(uint64_t pc, uint32_t reg, uint32_t op0, uint32_t op1, uint32_t crn, uint32_t crm, uint32_t op2) "unhandled sysreg write at pc=0x%"PRIx64": 0x%08x (op0=%d op1=%d crn=%d crm=%d op2=%d)"
958
+hvf_inject_fiq(void) "injecting FIQ"
959
+hvf_inject_irq(void) "injecting IRQ"
960
+hvf_data_abort(uint64_t pc, uint64_t va, uint64_t pa, bool isv, bool iswrite, bool s1ptw, uint32_t len, uint32_t srt) "data abort: [pc=0x%"PRIx64" va=0x%016"PRIx64" pa=0x%016"PRIx64" isv=%d iswrite=%d s1ptw=%d len=%d srt=%d]"
961
+hvf_sysreg_read(uint32_t reg, uint32_t op0, uint32_t op1, uint32_t crn, uint32_t crm, uint32_t op2, uint64_t val) "sysreg read 0x%08x (op0=%d op1=%d crn=%d crm=%d op2=%d) = 0x%016"PRIx64
962
+hvf_sysreg_write(uint32_t reg, uint32_t op0, uint32_t op1, uint32_t crn, uint32_t crm, uint32_t op2, uint64_t val) "sysreg write 0x%08x (op0=%d op1=%d crn=%d crm=%d op2=%d, val=0x%016"PRIx64")"
963
+hvf_unknown_hvc(uint64_t x0) "unknown HVC! 0x%016"PRIx64
964
+hvf_unknown_smc(uint64_t x0) "unknown SMC! 0x%016"PRIx64
965
+hvf_exit(uint64_t syndrome, uint32_t ec, uint64_t pc) "exit: 0x%"PRIx64" [ec=0x%x pc=0x%"PRIx64"]"
966
--
698
--
967
2.20.1
699
2.25.1
968
969
diff view generated by jsdifflib
1
From: Peter Collingbourne <pcc@google.com>
1
From: "Edgar E. Iglesias" <edgar.iglesias@amd.com>
2
2
3
Sleep on WFI until the VTIMER is due but allow ourselves to be woken
3
Connect the CRL (Clock Reset LPD) to the Versal SoC.
4
up on IPI.
5
4
6
In this implementation IPI is blocked on the CPU thread at startup and
5
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>
7
pselect() is used to atomically unblock the signal and begin sleeping.
6
Reviewed-by: Frederic Konrad <fkonrad@amd.com>
8
The signal is sent unconditionally so there's no need to worry about
7
Reviewed-by: Francisco Iglesias <francisco.iglesias@amd.com>
9
races between actually sleeping and the "we think we're sleeping"
8
Message-id: 20220406174303.2022038-5-edgar.iglesias@xilinx.com
10
state. It may lead to an extra wakeup but that's better than missing
11
it entirely.
12
13
Signed-off-by: Peter Collingbourne <pcc@google.com>
14
Signed-off-by: Alexander Graf <agraf@csgraf.de>
15
Acked-by: Roman Bolshakov <r.bolshakov@yadro.com>
16
Reviewed-by: Sergio Lopez <slp@redhat.com>
17
Message-id: 20210916155404.86958-6-agraf@csgraf.de
18
[agraf: Remove unused 'set' variable, always advance PC on WFX trap,
19
support vm stop / continue operations and cntv offsets]
20
Signed-off-by: Alexander Graf <agraf@csgraf.de>
21
Acked-by: Roman Bolshakov <r.bolshakov@yadro.com>
22
Reviewed-by: Sergio Lopez <slp@redhat.com>
23
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
24
---
10
---
25
include/sysemu/hvf_int.h | 1 +
11
include/hw/arm/xlnx-versal.h | 4 +++
26
accel/hvf/hvf-accel-ops.c | 5 +--
12
hw/arm/xlnx-versal.c | 54 ++++++++++++++++++++++++++++++++++--
27
target/arm/hvf/hvf.c | 79 +++++++++++++++++++++++++++++++++++++++
13
2 files changed, 56 insertions(+), 2 deletions(-)
28
3 files changed, 82 insertions(+), 3 deletions(-)
29
14
30
diff --git a/include/sysemu/hvf_int.h b/include/sysemu/hvf_int.h
15
diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
31
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
32
--- a/include/sysemu/hvf_int.h
17
--- a/include/hw/arm/xlnx-versal.h
33
+++ b/include/sysemu/hvf_int.h
18
+++ b/include/hw/arm/xlnx-versal.h
34
@@ -XXX,XX +XXX,XX @@ struct hvf_vcpu_state {
19
@@ -XXX,XX +XXX,XX @@
35
uint64_t fd;
20
#include "hw/nvram/xlnx-versal-efuse.h"
36
void *exit;
21
#include "hw/ssi/xlnx-versal-ospi.h"
37
bool vtimer_masked;
22
#include "hw/dma/xlnx_csu_dma.h"
38
+ sigset_t unblock_ipi_mask;
23
+#include "hw/misc/xlnx-versal-crl.h"
39
};
24
#include "hw/misc/xlnx-versal-pmc-iou-slcr.h"
40
25
41
void assert_hvf_ok(hv_return_t ret);
26
#define TYPE_XLNX_VERSAL "xlnx-versal"
42
diff --git a/accel/hvf/hvf-accel-ops.c b/accel/hvf/hvf-accel-ops.c
27
@@ -XXX,XX +XXX,XX @@ struct Versal {
28
qemu_or_irq irq_orgate;
29
XlnxXramCtrl ctrl[XLNX_VERSAL_NR_XRAM];
30
} xram;
31
+
32
+ XlnxVersalCRL crl;
33
} lpd;
34
35
/* The Platform Management Controller subsystem. */
36
@@ -XXX,XX +XXX,XX @@ struct Versal {
37
#define VERSAL_TIMER_NS_EL1_IRQ 14
38
#define VERSAL_TIMER_NS_EL2_IRQ 10
39
40
+#define VERSAL_CRL_IRQ 10
41
#define VERSAL_UART0_IRQ_0 18
42
#define VERSAL_UART1_IRQ_0 19
43
#define VERSAL_USB0_IRQ_0 22
44
diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
43
index XXXXXXX..XXXXXXX 100644
45
index XXXXXXX..XXXXXXX 100644
44
--- a/accel/hvf/hvf-accel-ops.c
46
--- a/hw/arm/xlnx-versal.c
45
+++ b/accel/hvf/hvf-accel-ops.c
47
+++ b/hw/arm/xlnx-versal.c
46
@@ -XXX,XX +XXX,XX @@ static int hvf_init_vcpu(CPUState *cpu)
48
@@ -XXX,XX +XXX,XX @@ static void versal_create_ospi(Versal *s, qemu_irq *pic)
47
cpu->hvf = g_malloc0(sizeof(*cpu->hvf));
49
qdev_connect_gpio_out(orgate, 0, pic[VERSAL_OSPI_IRQ]);
48
49
/* init cpu signals */
50
- sigset_t set;
51
struct sigaction sigact;
52
53
memset(&sigact, 0, sizeof(sigact));
54
sigact.sa_handler = dummy_signal;
55
sigaction(SIG_IPI, &sigact, NULL);
56
57
- pthread_sigmask(SIG_BLOCK, NULL, &set);
58
- sigdelset(&set, SIG_IPI);
59
+ pthread_sigmask(SIG_BLOCK, NULL, &cpu->hvf->unblock_ipi_mask);
60
+ sigdelset(&cpu->hvf->unblock_ipi_mask, SIG_IPI);
61
62
#ifdef __aarch64__
63
r = hv_vcpu_create(&cpu->hvf->fd, (hv_vcpu_exit_t **)&cpu->hvf->exit, NULL);
64
diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c
65
index XXXXXXX..XXXXXXX 100644
66
--- a/target/arm/hvf/hvf.c
67
+++ b/target/arm/hvf/hvf.c
68
@@ -XXX,XX +XXX,XX @@
69
* QEMU Hypervisor.framework support for Apple Silicon
70
71
* Copyright 2020 Alexander Graf <agraf@csgraf.de>
72
+ * Copyright 2020 Google LLC
73
*
74
* This work is licensed under the terms of the GNU GPL, version 2 or later.
75
* See the COPYING file in the top-level directory.
76
@@ -XXX,XX +XXX,XX @@ int hvf_arch_init_vcpu(CPUState *cpu)
77
78
void hvf_kick_vcpu_thread(CPUState *cpu)
79
{
80
+ cpus_kick_thread(cpu);
81
hv_vcpus_exit(&cpu->hvf->fd, 1);
82
}
50
}
83
51
84
@@ -XXX,XX +XXX,XX @@ static uint64_t hvf_vtimer_val_raw(void)
52
+static void versal_create_crl(Versal *s, qemu_irq *pic)
85
return mach_absolute_time() - hvf_state->vtimer_offset;
86
}
87
88
+static uint64_t hvf_vtimer_val(void)
89
+{
53
+{
90
+ if (!runstate_is_running()) {
54
+ SysBusDevice *sbd;
91
+ /* VM is paused, the vtimer value is in vtimer.vtimer_val */
55
+ int i;
92
+ return vtimer.vtimer_val;
56
+
57
+ object_initialize_child(OBJECT(s), "crl", &s->lpd.crl,
58
+ TYPE_XLNX_VERSAL_CRL);
59
+ sbd = SYS_BUS_DEVICE(&s->lpd.crl);
60
+
61
+ for (i = 0; i < ARRAY_SIZE(s->lpd.rpu.cpu); i++) {
62
+ g_autofree gchar *name = g_strdup_printf("cpu_r5[%d]", i);
63
+
64
+ object_property_set_link(OBJECT(&s->lpd.crl),
65
+ name, OBJECT(&s->lpd.rpu.cpu[i]),
66
+ &error_abort);
93
+ }
67
+ }
94
+
68
+
95
+ return hvf_vtimer_val_raw();
69
+ for (i = 0; i < ARRAY_SIZE(s->lpd.iou.gem); i++) {
70
+ g_autofree gchar *name = g_strdup_printf("gem[%d]", i);
71
+
72
+ object_property_set_link(OBJECT(&s->lpd.crl),
73
+ name, OBJECT(&s->lpd.iou.gem[i]),
74
+ &error_abort);
75
+ }
76
+
77
+ for (i = 0; i < ARRAY_SIZE(s->lpd.iou.adma); i++) {
78
+ g_autofree gchar *name = g_strdup_printf("adma[%d]", i);
79
+
80
+ object_property_set_link(OBJECT(&s->lpd.crl),
81
+ name, OBJECT(&s->lpd.iou.adma[i]),
82
+ &error_abort);
83
+ }
84
+
85
+ for (i = 0; i < ARRAY_SIZE(s->lpd.iou.uart); i++) {
86
+ g_autofree gchar *name = g_strdup_printf("uart[%d]", i);
87
+
88
+ object_property_set_link(OBJECT(&s->lpd.crl),
89
+ name, OBJECT(&s->lpd.iou.uart[i]),
90
+ &error_abort);
91
+ }
92
+
93
+ object_property_set_link(OBJECT(&s->lpd.crl),
94
+ "usb", OBJECT(&s->lpd.iou.usb),
95
+ &error_abort);
96
+
97
+ sysbus_realize(sbd, &error_fatal);
98
+ memory_region_add_subregion(&s->mr_ps, MM_CRL,
99
+ sysbus_mmio_get_region(sbd, 0));
100
+ sysbus_connect_irq(sbd, 0, pic[VERSAL_CRL_IRQ]);
96
+}
101
+}
97
+
102
+
98
+static void hvf_wait_for_ipi(CPUState *cpu, struct timespec *ts)
103
/* This takes the board allocated linear DDR memory and creates aliases
99
+{
104
* for each split DDR range/aperture on the Versal address map.
100
+ /*
105
*/
101
+ * Use pselect to sleep so that other threads can IPI us while we're
106
@@ -XXX,XX +XXX,XX @@ static void versal_unimp(Versal *s)
102
+ * sleeping.
107
103
+ */
108
versal_unimp_area(s, "psm", &s->mr_ps,
104
+ qatomic_mb_set(&cpu->thread_kicked, false);
109
MM_PSM_START, MM_PSM_END - MM_PSM_START);
105
+ qemu_mutex_unlock_iothread();
110
- versal_unimp_area(s, "crl", &s->mr_ps,
106
+ pselect(0, 0, 0, 0, ts, &cpu->hvf->unblock_ipi_mask);
111
- MM_CRL, MM_CRL_SIZE);
107
+ qemu_mutex_lock_iothread();
112
versal_unimp_area(s, "crf", &s->mr_ps,
108
+}
113
MM_FPD_CRF, MM_FPD_CRF_SIZE);
109
+
114
versal_unimp_area(s, "apu", &s->mr_ps,
110
+static void hvf_wfi(CPUState *cpu)
115
@@ -XXX,XX +XXX,XX @@ static void versal_realize(DeviceState *dev, Error **errp)
111
+{
116
versal_create_efuse(s, pic);
112
+ ARMCPU *arm_cpu = ARM_CPU(cpu);
117
versal_create_pmc_iou_slcr(s, pic);
113
+ struct timespec ts;
118
versal_create_ospi(s, pic);
114
+ hv_return_t r;
119
+ versal_create_crl(s, pic);
115
+ uint64_t ctl;
120
versal_map_ddr(s);
116
+ uint64_t cval;
121
versal_unimp(s);
117
+ int64_t ticks_to_sleep;
122
118
+ uint64_t seconds;
119
+ uint64_t nanos;
120
+ uint32_t cntfrq;
121
+
122
+ if (cpu->interrupt_request & (CPU_INTERRUPT_HARD | CPU_INTERRUPT_FIQ)) {
123
+ /* Interrupt pending, no need to wait */
124
+ return;
125
+ }
126
+
127
+ r = hv_vcpu_get_sys_reg(cpu->hvf->fd, HV_SYS_REG_CNTV_CTL_EL0, &ctl);
128
+ assert_hvf_ok(r);
129
+
130
+ if (!(ctl & 1) || (ctl & 2)) {
131
+ /* Timer disabled or masked, just wait for an IPI. */
132
+ hvf_wait_for_ipi(cpu, NULL);
133
+ return;
134
+ }
135
+
136
+ r = hv_vcpu_get_sys_reg(cpu->hvf->fd, HV_SYS_REG_CNTV_CVAL_EL0, &cval);
137
+ assert_hvf_ok(r);
138
+
139
+ ticks_to_sleep = cval - hvf_vtimer_val();
140
+ if (ticks_to_sleep < 0) {
141
+ return;
142
+ }
143
+
144
+ cntfrq = gt_cntfrq_period_ns(arm_cpu);
145
+ seconds = muldiv64(ticks_to_sleep, cntfrq, NANOSECONDS_PER_SECOND);
146
+ ticks_to_sleep -= muldiv64(seconds, NANOSECONDS_PER_SECOND, cntfrq);
147
+ nanos = ticks_to_sleep * cntfrq;
148
+
149
+ /*
150
+ * Don't sleep for less than the time a context switch would take,
151
+ * so that we can satisfy fast timer requests on the same CPU.
152
+ * Measurements on M1 show the sweet spot to be ~2ms.
153
+ */
154
+ if (!seconds && nanos < (2 * SCALE_MS)) {
155
+ return;
156
+ }
157
+
158
+ ts = (struct timespec) { seconds, nanos };
159
+ hvf_wait_for_ipi(cpu, &ts);
160
+}
161
+
162
static void hvf_sync_vtimer(CPUState *cpu)
163
{
164
ARMCPU *arm_cpu = ARM_CPU(cpu);
165
@@ -XXX,XX +XXX,XX @@ int hvf_vcpu_exec(CPUState *cpu)
166
}
167
case EC_WFX_TRAP:
168
advance_pc = true;
169
+ if (!(syndrome & WFX_IS_WFE)) {
170
+ hvf_wfi(cpu);
171
+ }
172
break;
173
case EC_AA64_HVC:
174
cpu_synchronize_state(cpu);
175
--
123
--
176
2.20.1
124
2.25.1
177
178
diff view generated by jsdifflib
1
Optimize the MVE 1op-immediate insns (VORR, VBIC, VMOV) to
1
The Exynos4210 SoC device currently uses a custom device
2
use TCG vector ops when possible.
2
"exynos4210.irq_gate" to model the OR gate that feeds each CPU's IRQ
3
line. We have a standard TYPE_OR_IRQ device for this now, so use
4
that instead.
5
6
(This is a migration compatibility break, but that is OK for this
7
machine type.)
3
8
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20210913095440.13462-13-peter.maydell@linaro.org
11
Message-id: 20220404154658.565020-2-peter.maydell@linaro.org
7
---
12
---
8
target/arm/translate-mve.c | 26 +++++++++++++++++++++-----
13
include/hw/arm/exynos4210.h | 1 +
9
1 file changed, 21 insertions(+), 5 deletions(-)
14
hw/arm/exynos4210.c | 31 ++++++++++++++++---------------
15
2 files changed, 17 insertions(+), 15 deletions(-)
10
16
11
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
17
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
12
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
13
--- a/target/arm/translate-mve.c
19
--- a/include/hw/arm/exynos4210.h
14
+++ b/target/arm/translate-mve.c
20
+++ b/include/hw/arm/exynos4210.h
15
@@ -XXX,XX +XXX,XX @@ static bool trans_VADDLV(DisasContext *s, arg_VADDLV *a)
21
@@ -XXX,XX +XXX,XX @@ struct Exynos4210State {
16
return true;
22
MemoryRegion bootreg_mem;
23
I2CBus *i2c_if[EXYNOS4210_I2C_NUMBER];
24
qemu_or_irq pl330_irq_orgate[EXYNOS4210_NUM_DMA];
25
+ qemu_or_irq cpu_irq_orgate[EXYNOS4210_NCPUS];
26
};
27
28
#define TYPE_EXYNOS4210_SOC "exynos4210"
29
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
30
index XXXXXXX..XXXXXXX 100644
31
--- a/hw/arm/exynos4210.c
32
+++ b/hw/arm/exynos4210.c
33
@@ -XXX,XX +XXX,XX @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
34
{
35
Exynos4210State *s = EXYNOS4210_SOC(socdev);
36
MemoryRegion *system_mem = get_system_memory();
37
- qemu_irq gate_irq[EXYNOS4210_NCPUS][EXYNOS4210_IRQ_GATE_NINPUTS];
38
SysBusDevice *busdev;
39
DeviceState *dev, *uart[4], *pl330[3];
40
int i, n;
41
@@ -XXX,XX +XXX,XX @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
42
43
/* IRQ Gate */
44
for (i = 0; i < EXYNOS4210_NCPUS; i++) {
45
- dev = qdev_new("exynos4210.irq_gate");
46
- qdev_prop_set_uint32(dev, "n_in", EXYNOS4210_IRQ_GATE_NINPUTS);
47
- sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
48
- /* Get IRQ Gate input in gate_irq */
49
- for (n = 0; n < EXYNOS4210_IRQ_GATE_NINPUTS; n++) {
50
- gate_irq[i][n] = qdev_get_gpio_in(dev, n);
51
- }
52
- busdev = SYS_BUS_DEVICE(dev);
53
-
54
- /* Connect IRQ Gate output to CPU's IRQ line */
55
- sysbus_connect_irq(busdev, 0,
56
- qdev_get_gpio_in(DEVICE(s->cpu[i]), ARM_CPU_IRQ));
57
+ DeviceState *orgate = DEVICE(&s->cpu_irq_orgate[i]);
58
+ object_property_set_int(OBJECT(orgate), "num-lines",
59
+ EXYNOS4210_IRQ_GATE_NINPUTS,
60
+ &error_abort);
61
+ qdev_realize(orgate, NULL, &error_abort);
62
+ qdev_connect_gpio_out(orgate, 0,
63
+ qdev_get_gpio_in(DEVICE(s->cpu[i]), ARM_CPU_IRQ));
64
}
65
66
/* Private memory region and Internal GIC */
67
@@ -XXX,XX +XXX,XX @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
68
sysbus_realize_and_unref(busdev, &error_fatal);
69
sysbus_mmio_map(busdev, 0, EXYNOS4210_SMP_PRIVATE_BASE_ADDR);
70
for (n = 0; n < EXYNOS4210_NCPUS; n++) {
71
- sysbus_connect_irq(busdev, n, gate_irq[n][0]);
72
+ sysbus_connect_irq(busdev, n,
73
+ qdev_get_gpio_in(DEVICE(&s->cpu_irq_orgate[n]), 0));
74
}
75
for (n = 0; n < EXYNOS4210_INT_GIC_NIRQ; n++) {
76
s->irqs.int_gic_irq[n] = qdev_get_gpio_in(dev, n);
77
@@ -XXX,XX +XXX,XX @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
78
/* Map Distributer interface */
79
sysbus_mmio_map(busdev, 1, EXYNOS4210_EXT_GIC_DIST_BASE_ADDR);
80
for (n = 0; n < EXYNOS4210_NCPUS; n++) {
81
- sysbus_connect_irq(busdev, n, gate_irq[n][1]);
82
+ sysbus_connect_irq(busdev, n,
83
+ qdev_get_gpio_in(DEVICE(&s->cpu_irq_orgate[n]), 1));
84
}
85
for (n = 0; n < EXYNOS4210_EXT_GIC_NIRQ; n++) {
86
s->irqs.ext_gic_irq[n] = qdev_get_gpio_in(dev, n);
87
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init(Object *obj)
88
object_initialize_child(obj, name, orgate, TYPE_OR_IRQ);
89
g_free(name);
90
}
91
+
92
+ for (i = 0; i < ARRAY_SIZE(s->cpu_irq_orgate); i++) {
93
+ g_autofree char *name = g_strdup_printf("cpu-irq-orgate%d", i);
94
+ object_initialize_child(obj, name, &s->cpu_irq_orgate[i], TYPE_OR_IRQ);
95
+ }
17
}
96
}
18
97
19
-static bool do_1imm(DisasContext *s, arg_1imm *a, MVEGenOneOpImmFn *fn)
98
static void exynos4210_class_init(ObjectClass *klass, void *data)
20
+static bool do_1imm(DisasContext *s, arg_1imm *a, MVEGenOneOpImmFn *fn,
21
+ GVecGen2iFn *vecfn)
22
{
23
TCGv_ptr qd;
24
uint64_t imm;
25
@@ -XXX,XX +XXX,XX @@ static bool do_1imm(DisasContext *s, arg_1imm *a, MVEGenOneOpImmFn *fn)
26
27
imm = asimd_imm_const(a->imm, a->cmode, a->op);
28
29
- qd = mve_qreg_ptr(a->qd);
30
- fn(cpu_env, qd, tcg_constant_i64(imm));
31
- tcg_temp_free_ptr(qd);
32
+ if (vecfn && mve_no_predication(s)) {
33
+ vecfn(MO_64, mve_qreg_offset(a->qd), mve_qreg_offset(a->qd),
34
+ imm, 16, 16);
35
+ } else {
36
+ qd = mve_qreg_ptr(a->qd);
37
+ fn(cpu_env, qd, tcg_constant_i64(imm));
38
+ tcg_temp_free_ptr(qd);
39
+ }
40
mve_update_eci(s);
41
return true;
42
}
43
44
+static void gen_gvec_vmovi(unsigned vece, uint32_t dofs, uint32_t aofs,
45
+ int64_t c, uint32_t oprsz, uint32_t maxsz)
46
+{
47
+ tcg_gen_gvec_dup_imm(vece, dofs, oprsz, maxsz, c);
48
+}
49
+
50
static bool trans_Vimm_1r(DisasContext *s, arg_1imm *a)
51
{
52
/* Handle decode of cmode/op here between VORR/VBIC/VMOV */
53
MVEGenOneOpImmFn *fn;
54
+ GVecGen2iFn *vecfn;
55
56
if ((a->cmode & 1) && a->cmode < 12) {
57
if (a->op) {
58
@@ -XXX,XX +XXX,XX @@ static bool trans_Vimm_1r(DisasContext *s, arg_1imm *a)
59
* so the VBIC becomes a logical AND operation.
60
*/
61
fn = gen_helper_mve_vandi;
62
+ vecfn = tcg_gen_gvec_andi;
63
} else {
64
fn = gen_helper_mve_vorri;
65
+ vecfn = tcg_gen_gvec_ori;
66
}
67
} else {
68
/* There is one unallocated cmode/op combination in this space */
69
@@ -XXX,XX +XXX,XX @@ static bool trans_Vimm_1r(DisasContext *s, arg_1imm *a)
70
}
71
/* asimd_imm_const() sorts out VMVNI vs VMOVI for us */
72
fn = gen_helper_mve_vmovi;
73
+ vecfn = gen_gvec_vmovi;
74
}
75
- return do_1imm(s, a, fn);
76
+ return do_1imm(s, a, fn, vecfn);
77
}
78
79
static bool do_2shift_vec(DisasContext *s, arg_2shift *a, MVEGenTwoOpShiftFn fn,
80
--
99
--
81
2.20.1
100
2.25.1
82
83
diff view generated by jsdifflib
1
Optimize the MVE VNEG and VABS insns by using TCG
1
Now we have removed the only use of TYPE_EXYNOS4210_IRQ_GATE we can
2
vector ops when possible.
2
delete the device entirely.
3
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
5
Reviewed-by: Francisco Iglesias <frasse.iglesias@gmail.com>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20220404154658.565020-3-peter.maydell@linaro.org
7
Message-id: 20210913095440.13462-7-peter.maydell@linaro.org
8
---
7
---
9
target/arm/translate-mve.c | 32 ++++++++++++++++++++++----------
8
hw/intc/exynos4210_gic.c | 107 ---------------------------------------
10
1 file changed, 22 insertions(+), 10 deletions(-)
9
1 file changed, 107 deletions(-)
11
10
12
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
11
diff --git a/hw/intc/exynos4210_gic.c b/hw/intc/exynos4210_gic.c
13
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/translate-mve.c
13
--- a/hw/intc/exynos4210_gic.c
15
+++ b/target/arm/translate-mve.c
14
+++ b/hw/intc/exynos4210_gic.c
16
@@ -XXX,XX +XXX,XX @@ static bool trans_VDUP(DisasContext *s, arg_VDUP *a)
15
@@ -XXX,XX +XXX,XX @@ static void exynos4210_gic_register_types(void)
17
return true;
18
}
16
}
19
17
20
-static bool do_1op(DisasContext *s, arg_1op *a, MVEGenOneOpFn fn)
18
type_init(exynos4210_gic_register_types)
21
+static bool do_1op_vec(DisasContext *s, arg_1op *a, MVEGenOneOpFn fn,
19
-
22
+ GVecGen2Fn vecfn)
20
-/* IRQ OR Gate struct.
23
{
21
- *
24
TCGv_ptr qd, qm;
22
- * This device models an OR gate. There are n_in input qdev gpio lines and one
25
23
- * output sysbus IRQ line. The output IRQ level is formed as OR between all
26
@@ -XXX,XX +XXX,XX @@ static bool do_1op(DisasContext *s, arg_1op *a, MVEGenOneOpFn fn)
24
- * gpio inputs.
27
return true;
25
- */
28
}
26
-
29
27
-#define TYPE_EXYNOS4210_IRQ_GATE "exynos4210.irq_gate"
30
- qd = mve_qreg_ptr(a->qd);
28
-OBJECT_DECLARE_SIMPLE_TYPE(Exynos4210IRQGateState, EXYNOS4210_IRQ_GATE)
31
- qm = mve_qreg_ptr(a->qm);
29
-
32
- fn(cpu_env, qd, qm);
30
-struct Exynos4210IRQGateState {
33
- tcg_temp_free_ptr(qd);
31
- SysBusDevice parent_obj;
34
- tcg_temp_free_ptr(qm);
32
-
35
+ if (vecfn && mve_no_predication(s)) {
33
- uint32_t n_in; /* inputs amount */
36
+ vecfn(a->size, mve_qreg_offset(a->qd), mve_qreg_offset(a->qm), 16, 16);
34
- uint32_t *level; /* input levels */
37
+ } else {
35
- qemu_irq out; /* output IRQ */
38
+ qd = mve_qreg_ptr(a->qd);
36
-};
39
+ qm = mve_qreg_ptr(a->qm);
37
-
40
+ fn(cpu_env, qd, qm);
38
-static Property exynos4210_irq_gate_properties[] = {
41
+ tcg_temp_free_ptr(qd);
39
- DEFINE_PROP_UINT32("n_in", Exynos4210IRQGateState, n_in, 1),
42
+ tcg_temp_free_ptr(qm);
40
- DEFINE_PROP_END_OF_LIST(),
43
+ }
41
-};
44
mve_update_eci(s);
42
-
45
return true;
43
-static const VMStateDescription vmstate_exynos4210_irq_gate = {
46
}
44
- .name = "exynos4210.irq_gate",
47
45
- .version_id = 2,
48
-#define DO_1OP(INSN, FN) \
46
- .minimum_version_id = 2,
49
+static bool do_1op(DisasContext *s, arg_1op *a, MVEGenOneOpFn fn)
47
- .fields = (VMStateField[]) {
50
+{
48
- VMSTATE_VBUFFER_UINT32(level, Exynos4210IRQGateState, 1, NULL, n_in),
51
+ return do_1op_vec(s, a, fn, NULL);
49
- VMSTATE_END_OF_LIST()
52
+}
50
- }
53
+
51
-};
54
+#define DO_1OP_VEC(INSN, FN, VECFN) \
52
-
55
static bool trans_##INSN(DisasContext *s, arg_1op *a) \
53
-/* Process a change in IRQ input. */
56
{ \
54
-static void exynos4210_irq_gate_handler(void *opaque, int irq, int level)
57
static MVEGenOneOpFn * const fns[] = { \
55
-{
58
@@ -XXX,XX +XXX,XX @@ static bool do_1op(DisasContext *s, arg_1op *a, MVEGenOneOpFn fn)
56
- Exynos4210IRQGateState *s = (Exynos4210IRQGateState *)opaque;
59
gen_helper_mve_##FN##w, \
57
- uint32_t i;
60
NULL, \
58
-
61
}; \
59
- assert(irq < s->n_in);
62
- return do_1op(s, a, fns[a->size]); \
60
-
63
+ return do_1op_vec(s, a, fns[a->size], VECFN); \
61
- s->level[irq] = level;
64
}
62
-
65
63
- for (i = 0; i < s->n_in; i++) {
66
+#define DO_1OP(INSN, FN) DO_1OP_VEC(INSN, FN, NULL)
64
- if (s->level[i] >= 1) {
67
+
65
- qemu_irq_raise(s->out);
68
DO_1OP(VCLZ, vclz)
66
- return;
69
DO_1OP(VCLS, vcls)
67
- }
70
-DO_1OP(VABS, vabs)
68
- }
71
-DO_1OP(VNEG, vneg)
69
-
72
+DO_1OP_VEC(VABS, vabs, tcg_gen_gvec_abs)
70
- qemu_irq_lower(s->out);
73
+DO_1OP_VEC(VNEG, vneg, tcg_gen_gvec_neg)
71
-}
74
DO_1OP(VQABS, vqabs)
72
-
75
DO_1OP(VQNEG, vqneg)
73
-static void exynos4210_irq_gate_reset(DeviceState *d)
76
DO_1OP(VMAXA, vmaxa)
74
-{
75
- Exynos4210IRQGateState *s = EXYNOS4210_IRQ_GATE(d);
76
-
77
- memset(s->level, 0, s->n_in * sizeof(*s->level));
78
-}
79
-
80
-/*
81
- * IRQ Gate initialization.
82
- */
83
-static void exynos4210_irq_gate_init(Object *obj)
84
-{
85
- Exynos4210IRQGateState *s = EXYNOS4210_IRQ_GATE(obj);
86
- SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
87
-
88
- sysbus_init_irq(sbd, &s->out);
89
-}
90
-
91
-static void exynos4210_irq_gate_realize(DeviceState *dev, Error **errp)
92
-{
93
- Exynos4210IRQGateState *s = EXYNOS4210_IRQ_GATE(dev);
94
-
95
- /* Allocate general purpose input signals and connect a handler to each of
96
- * them */
97
- qdev_init_gpio_in(dev, exynos4210_irq_gate_handler, s->n_in);
98
-
99
- s->level = g_malloc0(s->n_in * sizeof(*s->level));
100
-}
101
-
102
-static void exynos4210_irq_gate_class_init(ObjectClass *klass, void *data)
103
-{
104
- DeviceClass *dc = DEVICE_CLASS(klass);
105
-
106
- dc->reset = exynos4210_irq_gate_reset;
107
- dc->vmsd = &vmstate_exynos4210_irq_gate;
108
- device_class_set_props(dc, exynos4210_irq_gate_properties);
109
- dc->realize = exynos4210_irq_gate_realize;
110
-}
111
-
112
-static const TypeInfo exynos4210_irq_gate_info = {
113
- .name = TYPE_EXYNOS4210_IRQ_GATE,
114
- .parent = TYPE_SYS_BUS_DEVICE,
115
- .instance_size = sizeof(Exynos4210IRQGateState),
116
- .instance_init = exynos4210_irq_gate_init,
117
- .class_init = exynos4210_irq_gate_class_init,
118
-};
119
-
120
-static void exynos4210_irq_gate_register_types(void)
121
-{
122
- type_register_static(&exynos4210_irq_gate_info);
123
-}
124
-
125
-type_init(exynos4210_irq_gate_register_types)
77
--
126
--
78
2.20.1
127
2.25.1
79
80
diff view generated by jsdifflib
1
There's no particular reason why the exclusive monitor should
1
The exynos4210 SoC mostly creates its child devices as if it were
2
be only cleared on reset in system emulation mode. It doesn't
2
board code. This includes the a9mpcore object. Switch that to a
3
hurt if it isn't cleared in user mode, but we might as well
3
new-style "embedded in the state struct" creation, because in the
4
reduce the amount of code we have that's inside an ifdef.
4
next commit we're going to want to refer to the object again further
5
down in the exynos4210_realize() function.
5
6
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20210914120725.24992-3-peter.maydell@linaro.org
9
Message-id: 20220404154658.565020-4-peter.maydell@linaro.org
9
---
10
---
10
target/arm/cpu.c | 6 +++---
11
include/hw/arm/exynos4210.h | 2 ++
11
1 file changed, 3 insertions(+), 3 deletions(-)
12
hw/arm/exynos4210.c | 11 ++++++-----
13
2 files changed, 8 insertions(+), 5 deletions(-)
12
14
13
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
15
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
14
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/cpu.c
17
--- a/include/hw/arm/exynos4210.h
16
+++ b/target/arm/cpu.c
18
+++ b/include/hw/arm/exynos4210.h
17
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_reset(DeviceState *dev)
19
@@ -XXX,XX +XXX,XX @@
18
env->regs[15] = 0xFFFF0000;
20
21
#include "hw/or-irq.h"
22
#include "hw/sysbus.h"
23
+#include "hw/cpu/a9mpcore.h"
24
#include "target/arm/cpu-qom.h"
25
#include "qom/object.h"
26
27
@@ -XXX,XX +XXX,XX @@ struct Exynos4210State {
28
I2CBus *i2c_if[EXYNOS4210_I2C_NUMBER];
29
qemu_or_irq pl330_irq_orgate[EXYNOS4210_NUM_DMA];
30
qemu_or_irq cpu_irq_orgate[EXYNOS4210_NCPUS];
31
+ A9MPPrivState a9mpcore;
32
};
33
34
#define TYPE_EXYNOS4210_SOC "exynos4210"
35
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
36
index XXXXXXX..XXXXXXX 100644
37
--- a/hw/arm/exynos4210.c
38
+++ b/hw/arm/exynos4210.c
39
@@ -XXX,XX +XXX,XX @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
19
}
40
}
20
41
21
+ env->vfp.xregs[ARM_VFP_FPEXC] = 0;
42
/* Private memory region and Internal GIC */
22
+#endif
43
- dev = qdev_new(TYPE_A9MPCORE_PRIV);
44
- qdev_prop_set_uint32(dev, "num-cpu", EXYNOS4210_NCPUS);
45
- busdev = SYS_BUS_DEVICE(dev);
46
- sysbus_realize_and_unref(busdev, &error_fatal);
47
+ qdev_prop_set_uint32(DEVICE(&s->a9mpcore), "num-cpu", EXYNOS4210_NCPUS);
48
+ busdev = SYS_BUS_DEVICE(&s->a9mpcore);
49
+ sysbus_realize(busdev, &error_fatal);
50
sysbus_mmio_map(busdev, 0, EXYNOS4210_SMP_PRIVATE_BASE_ADDR);
51
for (n = 0; n < EXYNOS4210_NCPUS; n++) {
52
sysbus_connect_irq(busdev, n,
53
qdev_get_gpio_in(DEVICE(&s->cpu_irq_orgate[n]), 0));
54
}
55
for (n = 0; n < EXYNOS4210_INT_GIC_NIRQ; n++) {
56
- s->irqs.int_gic_irq[n] = qdev_get_gpio_in(dev, n);
57
+ s->irqs.int_gic_irq[n] = qdev_get_gpio_in(DEVICE(&s->a9mpcore), n);
58
}
59
60
/* Cache controller */
61
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init(Object *obj)
62
g_autofree char *name = g_strdup_printf("cpu-irq-orgate%d", i);
63
object_initialize_child(obj, name, &s->cpu_irq_orgate[i], TYPE_OR_IRQ);
64
}
23
+
65
+
24
/* M profile requires that reset clears the exclusive monitor;
66
+ object_initialize_child(obj, "a9mpcore", &s->a9mpcore, TYPE_A9MPCORE_PRIV);
25
* A profile does not, but clearing it makes more sense than having it
67
}
26
* set with an exclusive access on address zero.
68
27
*/
69
static void exynos4210_class_init(ObjectClass *klass, void *data)
28
arm_clear_exclusive(env);
29
30
- env->vfp.xregs[ARM_VFP_FPEXC] = 0;
31
-#endif
32
-
33
if (arm_feature(env, ARM_FEATURE_PMSA)) {
34
if (cpu->pmsav7_dregion > 0) {
35
if (arm_feature(env, ARM_FEATURE_V8)) {
36
--
70
--
37
2.20.1
71
2.25.1
38
39
diff view generated by jsdifflib
New patch
1
The only time we use the int_gic_irq[] array in the Exynos4210Irq
2
struct is in the exynos4210_realize() function: we initialize it with
3
the GPIO inputs of the a9mpcore device, and then a bit later on we
4
connect those to the outputs of the internal combiner. Now that the
5
a9mpcore object is easily accessible as s->a9mpcore we can make the
6
connection directly from one device to the other without going via
7
this array.
1
8
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20220404154658.565020-5-peter.maydell@linaro.org
12
---
13
include/hw/arm/exynos4210.h | 1 -
14
hw/arm/exynos4210.c | 6 ++----
15
2 files changed, 2 insertions(+), 5 deletions(-)
16
17
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
18
index XXXXXXX..XXXXXXX 100644
19
--- a/include/hw/arm/exynos4210.h
20
+++ b/include/hw/arm/exynos4210.h
21
@@ -XXX,XX +XXX,XX @@
22
typedef struct Exynos4210Irq {
23
qemu_irq int_combiner_irq[EXYNOS4210_MAX_INT_COMBINER_IN_IRQ];
24
qemu_irq ext_combiner_irq[EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ];
25
- qemu_irq int_gic_irq[EXYNOS4210_INT_GIC_NIRQ];
26
qemu_irq ext_gic_irq[EXYNOS4210_EXT_GIC_NIRQ];
27
qemu_irq board_irqs[EXYNOS4210_MAX_INT_COMBINER_IN_IRQ];
28
} Exynos4210Irq;
29
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
30
index XXXXXXX..XXXXXXX 100644
31
--- a/hw/arm/exynos4210.c
32
+++ b/hw/arm/exynos4210.c
33
@@ -XXX,XX +XXX,XX @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
34
sysbus_connect_irq(busdev, n,
35
qdev_get_gpio_in(DEVICE(&s->cpu_irq_orgate[n]), 0));
36
}
37
- for (n = 0; n < EXYNOS4210_INT_GIC_NIRQ; n++) {
38
- s->irqs.int_gic_irq[n] = qdev_get_gpio_in(DEVICE(&s->a9mpcore), n);
39
- }
40
41
/* Cache controller */
42
sysbus_create_simple("l2x0", EXYNOS4210_L2X0_BASE_ADDR, NULL);
43
@@ -XXX,XX +XXX,XX @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
44
busdev = SYS_BUS_DEVICE(dev);
45
sysbus_realize_and_unref(busdev, &error_fatal);
46
for (n = 0; n < EXYNOS4210_MAX_INT_COMBINER_OUT_IRQ; n++) {
47
- sysbus_connect_irq(busdev, n, s->irqs.int_gic_irq[n]);
48
+ sysbus_connect_irq(busdev, n,
49
+ qdev_get_gpio_in(DEVICE(&s->a9mpcore), n));
50
}
51
exynos4210_combiner_get_gpioin(&s->irqs, dev, 0);
52
sysbus_mmio_map(busdev, 0, EXYNOS4210_INT_COMBINER_BASE_ADDR);
53
--
54
2.25.1
diff view generated by jsdifflib
1
Optimize the MVE VDUP insns by using TCG vector ops when possible.
1
The exynos4210 code currently has two very similar arrays of IRQs:
2
3
* board_irqs is a field of the Exynos4210Irq struct which is filled
4
in by exynos4210_init_board_irqs() with the appropriate qemu_irqs
5
for each IRQ the board/SoC can assert
6
* irq_table is a set of qemu_irqs pointed to from the
7
Exynos4210State struct. It's allocated in exynos4210_init_irq,
8
and the only behaviour these irqs have is that they pass on the
9
level to the equivalent board_irqs[] irq
10
11
The extra indirection through irq_table is unnecessary, so coalesce
12
these into a single irq_table[] array as a direct field in
13
Exynos4210State which exynos4210_init_board_irqs() fills in.
2
14
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
16
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20210913095440.13462-8-peter.maydell@linaro.org
17
Message-id: 20220404154658.565020-6-peter.maydell@linaro.org
6
---
18
---
7
target/arm/translate-mve.c | 12 ++++++++----
19
include/hw/arm/exynos4210.h | 8 ++------
8
1 file changed, 8 insertions(+), 4 deletions(-)
20
hw/arm/exynos4210.c | 6 +-----
21
hw/intc/exynos4210_gic.c | 32 ++++++++------------------------
22
3 files changed, 11 insertions(+), 35 deletions(-)
9
23
10
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
24
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
11
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
12
--- a/target/arm/translate-mve.c
26
--- a/include/hw/arm/exynos4210.h
13
+++ b/target/arm/translate-mve.c
27
+++ b/include/hw/arm/exynos4210.h
14
@@ -XXX,XX +XXX,XX @@ static bool trans_VDUP(DisasContext *s, arg_VDUP *a)
28
@@ -XXX,XX +XXX,XX @@ typedef struct Exynos4210Irq {
15
return true;
29
qemu_irq int_combiner_irq[EXYNOS4210_MAX_INT_COMBINER_IN_IRQ];
30
qemu_irq ext_combiner_irq[EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ];
31
qemu_irq ext_gic_irq[EXYNOS4210_EXT_GIC_NIRQ];
32
- qemu_irq board_irqs[EXYNOS4210_MAX_INT_COMBINER_IN_IRQ];
33
} Exynos4210Irq;
34
35
struct Exynos4210State {
36
@@ -XXX,XX +XXX,XX @@ struct Exynos4210State {
37
/*< public >*/
38
ARMCPU *cpu[EXYNOS4210_NCPUS];
39
Exynos4210Irq irqs;
40
- qemu_irq *irq_table;
41
+ qemu_irq irq_table[EXYNOS4210_MAX_INT_COMBINER_IN_IRQ];
42
43
MemoryRegion chipid_mem;
44
MemoryRegion iram_mem;
45
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_SIMPLE_TYPE(Exynos4210State, EXYNOS4210_SOC)
46
void exynos4210_write_secondary(ARMCPU *cpu,
47
const struct arm_boot_info *info);
48
49
-/* Initialize exynos4210 IRQ subsystem stub */
50
-qemu_irq *exynos4210_init_irq(Exynos4210Irq *env);
51
-
52
/* Initialize board IRQs.
53
* These IRQs contain splitted Int/External Combiner and External Gic IRQs */
54
-void exynos4210_init_board_irqs(Exynos4210Irq *s);
55
+void exynos4210_init_board_irqs(Exynos4210State *s);
56
57
/* Get IRQ number from exynos4210 IRQ subsystem stub.
58
* To identify IRQ source use internal combiner group and bit number
59
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
60
index XXXXXXX..XXXXXXX 100644
61
--- a/hw/arm/exynos4210.c
62
+++ b/hw/arm/exynos4210.c
63
@@ -XXX,XX +XXX,XX @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
64
qdev_realize(DEVICE(cpuobj), NULL, &error_fatal);
16
}
65
}
17
66
18
- qd = mve_qreg_ptr(a->qd);
67
- /*** IRQs ***/
19
rt = load_reg(s, a->rt);
68
-
20
- tcg_gen_dup_i32(a->size, rt, rt);
69
- s->irq_table = exynos4210_init_irq(&s->irqs);
21
- gen_helper_mve_vdup(cpu_env, qd, rt);
70
-
22
- tcg_temp_free_ptr(qd);
71
/* IRQ Gate */
23
+ if (mve_no_predication(s)) {
72
for (i = 0; i < EXYNOS4210_NCPUS; i++) {
24
+ tcg_gen_gvec_dup_i32(a->size, mve_qreg_offset(a->qd), 16, 16, rt);
73
DeviceState *orgate = DEVICE(&s->cpu_irq_orgate[i]);
25
+ } else {
74
@@ -XXX,XX +XXX,XX @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
26
+ qd = mve_qreg_ptr(a->qd);
75
sysbus_mmio_map(busdev, 0, EXYNOS4210_EXT_COMBINER_BASE_ADDR);
27
+ tcg_gen_dup_i32(a->size, rt, rt);
76
28
+ gen_helper_mve_vdup(cpu_env, qd, rt);
77
/* Initialize board IRQs. */
29
+ tcg_temp_free_ptr(qd);
78
- exynos4210_init_board_irqs(&s->irqs);
30
+ }
79
+ exynos4210_init_board_irqs(s);
31
tcg_temp_free_i32(rt);
80
32
mve_update_eci(s);
81
/*** Memory ***/
33
return true;
82
83
diff --git a/hw/intc/exynos4210_gic.c b/hw/intc/exynos4210_gic.c
84
index XXXXXXX..XXXXXXX 100644
85
--- a/hw/intc/exynos4210_gic.c
86
+++ b/hw/intc/exynos4210_gic.c
87
@@ -XXX,XX +XXX,XX @@ combiner_grp_to_gic_id[64-EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][8] = {
88
#define EXYNOS4210_GIC_CPU_REGION_SIZE 0x100
89
#define EXYNOS4210_GIC_DIST_REGION_SIZE 0x1000
90
91
-static void exynos4210_irq_handler(void *opaque, int irq, int level)
92
-{
93
- Exynos4210Irq *s = (Exynos4210Irq *)opaque;
94
-
95
- /* Bypass */
96
- qemu_set_irq(s->board_irqs[irq], level);
97
-}
98
-
99
-/*
100
- * Initialize exynos4210 IRQ subsystem stub.
101
- */
102
-qemu_irq *exynos4210_init_irq(Exynos4210Irq *s)
103
-{
104
- return qemu_allocate_irqs(exynos4210_irq_handler, s,
105
- EXYNOS4210_MAX_INT_COMBINER_IN_IRQ);
106
-}
107
-
108
/*
109
* Initialize board IRQs.
110
* These IRQs contain splitted Int/External Combiner and External Gic IRQs.
111
*/
112
-void exynos4210_init_board_irqs(Exynos4210Irq *s)
113
+void exynos4210_init_board_irqs(Exynos4210State *s)
114
{
115
uint32_t grp, bit, irq_id, n;
116
+ Exynos4210Irq *is = &s->irqs;
117
118
for (n = 0; n < EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ; n++) {
119
irq_id = 0;
120
@@ -XXX,XX +XXX,XX @@ void exynos4210_init_board_irqs(Exynos4210Irq *s)
121
irq_id = EXT_GIC_ID_MCT_G1;
122
}
123
if (irq_id) {
124
- s->board_irqs[n] = qemu_irq_split(s->int_combiner_irq[n],
125
- s->ext_gic_irq[irq_id-32]);
126
+ s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
127
+ is->ext_gic_irq[irq_id - 32]);
128
} else {
129
- s->board_irqs[n] = qemu_irq_split(s->int_combiner_irq[n],
130
- s->ext_combiner_irq[n]);
131
+ s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
132
+ is->ext_combiner_irq[n]);
133
}
134
}
135
for (; n < EXYNOS4210_MAX_INT_COMBINER_IN_IRQ; n++) {
136
@@ -XXX,XX +XXX,XX @@ void exynos4210_init_board_irqs(Exynos4210Irq *s)
137
EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][bit];
138
139
if (irq_id) {
140
- s->board_irqs[n] = qemu_irq_split(s->int_combiner_irq[n],
141
- s->ext_gic_irq[irq_id-32]);
142
+ s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
143
+ is->ext_gic_irq[irq_id - 32]);
144
}
145
}
146
}
34
--
147
--
35
2.20.1
148
2.25.1
36
37
diff view generated by jsdifflib
1
Optimize the MVE VMVN insn by using TCG vector ops when possible.
1
Fix a missing set of spaces around '-' in the definition of
2
combiner_grp_to_gic_id[]. We're about to move this code, so
3
fix the style issue first to keep checkpatch happy with the
4
code-motion patch.
2
5
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20210913095440.13462-9-peter.maydell@linaro.org
8
Message-id: 20220404154658.565020-7-peter.maydell@linaro.org
6
---
9
---
7
target/arm/translate-mve.c | 2 +-
10
hw/intc/exynos4210_gic.c | 2 +-
8
1 file changed, 1 insertion(+), 1 deletion(-)
11
1 file changed, 1 insertion(+), 1 deletion(-)
9
12
10
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
13
diff --git a/hw/intc/exynos4210_gic.c b/hw/intc/exynos4210_gic.c
11
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
12
--- a/target/arm/translate-mve.c
15
--- a/hw/intc/exynos4210_gic.c
13
+++ b/target/arm/translate-mve.c
16
+++ b/hw/intc/exynos4210_gic.c
14
@@ -XXX,XX +XXX,XX @@ static bool trans_VREV64(DisasContext *s, arg_1op *a)
17
@@ -XXX,XX +XXX,XX @@ enum ExtInt {
15
18
*/
16
static bool trans_VMVN(DisasContext *s, arg_1op *a)
19
17
{
20
static const uint32_t
18
- return do_1op(s, a, gen_helper_mve_vmvn);
21
-combiner_grp_to_gic_id[64-EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][8] = {
19
+ return do_1op_vec(s, a, gen_helper_mve_vmvn, tcg_gen_gvec_not);
22
+combiner_grp_to_gic_id[64 - EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][8] = {
20
}
23
/* int combiner groups 16-19 */
21
24
{ }, { }, { }, { },
22
static bool trans_VABS_fp(DisasContext *s, arg_1op *a)
25
/* int combiner group 20 */
23
--
26
--
24
2.20.1
27
2.25.1
25
26
diff view generated by jsdifflib
1
Optimize the MVE VSHLL insns by using TCG vector ops when possible.
1
The function exynos4210_init_board_irqs() currently lives in
2
This includes the VMOVL insn, which we handle in mve.decode as "VSHLL
2
exynos4210_gic.c, but it isn't really part of the exynos4210.gic
3
with zero shift count".
3
device -- it is a function that implements (some of) the wiring up of
4
interrupts between the SoC's GIC and combiner components. This means
5
it fits better in exynos4210.c, which is the SoC-level code. Move it
6
there. Similarly, exynos4210_git_irq() is used almost only in the
7
SoC-level code, so move it too.
4
8
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20210913095440.13462-11-peter.maydell@linaro.org
11
Message-id: 20220404154658.565020-8-peter.maydell@linaro.org
8
---
12
---
9
target/arm/translate-mve.c | 67 +++++++++++++++++++++++++++++++++-----
13
include/hw/arm/exynos4210.h | 4 -
10
1 file changed, 59 insertions(+), 8 deletions(-)
14
hw/arm/exynos4210.c | 202 +++++++++++++++++++++++++++++++++++
15
hw/intc/exynos4210_gic.c | 204 ------------------------------------
16
3 files changed, 202 insertions(+), 208 deletions(-)
11
17
12
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
18
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
13
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/translate-mve.c
20
--- a/include/hw/arm/exynos4210.h
15
+++ b/target/arm/translate-mve.c
21
+++ b/include/hw/arm/exynos4210.h
16
@@ -XXX,XX +XXX,XX @@ DO_2SHIFT_SCALAR(VQSHL_U_scalar, vqshli_u)
22
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_SIMPLE_TYPE(Exynos4210State, EXYNOS4210_SOC)
17
DO_2SHIFT_SCALAR(VQRSHL_S_scalar, vqrshli_s)
23
void exynos4210_write_secondary(ARMCPU *cpu,
18
DO_2SHIFT_SCALAR(VQRSHL_U_scalar, vqrshli_u)
24
const struct arm_boot_info *info);
19
25
20
-#define DO_VSHLL(INSN, FN) \
26
-/* Initialize board IRQs.
21
- static bool trans_##INSN(DisasContext *s, arg_2shift *a) \
27
- * These IRQs contain splitted Int/External Combiner and External Gic IRQs */
22
- { \
28
-void exynos4210_init_board_irqs(Exynos4210State *s);
23
- static MVEGenTwoOpShiftFn * const fns[] = { \
29
-
24
- gen_helper_mve_##FN##b, \
30
/* Get IRQ number from exynos4210 IRQ subsystem stub.
25
- gen_helper_mve_##FN##h, \
31
* To identify IRQ source use internal combiner group and bit number
26
- }; \
32
* grp - group number
27
- return do_2shift(s, a, fns[a->size], false); \
33
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
28
+#define DO_VSHLL(INSN, FN) \
34
index XXXXXXX..XXXXXXX 100644
29
+ static bool trans_##INSN(DisasContext *s, arg_2shift *a) \
35
--- a/hw/arm/exynos4210.c
30
+ { \
36
+++ b/hw/arm/exynos4210.c
31
+ static MVEGenTwoOpShiftFn * const fns[] = { \
37
@@ -XXX,XX +XXX,XX @@
32
+ gen_helper_mve_##FN##b, \
38
#define EXYNOS4210_PL330_BASE1_ADDR 0x12690000
33
+ gen_helper_mve_##FN##h, \
39
#define EXYNOS4210_PL330_BASE2_ADDR 0x12850000
34
+ }; \
40
35
+ return do_2shift_vec(s, a, fns[a->size], false, do_gvec_##FN); \
41
+enum ExtGicId {
36
}
42
+ EXT_GIC_ID_MDMA_LCD0 = 66,
37
43
+ EXT_GIC_ID_PDMA0,
44
+ EXT_GIC_ID_PDMA1,
45
+ EXT_GIC_ID_TIMER0,
46
+ EXT_GIC_ID_TIMER1,
47
+ EXT_GIC_ID_TIMER2,
48
+ EXT_GIC_ID_TIMER3,
49
+ EXT_GIC_ID_TIMER4,
50
+ EXT_GIC_ID_MCT_L0,
51
+ EXT_GIC_ID_WDT,
52
+ EXT_GIC_ID_RTC_ALARM,
53
+ EXT_GIC_ID_RTC_TIC,
54
+ EXT_GIC_ID_GPIO_XB,
55
+ EXT_GIC_ID_GPIO_XA,
56
+ EXT_GIC_ID_MCT_L1,
57
+ EXT_GIC_ID_IEM_APC,
58
+ EXT_GIC_ID_IEM_IEC,
59
+ EXT_GIC_ID_NFC,
60
+ EXT_GIC_ID_UART0,
61
+ EXT_GIC_ID_UART1,
62
+ EXT_GIC_ID_UART2,
63
+ EXT_GIC_ID_UART3,
64
+ EXT_GIC_ID_UART4,
65
+ EXT_GIC_ID_MCT_G0,
66
+ EXT_GIC_ID_I2C0,
67
+ EXT_GIC_ID_I2C1,
68
+ EXT_GIC_ID_I2C2,
69
+ EXT_GIC_ID_I2C3,
70
+ EXT_GIC_ID_I2C4,
71
+ EXT_GIC_ID_I2C5,
72
+ EXT_GIC_ID_I2C6,
73
+ EXT_GIC_ID_I2C7,
74
+ EXT_GIC_ID_SPI0,
75
+ EXT_GIC_ID_SPI1,
76
+ EXT_GIC_ID_SPI2,
77
+ EXT_GIC_ID_MCT_G1,
78
+ EXT_GIC_ID_USB_HOST,
79
+ EXT_GIC_ID_USB_DEVICE,
80
+ EXT_GIC_ID_MODEMIF,
81
+ EXT_GIC_ID_HSMMC0,
82
+ EXT_GIC_ID_HSMMC1,
83
+ EXT_GIC_ID_HSMMC2,
84
+ EXT_GIC_ID_HSMMC3,
85
+ EXT_GIC_ID_SDMMC,
86
+ EXT_GIC_ID_MIPI_CSI_4LANE,
87
+ EXT_GIC_ID_MIPI_DSI_4LANE,
88
+ EXT_GIC_ID_MIPI_CSI_2LANE,
89
+ EXT_GIC_ID_MIPI_DSI_2LANE,
90
+ EXT_GIC_ID_ONENAND_AUDI,
91
+ EXT_GIC_ID_ROTATOR,
92
+ EXT_GIC_ID_FIMC0,
93
+ EXT_GIC_ID_FIMC1,
94
+ EXT_GIC_ID_FIMC2,
95
+ EXT_GIC_ID_FIMC3,
96
+ EXT_GIC_ID_JPEG,
97
+ EXT_GIC_ID_2D,
98
+ EXT_GIC_ID_PCIe,
99
+ EXT_GIC_ID_MIXER,
100
+ EXT_GIC_ID_HDMI,
101
+ EXT_GIC_ID_HDMI_I2C,
102
+ EXT_GIC_ID_MFC,
103
+ EXT_GIC_ID_TVENC,
104
+};
105
+
106
+enum ExtInt {
107
+ EXT_GIC_ID_EXTINT0 = 48,
108
+ EXT_GIC_ID_EXTINT1,
109
+ EXT_GIC_ID_EXTINT2,
110
+ EXT_GIC_ID_EXTINT3,
111
+ EXT_GIC_ID_EXTINT4,
112
+ EXT_GIC_ID_EXTINT5,
113
+ EXT_GIC_ID_EXTINT6,
114
+ EXT_GIC_ID_EXTINT7,
115
+ EXT_GIC_ID_EXTINT8,
116
+ EXT_GIC_ID_EXTINT9,
117
+ EXT_GIC_ID_EXTINT10,
118
+ EXT_GIC_ID_EXTINT11,
119
+ EXT_GIC_ID_EXTINT12,
120
+ EXT_GIC_ID_EXTINT13,
121
+ EXT_GIC_ID_EXTINT14,
122
+ EXT_GIC_ID_EXTINT15
123
+};
124
+
38
+/*
125
+/*
39
+ * For the VSHLL vector helpers, the vece is the size of the input
126
+ * External GIC sources which are not from External Interrupt Combiner or
40
+ * (ie MO_8 or MO_16); the helpers want to work in the output size.
127
+ * External Interrupts are starting from EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ,
41
+ * The shift count can be 0..<input size>, inclusive. (0 is VMOVL.)
128
+ * which is INTG16 in Internal Interrupt Combiner.
42
+ */
129
+ */
43
+static void do_gvec_vshllbs(unsigned vece, uint32_t dofs, uint32_t aofs,
130
+
44
+ int64_t shift, uint32_t oprsz, uint32_t maxsz)
131
+static const uint32_t
132
+combiner_grp_to_gic_id[64 - EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][8] = {
133
+ /* int combiner groups 16-19 */
134
+ { }, { }, { }, { },
135
+ /* int combiner group 20 */
136
+ { 0, EXT_GIC_ID_MDMA_LCD0 },
137
+ /* int combiner group 21 */
138
+ { EXT_GIC_ID_PDMA0, EXT_GIC_ID_PDMA1 },
139
+ /* int combiner group 22 */
140
+ { EXT_GIC_ID_TIMER0, EXT_GIC_ID_TIMER1, EXT_GIC_ID_TIMER2,
141
+ EXT_GIC_ID_TIMER3, EXT_GIC_ID_TIMER4 },
142
+ /* int combiner group 23 */
143
+ { EXT_GIC_ID_RTC_ALARM, EXT_GIC_ID_RTC_TIC },
144
+ /* int combiner group 24 */
145
+ { EXT_GIC_ID_GPIO_XB, EXT_GIC_ID_GPIO_XA },
146
+ /* int combiner group 25 */
147
+ { EXT_GIC_ID_IEM_APC, EXT_GIC_ID_IEM_IEC },
148
+ /* int combiner group 26 */
149
+ { EXT_GIC_ID_UART0, EXT_GIC_ID_UART1, EXT_GIC_ID_UART2, EXT_GIC_ID_UART3,
150
+ EXT_GIC_ID_UART4 },
151
+ /* int combiner group 27 */
152
+ { EXT_GIC_ID_I2C0, EXT_GIC_ID_I2C1, EXT_GIC_ID_I2C2, EXT_GIC_ID_I2C3,
153
+ EXT_GIC_ID_I2C4, EXT_GIC_ID_I2C5, EXT_GIC_ID_I2C6,
154
+ EXT_GIC_ID_I2C7 },
155
+ /* int combiner group 28 */
156
+ { EXT_GIC_ID_SPI0, EXT_GIC_ID_SPI1, EXT_GIC_ID_SPI2 , EXT_GIC_ID_USB_HOST},
157
+ /* int combiner group 29 */
158
+ { EXT_GIC_ID_HSMMC0, EXT_GIC_ID_HSMMC1, EXT_GIC_ID_HSMMC2,
159
+ EXT_GIC_ID_HSMMC3, EXT_GIC_ID_SDMMC },
160
+ /* int combiner group 30 */
161
+ { EXT_GIC_ID_MIPI_CSI_4LANE, EXT_GIC_ID_MIPI_CSI_2LANE },
162
+ /* int combiner group 31 */
163
+ { EXT_GIC_ID_MIPI_DSI_4LANE, EXT_GIC_ID_MIPI_DSI_2LANE },
164
+ /* int combiner group 32 */
165
+ { EXT_GIC_ID_FIMC0, EXT_GIC_ID_FIMC1 },
166
+ /* int combiner group 33 */
167
+ { EXT_GIC_ID_FIMC2, EXT_GIC_ID_FIMC3 },
168
+ /* int combiner group 34 */
169
+ { EXT_GIC_ID_ONENAND_AUDI, EXT_GIC_ID_NFC },
170
+ /* int combiner group 35 */
171
+ { 0, 0, 0, EXT_GIC_ID_MCT_L1, EXT_GIC_ID_MCT_G0, EXT_GIC_ID_MCT_G1 },
172
+ /* int combiner group 36 */
173
+ { EXT_GIC_ID_MIXER },
174
+ /* int combiner group 37 */
175
+ { EXT_GIC_ID_EXTINT4, EXT_GIC_ID_EXTINT5, EXT_GIC_ID_EXTINT6,
176
+ EXT_GIC_ID_EXTINT7 },
177
+ /* groups 38-50 */
178
+ { }, { }, { }, { }, { }, { }, { }, { }, { }, { }, { }, { }, { },
179
+ /* int combiner group 51 */
180
+ { EXT_GIC_ID_MCT_L0, 0, 0, 0, EXT_GIC_ID_MCT_G0, EXT_GIC_ID_MCT_G1 },
181
+ /* group 52 */
182
+ { },
183
+ /* int combiner group 53 */
184
+ { EXT_GIC_ID_WDT, 0, 0, 0, EXT_GIC_ID_MCT_G0, EXT_GIC_ID_MCT_G1 },
185
+ /* groups 54-63 */
186
+ { }, { }, { }, { }, { }, { }, { }, { }, { }, { }
187
+};
188
+
189
+/*
190
+ * Initialize board IRQs.
191
+ * These IRQs contain splitted Int/External Combiner and External Gic IRQs.
192
+ */
193
+static void exynos4210_init_board_irqs(Exynos4210State *s)
45
+{
194
+{
46
+ unsigned ovece = vece + 1;
195
+ uint32_t grp, bit, irq_id, n;
47
+ unsigned ibits = vece == MO_8 ? 8 : 16;
196
+ Exynos4210Irq *is = &s->irqs;
48
+ tcg_gen_gvec_shli(ovece, dofs, aofs, ibits, oprsz, maxsz);
197
+
49
+ tcg_gen_gvec_sari(ovece, dofs, dofs, ibits - shift, oprsz, maxsz);
198
+ for (n = 0; n < EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ; n++) {
50
+}
199
+ irq_id = 0;
51
+
200
+ if (n == EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 4) ||
52
+static void do_gvec_vshllbu(unsigned vece, uint32_t dofs, uint32_t aofs,
201
+ n == EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 4)) {
53
+ int64_t shift, uint32_t oprsz, uint32_t maxsz)
202
+ /* MCT_G0 is passed to External GIC */
54
+{
203
+ irq_id = EXT_GIC_ID_MCT_G0;
55
+ unsigned ovece = vece + 1;
204
+ }
56
+ tcg_gen_gvec_andi(ovece, dofs, aofs,
205
+ if (n == EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 5) ||
57
+ ovece == MO_16 ? 0xff : 0xffff, oprsz, maxsz);
206
+ n == EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 5)) {
58
+ tcg_gen_gvec_shli(ovece, dofs, dofs, shift, oprsz, maxsz);
207
+ /* MCT_G1 is passed to External and GIC */
59
+}
208
+ irq_id = EXT_GIC_ID_MCT_G1;
60
+
209
+ }
61
+static void do_gvec_vshllts(unsigned vece, uint32_t dofs, uint32_t aofs,
210
+ if (irq_id) {
62
+ int64_t shift, uint32_t oprsz, uint32_t maxsz)
211
+ s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
63
+{
212
+ is->ext_gic_irq[irq_id - 32]);
64
+ unsigned ovece = vece + 1;
213
+ } else {
65
+ unsigned ibits = vece == MO_8 ? 8 : 16;
214
+ s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
66
+ if (shift == 0) {
215
+ is->ext_combiner_irq[n]);
67
+ tcg_gen_gvec_sari(ovece, dofs, aofs, ibits, oprsz, maxsz);
216
+ }
68
+ } else {
217
+ }
69
+ tcg_gen_gvec_andi(ovece, dofs, aofs,
218
+ for (; n < EXYNOS4210_MAX_INT_COMBINER_IN_IRQ; n++) {
70
+ ovece == MO_16 ? 0xff00 : 0xffff0000, oprsz, maxsz);
219
+ /* these IDs are passed to Internal Combiner and External GIC */
71
+ tcg_gen_gvec_sari(ovece, dofs, dofs, ibits - shift, oprsz, maxsz);
220
+ grp = EXYNOS4210_COMBINER_GET_GRP_NUM(n);
221
+ bit = EXYNOS4210_COMBINER_GET_BIT_NUM(n);
222
+ irq_id = combiner_grp_to_gic_id[grp -
223
+ EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][bit];
224
+
225
+ if (irq_id) {
226
+ s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
227
+ is->ext_gic_irq[irq_id - 32]);
228
+ }
72
+ }
229
+ }
73
+}
230
+}
74
+
231
+
75
+static void do_gvec_vshlltu(unsigned vece, uint32_t dofs, uint32_t aofs,
232
+/*
76
+ int64_t shift, uint32_t oprsz, uint32_t maxsz)
233
+ * Get IRQ number from exynos4210 IRQ subsystem stub.
234
+ * To identify IRQ source use internal combiner group and bit number
235
+ * grp - group number
236
+ * bit - bit number inside group
237
+ */
238
+uint32_t exynos4210_get_irq(uint32_t grp, uint32_t bit)
77
+{
239
+{
78
+ unsigned ovece = vece + 1;
240
+ return EXYNOS4210_COMBINER_GET_IRQ_NUM(grp, bit);
79
+ unsigned ibits = vece == MO_8 ? 8 : 16;
80
+ if (shift == 0) {
81
+ tcg_gen_gvec_shri(ovece, dofs, aofs, ibits, oprsz, maxsz);
82
+ } else {
83
+ tcg_gen_gvec_andi(ovece, dofs, aofs,
84
+ ovece == MO_16 ? 0xff00 : 0xffff0000, oprsz, maxsz);
85
+ tcg_gen_gvec_shri(ovece, dofs, dofs, ibits - shift, oprsz, maxsz);
86
+ }
87
+}
241
+}
88
+
242
+
89
DO_VSHLL(VSHLL_BS, vshllbs)
243
static uint8_t chipid_and_omr[] = { 0x11, 0x02, 0x21, 0x43,
90
DO_VSHLL(VSHLL_BU, vshllbu)
244
0x09, 0x00, 0x00, 0x00 };
91
DO_VSHLL(VSHLL_TS, vshllts)
245
246
diff --git a/hw/intc/exynos4210_gic.c b/hw/intc/exynos4210_gic.c
247
index XXXXXXX..XXXXXXX 100644
248
--- a/hw/intc/exynos4210_gic.c
249
+++ b/hw/intc/exynos4210_gic.c
250
@@ -XXX,XX +XXX,XX @@
251
#include "hw/arm/exynos4210.h"
252
#include "qom/object.h"
253
254
-enum ExtGicId {
255
- EXT_GIC_ID_MDMA_LCD0 = 66,
256
- EXT_GIC_ID_PDMA0,
257
- EXT_GIC_ID_PDMA1,
258
- EXT_GIC_ID_TIMER0,
259
- EXT_GIC_ID_TIMER1,
260
- EXT_GIC_ID_TIMER2,
261
- EXT_GIC_ID_TIMER3,
262
- EXT_GIC_ID_TIMER4,
263
- EXT_GIC_ID_MCT_L0,
264
- EXT_GIC_ID_WDT,
265
- EXT_GIC_ID_RTC_ALARM,
266
- EXT_GIC_ID_RTC_TIC,
267
- EXT_GIC_ID_GPIO_XB,
268
- EXT_GIC_ID_GPIO_XA,
269
- EXT_GIC_ID_MCT_L1,
270
- EXT_GIC_ID_IEM_APC,
271
- EXT_GIC_ID_IEM_IEC,
272
- EXT_GIC_ID_NFC,
273
- EXT_GIC_ID_UART0,
274
- EXT_GIC_ID_UART1,
275
- EXT_GIC_ID_UART2,
276
- EXT_GIC_ID_UART3,
277
- EXT_GIC_ID_UART4,
278
- EXT_GIC_ID_MCT_G0,
279
- EXT_GIC_ID_I2C0,
280
- EXT_GIC_ID_I2C1,
281
- EXT_GIC_ID_I2C2,
282
- EXT_GIC_ID_I2C3,
283
- EXT_GIC_ID_I2C4,
284
- EXT_GIC_ID_I2C5,
285
- EXT_GIC_ID_I2C6,
286
- EXT_GIC_ID_I2C7,
287
- EXT_GIC_ID_SPI0,
288
- EXT_GIC_ID_SPI1,
289
- EXT_GIC_ID_SPI2,
290
- EXT_GIC_ID_MCT_G1,
291
- EXT_GIC_ID_USB_HOST,
292
- EXT_GIC_ID_USB_DEVICE,
293
- EXT_GIC_ID_MODEMIF,
294
- EXT_GIC_ID_HSMMC0,
295
- EXT_GIC_ID_HSMMC1,
296
- EXT_GIC_ID_HSMMC2,
297
- EXT_GIC_ID_HSMMC3,
298
- EXT_GIC_ID_SDMMC,
299
- EXT_GIC_ID_MIPI_CSI_4LANE,
300
- EXT_GIC_ID_MIPI_DSI_4LANE,
301
- EXT_GIC_ID_MIPI_CSI_2LANE,
302
- EXT_GIC_ID_MIPI_DSI_2LANE,
303
- EXT_GIC_ID_ONENAND_AUDI,
304
- EXT_GIC_ID_ROTATOR,
305
- EXT_GIC_ID_FIMC0,
306
- EXT_GIC_ID_FIMC1,
307
- EXT_GIC_ID_FIMC2,
308
- EXT_GIC_ID_FIMC3,
309
- EXT_GIC_ID_JPEG,
310
- EXT_GIC_ID_2D,
311
- EXT_GIC_ID_PCIe,
312
- EXT_GIC_ID_MIXER,
313
- EXT_GIC_ID_HDMI,
314
- EXT_GIC_ID_HDMI_I2C,
315
- EXT_GIC_ID_MFC,
316
- EXT_GIC_ID_TVENC,
317
-};
318
-
319
-enum ExtInt {
320
- EXT_GIC_ID_EXTINT0 = 48,
321
- EXT_GIC_ID_EXTINT1,
322
- EXT_GIC_ID_EXTINT2,
323
- EXT_GIC_ID_EXTINT3,
324
- EXT_GIC_ID_EXTINT4,
325
- EXT_GIC_ID_EXTINT5,
326
- EXT_GIC_ID_EXTINT6,
327
- EXT_GIC_ID_EXTINT7,
328
- EXT_GIC_ID_EXTINT8,
329
- EXT_GIC_ID_EXTINT9,
330
- EXT_GIC_ID_EXTINT10,
331
- EXT_GIC_ID_EXTINT11,
332
- EXT_GIC_ID_EXTINT12,
333
- EXT_GIC_ID_EXTINT13,
334
- EXT_GIC_ID_EXTINT14,
335
- EXT_GIC_ID_EXTINT15
336
-};
337
-
338
-/*
339
- * External GIC sources which are not from External Interrupt Combiner or
340
- * External Interrupts are starting from EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ,
341
- * which is INTG16 in Internal Interrupt Combiner.
342
- */
343
-
344
-static const uint32_t
345
-combiner_grp_to_gic_id[64 - EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][8] = {
346
- /* int combiner groups 16-19 */
347
- { }, { }, { }, { },
348
- /* int combiner group 20 */
349
- { 0, EXT_GIC_ID_MDMA_LCD0 },
350
- /* int combiner group 21 */
351
- { EXT_GIC_ID_PDMA0, EXT_GIC_ID_PDMA1 },
352
- /* int combiner group 22 */
353
- { EXT_GIC_ID_TIMER0, EXT_GIC_ID_TIMER1, EXT_GIC_ID_TIMER2,
354
- EXT_GIC_ID_TIMER3, EXT_GIC_ID_TIMER4 },
355
- /* int combiner group 23 */
356
- { EXT_GIC_ID_RTC_ALARM, EXT_GIC_ID_RTC_TIC },
357
- /* int combiner group 24 */
358
- { EXT_GIC_ID_GPIO_XB, EXT_GIC_ID_GPIO_XA },
359
- /* int combiner group 25 */
360
- { EXT_GIC_ID_IEM_APC, EXT_GIC_ID_IEM_IEC },
361
- /* int combiner group 26 */
362
- { EXT_GIC_ID_UART0, EXT_GIC_ID_UART1, EXT_GIC_ID_UART2, EXT_GIC_ID_UART3,
363
- EXT_GIC_ID_UART4 },
364
- /* int combiner group 27 */
365
- { EXT_GIC_ID_I2C0, EXT_GIC_ID_I2C1, EXT_GIC_ID_I2C2, EXT_GIC_ID_I2C3,
366
- EXT_GIC_ID_I2C4, EXT_GIC_ID_I2C5, EXT_GIC_ID_I2C6,
367
- EXT_GIC_ID_I2C7 },
368
- /* int combiner group 28 */
369
- { EXT_GIC_ID_SPI0, EXT_GIC_ID_SPI1, EXT_GIC_ID_SPI2 , EXT_GIC_ID_USB_HOST},
370
- /* int combiner group 29 */
371
- { EXT_GIC_ID_HSMMC0, EXT_GIC_ID_HSMMC1, EXT_GIC_ID_HSMMC2,
372
- EXT_GIC_ID_HSMMC3, EXT_GIC_ID_SDMMC },
373
- /* int combiner group 30 */
374
- { EXT_GIC_ID_MIPI_CSI_4LANE, EXT_GIC_ID_MIPI_CSI_2LANE },
375
- /* int combiner group 31 */
376
- { EXT_GIC_ID_MIPI_DSI_4LANE, EXT_GIC_ID_MIPI_DSI_2LANE },
377
- /* int combiner group 32 */
378
- { EXT_GIC_ID_FIMC0, EXT_GIC_ID_FIMC1 },
379
- /* int combiner group 33 */
380
- { EXT_GIC_ID_FIMC2, EXT_GIC_ID_FIMC3 },
381
- /* int combiner group 34 */
382
- { EXT_GIC_ID_ONENAND_AUDI, EXT_GIC_ID_NFC },
383
- /* int combiner group 35 */
384
- { 0, 0, 0, EXT_GIC_ID_MCT_L1, EXT_GIC_ID_MCT_G0, EXT_GIC_ID_MCT_G1 },
385
- /* int combiner group 36 */
386
- { EXT_GIC_ID_MIXER },
387
- /* int combiner group 37 */
388
- { EXT_GIC_ID_EXTINT4, EXT_GIC_ID_EXTINT5, EXT_GIC_ID_EXTINT6,
389
- EXT_GIC_ID_EXTINT7 },
390
- /* groups 38-50 */
391
- { }, { }, { }, { }, { }, { }, { }, { }, { }, { }, { }, { }, { },
392
- /* int combiner group 51 */
393
- { EXT_GIC_ID_MCT_L0, 0, 0, 0, EXT_GIC_ID_MCT_G0, EXT_GIC_ID_MCT_G1 },
394
- /* group 52 */
395
- { },
396
- /* int combiner group 53 */
397
- { EXT_GIC_ID_WDT, 0, 0, 0, EXT_GIC_ID_MCT_G0, EXT_GIC_ID_MCT_G1 },
398
- /* groups 54-63 */
399
- { }, { }, { }, { }, { }, { }, { }, { }, { }, { }
400
-};
401
-
402
#define EXYNOS4210_GIC_NIRQ 160
403
404
#define EXYNOS4210_EXT_GIC_CPU_REGION_SIZE 0x10000
405
@@ -XXX,XX +XXX,XX @@ combiner_grp_to_gic_id[64 - EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][8] = {
406
#define EXYNOS4210_GIC_CPU_REGION_SIZE 0x100
407
#define EXYNOS4210_GIC_DIST_REGION_SIZE 0x1000
408
409
-/*
410
- * Initialize board IRQs.
411
- * These IRQs contain splitted Int/External Combiner and External Gic IRQs.
412
- */
413
-void exynos4210_init_board_irqs(Exynos4210State *s)
414
-{
415
- uint32_t grp, bit, irq_id, n;
416
- Exynos4210Irq *is = &s->irqs;
417
-
418
- for (n = 0; n < EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ; n++) {
419
- irq_id = 0;
420
- if (n == EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 4) ||
421
- n == EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 4)) {
422
- /* MCT_G0 is passed to External GIC */
423
- irq_id = EXT_GIC_ID_MCT_G0;
424
- }
425
- if (n == EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 5) ||
426
- n == EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 5)) {
427
- /* MCT_G1 is passed to External and GIC */
428
- irq_id = EXT_GIC_ID_MCT_G1;
429
- }
430
- if (irq_id) {
431
- s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
432
- is->ext_gic_irq[irq_id - 32]);
433
- } else {
434
- s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
435
- is->ext_combiner_irq[n]);
436
- }
437
- }
438
- for (; n < EXYNOS4210_MAX_INT_COMBINER_IN_IRQ; n++) {
439
- /* these IDs are passed to Internal Combiner and External GIC */
440
- grp = EXYNOS4210_COMBINER_GET_GRP_NUM(n);
441
- bit = EXYNOS4210_COMBINER_GET_BIT_NUM(n);
442
- irq_id = combiner_grp_to_gic_id[grp -
443
- EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][bit];
444
-
445
- if (irq_id) {
446
- s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
447
- is->ext_gic_irq[irq_id - 32]);
448
- }
449
- }
450
-}
451
-
452
-/*
453
- * Get IRQ number from exynos4210 IRQ subsystem stub.
454
- * To identify IRQ source use internal combiner group and bit number
455
- * grp - group number
456
- * bit - bit number inside group
457
- */
458
-uint32_t exynos4210_get_irq(uint32_t grp, uint32_t bit)
459
-{
460
- return EXYNOS4210_COMBINER_GET_IRQ_NUM(grp, bit);
461
-}
462
-
463
-/********* GIC part *********/
464
-
465
#define TYPE_EXYNOS4210_GIC "exynos4210.gic"
466
OBJECT_DECLARE_SIMPLE_TYPE(Exynos4210GicState, EXYNOS4210_GIC)
467
92
--
468
--
93
2.20.1
469
2.25.1
94
95
diff view generated by jsdifflib
1
Move an ifndef CONFIG_USER_ONLY code block up in arm_cpu_reset() so
1
Switch the creation of the external GIC to the new-style "embedded in
2
it can be merged with another earlier one.
2
state struct" approach, so we can easily refer to the object
3
elsewhere during realize.
3
4
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20210914120725.24992-4-peter.maydell@linaro.org
7
Message-id: 20220404154658.565020-9-peter.maydell@linaro.org
7
---
8
---
8
target/arm/cpu.c | 22 ++++++++++------------
9
include/hw/arm/exynos4210.h | 2 ++
9
1 file changed, 10 insertions(+), 12 deletions(-)
10
include/hw/intc/exynos4210_gic.h | 43 ++++++++++++++++++++++++++++++++
11
hw/arm/exynos4210.c | 10 ++++----
12
hw/intc/exynos4210_gic.c | 17 ++-----------
13
MAINTAINERS | 2 +-
14
5 files changed, 53 insertions(+), 21 deletions(-)
15
create mode 100644 include/hw/intc/exynos4210_gic.h
10
16
11
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
17
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
12
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
13
--- a/target/arm/cpu.c
19
--- a/include/hw/arm/exynos4210.h
14
+++ b/target/arm/cpu.c
20
+++ b/include/hw/arm/exynos4210.h
15
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_reset(DeviceState *dev)
21
@@ -XXX,XX +XXX,XX @@
16
env->uncached_cpsr = ARM_CPU_MODE_SVC;
22
#include "hw/or-irq.h"
23
#include "hw/sysbus.h"
24
#include "hw/cpu/a9mpcore.h"
25
+#include "hw/intc/exynos4210_gic.h"
26
#include "target/arm/cpu-qom.h"
27
#include "qom/object.h"
28
29
@@ -XXX,XX +XXX,XX @@ struct Exynos4210State {
30
qemu_or_irq pl330_irq_orgate[EXYNOS4210_NUM_DMA];
31
qemu_or_irq cpu_irq_orgate[EXYNOS4210_NCPUS];
32
A9MPPrivState a9mpcore;
33
+ Exynos4210GicState ext_gic;
34
};
35
36
#define TYPE_EXYNOS4210_SOC "exynos4210"
37
diff --git a/include/hw/intc/exynos4210_gic.h b/include/hw/intc/exynos4210_gic.h
38
new file mode 100644
39
index XXXXXXX..XXXXXXX
40
--- /dev/null
41
+++ b/include/hw/intc/exynos4210_gic.h
42
@@ -XXX,XX +XXX,XX @@
43
+/*
44
+ * Samsung exynos4210 GIC implementation. Based on hw/arm_gic.c
45
+ *
46
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd.
47
+ * All rights reserved.
48
+ *
49
+ * Evgeny Voevodin <e.voevodin@samsung.com>
50
+ *
51
+ * This program is free software; you can redistribute it and/or modify it
52
+ * under the terms of the GNU General Public License as published by the
53
+ * Free Software Foundation; either version 2 of the License, or (at your
54
+ * option) any later version.
55
+ *
56
+ * This program is distributed in the hope that it will be useful,
57
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
58
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
59
+ * See the GNU General Public License for more details.
60
+ *
61
+ * You should have received a copy of the GNU General Public License along
62
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
63
+ */
64
+#ifndef HW_INTC_EXYNOS4210_GIC_H
65
+#define HW_INTC_EXYNOS4210_GIC_H
66
+
67
+#include "hw/sysbus.h"
68
+
69
+#define TYPE_EXYNOS4210_GIC "exynos4210.gic"
70
+OBJECT_DECLARE_SIMPLE_TYPE(Exynos4210GicState, EXYNOS4210_GIC)
71
+
72
+#define EXYNOS4210_GIC_NCPUS 2
73
+
74
+struct Exynos4210GicState {
75
+ SysBusDevice parent_obj;
76
+
77
+ MemoryRegion cpu_container;
78
+ MemoryRegion dist_container;
79
+ MemoryRegion cpu_alias[EXYNOS4210_GIC_NCPUS];
80
+ MemoryRegion dist_alias[EXYNOS4210_GIC_NCPUS];
81
+ uint32_t num_cpu;
82
+ DeviceState *gic;
83
+};
84
+
85
+#endif
86
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
87
index XXXXXXX..XXXXXXX 100644
88
--- a/hw/arm/exynos4210.c
89
+++ b/hw/arm/exynos4210.c
90
@@ -XXX,XX +XXX,XX @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
91
sysbus_create_simple("l2x0", EXYNOS4210_L2X0_BASE_ADDR, NULL);
92
93
/* External GIC */
94
- dev = qdev_new("exynos4210.gic");
95
- qdev_prop_set_uint32(dev, "num-cpu", EXYNOS4210_NCPUS);
96
- busdev = SYS_BUS_DEVICE(dev);
97
- sysbus_realize_and_unref(busdev, &error_fatal);
98
+ qdev_prop_set_uint32(DEVICE(&s->ext_gic), "num-cpu", EXYNOS4210_NCPUS);
99
+ busdev = SYS_BUS_DEVICE(&s->ext_gic);
100
+ sysbus_realize(busdev, &error_fatal);
101
/* Map CPU interface */
102
sysbus_mmio_map(busdev, 0, EXYNOS4210_EXT_GIC_CPU_BASE_ADDR);
103
/* Map Distributer interface */
104
@@ -XXX,XX +XXX,XX @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
105
qdev_get_gpio_in(DEVICE(&s->cpu_irq_orgate[n]), 1));
17
}
106
}
18
env->daif = PSTATE_D | PSTATE_A | PSTATE_I | PSTATE_F;
107
for (n = 0; n < EXYNOS4210_EXT_GIC_NIRQ; n++) {
19
+
108
- s->irqs.ext_gic_irq[n] = qdev_get_gpio_in(dev, n);
20
+ /* AArch32 has a hard highvec setting of 0xFFFF0000. If we are currently
109
+ s->irqs.ext_gic_irq[n] = qdev_get_gpio_in(DEVICE(&s->ext_gic), n);
21
+ * executing as AArch32 then check if highvecs are enabled and
22
+ * adjust the PC accordingly.
23
+ */
24
+ if (A32_BANKED_CURRENT_REG_GET(env, sctlr) & SCTLR_V) {
25
+ env->regs[15] = 0xFFFF0000;
26
+ }
27
+
28
+ env->vfp.xregs[ARM_VFP_FPEXC] = 0;
29
#endif
30
31
if (arm_feature(env, ARM_FEATURE_M)) {
32
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_reset(DeviceState *dev)
33
#endif
34
}
110
}
35
111
36
-#ifndef CONFIG_USER_ONLY
112
/* Internal Interrupt Combiner */
37
- /* AArch32 has a hard highvec setting of 0xFFFF0000. If we are currently
113
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init(Object *obj)
38
- * executing as AArch32 then check if highvecs are enabled and
114
}
39
- * adjust the PC accordingly.
115
40
- */
116
object_initialize_child(obj, "a9mpcore", &s->a9mpcore, TYPE_A9MPCORE_PRIV);
41
- if (A32_BANKED_CURRENT_REG_GET(env, sctlr) & SCTLR_V) {
117
+ object_initialize_child(obj, "ext-gic", &s->ext_gic, TYPE_EXYNOS4210_GIC);
42
- env->regs[15] = 0xFFFF0000;
118
}
43
- }
119
120
static void exynos4210_class_init(ObjectClass *klass, void *data)
121
diff --git a/hw/intc/exynos4210_gic.c b/hw/intc/exynos4210_gic.c
122
index XXXXXXX..XXXXXXX 100644
123
--- a/hw/intc/exynos4210_gic.c
124
+++ b/hw/intc/exynos4210_gic.c
125
@@ -XXX,XX +XXX,XX @@
126
#include "qemu/module.h"
127
#include "hw/irq.h"
128
#include "hw/qdev-properties.h"
129
+#include "hw/intc/exynos4210_gic.h"
130
#include "hw/arm/exynos4210.h"
131
#include "qom/object.h"
132
133
@@ -XXX,XX +XXX,XX @@
134
#define EXYNOS4210_GIC_CPU_REGION_SIZE 0x100
135
#define EXYNOS4210_GIC_DIST_REGION_SIZE 0x1000
136
137
-#define TYPE_EXYNOS4210_GIC "exynos4210.gic"
138
-OBJECT_DECLARE_SIMPLE_TYPE(Exynos4210GicState, EXYNOS4210_GIC)
44
-
139
-
45
- env->vfp.xregs[ARM_VFP_FPEXC] = 0;
140
-struct Exynos4210GicState {
46
-#endif
141
- SysBusDevice parent_obj;
47
-
142
-
48
/* M profile requires that reset clears the exclusive monitor;
143
- MemoryRegion cpu_container;
49
* A profile does not, but clearing it makes more sense than having it
144
- MemoryRegion dist_container;
50
* set with an exclusive access on address zero.
145
- MemoryRegion cpu_alias[EXYNOS4210_NCPUS];
146
- MemoryRegion dist_alias[EXYNOS4210_NCPUS];
147
- uint32_t num_cpu;
148
- DeviceState *gic;
149
-};
150
-
151
static void exynos4210_gic_set_irq(void *opaque, int irq, int level)
152
{
153
Exynos4210GicState *s = (Exynos4210GicState *)opaque;
154
@@ -XXX,XX +XXX,XX @@ static void exynos4210_gic_realize(DeviceState *dev, Error **errp)
155
* enough room for the cpu numbers. gcc 9.2.1 on 32-bit x86
156
* doesn't figure this out, otherwise and gives spurious warnings.
157
*/
158
- assert(n <= EXYNOS4210_NCPUS);
159
+ assert(n <= EXYNOS4210_GIC_NCPUS);
160
for (i = 0; i < n; i++) {
161
/* Map CPU interface per SMP Core */
162
sprintf(cpu_alias_name, "%s%x", cpu_prefix, i);
163
diff --git a/MAINTAINERS b/MAINTAINERS
164
index XXXXXXX..XXXXXXX 100644
165
--- a/MAINTAINERS
166
+++ b/MAINTAINERS
167
@@ -XXX,XX +XXX,XX @@ M: Peter Maydell <peter.maydell@linaro.org>
168
L: qemu-arm@nongnu.org
169
S: Odd Fixes
170
F: hw/*/exynos*
171
-F: include/hw/arm/exynos4210.h
172
+F: include/hw/*/exynos*
173
174
Calxeda Highbank
175
M: Rob Herring <robh@kernel.org>
51
--
176
--
52
2.20.1
177
2.25.1
53
54
diff view generated by jsdifflib
1
Currently gen_jmp_tb() assumes that if it is called then the jump it
1
The only time we use the ext_gic_irq[] array in the Exynos4210Irq
2
is handling is the only reason that we might be trying to end the TB,
2
struct is during realize of the SoC -- we initialize it with the
3
so it will use goto_tb if it can. This is usually the case: mostly
3
input IRQs of the external GIC device, and then connect those to
4
"we did something that means we must end the TB" happens on a
4
outputs of other devices further on in realize (including in the
5
non-branch instruction. However, there are cases where we decide
5
exynos4210_init_board_irqs() function). Now that the ext_gic object
6
early in handling an instruction that we need to end the TB and
6
is easily accessible as s->ext_gic we can make the connections
7
return to the main loop, and then the insn is a complex one that
7
directly from one device to the other without going via this array.
8
involves gen_jmp_tb(). For instance, for M-profile FP instructions,
9
in gen_preserve_fp_state() which is called from vfp_access_check() we
10
want to force an exit to the main loop if lazy state preservation is
11
active and we are in icount mode.
12
13
Make gen_jmp_tb() look at the current value of is_jmp, and only use
14
goto_tb if the previous is_jmp was DISAS_NEXT or DISAS_TOO_MANY.
15
8
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
18
Message-id: 20210913095440.13462-2-peter.maydell@linaro.org
11
Message-id: 20220404154658.565020-10-peter.maydell@linaro.org
19
---
12
---
20
target/arm/translate.c | 34 +++++++++++++++++++++++++++++++++-
13
include/hw/arm/exynos4210.h | 1 -
21
1 file changed, 33 insertions(+), 1 deletion(-)
14
hw/arm/exynos4210.c | 12 ++++++------
15
2 files changed, 6 insertions(+), 7 deletions(-)
22
16
23
diff --git a/target/arm/translate.c b/target/arm/translate.c
17
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
24
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
25
--- a/target/arm/translate.c
19
--- a/include/hw/arm/exynos4210.h
26
+++ b/target/arm/translate.c
20
+++ b/include/hw/arm/exynos4210.h
27
@@ -XXX,XX +XXX,XX @@ static inline void gen_jmp_tb(DisasContext *s, uint32_t dest, int tbno)
21
@@ -XXX,XX +XXX,XX @@
28
/* An indirect jump so that we still trigger the debug exception. */
22
typedef struct Exynos4210Irq {
29
gen_set_pc_im(s, dest);
23
qemu_irq int_combiner_irq[EXYNOS4210_MAX_INT_COMBINER_IN_IRQ];
30
s->base.is_jmp = DISAS_JUMP;
24
qemu_irq ext_combiner_irq[EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ];
31
- } else {
25
- qemu_irq ext_gic_irq[EXYNOS4210_EXT_GIC_NIRQ];
32
+ return;
26
} Exynos4210Irq;
33
+ }
27
34
+ switch (s->base.is_jmp) {
28
struct Exynos4210State {
35
+ case DISAS_NEXT:
29
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
36
+ case DISAS_TOO_MANY:
30
index XXXXXXX..XXXXXXX 100644
37
+ case DISAS_NORETURN:
31
--- a/hw/arm/exynos4210.c
38
+ /*
32
+++ b/hw/arm/exynos4210.c
39
+ * The normal case: just go to the destination TB.
33
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init_board_irqs(Exynos4210State *s)
40
+ * NB: NORETURN happens if we generate code like
34
{
41
+ * gen_brcondi(l);
35
uint32_t grp, bit, irq_id, n;
42
+ * gen_jmp();
36
Exynos4210Irq *is = &s->irqs;
43
+ * gen_set_label(l);
37
+ DeviceState *extgicdev = DEVICE(&s->ext_gic);
44
+ * gen_jmp();
38
45
+ * on the second call to gen_jmp().
39
for (n = 0; n < EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ; n++) {
46
+ */
40
irq_id = 0;
47
gen_goto_tb(s, tbno, dest);
41
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init_board_irqs(Exynos4210State *s)
48
+ break;
42
}
49
+ case DISAS_UPDATE_NOCHAIN:
43
if (irq_id) {
50
+ case DISAS_UPDATE_EXIT:
44
s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
51
+ /*
45
- is->ext_gic_irq[irq_id - 32]);
52
+ * We already decided we're leaving the TB for some other reason.
46
+ qdev_get_gpio_in(extgicdev,
53
+ * Avoid using goto_tb so we really do exit back to the main loop
47
+ irq_id - 32));
54
+ * and don't chain to another TB.
48
} else {
55
+ */
49
s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
56
+ gen_set_pc_im(s, dest);
50
is->ext_combiner_irq[n]);
57
+ gen_goto_ptr();
51
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init_board_irqs(Exynos4210State *s)
58
+ s->base.is_jmp = DISAS_NORETURN;
52
59
+ break;
53
if (irq_id) {
60
+ default:
54
s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
61
+ /*
55
- is->ext_gic_irq[irq_id - 32]);
62
+ * We shouldn't be emitting code for a jump and also have
56
+ qdev_get_gpio_in(extgicdev,
63
+ * is_jmp set to one of the special cases like DISAS_SWI.
57
+ irq_id - 32));
64
+ */
58
}
65
+ g_assert_not_reached();
66
}
59
}
67
}
60
}
68
61
@@ -XXX,XX +XXX,XX @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
62
sysbus_connect_irq(busdev, n,
63
qdev_get_gpio_in(DEVICE(&s->cpu_irq_orgate[n]), 1));
64
}
65
- for (n = 0; n < EXYNOS4210_EXT_GIC_NIRQ; n++) {
66
- s->irqs.ext_gic_irq[n] = qdev_get_gpio_in(DEVICE(&s->ext_gic), n);
67
- }
68
69
/* Internal Interrupt Combiner */
70
dev = qdev_new("exynos4210.combiner");
71
@@ -XXX,XX +XXX,XX @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
72
busdev = SYS_BUS_DEVICE(dev);
73
sysbus_realize_and_unref(busdev, &error_fatal);
74
for (n = 0; n < EXYNOS4210_MAX_INT_COMBINER_OUT_IRQ; n++) {
75
- sysbus_connect_irq(busdev, n, s->irqs.ext_gic_irq[n]);
76
+ sysbus_connect_irq(busdev, n, qdev_get_gpio_in(DEVICE(&s->ext_gic), n));
77
}
78
exynos4210_combiner_get_gpioin(&s->irqs, dev, 1);
79
sysbus_mmio_map(busdev, 0, EXYNOS4210_EXT_COMBINER_BASE_ADDR);
69
--
80
--
70
2.20.1
81
2.25.1
71
72
diff view generated by jsdifflib
1
Optimize the MVE VSHL and VSHR immediate forms by using TCG vector
1
The function exynos4210_combiner_get_gpioin() currently lives in
2
ops when possible.
2
exynos4210_combiner.c, but it isn't really part of the combiner
3
device itself -- it is a function that implements the wiring up of
4
some interrupt sources to multiple combiner inputs. Move it to live
5
with the other SoC-level code in exynos4210.c, along with a few
6
macros previously defined in exynos4210.h which are now used only
7
in exynos4210.c.
3
8
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20210913095440.13462-10-peter.maydell@linaro.org
11
Message-id: 20220404154658.565020-11-peter.maydell@linaro.org
7
---
12
---
8
target/arm/translate-mve.c | 83 +++++++++++++++++++++++++++++---------
13
include/hw/arm/exynos4210.h | 11 -----
9
1 file changed, 63 insertions(+), 20 deletions(-)
14
hw/arm/exynos4210.c | 82 +++++++++++++++++++++++++++++++++++
15
hw/intc/exynos4210_combiner.c | 77 --------------------------------
16
3 files changed, 82 insertions(+), 88 deletions(-)
10
17
11
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
18
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
12
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
13
--- a/target/arm/translate-mve.c
20
--- a/include/hw/arm/exynos4210.h
14
+++ b/target/arm/translate-mve.c
21
+++ b/include/hw/arm/exynos4210.h
15
@@ -XXX,XX +XXX,XX @@ static bool trans_Vimm_1r(DisasContext *s, arg_1imm *a)
22
@@ -XXX,XX +XXX,XX @@
16
return do_1imm(s, a, fn);
23
#define EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ \
24
(EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ * 8)
25
26
-#define EXYNOS4210_COMBINER_GET_IRQ_NUM(grp, bit) ((grp)*8 + (bit))
27
-#define EXYNOS4210_COMBINER_GET_GRP_NUM(irq) ((irq) / 8)
28
-#define EXYNOS4210_COMBINER_GET_BIT_NUM(irq) \
29
- ((irq) - 8 * EXYNOS4210_COMBINER_GET_GRP_NUM(irq))
30
-
31
/* IRQs number for external and internal GIC */
32
#define EXYNOS4210_EXT_GIC_NIRQ (160-32)
33
#define EXYNOS4210_INT_GIC_NIRQ 64
34
@@ -XXX,XX +XXX,XX @@ void exynos4210_write_secondary(ARMCPU *cpu,
35
* bit - bit number inside group */
36
uint32_t exynos4210_get_irq(uint32_t grp, uint32_t bit);
37
38
-/*
39
- * Get Combiner input GPIO into irqs structure
40
- */
41
-void exynos4210_combiner_get_gpioin(Exynos4210Irq *irqs, DeviceState *dev,
42
- int ext);
43
-
44
/*
45
* exynos4210 UART
46
*/
47
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
48
index XXXXXXX..XXXXXXX 100644
49
--- a/hw/arm/exynos4210.c
50
+++ b/hw/arm/exynos4210.c
51
@@ -XXX,XX +XXX,XX @@ combiner_grp_to_gic_id[64 - EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][8] = {
52
{ }, { }, { }, { }, { }, { }, { }, { }, { }, { }
53
};
54
55
+#define EXYNOS4210_COMBINER_GET_IRQ_NUM(grp, bit) ((grp) * 8 + (bit))
56
+#define EXYNOS4210_COMBINER_GET_GRP_NUM(irq) ((irq) / 8)
57
+#define EXYNOS4210_COMBINER_GET_BIT_NUM(irq) \
58
+ ((irq) - 8 * EXYNOS4210_COMBINER_GET_GRP_NUM(irq))
59
+
60
/*
61
* Initialize board IRQs.
62
* These IRQs contain splitted Int/External Combiner and External Gic IRQs.
63
@@ -XXX,XX +XXX,XX @@ uint32_t exynos4210_get_irq(uint32_t grp, uint32_t bit)
64
return EXYNOS4210_COMBINER_GET_IRQ_NUM(grp, bit);
17
}
65
}
18
66
19
-static bool do_2shift(DisasContext *s, arg_2shift *a, MVEGenTwoOpShiftFn fn,
67
+/*
20
- bool negateshift)
68
+ * Get Combiner input GPIO into irqs structure
21
+static bool do_2shift_vec(DisasContext *s, arg_2shift *a, MVEGenTwoOpShiftFn fn,
69
+ */
22
+ bool negateshift, GVecGen2iFn vecfn)
70
+static void exynos4210_combiner_get_gpioin(Exynos4210Irq *irqs,
23
{
71
+ DeviceState *dev, int ext)
24
TCGv_ptr qd, qm;
25
int shift = a->shift;
26
@@ -XXX,XX +XXX,XX @@ static bool do_2shift(DisasContext *s, arg_2shift *a, MVEGenTwoOpShiftFn fn,
27
shift = -shift;
28
}
29
30
- qd = mve_qreg_ptr(a->qd);
31
- qm = mve_qreg_ptr(a->qm);
32
- fn(cpu_env, qd, qm, tcg_constant_i32(shift));
33
- tcg_temp_free_ptr(qd);
34
- tcg_temp_free_ptr(qm);
35
+ if (vecfn && mve_no_predication(s)) {
36
+ vecfn(a->size, mve_qreg_offset(a->qd), mve_qreg_offset(a->qm),
37
+ shift, 16, 16);
38
+ } else {
39
+ qd = mve_qreg_ptr(a->qd);
40
+ qm = mve_qreg_ptr(a->qm);
41
+ fn(cpu_env, qd, qm, tcg_constant_i32(shift));
42
+ tcg_temp_free_ptr(qd);
43
+ tcg_temp_free_ptr(qm);
44
+ }
45
mve_update_eci(s);
46
return true;
47
}
48
49
-#define DO_2SHIFT(INSN, FN, NEGATESHIFT) \
50
- static bool trans_##INSN(DisasContext *s, arg_2shift *a) \
51
- { \
52
- static MVEGenTwoOpShiftFn * const fns[] = { \
53
- gen_helper_mve_##FN##b, \
54
- gen_helper_mve_##FN##h, \
55
- gen_helper_mve_##FN##w, \
56
- NULL, \
57
- }; \
58
- return do_2shift(s, a, fns[a->size], NEGATESHIFT); \
59
+static bool do_2shift(DisasContext *s, arg_2shift *a, MVEGenTwoOpShiftFn fn,
60
+ bool negateshift)
61
+{
72
+{
62
+ return do_2shift_vec(s, a, fn, negateshift, NULL);
73
+ int n;
63
+}
74
+ int bit;
64
+
75
+ int max;
65
+#define DO_2SHIFT_VEC(INSN, FN, NEGATESHIFT, VECFN) \
76
+ qemu_irq *irq;
66
+ static bool trans_##INSN(DisasContext *s, arg_2shift *a) \
77
+
67
+ { \
78
+ max = ext ? EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ :
68
+ static MVEGenTwoOpShiftFn * const fns[] = { \
79
+ EXYNOS4210_MAX_INT_COMBINER_IN_IRQ;
69
+ gen_helper_mve_##FN##b, \
80
+ irq = ext ? irqs->ext_combiner_irq : irqs->int_combiner_irq;
70
+ gen_helper_mve_##FN##h, \
81
+
71
+ gen_helper_mve_##FN##w, \
72
+ NULL, \
73
+ }; \
74
+ return do_2shift_vec(s, a, fns[a->size], NEGATESHIFT, VECFN); \
75
}
76
77
-DO_2SHIFT(VSHLI, vshli_u, false)
78
+#define DO_2SHIFT(INSN, FN, NEGATESHIFT) \
79
+ DO_2SHIFT_VEC(INSN, FN, NEGATESHIFT, NULL)
80
+
81
+static void do_gvec_shri_s(unsigned vece, uint32_t dofs, uint32_t aofs,
82
+ int64_t shift, uint32_t oprsz, uint32_t maxsz)
83
+{
84
+ /*
82
+ /*
85
+ * We get here with a negated shift count, and we must handle
83
+ * Some IRQs of Int/External Combiner are going to two Combiners groups,
86
+ * shifts by the element size, which tcg_gen_gvec_sari() does not do.
84
+ * so let split them.
87
+ */
85
+ */
88
+ shift = -shift;
86
+ for (n = 0; n < max; n++) {
89
+ if (shift == (8 << vece)) {
87
+
90
+ shift--;
88
+ bit = EXYNOS4210_COMBINER_GET_BIT_NUM(n);
91
+ }
89
+
92
+ tcg_gen_gvec_sari(vece, dofs, aofs, shift, oprsz, maxsz);
90
+ switch (n) {
93
+}
91
+ /* MDNIE_LCD1 INTG1 */
94
+
92
+ case EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 0) ...
95
+static void do_gvec_shri_u(unsigned vece, uint32_t dofs, uint32_t aofs,
93
+ EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 3):
96
+ int64_t shift, uint32_t oprsz, uint32_t maxsz)
94
+ irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
97
+{
95
+ irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(0, bit + 4)]);
98
+ /*
96
+ continue;
99
+ * We get here with a negated shift count, and we must handle
97
+
100
+ * shifts by the element size, which tcg_gen_gvec_shri() does not do.
98
+ /* TMU INTG3 */
101
+ */
99
+ case EXYNOS4210_COMBINER_GET_IRQ_NUM(3, 4):
102
+ shift = -shift;
100
+ irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
103
+ if (shift == (8 << vece)) {
101
+ irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(2, bit)]);
104
+ tcg_gen_gvec_dup_imm(vece, dofs, oprsz, maxsz, 0);
102
+ continue;
105
+ } else {
103
+
106
+ tcg_gen_gvec_shri(vece, dofs, aofs, shift, oprsz, maxsz);
104
+ /* LCD1 INTG12 */
105
+ case EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 0) ...
106
+ EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 3):
107
+ irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
108
+ irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(11, bit + 4)]);
109
+ continue;
110
+
111
+ /* Multi-Core Timer INTG12 */
112
+ case EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 4) ...
113
+ EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 8):
114
+ irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
115
+ irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(1, bit + 4)]);
116
+ continue;
117
+
118
+ /* Multi-Core Timer INTG35 */
119
+ case EXYNOS4210_COMBINER_GET_IRQ_NUM(35, 4) ...
120
+ EXYNOS4210_COMBINER_GET_IRQ_NUM(35, 8):
121
+ irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
122
+ irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(1, bit + 4)]);
123
+ continue;
124
+
125
+ /* Multi-Core Timer INTG51 */
126
+ case EXYNOS4210_COMBINER_GET_IRQ_NUM(51, 4) ...
127
+ EXYNOS4210_COMBINER_GET_IRQ_NUM(51, 8):
128
+ irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
129
+ irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(1, bit + 4)]);
130
+ continue;
131
+
132
+ /* Multi-Core Timer INTG53 */
133
+ case EXYNOS4210_COMBINER_GET_IRQ_NUM(53, 4) ...
134
+ EXYNOS4210_COMBINER_GET_IRQ_NUM(53, 8):
135
+ irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
136
+ irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(1, bit + 4)]);
137
+ continue;
138
+ }
139
+
140
+ irq[n] = qdev_get_gpio_in(dev, n);
107
+ }
141
+ }
108
+}
142
+}
109
+
143
+
110
+DO_2SHIFT_VEC(VSHLI, vshli_u, false, tcg_gen_gvec_shli)
144
static uint8_t chipid_and_omr[] = { 0x11, 0x02, 0x21, 0x43,
111
DO_2SHIFT(VQSHLI_S, vqshli_s, false)
145
0x09, 0x00, 0x00, 0x00 };
112
DO_2SHIFT(VQSHLI_U, vqshli_u, false)
146
113
DO_2SHIFT(VQSHLUI, vqshlui_s, false)
147
diff --git a/hw/intc/exynos4210_combiner.c b/hw/intc/exynos4210_combiner.c
114
/* These right shifts use a left-shift helper with negated shift count */
148
index XXXXXXX..XXXXXXX 100644
115
-DO_2SHIFT(VSHRI_S, vshli_s, true)
149
--- a/hw/intc/exynos4210_combiner.c
116
-DO_2SHIFT(VSHRI_U, vshli_u, true)
150
+++ b/hw/intc/exynos4210_combiner.c
117
+DO_2SHIFT_VEC(VSHRI_S, vshli_s, true, do_gvec_shri_s)
151
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_exynos4210_combiner = {
118
+DO_2SHIFT_VEC(VSHRI_U, vshli_u, true, do_gvec_shri_u)
152
}
119
DO_2SHIFT(VRSHRI_S, vrshli_s, true)
153
};
120
DO_2SHIFT(VRSHRI_U, vrshli_u, true)
154
121
155
-/*
156
- * Get Combiner input GPIO into irqs structure
157
- */
158
-void exynos4210_combiner_get_gpioin(Exynos4210Irq *irqs, DeviceState *dev,
159
- int ext)
160
-{
161
- int n;
162
- int bit;
163
- int max;
164
- qemu_irq *irq;
165
-
166
- max = ext ? EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ :
167
- EXYNOS4210_MAX_INT_COMBINER_IN_IRQ;
168
- irq = ext ? irqs->ext_combiner_irq : irqs->int_combiner_irq;
169
-
170
- /*
171
- * Some IRQs of Int/External Combiner are going to two Combiners groups,
172
- * so let split them.
173
- */
174
- for (n = 0; n < max; n++) {
175
-
176
- bit = EXYNOS4210_COMBINER_GET_BIT_NUM(n);
177
-
178
- switch (n) {
179
- /* MDNIE_LCD1 INTG1 */
180
- case EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 0) ...
181
- EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 3):
182
- irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
183
- irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(0, bit + 4)]);
184
- continue;
185
-
186
- /* TMU INTG3 */
187
- case EXYNOS4210_COMBINER_GET_IRQ_NUM(3, 4):
188
- irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
189
- irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(2, bit)]);
190
- continue;
191
-
192
- /* LCD1 INTG12 */
193
- case EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 0) ...
194
- EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 3):
195
- irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
196
- irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(11, bit + 4)]);
197
- continue;
198
-
199
- /* Multi-Core Timer INTG12 */
200
- case EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 4) ...
201
- EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 8):
202
- irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
203
- irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(1, bit + 4)]);
204
- continue;
205
-
206
- /* Multi-Core Timer INTG35 */
207
- case EXYNOS4210_COMBINER_GET_IRQ_NUM(35, 4) ...
208
- EXYNOS4210_COMBINER_GET_IRQ_NUM(35, 8):
209
- irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
210
- irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(1, bit + 4)]);
211
- continue;
212
-
213
- /* Multi-Core Timer INTG51 */
214
- case EXYNOS4210_COMBINER_GET_IRQ_NUM(51, 4) ...
215
- EXYNOS4210_COMBINER_GET_IRQ_NUM(51, 8):
216
- irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
217
- irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(1, bit + 4)]);
218
- continue;
219
-
220
- /* Multi-Core Timer INTG53 */
221
- case EXYNOS4210_COMBINER_GET_IRQ_NUM(53, 4) ...
222
- EXYNOS4210_COMBINER_GET_IRQ_NUM(53, 8):
223
- irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
224
- irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(1, bit + 4)]);
225
- continue;
226
- }
227
-
228
- irq[n] = qdev_get_gpio_in(dev, n);
229
- }
230
-}
231
-
232
static uint64_t
233
exynos4210_combiner_read(void *opaque, hwaddr offset, unsigned size)
234
{
122
--
235
--
123
2.20.1
236
2.25.1
124
125
diff view generated by jsdifflib
New patch
1
Delete a couple of #defines which are never used.
1
2
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20220404154658.565020-12-peter.maydell@linaro.org
6
---
7
include/hw/arm/exynos4210.h | 4 ----
8
1 file changed, 4 deletions(-)
9
10
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
11
index XXXXXXX..XXXXXXX 100644
12
--- a/include/hw/arm/exynos4210.h
13
+++ b/include/hw/arm/exynos4210.h
14
@@ -XXX,XX +XXX,XX @@
15
#define EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ \
16
(EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ * 8)
17
18
-/* IRQs number for external and internal GIC */
19
-#define EXYNOS4210_EXT_GIC_NIRQ (160-32)
20
-#define EXYNOS4210_INT_GIC_NIRQ 64
21
-
22
#define EXYNOS4210_I2C_NUMBER 9
23
24
#define EXYNOS4210_NUM_DMA 3
25
--
26
2.25.1
diff view generated by jsdifflib
1
Optimize MVE arithmetic ops when we have a TCG
1
In exynos4210_init_board_irqs(), use the TYPE_SPLIT_IRQ device
2
vector operation we can use.
2
instead of qemu_irq_split().
3
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20210913095440.13462-6-peter.maydell@linaro.org
6
Message-id: 20220404154658.565020-13-peter.maydell@linaro.org
8
---
7
---
9
target/arm/translate-mve.c | 20 +++++++++++---------
8
include/hw/arm/exynos4210.h | 9 ++++++++
10
1 file changed, 11 insertions(+), 9 deletions(-)
9
hw/arm/exynos4210.c | 41 +++++++++++++++++++++++++++++--------
10
2 files changed, 42 insertions(+), 8 deletions(-)
11
11
12
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
12
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
13
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/translate-mve.c
14
--- a/include/hw/arm/exynos4210.h
15
+++ b/target/arm/translate-mve.c
15
+++ b/include/hw/arm/exynos4210.h
16
@@ -XXX,XX +XXX,XX @@ static bool trans_VPSEL(DisasContext *s, arg_2op *a)
16
@@ -XXX,XX +XXX,XX @@
17
return do_2op(s, a, gen_helper_mve_vpsel);
17
#include "hw/sysbus.h"
18
#include "hw/cpu/a9mpcore.h"
19
#include "hw/intc/exynos4210_gic.h"
20
+#include "hw/core/split-irq.h"
21
#include "target/arm/cpu-qom.h"
22
#include "qom/object.h"
23
24
@@ -XXX,XX +XXX,XX @@
25
26
#define EXYNOS4210_NUM_DMA 3
27
28
+/*
29
+ * We need one splitter for every external combiner input, plus
30
+ * one for every non-zero entry in combiner_grp_to_gic_id[].
31
+ * We'll assert in exynos4210_init_board_irqs() if this is wrong.
32
+ */
33
+#define EXYNOS4210_NUM_SPLITTERS (EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ + 60)
34
+
35
typedef struct Exynos4210Irq {
36
qemu_irq int_combiner_irq[EXYNOS4210_MAX_INT_COMBINER_IN_IRQ];
37
qemu_irq ext_combiner_irq[EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ];
38
@@ -XXX,XX +XXX,XX @@ struct Exynos4210State {
39
qemu_or_irq cpu_irq_orgate[EXYNOS4210_NCPUS];
40
A9MPPrivState a9mpcore;
41
Exynos4210GicState ext_gic;
42
+ SplitIRQ splitter[EXYNOS4210_NUM_SPLITTERS];
43
};
44
45
#define TYPE_EXYNOS4210_SOC "exynos4210"
46
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
47
index XXXXXXX..XXXXXXX 100644
48
--- a/hw/arm/exynos4210.c
49
+++ b/hw/arm/exynos4210.c
50
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init_board_irqs(Exynos4210State *s)
51
uint32_t grp, bit, irq_id, n;
52
Exynos4210Irq *is = &s->irqs;
53
DeviceState *extgicdev = DEVICE(&s->ext_gic);
54
+ int splitcount = 0;
55
+ DeviceState *splitter;
56
57
for (n = 0; n < EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ; n++) {
58
irq_id = 0;
59
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init_board_irqs(Exynos4210State *s)
60
/* MCT_G1 is passed to External and GIC */
61
irq_id = EXT_GIC_ID_MCT_G1;
62
}
63
+
64
+ assert(splitcount < EXYNOS4210_NUM_SPLITTERS);
65
+ splitter = DEVICE(&s->splitter[splitcount]);
66
+ qdev_prop_set_uint16(splitter, "num-lines", 2);
67
+ qdev_realize(splitter, NULL, &error_abort);
68
+ splitcount++;
69
+ s->irq_table[n] = qdev_get_gpio_in(splitter, 0);
70
+ qdev_connect_gpio_out(splitter, 0, is->int_combiner_irq[n]);
71
if (irq_id) {
72
- s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
73
- qdev_get_gpio_in(extgicdev,
74
- irq_id - 32));
75
+ qdev_connect_gpio_out(splitter, 1,
76
+ qdev_get_gpio_in(extgicdev, irq_id - 32));
77
} else {
78
- s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
79
- is->ext_combiner_irq[n]);
80
+ qdev_connect_gpio_out(splitter, 1, is->ext_combiner_irq[n]);
81
}
82
}
83
for (; n < EXYNOS4210_MAX_INT_COMBINER_IN_IRQ; n++) {
84
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init_board_irqs(Exynos4210State *s)
85
EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][bit];
86
87
if (irq_id) {
88
- s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
89
- qdev_get_gpio_in(extgicdev,
90
- irq_id - 32));
91
+ assert(splitcount < EXYNOS4210_NUM_SPLITTERS);
92
+ splitter = DEVICE(&s->splitter[splitcount]);
93
+ qdev_prop_set_uint16(splitter, "num-lines", 2);
94
+ qdev_realize(splitter, NULL, &error_abort);
95
+ splitcount++;
96
+ s->irq_table[n] = qdev_get_gpio_in(splitter, 0);
97
+ qdev_connect_gpio_out(splitter, 0, is->int_combiner_irq[n]);
98
+ qdev_connect_gpio_out(splitter, 1,
99
+ qdev_get_gpio_in(extgicdev, irq_id - 32));
100
}
101
}
102
+ /*
103
+ * We check this here to avoid a more obscure assert later when
104
+ * qdev_assert_realized_properly() checks that we realized every
105
+ * child object we initialized.
106
+ */
107
+ assert(splitcount == EXYNOS4210_NUM_SPLITTERS);
18
}
108
}
19
109
20
-#define DO_2OP(INSN, FN) \
110
/*
21
+#define DO_2OP_VEC(INSN, FN, VECFN) \
111
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init(Object *obj)
22
static bool trans_##INSN(DisasContext *s, arg_2op *a) \
112
object_initialize_child(obj, name, &s->cpu_irq_orgate[i], TYPE_OR_IRQ);
23
{ \
24
static MVEGenTwoOpFn * const fns[] = { \
25
@@ -XXX,XX +XXX,XX @@ static bool trans_VPSEL(DisasContext *s, arg_2op *a)
26
gen_helper_mve_##FN##w, \
27
NULL, \
28
}; \
29
- return do_2op(s, a, fns[a->size]); \
30
+ return do_2op_vec(s, a, fns[a->size], VECFN); \
31
}
113
}
32
114
33
-DO_2OP(VADD, vadd)
115
+ for (i = 0; i < ARRAY_SIZE(s->splitter); i++) {
34
-DO_2OP(VSUB, vsub)
116
+ g_autofree char *name = g_strdup_printf("irq-splitter%d", i);
35
-DO_2OP(VMUL, vmul)
117
+ object_initialize_child(obj, name, &s->splitter[i], TYPE_SPLIT_IRQ);
36
+#define DO_2OP(INSN, FN) DO_2OP_VEC(INSN, FN, NULL)
118
+ }
37
+
119
+
38
+DO_2OP_VEC(VADD, vadd, tcg_gen_gvec_add)
120
object_initialize_child(obj, "a9mpcore", &s->a9mpcore, TYPE_A9MPCORE_PRIV);
39
+DO_2OP_VEC(VSUB, vsub, tcg_gen_gvec_sub)
121
object_initialize_child(obj, "ext-gic", &s->ext_gic, TYPE_EXYNOS4210_GIC);
40
+DO_2OP_VEC(VMUL, vmul, tcg_gen_gvec_mul)
122
}
41
DO_2OP(VMULH_S, vmulhs)
42
DO_2OP(VMULH_U, vmulhu)
43
DO_2OP(VRMULH_S, vrmulhs)
44
DO_2OP(VRMULH_U, vrmulhu)
45
-DO_2OP(VMAX_S, vmaxs)
46
-DO_2OP(VMAX_U, vmaxu)
47
-DO_2OP(VMIN_S, vmins)
48
-DO_2OP(VMIN_U, vminu)
49
+DO_2OP_VEC(VMAX_S, vmaxs, tcg_gen_gvec_smax)
50
+DO_2OP_VEC(VMAX_U, vmaxu, tcg_gen_gvec_umax)
51
+DO_2OP_VEC(VMIN_S, vmins, tcg_gen_gvec_smin)
52
+DO_2OP_VEC(VMIN_U, vminu, tcg_gen_gvec_umin)
53
DO_2OP(VABD_S, vabds)
54
DO_2OP(VABD_U, vabdu)
55
DO_2OP(VHADD_S, vhadds)
56
--
123
--
57
2.20.1
124
2.25.1
58
59
diff view generated by jsdifflib
1
Optimize the MVE shift-and-insert insns by using TCG
1
In exynos4210_init_board_irqs(), the loop that handles IRQ lines that
2
vector ops when possible.
2
are in a range that applies to the internal combiner only creates a
3
splitter for those interrupts which go to both the internal combiner
4
and to the external GIC, but it does nothing at all for the
5
interrupts which don't go to the external GIC, leaving the
6
irq_table[] array element empty for those. (This will result in
7
those interrupts simply being lost, not in a QEMU crash.)
8
9
I don't have a reliable datasheet for this SoC, but since we do wire
10
up one interrupt line in this category (the HDMI I2C device on
11
interrupt 16,1), this seems like it must be a bug in the existing
12
QEMU code. Fill in the irq_table[] entries where we're not splitting
13
the IRQ to both the internal combiner and the external GIC with the
14
IRQ line of the internal combiner. (That is, these IRQ lines go to
15
just one device, not multiple.)
16
17
This bug didn't have any visible guest effects because the only
18
implemented device that was affected was the HDMI I2C controller,
19
and we never connect any I2C devices to that bus.
3
20
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
22
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20210913095440.13462-12-peter.maydell@linaro.org
23
Message-id: 20220404154658.565020-14-peter.maydell@linaro.org
7
---
24
---
8
target/arm/translate-mve.c | 4 ++--
25
hw/arm/exynos4210.c | 2 ++
9
1 file changed, 2 insertions(+), 2 deletions(-)
26
1 file changed, 2 insertions(+)
10
27
11
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
28
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
12
index XXXXXXX..XXXXXXX 100644
29
index XXXXXXX..XXXXXXX 100644
13
--- a/target/arm/translate-mve.c
30
--- a/hw/arm/exynos4210.c
14
+++ b/target/arm/translate-mve.c
31
+++ b/hw/arm/exynos4210.c
15
@@ -XXX,XX +XXX,XX @@ DO_2SHIFT_VEC(VSHRI_U, vshli_u, true, do_gvec_shri_u)
32
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init_board_irqs(Exynos4210State *s)
16
DO_2SHIFT(VRSHRI_S, vrshli_s, true)
33
qdev_connect_gpio_out(splitter, 0, is->int_combiner_irq[n]);
17
DO_2SHIFT(VRSHRI_U, vrshli_u, true)
34
qdev_connect_gpio_out(splitter, 1,
18
35
qdev_get_gpio_in(extgicdev, irq_id - 32));
19
-DO_2SHIFT(VSRI, vsri, false)
36
+ } else {
20
-DO_2SHIFT(VSLI, vsli, false)
37
+ s->irq_table[n] = is->int_combiner_irq[n];
21
+DO_2SHIFT_VEC(VSRI, vsri, false, gen_gvec_sri)
38
}
22
+DO_2SHIFT_VEC(VSLI, vsli, false, gen_gvec_sli)
39
}
23
40
/*
24
#define DO_2SHIFT_FP(INSN, FN) \
25
static bool trans_##INSN(DisasContext *s, arg_2shift *a) \
26
--
41
--
27
2.20.1
42
2.25.1
28
29
diff view generated by jsdifflib
1
Architecturally, for an M-profile CPU with the LOB feature the
1
Currently for the interrupts MCT_G0 and MCT_G1 which are
2
LTPSIZE field in FPDSCR is always constant 4. QEMU's implementation
2
the only ones in the input range of the external combiner
3
enforces this everywhere, except that we don't check that it is true
3
and which are also wired to the external GIC, we connect
4
in incoming migration data.
4
them only to the internal combiner and the external GIC.
5
This seems likely to be a bug, as all other interrupts
6
which are in the input range of both combiners are
7
connected to both combiners. (The fact that the code in
8
exynos4210_combiner_get_gpioin() is also trying to wire
9
up these inputs on both combiners also suggests this.)
5
10
6
We're going to add come in gen_update_fp_context() which relies on
11
Wire these interrupts up to both combiners, like the rest.
7
the "always 4" property. Since this is TCG-only, we don't actually
8
need to be robust to bogus incoming migration data, and the effect of
9
it being wrong would be wrong code generation rather than a QEMU
10
crash; but if it did ever happen somehow it would be very difficult
11
to track down the cause. Add a check so that we fail the inbound
12
migration if the FPDSCR.LTPSIZE value is incorrect.
13
12
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
16
Message-id: 20210913095440.13462-3-peter.maydell@linaro.org
15
Message-id: 20220404154658.565020-15-peter.maydell@linaro.org
17
---
16
---
18
target/arm/machine.c | 13 +++++++++++++
17
hw/arm/exynos4210.c | 7 +++----
19
1 file changed, 13 insertions(+)
18
1 file changed, 3 insertions(+), 4 deletions(-)
20
19
21
diff --git a/target/arm/machine.c b/target/arm/machine.c
20
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
22
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
23
--- a/target/arm/machine.c
22
--- a/hw/arm/exynos4210.c
24
+++ b/target/arm/machine.c
23
+++ b/hw/arm/exynos4210.c
25
@@ -XXX,XX +XXX,XX @@ static int cpu_post_load(void *opaque, int version_id)
24
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init_board_irqs(Exynos4210State *s)
26
hw_breakpoint_update_all(cpu);
25
27
hw_watchpoint_update_all(cpu);
26
assert(splitcount < EXYNOS4210_NUM_SPLITTERS);
28
27
splitter = DEVICE(&s->splitter[splitcount]);
29
+ /*
28
- qdev_prop_set_uint16(splitter, "num-lines", 2);
30
+ * TCG gen_update_fp_context() relies on the invariant that
29
+ qdev_prop_set_uint16(splitter, "num-lines", irq_id ? 3 : 2);
31
+ * FPDSCR.LTPSIZE is constant 4 for M-profile with the LOB extension;
30
qdev_realize(splitter, NULL, &error_abort);
32
+ * forbid bogus incoming data with some other value.
31
splitcount++;
33
+ */
32
s->irq_table[n] = qdev_get_gpio_in(splitter, 0);
34
+ if (arm_feature(env, ARM_FEATURE_M) && cpu_isar_feature(aa32_lob, cpu)) {
33
qdev_connect_gpio_out(splitter, 0, is->int_combiner_irq[n]);
35
+ if (extract32(env->v7m.fpdscr[M_REG_NS],
34
+ qdev_connect_gpio_out(splitter, 1, is->ext_combiner_irq[n]);
36
+ FPCR_LTPSIZE_SHIFT, FPCR_LTPSIZE_LENGTH) != 4 ||
35
if (irq_id) {
37
+ extract32(env->v7m.fpdscr[M_REG_S],
36
- qdev_connect_gpio_out(splitter, 1,
38
+ FPCR_LTPSIZE_SHIFT, FPCR_LTPSIZE_LENGTH) != 4) {
37
+ qdev_connect_gpio_out(splitter, 2,
39
+ return -1;
38
qdev_get_gpio_in(extgicdev, irq_id - 32));
40
+ }
39
- } else {
41
+ }
40
- qdev_connect_gpio_out(splitter, 1, is->ext_combiner_irq[n]);
42
if (!kvm_enabled()) {
41
}
43
pmu_op_finish(&cpu->env);
44
}
42
}
43
for (; n < EXYNOS4210_MAX_INT_COMBINER_IN_IRQ; n++) {
45
--
44
--
46
2.20.1
45
2.25.1
47
48
diff view generated by jsdifflib
1
Currently all of the M-profile specific code in arm_cpu_reset() is
1
The combiner_grp_to_gic_id[] array includes the EXT_GIC_ID_MCT_G0
2
inside a !defined(CONFIG_USER_ONLY) ifdef block. This is
2
and EXT_GIC_ID_MCT_G1 multiple times. This means that we will
3
unintentional: it happened because originally the only
3
connect multiple IRQs up to the same external GIC input, which
4
M-profile-specific handling was the setup of the initial SP and PC
4
is not permitted. We do the same thing in the code in
5
from the vector table, which is system-emulation only. But then we
5
exynos4210_init_board_irqs() because the conditionals selecting
6
added a lot of other M-profile setup to the same "if (ARM_FEATURE_M)"
6
an irq_id in the first loop match multiple interrupt IDs.
7
code block without noticing that it was all inside a not-user-mode
8
ifdef. This has generally been harmless, but with the addition of
9
v8.1M low-overhead-loop support we ran into a problem: the reset of
10
FPSCR.LTPSIZE to 4 was only being done for system emulation mode, so
11
if a user-mode guest tried to execute the LE instruction it would
12
incorrectly take a UsageFault.
13
7
14
Adjust the ifdefs so only the really system-emulation specific parts
8
Overall we do this for interrupt IDs
15
are covered. Because this means we now run some reset code that sets
9
(1, 4), (12, 4), (35, 4), (51, 4), (53, 4) for EXT_GIC_ID_MCT_G0
16
up initial values in the FPCCR and similar FPU related registers,
10
and
17
explicitly set up the registers controlling FPU context handling in
11
(1, 5), (12, 5), (35, 5), (51, 5), (53, 5) for EXT_GIC_ID_MCT_G1
18
user-emulation mode so that the FPU works by design and not by
19
chance.
20
12
21
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/613
13
These correspond to the cases for the multi-core timer that we are
22
Cc: qemu-stable@nongnu.org
14
wiring up to multiple inputs on the combiner in
15
exynos4210_combiner_get_gpioin(). That code already deals with all
16
these interrupt IDs being the same input source, so we don't need to
17
connect the external GIC interrupt for any of them except the first
18
(1, 4) and (1, 5). Remove the array entries and conditionals which
19
were incorrectly causing us to wire up extra lines.
20
21
This bug didn't cause any visible effects, because we only connect
22
up a device to the "primary" ID values (1, 4) and (1, 5), so the
23
extra lines would never be set to a level.
24
23
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
25
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
24
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
26
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
25
Message-id: 20210914120725.24992-2-peter.maydell@linaro.org
27
Message-id: 20220404154658.565020-16-peter.maydell@linaro.org
26
---
28
---
27
target/arm/cpu.c | 19 +++++++++++++++++++
29
include/hw/arm/exynos4210.h | 2 +-
28
1 file changed, 19 insertions(+)
30
hw/arm/exynos4210.c | 12 +++++-------
31
2 files changed, 6 insertions(+), 8 deletions(-)
29
32
30
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
33
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
31
index XXXXXXX..XXXXXXX 100644
34
index XXXXXXX..XXXXXXX 100644
32
--- a/target/arm/cpu.c
35
--- a/include/hw/arm/exynos4210.h
33
+++ b/target/arm/cpu.c
36
+++ b/include/hw/arm/exynos4210.h
34
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_reset(DeviceState *dev)
37
@@ -XXX,XX +XXX,XX @@
35
env->uncached_cpsr = ARM_CPU_MODE_SVC;
38
* one for every non-zero entry in combiner_grp_to_gic_id[].
36
}
39
* We'll assert in exynos4210_init_board_irqs() if this is wrong.
37
env->daif = PSTATE_D | PSTATE_A | PSTATE_I | PSTATE_F;
40
*/
38
+#endif
41
-#define EXYNOS4210_NUM_SPLITTERS (EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ + 60)
39
42
+#define EXYNOS4210_NUM_SPLITTERS (EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ + 54)
40
if (arm_feature(env, ARM_FEATURE_M)) {
43
41
+#ifndef CONFIG_USER_ONLY
44
typedef struct Exynos4210Irq {
42
uint32_t initial_msp; /* Loaded from 0x0 */
45
qemu_irq int_combiner_irq[EXYNOS4210_MAX_INT_COMBINER_IN_IRQ];
43
uint32_t initial_pc; /* Loaded from 0x4 */
46
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
44
uint8_t *rom;
47
index XXXXXXX..XXXXXXX 100644
45
uint32_t vecbase;
48
--- a/hw/arm/exynos4210.c
46
+#endif
49
+++ b/hw/arm/exynos4210.c
47
50
@@ -XXX,XX +XXX,XX @@ combiner_grp_to_gic_id[64 - EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][8] = {
48
if (cpu_isar_feature(aa32_lob, cpu)) {
51
/* int combiner group 34 */
49
/*
52
{ EXT_GIC_ID_ONENAND_AUDI, EXT_GIC_ID_NFC },
50
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_reset(DeviceState *dev)
53
/* int combiner group 35 */
51
env->v7m.fpccr[M_REG_S] = R_V7M_FPCCR_ASPEN_MASK |
54
- { 0, 0, 0, EXT_GIC_ID_MCT_L1, EXT_GIC_ID_MCT_G0, EXT_GIC_ID_MCT_G1 },
52
R_V7M_FPCCR_LSPEN_MASK | R_V7M_FPCCR_S_MASK;
55
+ { 0, 0, 0, EXT_GIC_ID_MCT_L1 },
56
/* int combiner group 36 */
57
{ EXT_GIC_ID_MIXER },
58
/* int combiner group 37 */
59
@@ -XXX,XX +XXX,XX @@ combiner_grp_to_gic_id[64 - EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][8] = {
60
/* groups 38-50 */
61
{ }, { }, { }, { }, { }, { }, { }, { }, { }, { }, { }, { }, { },
62
/* int combiner group 51 */
63
- { EXT_GIC_ID_MCT_L0, 0, 0, 0, EXT_GIC_ID_MCT_G0, EXT_GIC_ID_MCT_G1 },
64
+ { EXT_GIC_ID_MCT_L0 },
65
/* group 52 */
66
{ },
67
/* int combiner group 53 */
68
- { EXT_GIC_ID_WDT, 0, 0, 0, EXT_GIC_ID_MCT_G0, EXT_GIC_ID_MCT_G1 },
69
+ { EXT_GIC_ID_WDT },
70
/* groups 54-63 */
71
{ }, { }, { }, { }, { }, { }, { }, { }, { }, { }
72
};
73
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init_board_irqs(Exynos4210State *s)
74
75
for (n = 0; n < EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ; n++) {
76
irq_id = 0;
77
- if (n == EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 4) ||
78
- n == EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 4)) {
79
+ if (n == EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 4)) {
80
/* MCT_G0 is passed to External GIC */
81
irq_id = EXT_GIC_ID_MCT_G0;
53
}
82
}
54
+
83
- if (n == EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 5) ||
55
+#ifndef CONFIG_USER_ONLY
84
- n == EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 5)) {
56
/* Unlike A/R profile, M profile defines the reset LR value */
85
+ if (n == EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 5)) {
57
env->regs[14] = 0xffffffff;
86
/* MCT_G1 is passed to External and GIC */
58
87
irq_id = EXT_GIC_ID_MCT_G1;
59
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_reset(DeviceState *dev)
88
}
60
env->regs[13] = initial_msp & 0xFFFFFFFC;
61
env->regs[15] = initial_pc & ~1;
62
env->thumb = initial_pc & 1;
63
+#else
64
+ /*
65
+ * For user mode we run non-secure and with access to the FPU.
66
+ * The FPU context is active (ie does not need further setup)
67
+ * and is owned by non-secure.
68
+ */
69
+ env->v7m.secure = false;
70
+ env->v7m.nsacr = 0xcff;
71
+ env->v7m.cpacr[M_REG_NS] = 0xf0ffff;
72
+ env->v7m.fpccr[M_REG_S] &=
73
+ ~(R_V7M_FPCCR_LSPEN_MASK | R_V7M_FPCCR_S_MASK);
74
+ env->v7m.control[M_REG_S] |= R_V7M_CONTROL_FPCA_MASK;
75
+#endif
76
}
77
78
+#ifndef CONFIG_USER_ONLY
79
/* AArch32 has a hard highvec setting of 0xFFFF0000. If we are currently
80
* executing as AArch32 then check if highvecs are enabled and
81
* adjust the PC accordingly.
82
--
89
--
83
2.20.1
90
2.25.1
84
85
diff view generated by jsdifflib
1
Our current codegen for MVE always calls out to helper functions,
1
At this point, the function exynos4210_init_board_irqs() splits input
2
because some byte lanes might be predicated. The common case is that
2
IRQ lines to connect them to the input combiner, output combiner and
3
in fact there is no predication active and all lanes should be
3
external GIC. The function exynos4210_combiner_get_gpioin() splits
4
updated together, so we can produce better code by detecting that and
4
some of the combiner input lines further to connect them to multiple
5
using the TCG generic vector infrastructure.
5
different inputs on the combiner.
6
6
7
Add a TB flag that is set when we can guarantee that there is no
7
Because (unlike qemu_irq_split()) the TYPE_SPLIT_IRQ device has a
8
active MVE predication, and a bool in the DisasContext. Subsequent
8
configurable number of outputs, we can do all this in one place, by
9
patches will use this flag to generate improved code for some
9
making exynos4210_init_board_irqs() add extra outputs to the splitter
10
instructions.
10
device when it must be connected to more than one input on each
11
11
combiner.
12
In most cases when the predication state changes we simply end the TB
12
13
after that instruction. For the code called from vfp_access_check()
13
We do this with a new data structure, the combinermap, which is an
14
that handles lazy state preservation and creating a new FP context,
14
array each of whose elements is a list of the interrupt IDs on the
15
we can usually avoid having to try to end the TB because luckily the
15
combiner which must be tied together. As we loop through each
16
new value of the flag following the register changes in those
16
interrupt ID, if we find that it is the first one in one of these
17
sequences doesn't depend on any runtime decisions. We do have to end
17
lists, we configure the splitter device with eonugh extra outputs and
18
the TB if the guest has enabled lazy FP state preservation but not
18
wire them up to the other interrupt IDs in the list.
19
automatic state preservation, but this is an odd corner case that is
19
20
not going to be common in real-world code.
20
Conveniently, for all the cases where this is necessary, the
21
lowest-numbered interrupt ID in each group is in the range of the
22
external combiner, so we only need to code for this in the first of
23
the two loops in exynos4210_init_board_irqs().
24
25
The old code in exynos4210_combiner_get_gpioin() which is being
26
deleted here had several problems which don't exist in the new code
27
in its handling of the multi-core timer interrupts:
28
(1) the case labels specified bits 4 ... 8, but bit '8' doesn't
29
exist; these should have been 4 ... 7
30
(2) it used the input irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(1, bit + 4)]
31
multiple times as the input of several different splitters,
32
which isn't allowed
33
(3) in an apparent cut-and-paste error, the cases for all the
34
multi-core timer inputs used "bit + 4" even though the
35
bit range for the case was (intended to be) 4 ... 7, which
36
meant it was looking at non-existent bits 8 ... 11.
37
None of these exist in the new code.
21
38
22
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
39
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
23
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
40
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
24
Message-id: 20210913095440.13462-4-peter.maydell@linaro.org
41
Message-id: 20220404154658.565020-17-peter.maydell@linaro.org
25
---
42
---
26
target/arm/cpu.h | 4 +++-
43
include/hw/arm/exynos4210.h | 6 +-
27
target/arm/translate.h | 2 ++
44
hw/arm/exynos4210.c | 178 +++++++++++++++++++++++-------------
28
target/arm/helper.c | 33 +++++++++++++++++++++++++++++++++
45
2 files changed, 119 insertions(+), 65 deletions(-)
29
target/arm/translate-m-nocp.c | 8 +++++++-
46
30
target/arm/translate-mve.c | 13 ++++++++++++-
47
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
31
target/arm/translate-vfp.c | 33 +++++++++++++++++++++++++++------
32
target/arm/translate.c | 8 ++++++++
33
7 files changed, 92 insertions(+), 9 deletions(-)
34
35
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
36
index XXXXXXX..XXXXXXX 100644
48
index XXXXXXX..XXXXXXX 100644
37
--- a/target/arm/cpu.h
49
--- a/include/hw/arm/exynos4210.h
38
+++ b/target/arm/cpu.h
50
+++ b/include/hw/arm/exynos4210.h
39
@@ -XXX,XX +XXX,XX @@ typedef ARMCPU ArchCPU;
51
@@ -XXX,XX +XXX,XX @@
40
* | TBFLAG_AM32 | +-----+----------+
52
41
* | | |TBFLAG_M32|
53
/*
42
* +-------------+----------------+----------+
54
* We need one splitter for every external combiner input, plus
43
- * 31 23 5 4 0
55
- * one for every non-zero entry in combiner_grp_to_gic_id[].
44
+ * 31 23 6 5 0
56
+ * one for every non-zero entry in combiner_grp_to_gic_id[],
45
*
57
+ * minus one for every external combiner ID in second or later
46
* Unless otherwise noted, these bits are cached in env->hflags.
58
+ * places in a combinermap[] line.
59
* We'll assert in exynos4210_init_board_irqs() if this is wrong.
47
*/
60
*/
48
@@ -XXX,XX +XXX,XX @@ FIELD(TBFLAG_M32, LSPACT, 2, 1) /* Not cached. */
61
-#define EXYNOS4210_NUM_SPLITTERS (EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ + 54)
49
FIELD(TBFLAG_M32, NEW_FP_CTXT_NEEDED, 3, 1) /* Not cached. */
62
+#define EXYNOS4210_NUM_SPLITTERS (EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ + 38)
50
/* Set if FPCCR.S does not match current security state */
63
51
FIELD(TBFLAG_M32, FPCCR_S_WRONG, 4, 1) /* Not cached. */
64
typedef struct Exynos4210Irq {
52
+/* Set if MVE insns are definitely not predicated by VPR or LTPSIZE */
65
qemu_irq int_combiner_irq[EXYNOS4210_MAX_INT_COMBINER_IN_IRQ];
53
+FIELD(TBFLAG_M32, MVE_NO_PRED, 5, 1) /* Not cached. */
66
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
54
55
/*
56
* Bit usage when in AArch64 state
57
diff --git a/target/arm/translate.h b/target/arm/translate.h
58
index XXXXXXX..XXXXXXX 100644
67
index XXXXXXX..XXXXXXX 100644
59
--- a/target/arm/translate.h
68
--- a/hw/arm/exynos4210.c
60
+++ b/target/arm/translate.h
69
+++ b/hw/arm/exynos4210.c
61
@@ -XXX,XX +XXX,XX @@ typedef struct DisasContext {
70
@@ -XXX,XX +XXX,XX @@ combiner_grp_to_gic_id[64 - EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][8] = {
62
bool align_mem;
71
#define EXYNOS4210_COMBINER_GET_BIT_NUM(irq) \
63
/* True if PSTATE.IL is set */
72
((irq) - 8 * EXYNOS4210_COMBINER_GET_GRP_NUM(irq))
64
bool pstate_il;
73
65
+ /* True if MVE insns are definitely not predicated by VPR or LTPSIZE */
74
+/*
66
+ bool mve_no_pred;
75
+ * Some interrupt lines go to multiple combiner inputs.
67
/*
76
+ * This data structure defines those: each array element is
68
* >= 0, a copy of PSTATE.BTYPE, which will be 0 without v8.5-BTI.
77
+ * a list of combiner inputs which are connected together;
69
* < 0, set by the current instruction.
78
+ * the one with the smallest interrupt ID value must be first.
70
diff --git a/target/arm/helper.c b/target/arm/helper.c
79
+ * As with combiner_grp_to_gic_id[], we rely on (0, 0) not being
71
index XXXXXXX..XXXXXXX 100644
80
+ * wired to anything so we can use 0 as a terminator.
72
--- a/target/arm/helper.c
81
+ */
73
+++ b/target/arm/helper.c
82
+#define IRQNO(G, B) EXYNOS4210_COMBINER_GET_IRQ_NUM(G, B)
74
@@ -XXX,XX +XXX,XX @@ static inline void assert_hflags_rebuild_correctly(CPUARMState *env)
83
+#define IRQNONE 0
75
#endif
84
+
76
}
85
+#define COMBINERMAP_SIZE 16
77
86
+
78
+static bool mve_no_pred(CPUARMState *env)
87
+static const int combinermap[COMBINERMAP_SIZE][6] = {
88
+ /* MDNIE_LCD1 */
89
+ { IRQNO(0, 4), IRQNO(1, 0), IRQNONE },
90
+ { IRQNO(0, 5), IRQNO(1, 1), IRQNONE },
91
+ { IRQNO(0, 6), IRQNO(1, 2), IRQNONE },
92
+ { IRQNO(0, 7), IRQNO(1, 3), IRQNONE },
93
+ /* TMU */
94
+ { IRQNO(2, 4), IRQNO(3, 4), IRQNONE },
95
+ { IRQNO(2, 5), IRQNO(3, 5), IRQNONE },
96
+ { IRQNO(2, 6), IRQNO(3, 6), IRQNONE },
97
+ { IRQNO(2, 7), IRQNO(3, 7), IRQNONE },
98
+ /* LCD1 */
99
+ { IRQNO(11, 4), IRQNO(12, 0), IRQNONE },
100
+ { IRQNO(11, 5), IRQNO(12, 1), IRQNONE },
101
+ { IRQNO(11, 6), IRQNO(12, 2), IRQNONE },
102
+ { IRQNO(11, 7), IRQNO(12, 3), IRQNONE },
103
+ /* Multi-core timer */
104
+ { IRQNO(1, 4), IRQNO(12, 4), IRQNO(35, 4), IRQNO(51, 4), IRQNO(53, 4), IRQNONE },
105
+ { IRQNO(1, 5), IRQNO(12, 5), IRQNO(35, 5), IRQNO(51, 5), IRQNO(53, 5), IRQNONE },
106
+ { IRQNO(1, 6), IRQNO(12, 6), IRQNO(35, 6), IRQNO(51, 6), IRQNO(53, 6), IRQNONE },
107
+ { IRQNO(1, 7), IRQNO(12, 7), IRQNO(35, 7), IRQNO(51, 7), IRQNO(53, 7), IRQNONE },
108
+};
109
+
110
+#undef IRQNO
111
+
112
+static const int *combinermap_entry(int irq)
79
+{
113
+{
80
+ /*
114
+ /*
81
+ * Return true if there is definitely no predication of MVE
115
+ * If the interrupt number passed in is the first entry in some
82
+ * instructions by VPR or LTPSIZE. (Returning false even if there
116
+ * line of the combinermap, return a pointer to that line;
83
+ * isn't any predication is OK; generated code will just be
117
+ * otherwise return NULL.
84
+ * a little worse.)
85
+ * If the CPU does not implement MVE then this TB flag is always 0.
86
+ *
87
+ * NOTE: if you change this logic, the "recalculate s->mve_no_pred"
88
+ * logic in gen_update_fp_context() needs to be updated to match.
89
+ *
90
+ * We do not include the effect of the ECI bits here -- they are
91
+ * tracked in other TB flags. This simplifies the logic for
92
+ * "when did we emit code that changes the MVE_NO_PRED TB flag
93
+ * and thus need to end the TB?".
94
+ */
118
+ */
95
+ if (cpu_isar_feature(aa32_mve, env_archcpu(env))) {
119
+ int i;
96
+ return false;
120
+ for (i = 0; i < COMBINERMAP_SIZE; i++) {
121
+ if (combinermap[i][0] == irq) {
122
+ return combinermap[i];
123
+ }
97
+ }
124
+ }
98
+ if (env->v7m.vpr) {
125
+ return NULL;
99
+ return false;
126
+}
127
+
128
+static int mapline_size(const int *mapline)
129
+{
130
+ /* Return number of entries in this mapline in total */
131
+ int i = 0;
132
+
133
+ if (!mapline) {
134
+ /* Not in the map? IRQ goes to exactly one combiner input */
135
+ return 1;
100
+ }
136
+ }
101
+ if (env->v7m.ltpsize < 4) {
137
+ while (*mapline != IRQNONE) {
102
+ return false;
138
+ mapline++;
139
+ i++;
103
+ }
140
+ }
104
+ return true;
141
+ return i;
105
+}
142
+}
106
+
143
+
107
void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
144
/*
108
target_ulong *cs_base, uint32_t *pflags)
145
* Initialize board IRQs.
146
* These IRQs contain splitted Int/External Combiner and External Gic IRQs.
147
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init_board_irqs(Exynos4210State *s)
148
DeviceState *extgicdev = DEVICE(&s->ext_gic);
149
int splitcount = 0;
150
DeviceState *splitter;
151
+ const int *mapline;
152
+ int numlines, splitin, in;
153
154
for (n = 0; n < EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ; n++) {
155
irq_id = 0;
156
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init_board_irqs(Exynos4210State *s)
157
irq_id = EXT_GIC_ID_MCT_G1;
158
}
159
160
+ if (s->irq_table[n]) {
161
+ /*
162
+ * This must be some non-first entry in a combinermap line,
163
+ * and we've already filled it in.
164
+ */
165
+ continue;
166
+ }
167
+ mapline = combinermap_entry(n);
168
+ /*
169
+ * We need to connect the IRQ to multiple inputs on both combiners
170
+ * and possibly also to the external GIC.
171
+ */
172
+ numlines = 2 * mapline_size(mapline);
173
+ if (irq_id) {
174
+ numlines++;
175
+ }
176
assert(splitcount < EXYNOS4210_NUM_SPLITTERS);
177
splitter = DEVICE(&s->splitter[splitcount]);
178
- qdev_prop_set_uint16(splitter, "num-lines", irq_id ? 3 : 2);
179
+ qdev_prop_set_uint16(splitter, "num-lines", numlines);
180
qdev_realize(splitter, NULL, &error_abort);
181
splitcount++;
182
- s->irq_table[n] = qdev_get_gpio_in(splitter, 0);
183
- qdev_connect_gpio_out(splitter, 0, is->int_combiner_irq[n]);
184
- qdev_connect_gpio_out(splitter, 1, is->ext_combiner_irq[n]);
185
+
186
+ in = n;
187
+ splitin = 0;
188
+ for (;;) {
189
+ s->irq_table[in] = qdev_get_gpio_in(splitter, 0);
190
+ qdev_connect_gpio_out(splitter, splitin, is->int_combiner_irq[in]);
191
+ qdev_connect_gpio_out(splitter, splitin + 1, is->ext_combiner_irq[in]);
192
+ splitin += 2;
193
+ if (!mapline) {
194
+ break;
195
+ }
196
+ mapline++;
197
+ in = *mapline;
198
+ if (in == IRQNONE) {
199
+ break;
200
+ }
201
+ }
202
if (irq_id) {
203
- qdev_connect_gpio_out(splitter, 2,
204
+ qdev_connect_gpio_out(splitter, splitin,
205
qdev_get_gpio_in(extgicdev, irq_id - 32));
206
}
207
}
208
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init_board_irqs(Exynos4210State *s)
209
irq_id = combiner_grp_to_gic_id[grp -
210
EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][bit];
211
212
+ if (s->irq_table[n]) {
213
+ /*
214
+ * This must be some non-first entry in a combinermap line,
215
+ * and we've already filled it in.
216
+ */
217
+ continue;
218
+ }
219
+
220
if (irq_id) {
221
assert(splitcount < EXYNOS4210_NUM_SPLITTERS);
222
splitter = DEVICE(&s->splitter[splitcount]);
223
@@ -XXX,XX +XXX,XX @@ static void exynos4210_combiner_get_gpioin(Exynos4210Irq *irqs,
224
DeviceState *dev, int ext)
109
{
225
{
110
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
226
int n;
111
if (env->v7m.fpccr[is_secure] & R_V7M_FPCCR_LSPACT_MASK) {
227
- int bit;
112
DP_TBFLAG_M32(flags, LSPACT, 1);
228
int max;
113
}
229
qemu_irq *irq;
114
+
230
115
+ if (mve_no_pred(env)) {
231
@@ -XXX,XX +XXX,XX @@ static void exynos4210_combiner_get_gpioin(Exynos4210Irq *irqs,
116
+ DP_TBFLAG_M32(flags, MVE_NO_PRED, 1);
232
EXYNOS4210_MAX_INT_COMBINER_IN_IRQ;
117
+ }
233
irq = ext ? irqs->ext_combiner_irq : irqs->int_combiner_irq;
118
} else {
234
119
/*
235
- /*
120
* Note that XSCALE_CPAR shares bits with VECSTRIDE.
236
- * Some IRQs of Int/External Combiner are going to two Combiners groups,
121
diff --git a/target/arm/translate-m-nocp.c b/target/arm/translate-m-nocp.c
237
- * so let split them.
122
index XXXXXXX..XXXXXXX 100644
238
- */
123
--- a/target/arm/translate-m-nocp.c
239
for (n = 0; n < max; n++) {
124
+++ b/target/arm/translate-m-nocp.c
240
-
125
@@ -XXX,XX +XXX,XX @@ static bool trans_VLLDM_VLSTM(DisasContext *s, arg_VLLDM_VLSTM *a)
241
- bit = EXYNOS4210_COMBINER_GET_BIT_NUM(n);
126
242
-
127
clear_eci_state(s);
243
- switch (n) {
128
244
- /* MDNIE_LCD1 INTG1 */
129
- /* End the TB, because we have updated FP control bits */
245
- case EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 0) ...
130
+ /*
246
- EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 3):
131
+ * End the TB, because we have updated FP control bits,
247
- irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
132
+ * and possibly VPR or LTPSIZE.
248
- irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(0, bit + 4)]);
133
+ */
249
- continue;
134
s->base.is_jmp = DISAS_UPDATE_EXIT;
250
-
135
return true;
251
- /* TMU INTG3 */
136
}
252
- case EXYNOS4210_COMBINER_GET_IRQ_NUM(3, 4):
137
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_write(DisasContext *s, int regno,
253
- irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
138
store_cpu_field(control, v7m.control[M_REG_S]);
254
- irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(2, bit)]);
139
tcg_gen_andi_i32(tmp, tmp, ~FPCR_NZCV_MASK);
255
- continue;
140
gen_helper_vfp_set_fpscr(cpu_env, tmp);
256
-
141
+ s->base.is_jmp = DISAS_UPDATE_NOCHAIN;
257
- /* LCD1 INTG12 */
142
tcg_temp_free_i32(tmp);
258
- case EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 0) ...
143
tcg_temp_free_i32(sfpa);
259
- EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 3):
144
break;
260
- irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
145
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_write(DisasContext *s, int regno,
261
- irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(11, bit + 4)]);
146
}
262
- continue;
147
tmp = loadfn(s, opaque, true);
263
-
148
store_cpu_field(tmp, v7m.vpr);
264
- /* Multi-Core Timer INTG12 */
149
+ s->base.is_jmp = DISAS_UPDATE_NOCHAIN;
265
- case EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 4) ...
150
break;
266
- EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 8):
151
case ARM_VFP_P0:
267
- irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
152
{
268
- irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(1, bit + 4)]);
153
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_write(DisasContext *s, int regno,
269
- continue;
154
tcg_gen_deposit_i32(vpr, vpr, tmp,
270
-
155
R_V7M_VPR_P0_SHIFT, R_V7M_VPR_P0_LENGTH);
271
- /* Multi-Core Timer INTG35 */
156
store_cpu_field(vpr, v7m.vpr);
272
- case EXYNOS4210_COMBINER_GET_IRQ_NUM(35, 4) ...
157
+ s->base.is_jmp = DISAS_UPDATE_NOCHAIN;
273
- EXYNOS4210_COMBINER_GET_IRQ_NUM(35, 8):
158
tcg_temp_free_i32(tmp);
274
- irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
159
break;
275
- irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(1, bit + 4)]);
160
}
276
- continue;
161
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
277
-
162
index XXXXXXX..XXXXXXX 100644
278
- /* Multi-Core Timer INTG51 */
163
--- a/target/arm/translate-mve.c
279
- case EXYNOS4210_COMBINER_GET_IRQ_NUM(51, 4) ...
164
+++ b/target/arm/translate-mve.c
280
- EXYNOS4210_COMBINER_GET_IRQ_NUM(51, 8):
165
@@ -XXX,XX +XXX,XX @@ DO_LOGIC(VORR, gen_helper_mve_vorr)
281
- irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
166
DO_LOGIC(VORN, gen_helper_mve_vorn)
282
- irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(1, bit + 4)]);
167
DO_LOGIC(VEOR, gen_helper_mve_veor)
283
- continue;
168
284
-
169
-DO_LOGIC(VPSEL, gen_helper_mve_vpsel)
285
- /* Multi-Core Timer INTG53 */
170
+static bool trans_VPSEL(DisasContext *s, arg_2op *a)
286
- case EXYNOS4210_COMBINER_GET_IRQ_NUM(53, 4) ...
171
+{
287
- EXYNOS4210_COMBINER_GET_IRQ_NUM(53, 8):
172
+ /* This insn updates predication bits */
288
- irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
173
+ s->base.is_jmp = DISAS_UPDATE_NOCHAIN;
289
- irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(1, bit + 4)]);
174
+ return do_2op(s, a, gen_helper_mve_vpsel);
290
- continue;
175
+}
291
- }
176
292
-
177
#define DO_2OP(INSN, FN) \
293
irq[n] = qdev_get_gpio_in(dev, n);
178
static bool trans_##INSN(DisasContext *s, arg_2op *a) \
179
@@ -XXX,XX +XXX,XX @@ static bool trans_VPNOT(DisasContext *s, arg_VPNOT *a)
180
}
181
182
gen_helper_mve_vpnot(cpu_env);
183
+ /* This insn updates predication bits */
184
+ s->base.is_jmp = DISAS_UPDATE_NOCHAIN;
185
mve_update_eci(s);
186
return true;
187
}
188
@@ -XXX,XX +XXX,XX @@ static bool do_vcmp(DisasContext *s, arg_vcmp *a, MVEGenCmpFn *fn)
189
/* VPT */
190
gen_vpst(s, a->mask);
191
}
192
+ /* This insn updates predication bits */
193
+ s->base.is_jmp = DISAS_UPDATE_NOCHAIN;
194
mve_update_eci(s);
195
return true;
196
}
197
@@ -XXX,XX +XXX,XX @@ static bool do_vcmp_scalar(DisasContext *s, arg_vcmp_scalar *a,
198
/* VPT */
199
gen_vpst(s, a->mask);
200
}
201
+ /* This insn updates predication bits */
202
+ s->base.is_jmp = DISAS_UPDATE_NOCHAIN;
203
mve_update_eci(s);
204
return true;
205
}
206
diff --git a/target/arm/translate-vfp.c b/target/arm/translate-vfp.c
207
index XXXXXXX..XXXXXXX 100644
208
--- a/target/arm/translate-vfp.c
209
+++ b/target/arm/translate-vfp.c
210
@@ -XXX,XX +XXX,XX @@ static inline long vfp_f16_offset(unsigned reg, bool top)
211
* Generate code for M-profile lazy FP state preservation if needed;
212
* this corresponds to the pseudocode PreserveFPState() function.
213
*/
214
-static void gen_preserve_fp_state(DisasContext *s)
215
+static void gen_preserve_fp_state(DisasContext *s, bool skip_context_update)
216
{
217
if (s->v7m_lspact) {
218
/*
219
@@ -XXX,XX +XXX,XX @@ static void gen_preserve_fp_state(DisasContext *s)
220
* any further FP insns in this TB.
221
*/
222
s->v7m_lspact = false;
223
+ /*
224
+ * The helper might have zeroed VPR, so we do not know the
225
+ * correct value for the MVE_NO_PRED TB flag any more.
226
+ * If we're about to create a new fp context then that
227
+ * will precisely determine the MVE_NO_PRED value (see
228
+ * gen_update_fp_context()). Otherwise, we must:
229
+ * - set s->mve_no_pred to false, so this instruction
230
+ * is generated to use helper functions
231
+ * - end the TB now, without chaining to the next TB
232
+ */
233
+ if (skip_context_update || !s->v7m_new_fp_ctxt_needed) {
234
+ s->mve_no_pred = false;
235
+ s->base.is_jmp = DISAS_UPDATE_NOCHAIN;
236
+ }
237
}
294
}
238
}
295
}
239
240
@@ -XXX,XX +XXX,XX @@ static void gen_update_fp_context(DisasContext *s)
241
TCGv_i32 z32 = tcg_const_i32(0);
242
store_cpu_field(z32, v7m.vpr);
243
}
244
-
245
/*
246
- * We don't need to arrange to end the TB, because the only
247
- * parts of FPSCR which we cache in the TB flags are the VECLEN
248
- * and VECSTRIDE, and those don't exist for M-profile.
249
+ * We just updated the FPSCR and VPR. Some of this state is cached
250
+ * in the MVE_NO_PRED TB flag. We want to avoid having to end the
251
+ * TB here, which means we need the new value of the MVE_NO_PRED
252
+ * flag to be exactly known here and the same for all executions.
253
+ * Luckily FPDSCR.LTPSIZE is always constant 4 and the VPR is
254
+ * always set to 0, so the new MVE_NO_PRED flag is always 1
255
+ * if and only if we have MVE.
256
+ *
257
+ * (The other FPSCR state cached in TB flags is VECLEN and VECSTRIDE,
258
+ * but those do not exist for M-profile, so are not relevant here.)
259
*/
260
+ s->mve_no_pred = dc_isar_feature(aa32_mve, s);
261
262
if (s->v8m_secure) {
263
bits |= R_V7M_CONTROL_SFPA_MASK;
264
@@ -XXX,XX +XXX,XX @@ bool vfp_access_check_m(DisasContext *s, bool skip_context_update)
265
/* Handle M-profile lazy FP state mechanics */
266
267
/* Trigger lazy-state preservation if necessary */
268
- gen_preserve_fp_state(s);
269
+ gen_preserve_fp_state(s, skip_context_update);
270
271
if (!skip_context_update) {
272
/* Update ownership of FP context and create new FP context if needed */
273
diff --git a/target/arm/translate.c b/target/arm/translate.c
274
index XXXXXXX..XXXXXXX 100644
275
--- a/target/arm/translate.c
276
+++ b/target/arm/translate.c
277
@@ -XXX,XX +XXX,XX @@ static bool trans_DLS(DisasContext *s, arg_DLS *a)
278
/* DLSTP: set FPSCR.LTPSIZE */
279
tmp = tcg_const_i32(a->size);
280
store_cpu_field(tmp, v7m.ltpsize);
281
+ s->base.is_jmp = DISAS_UPDATE_NOCHAIN;
282
}
283
return true;
284
}
285
@@ -XXX,XX +XXX,XX @@ static bool trans_WLS(DisasContext *s, arg_WLS *a)
286
assert(ok);
287
tmp = tcg_const_i32(a->size);
288
store_cpu_field(tmp, v7m.ltpsize);
289
+ /*
290
+ * LTPSIZE updated, but MVE_NO_PRED will always be the same thing (0)
291
+ * when we take this upcoming exit from this TB, so gen_jmp_tb() is OK.
292
+ */
293
}
294
gen_jmp_tb(s, s->base.pc_next, 1);
295
296
@@ -XXX,XX +XXX,XX @@ static bool trans_VCTP(DisasContext *s, arg_VCTP *a)
297
gen_helper_mve_vctp(cpu_env, masklen);
298
tcg_temp_free_i32(masklen);
299
tcg_temp_free_i32(rn_shifted);
300
+ /* This insn updates predication bits */
301
+ s->base.is_jmp = DISAS_UPDATE_NOCHAIN;
302
mve_update_eci(s);
303
return true;
304
}
305
@@ -XXX,XX +XXX,XX @@ static void arm_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
306
dc->v7m_new_fp_ctxt_needed =
307
EX_TBFLAG_M32(tb_flags, NEW_FP_CTXT_NEEDED);
308
dc->v7m_lspact = EX_TBFLAG_M32(tb_flags, LSPACT);
309
+ dc->mve_no_pred = EX_TBFLAG_M32(tb_flags, MVE_NO_PRED);
310
} else {
311
dc->debug_target_el = EX_TBFLAG_ANY(tb_flags, DEBUG_TARGET_EL);
312
dc->sctlr_b = EX_TBFLAG_A32(tb_flags, SCTLR__B);
313
--
296
--
314
2.20.1
297
2.25.1
315
316
diff view generated by jsdifflib
1
Now that we have working system register sync, we push more target CPU
1
Switch the creation of the combiner devices to the new-style
2
properties into the virtual machine. That might be useful in some
2
"embedded in state struct" approach, so we can easily refer
3
situations, but is not the typical case that users want.
3
to the object elsewhere during realize.
4
4
5
So let's add a -cpu host option that allows them to explicitly pass all
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
CPU capabilities of their host CPU into the guest.
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20220404154658.565020-18-peter.maydell@linaro.org
8
---
9
include/hw/arm/exynos4210.h | 3 ++
10
include/hw/intc/exynos4210_combiner.h | 57 +++++++++++++++++++++++++++
11
hw/arm/exynos4210.c | 20 +++++-----
12
hw/intc/exynos4210_combiner.c | 31 +--------------
13
4 files changed, 72 insertions(+), 39 deletions(-)
14
create mode 100644 include/hw/intc/exynos4210_combiner.h
7
15
8
Signed-off-by: Alexander Graf <agraf@csgraf.de>
16
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
9
Acked-by: Roman Bolshakov <r.bolshakov@yadro.com>
10
Reviewed-by: Sergio Lopez <slp@redhat.com>
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
Message-id: 20210916155404.86958-7-agraf@csgraf.de
13
[PMM: drop unnecessary #include line from .h file]
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
---
16
target/arm/cpu.h | 2 +
17
target/arm/hvf_arm.h | 18 +++++++++
18
target/arm/kvm_arm.h | 2 -
19
target/arm/cpu.c | 13 ++++--
20
target/arm/hvf/hvf.c | 95 ++++++++++++++++++++++++++++++++++++++++++++
21
5 files changed, 124 insertions(+), 6 deletions(-)
22
create mode 100644 target/arm/hvf_arm.h
23
24
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
25
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
26
--- a/target/arm/cpu.h
18
--- a/include/hw/arm/exynos4210.h
27
+++ b/target/arm/cpu.h
19
+++ b/include/hw/arm/exynos4210.h
28
@@ -XXX,XX +XXX,XX @@ bool write_cpustate_to_list(ARMCPU *cpu, bool kvm_sync);
20
@@ -XXX,XX +XXX,XX @@
29
#define ARM_CPU_TYPE_NAME(name) (name ARM_CPU_TYPE_SUFFIX)
21
#include "hw/sysbus.h"
30
#define CPU_RESOLVING_TYPE TYPE_ARM_CPU
22
#include "hw/cpu/a9mpcore.h"
31
23
#include "hw/intc/exynos4210_gic.h"
32
+#define TYPE_ARM_HOST_CPU "host-" TYPE_ARM_CPU
24
+#include "hw/intc/exynos4210_combiner.h"
33
+
25
#include "hw/core/split-irq.h"
34
#define cpu_signal_handler cpu_arm_signal_handler
26
#include "target/arm/cpu-qom.h"
35
#define cpu_list arm_cpu_list
27
#include "qom/object.h"
36
28
@@ -XXX,XX +XXX,XX @@ struct Exynos4210State {
37
diff --git a/target/arm/hvf_arm.h b/target/arm/hvf_arm.h
29
qemu_or_irq cpu_irq_orgate[EXYNOS4210_NCPUS];
30
A9MPPrivState a9mpcore;
31
Exynos4210GicState ext_gic;
32
+ Exynos4210CombinerState int_combiner;
33
+ Exynos4210CombinerState ext_combiner;
34
SplitIRQ splitter[EXYNOS4210_NUM_SPLITTERS];
35
};
36
37
diff --git a/include/hw/intc/exynos4210_combiner.h b/include/hw/intc/exynos4210_combiner.h
38
new file mode 100644
38
new file mode 100644
39
index XXXXXXX..XXXXXXX
39
index XXXXXXX..XXXXXXX
40
--- /dev/null
40
--- /dev/null
41
+++ b/target/arm/hvf_arm.h
41
+++ b/include/hw/intc/exynos4210_combiner.h
42
@@ -XXX,XX +XXX,XX @@
42
@@ -XXX,XX +XXX,XX @@
43
+/*
43
+/*
44
+ * QEMU Hypervisor.framework (HVF) support -- ARM specifics
44
+ * Samsung exynos4210 Interrupt Combiner
45
+ *
45
+ *
46
+ * Copyright (c) 2021 Alexander Graf
46
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd.
47
+ * All rights reserved.
47
+ *
48
+ *
48
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
49
+ * Evgeny Voevodin <e.voevodin@samsung.com>
49
+ * See the COPYING file in the top-level directory.
50
+ *
50
+ *
51
+ * This program is free software; you can redistribute it and/or modify it
52
+ * under the terms of the GNU General Public License as published by the
53
+ * Free Software Foundation; either version 2 of the License, or (at your
54
+ * option) any later version.
55
+ *
56
+ * This program is distributed in the hope that it will be useful,
57
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
58
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
59
+ * See the GNU General Public License for more details.
60
+ *
61
+ * You should have received a copy of the GNU General Public License along
62
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
51
+ */
63
+ */
52
+
64
+
53
+#ifndef QEMU_HVF_ARM_H
65
+#ifndef HW_INTC_EXYNOS4210_COMBINER
54
+#define QEMU_HVF_ARM_H
66
+#define HW_INTC_EXYNOS4210_COMBINER
55
+
67
+
56
+#include "cpu.h"
68
+#include "hw/sysbus.h"
57
+
69
+
58
+void hvf_arm_set_cpu_features_from_host(struct ARMCPU *cpu);
70
+/*
71
+ * State for each output signal of internal combiner
72
+ */
73
+typedef struct CombinerGroupState {
74
+ uint8_t src_mask; /* 1 - source enabled, 0 - disabled */
75
+ uint8_t src_pending; /* Pending source interrupts before masking */
76
+} CombinerGroupState;
77
+
78
+#define TYPE_EXYNOS4210_COMBINER "exynos4210.combiner"
79
+OBJECT_DECLARE_SIMPLE_TYPE(Exynos4210CombinerState, EXYNOS4210_COMBINER)
80
+
81
+/* Number of groups and total number of interrupts for the internal combiner */
82
+#define IIC_NGRP 64
83
+#define IIC_NIRQ (IIC_NGRP * 8)
84
+#define IIC_REGSET_SIZE 0x41
85
+
86
+struct Exynos4210CombinerState {
87
+ SysBusDevice parent_obj;
88
+
89
+ MemoryRegion iomem;
90
+
91
+ struct CombinerGroupState group[IIC_NGRP];
92
+ uint32_t reg_set[IIC_REGSET_SIZE];
93
+ uint32_t icipsr[2];
94
+ uint32_t external; /* 1 means that this combiner is external */
95
+
96
+ qemu_irq output_irq[IIC_NGRP];
97
+};
59
+
98
+
60
+#endif
99
+#endif
61
diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h
100
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
62
index XXXXXXX..XXXXXXX 100644
101
index XXXXXXX..XXXXXXX 100644
63
--- a/target/arm/kvm_arm.h
102
--- a/hw/arm/exynos4210.c
64
+++ b/target/arm/kvm_arm.h
103
+++ b/hw/arm/exynos4210.c
65
@@ -XXX,XX +XXX,XX @@ bool kvm_arm_create_scratch_host_vcpu(const uint32_t *cpus_to_try,
104
@@ -XXX,XX +XXX,XX @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
66
*/
105
}
67
void kvm_arm_destroy_scratch_host_vcpu(int *fdarray);
106
68
107
/* Internal Interrupt Combiner */
69
-#define TYPE_ARM_HOST_CPU "host-" TYPE_ARM_CPU
108
- dev = qdev_new("exynos4210.combiner");
109
- busdev = SYS_BUS_DEVICE(dev);
110
- sysbus_realize_and_unref(busdev, &error_fatal);
111
+ busdev = SYS_BUS_DEVICE(&s->int_combiner);
112
+ sysbus_realize(busdev, &error_fatal);
113
for (n = 0; n < EXYNOS4210_MAX_INT_COMBINER_OUT_IRQ; n++) {
114
sysbus_connect_irq(busdev, n,
115
qdev_get_gpio_in(DEVICE(&s->a9mpcore), n));
116
}
117
- exynos4210_combiner_get_gpioin(&s->irqs, dev, 0);
118
+ exynos4210_combiner_get_gpioin(&s->irqs, DEVICE(&s->int_combiner), 0);
119
sysbus_mmio_map(busdev, 0, EXYNOS4210_INT_COMBINER_BASE_ADDR);
120
121
/* External Interrupt Combiner */
122
- dev = qdev_new("exynos4210.combiner");
123
- qdev_prop_set_uint32(dev, "external", 1);
124
- busdev = SYS_BUS_DEVICE(dev);
125
- sysbus_realize_and_unref(busdev, &error_fatal);
126
+ qdev_prop_set_uint32(DEVICE(&s->ext_combiner), "external", 1);
127
+ busdev = SYS_BUS_DEVICE(&s->ext_combiner);
128
+ sysbus_realize(busdev, &error_fatal);
129
for (n = 0; n < EXYNOS4210_MAX_INT_COMBINER_OUT_IRQ; n++) {
130
sysbus_connect_irq(busdev, n, qdev_get_gpio_in(DEVICE(&s->ext_gic), n));
131
}
132
- exynos4210_combiner_get_gpioin(&s->irqs, dev, 1);
133
+ exynos4210_combiner_get_gpioin(&s->irqs, DEVICE(&s->ext_combiner), 1);
134
sysbus_mmio_map(busdev, 0, EXYNOS4210_EXT_COMBINER_BASE_ADDR);
135
136
/* Initialize board IRQs. */
137
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init(Object *obj)
138
139
object_initialize_child(obj, "a9mpcore", &s->a9mpcore, TYPE_A9MPCORE_PRIV);
140
object_initialize_child(obj, "ext-gic", &s->ext_gic, TYPE_EXYNOS4210_GIC);
141
+ object_initialize_child(obj, "int-combiner", &s->int_combiner,
142
+ TYPE_EXYNOS4210_COMBINER);
143
+ object_initialize_child(obj, "ext-combiner", &s->ext_combiner,
144
+ TYPE_EXYNOS4210_COMBINER);
145
}
146
147
static void exynos4210_class_init(ObjectClass *klass, void *data)
148
diff --git a/hw/intc/exynos4210_combiner.c b/hw/intc/exynos4210_combiner.c
149
index XXXXXXX..XXXXXXX 100644
150
--- a/hw/intc/exynos4210_combiner.c
151
+++ b/hw/intc/exynos4210_combiner.c
152
@@ -XXX,XX +XXX,XX @@
153
#include "hw/sysbus.h"
154
#include "migration/vmstate.h"
155
#include "qemu/module.h"
70
-
156
-
71
/**
157
+#include "hw/intc/exynos4210_combiner.h"
72
* ARMHostCPUFeatures: information about the host CPU (identified
158
#include "hw/arm/exynos4210.h"
73
* by asking the host kernel)
159
#include "hw/hw.h"
74
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
160
#include "hw/irq.h"
75
index XXXXXXX..XXXXXXX 100644
76
--- a/target/arm/cpu.c
77
+++ b/target/arm/cpu.c
78
@@ -XXX,XX +XXX,XX @@
161
@@ -XXX,XX +XXX,XX @@
79
#include "sysemu/tcg.h"
162
#define DPRINTF(fmt, ...) do {} while (0)
80
#include "sysemu/hw_accel.h"
81
#include "kvm_arm.h"
82
+#include "hvf_arm.h"
83
#include "disas/capstone.h"
84
#include "fpu/softfloat.h"
85
86
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
87
* this is the first point where we can report it.
88
*/
89
if (cpu->host_cpu_probe_failed) {
90
- if (!kvm_enabled()) {
91
- error_setg(errp, "The 'host' CPU type can only be used with KVM");
92
+ if (!kvm_enabled() && !hvf_enabled()) {
93
+ error_setg(errp, "The 'host' CPU type can only be used with KVM or HVF");
94
} else {
95
error_setg(errp, "Failed to retrieve host CPU features");
96
}
97
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_class_init(ObjectClass *oc, void *data)
98
#endif /* CONFIG_TCG */
99
}
100
101
-#ifdef CONFIG_KVM
102
+#if defined(CONFIG_KVM) || defined(CONFIG_HVF)
103
static void arm_host_initfn(Object *obj)
104
{
105
ARMCPU *cpu = ARM_CPU(obj);
106
107
+#ifdef CONFIG_KVM
108
kvm_arm_set_cpu_features_from_host(cpu);
109
if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) {
110
aarch64_add_sve_properties(obj);
111
}
112
+#else
113
+ hvf_arm_set_cpu_features_from_host(cpu);
114
+#endif
115
arm_cpu_post_init(obj);
116
}
117
118
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_register_types(void)
119
{
120
type_register_static(&arm_cpu_type_info);
121
122
-#ifdef CONFIG_KVM
123
+#if defined(CONFIG_KVM) || defined(CONFIG_HVF)
124
type_register_static(&host_arm_cpu_type_info);
125
#endif
163
#endif
126
}
164
127
diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c
165
-#define IIC_NGRP 64 /* Internal Interrupt Combiner
128
index XXXXXXX..XXXXXXX 100644
166
- Groups number */
129
--- a/target/arm/hvf/hvf.c
167
-#define IIC_NIRQ (IIC_NGRP * 8)/* Internal Interrupt Combiner
130
+++ b/target/arm/hvf/hvf.c
168
- Interrupts number */
131
@@ -XXX,XX +XXX,XX @@
169
#define IIC_REGION_SIZE 0x108 /* Size of memory mapped region */
132
#include "sysemu/hvf.h"
170
-#define IIC_REGSET_SIZE 0x41
133
#include "sysemu/hvf_int.h"
171
-
134
#include "sysemu/hw_accel.h"
172
-/*
135
+#include "hvf_arm.h"
173
- * State for each output signal of internal combiner
136
174
- */
137
#include <mach/mach_time.h>
175
-typedef struct CombinerGroupState {
138
176
- uint8_t src_mask; /* 1 - source enabled, 0 - disabled */
139
@@ -XXX,XX +XXX,XX @@ typedef struct HVFVTimer {
177
- uint8_t src_pending; /* Pending source interrupts before masking */
140
178
-} CombinerGroupState;
141
static HVFVTimer vtimer;
179
-
142
180
-#define TYPE_EXYNOS4210_COMBINER "exynos4210.combiner"
143
+typedef struct ARMHostCPUFeatures {
181
-OBJECT_DECLARE_SIMPLE_TYPE(Exynos4210CombinerState, EXYNOS4210_COMBINER)
144
+ ARMISARegisters isar;
182
-
145
+ uint64_t features;
183
-struct Exynos4210CombinerState {
146
+ uint64_t midr;
184
- SysBusDevice parent_obj;
147
+ uint32_t reset_sctlr;
185
-
148
+ const char *dtb_compatible;
186
- MemoryRegion iomem;
149
+} ARMHostCPUFeatures;
187
-
150
+
188
- struct CombinerGroupState group[IIC_NGRP];
151
+static ARMHostCPUFeatures arm_host_cpu_features;
189
- uint32_t reg_set[IIC_REGSET_SIZE];
152
+
190
- uint32_t icipsr[2];
153
struct hvf_reg_match {
191
- uint32_t external; /* 1 means that this combiner is external */
154
int reg;
192
-
155
uint64_t offset;
193
- qemu_irq output_irq[IIC_NGRP];
156
@@ -XXX,XX +XXX,XX @@ static uint64_t hvf_get_reg(CPUState *cpu, int rt)
194
-};
157
return val;
195
158
}
196
static const VMStateDescription vmstate_exynos4210_combiner_group_state = {
159
197
.name = "exynos4210.combiner.groupstate",
160
+static bool hvf_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
161
+{
162
+ ARMISARegisters host_isar = {};
163
+ const struct isar_regs {
164
+ int reg;
165
+ uint64_t *val;
166
+ } regs[] = {
167
+ { HV_SYS_REG_ID_AA64PFR0_EL1, &host_isar.id_aa64pfr0 },
168
+ { HV_SYS_REG_ID_AA64PFR1_EL1, &host_isar.id_aa64pfr1 },
169
+ { HV_SYS_REG_ID_AA64DFR0_EL1, &host_isar.id_aa64dfr0 },
170
+ { HV_SYS_REG_ID_AA64DFR1_EL1, &host_isar.id_aa64dfr1 },
171
+ { HV_SYS_REG_ID_AA64ISAR0_EL1, &host_isar.id_aa64isar0 },
172
+ { HV_SYS_REG_ID_AA64ISAR1_EL1, &host_isar.id_aa64isar1 },
173
+ { HV_SYS_REG_ID_AA64MMFR0_EL1, &host_isar.id_aa64mmfr0 },
174
+ { HV_SYS_REG_ID_AA64MMFR1_EL1, &host_isar.id_aa64mmfr1 },
175
+ { HV_SYS_REG_ID_AA64MMFR2_EL1, &host_isar.id_aa64mmfr2 },
176
+ };
177
+ hv_vcpu_t fd;
178
+ hv_return_t r = HV_SUCCESS;
179
+ hv_vcpu_exit_t *exit;
180
+ int i;
181
+
182
+ ahcf->dtb_compatible = "arm,arm-v8";
183
+ ahcf->features = (1ULL << ARM_FEATURE_V8) |
184
+ (1ULL << ARM_FEATURE_NEON) |
185
+ (1ULL << ARM_FEATURE_AARCH64) |
186
+ (1ULL << ARM_FEATURE_PMU) |
187
+ (1ULL << ARM_FEATURE_GENERIC_TIMER);
188
+
189
+ /* We set up a small vcpu to extract host registers */
190
+
191
+ if (hv_vcpu_create(&fd, &exit, NULL) != HV_SUCCESS) {
192
+ return false;
193
+ }
194
+
195
+ for (i = 0; i < ARRAY_SIZE(regs); i++) {
196
+ r |= hv_vcpu_get_sys_reg(fd, regs[i].reg, regs[i].val);
197
+ }
198
+ r |= hv_vcpu_get_sys_reg(fd, HV_SYS_REG_MIDR_EL1, &ahcf->midr);
199
+ r |= hv_vcpu_destroy(fd);
200
+
201
+ ahcf->isar = host_isar;
202
+
203
+ /*
204
+ * A scratch vCPU returns SCTLR 0, so let's fill our default with the M1
205
+ * boot SCTLR from https://github.com/AsahiLinux/m1n1/issues/97
206
+ */
207
+ ahcf->reset_sctlr = 0x30100180;
208
+ /*
209
+ * SPAN is disabled by default when SCTLR.SPAN=1. To improve compatibility,
210
+ * let's disable it on boot and then allow guest software to turn it on by
211
+ * setting it to 0.
212
+ */
213
+ ahcf->reset_sctlr |= 0x00800000;
214
+
215
+ /* Make sure we don't advertise AArch32 support for EL0/EL1 */
216
+ if ((host_isar.id_aa64pfr0 & 0xff) != 0x11) {
217
+ return false;
218
+ }
219
+
220
+ return r == HV_SUCCESS;
221
+}
222
+
223
+void hvf_arm_set_cpu_features_from_host(ARMCPU *cpu)
224
+{
225
+ if (!arm_host_cpu_features.dtb_compatible) {
226
+ if (!hvf_enabled() ||
227
+ !hvf_arm_get_host_cpu_features(&arm_host_cpu_features)) {
228
+ /*
229
+ * We can't report this error yet, so flag that we need to
230
+ * in arm_cpu_realizefn().
231
+ */
232
+ cpu->host_cpu_probe_failed = true;
233
+ return;
234
+ }
235
+ }
236
+
237
+ cpu->dtb_compatible = arm_host_cpu_features.dtb_compatible;
238
+ cpu->isar = arm_host_cpu_features.isar;
239
+ cpu->env.features = arm_host_cpu_features.features;
240
+ cpu->midr = arm_host_cpu_features.midr;
241
+ cpu->reset_sctlr = arm_host_cpu_features.reset_sctlr;
242
+}
243
+
244
void hvf_arch_vcpu_destroy(CPUState *cpu)
245
{
246
}
247
--
198
--
248
2.20.1
199
2.25.1
249
250
diff view generated by jsdifflib
1
When not predicating, implement the MVE bitwise logical insns
1
The only time we use the int_combiner_irq[] and ext_combiner_irq[]
2
directly using TCG vector operations.
2
arrays in the Exynos4210Irq struct is during realize of the SoC -- we
3
initialize them with the input IRQs of the combiner devices, and then
4
connect those to outputs of other devices in
5
exynos4210_init_board_irqs(). Now that the combiner objects are
6
easily accessible as s->int_combiner and s->ext_combiner we can make
7
the connections directly from one device to the other without going
8
via these arrays.
9
10
Since these are the only two remaining elements of Exynos4210Irq,
11
we can remove that struct entirely.
3
12
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20210913095440.13462-5-peter.maydell@linaro.org
15
Message-id: 20220404154658.565020-19-peter.maydell@linaro.org
8
---
16
---
9
target/arm/translate-mve.c | 51 +++++++++++++++++++++++++++-----------
17
include/hw/arm/exynos4210.h | 6 ------
10
1 file changed, 36 insertions(+), 15 deletions(-)
18
hw/arm/exynos4210.c | 34 ++++++++--------------------------
19
2 files changed, 8 insertions(+), 32 deletions(-)
11
20
12
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
21
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
13
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/translate-mve.c
23
--- a/include/hw/arm/exynos4210.h
15
+++ b/target/arm/translate-mve.c
24
+++ b/include/hw/arm/exynos4210.h
16
@@ -XXX,XX +XXX,XX @@ static TCGv_ptr mve_qreg_ptr(unsigned reg)
25
@@ -XXX,XX +XXX,XX @@
17
return ret;
26
*/
27
#define EXYNOS4210_NUM_SPLITTERS (EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ + 38)
28
29
-typedef struct Exynos4210Irq {
30
- qemu_irq int_combiner_irq[EXYNOS4210_MAX_INT_COMBINER_IN_IRQ];
31
- qemu_irq ext_combiner_irq[EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ];
32
-} Exynos4210Irq;
33
-
34
struct Exynos4210State {
35
/*< private >*/
36
SysBusDevice parent_obj;
37
/*< public >*/
38
ARMCPU *cpu[EXYNOS4210_NCPUS];
39
- Exynos4210Irq irqs;
40
qemu_irq irq_table[EXYNOS4210_MAX_INT_COMBINER_IN_IRQ];
41
42
MemoryRegion chipid_mem;
43
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
44
index XXXXXXX..XXXXXXX 100644
45
--- a/hw/arm/exynos4210.c
46
+++ b/hw/arm/exynos4210.c
47
@@ -XXX,XX +XXX,XX @@ static int mapline_size(const int *mapline)
48
static void exynos4210_init_board_irqs(Exynos4210State *s)
49
{
50
uint32_t grp, bit, irq_id, n;
51
- Exynos4210Irq *is = &s->irqs;
52
DeviceState *extgicdev = DEVICE(&s->ext_gic);
53
+ DeviceState *intcdev = DEVICE(&s->int_combiner);
54
+ DeviceState *extcdev = DEVICE(&s->ext_combiner);
55
int splitcount = 0;
56
DeviceState *splitter;
57
const int *mapline;
58
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init_board_irqs(Exynos4210State *s)
59
splitin = 0;
60
for (;;) {
61
s->irq_table[in] = qdev_get_gpio_in(splitter, 0);
62
- qdev_connect_gpio_out(splitter, splitin, is->int_combiner_irq[in]);
63
- qdev_connect_gpio_out(splitter, splitin + 1, is->ext_combiner_irq[in]);
64
+ qdev_connect_gpio_out(splitter, splitin,
65
+ qdev_get_gpio_in(intcdev, in));
66
+ qdev_connect_gpio_out(splitter, splitin + 1,
67
+ qdev_get_gpio_in(extcdev, in));
68
splitin += 2;
69
if (!mapline) {
70
break;
71
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init_board_irqs(Exynos4210State *s)
72
qdev_realize(splitter, NULL, &error_abort);
73
splitcount++;
74
s->irq_table[n] = qdev_get_gpio_in(splitter, 0);
75
- qdev_connect_gpio_out(splitter, 0, is->int_combiner_irq[n]);
76
+ qdev_connect_gpio_out(splitter, 0, qdev_get_gpio_in(intcdev, n));
77
qdev_connect_gpio_out(splitter, 1,
78
qdev_get_gpio_in(extgicdev, irq_id - 32));
79
} else {
80
- s->irq_table[n] = is->int_combiner_irq[n];
81
+ s->irq_table[n] = qdev_get_gpio_in(intcdev, n);
82
}
83
}
84
/*
85
@@ -XXX,XX +XXX,XX @@ uint32_t exynos4210_get_irq(uint32_t grp, uint32_t bit)
86
return EXYNOS4210_COMBINER_GET_IRQ_NUM(grp, bit);
18
}
87
}
19
88
20
+static bool mve_no_predication(DisasContext *s)
89
-/*
21
+{
90
- * Get Combiner input GPIO into irqs structure
22
+ /*
91
- */
23
+ * Return true if we are executing the entire MVE instruction
92
-static void exynos4210_combiner_get_gpioin(Exynos4210Irq *irqs,
24
+ * with no predication or partial-execution, and so we can safely
93
- DeviceState *dev, int ext)
25
+ * use an inline TCG vector implementation.
94
-{
26
+ */
95
- int n;
27
+ return s->eci == 0 && s->mve_no_pred;
96
- int max;
28
+}
97
- qemu_irq *irq;
29
+
98
-
30
static bool mve_check_qreg_bank(DisasContext *s, int qmask)
99
- max = ext ? EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ :
31
{
100
- EXYNOS4210_MAX_INT_COMBINER_IN_IRQ;
32
/*
101
- irq = ext ? irqs->ext_combiner_irq : irqs->int_combiner_irq;
33
@@ -XXX,XX +XXX,XX @@ static bool trans_VNEG_fp(DisasContext *s, arg_1op *a)
102
-
34
return do_1op(s, a, fns[a->size]);
103
- for (n = 0; n < max; n++) {
35
}
104
- irq[n] = qdev_get_gpio_in(dev, n);
36
105
- }
37
-static bool do_2op(DisasContext *s, arg_2op *a, MVEGenTwoOpFn fn)
106
-}
38
+static bool do_2op_vec(DisasContext *s, arg_2op *a, MVEGenTwoOpFn fn,
107
-
39
+ GVecGen3Fn *vecfn)
108
static uint8_t chipid_and_omr[] = { 0x11, 0x02, 0x21, 0x43,
40
{
109
0x09, 0x00, 0x00, 0x00 };
41
TCGv_ptr qd, qn, qm;
110
42
111
@@ -XXX,XX +XXX,XX @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
43
@@ -XXX,XX +XXX,XX @@ static bool do_2op(DisasContext *s, arg_2op *a, MVEGenTwoOpFn fn)
112
sysbus_connect_irq(busdev, n,
44
return true;
113
qdev_get_gpio_in(DEVICE(&s->a9mpcore), n));
45
}
114
}
46
115
- exynos4210_combiner_get_gpioin(&s->irqs, DEVICE(&s->int_combiner), 0);
47
- qd = mve_qreg_ptr(a->qd);
116
sysbus_mmio_map(busdev, 0, EXYNOS4210_INT_COMBINER_BASE_ADDR);
48
- qn = mve_qreg_ptr(a->qn);
117
49
- qm = mve_qreg_ptr(a->qm);
118
/* External Interrupt Combiner */
50
- fn(cpu_env, qd, qn, qm);
119
@@ -XXX,XX +XXX,XX @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
51
- tcg_temp_free_ptr(qd);
120
for (n = 0; n < EXYNOS4210_MAX_INT_COMBINER_OUT_IRQ; n++) {
52
- tcg_temp_free_ptr(qn);
121
sysbus_connect_irq(busdev, n, qdev_get_gpio_in(DEVICE(&s->ext_gic), n));
53
- tcg_temp_free_ptr(qm);
54
+ if (vecfn && mve_no_predication(s)) {
55
+ vecfn(a->size, mve_qreg_offset(a->qd), mve_qreg_offset(a->qn),
56
+ mve_qreg_offset(a->qm), 16, 16);
57
+ } else {
58
+ qd = mve_qreg_ptr(a->qd);
59
+ qn = mve_qreg_ptr(a->qn);
60
+ qm = mve_qreg_ptr(a->qm);
61
+ fn(cpu_env, qd, qn, qm);
62
+ tcg_temp_free_ptr(qd);
63
+ tcg_temp_free_ptr(qn);
64
+ tcg_temp_free_ptr(qm);
65
+ }
66
mve_update_eci(s);
67
return true;
68
}
69
70
-#define DO_LOGIC(INSN, HELPER) \
71
+static bool do_2op(DisasContext *s, arg_2op *a, MVEGenTwoOpFn *fn)
72
+{
73
+ return do_2op_vec(s, a, fn, NULL);
74
+}
75
+
76
+#define DO_LOGIC(INSN, HELPER, VECFN) \
77
static bool trans_##INSN(DisasContext *s, arg_2op *a) \
78
{ \
79
- return do_2op(s, a, HELPER); \
80
+ return do_2op_vec(s, a, HELPER, VECFN); \
81
}
122
}
82
123
- exynos4210_combiner_get_gpioin(&s->irqs, DEVICE(&s->ext_combiner), 1);
83
-DO_LOGIC(VAND, gen_helper_mve_vand)
124
sysbus_mmio_map(busdev, 0, EXYNOS4210_EXT_COMBINER_BASE_ADDR);
84
-DO_LOGIC(VBIC, gen_helper_mve_vbic)
125
85
-DO_LOGIC(VORR, gen_helper_mve_vorr)
126
/* Initialize board IRQs. */
86
-DO_LOGIC(VORN, gen_helper_mve_vorn)
87
-DO_LOGIC(VEOR, gen_helper_mve_veor)
88
+DO_LOGIC(VAND, gen_helper_mve_vand, tcg_gen_gvec_and)
89
+DO_LOGIC(VBIC, gen_helper_mve_vbic, tcg_gen_gvec_andc)
90
+DO_LOGIC(VORR, gen_helper_mve_vorr, tcg_gen_gvec_or)
91
+DO_LOGIC(VORN, gen_helper_mve_vorn, tcg_gen_gvec_orc)
92
+DO_LOGIC(VEOR, gen_helper_mve_veor, tcg_gen_gvec_xor)
93
94
static bool trans_VPSEL(DisasContext *s, arg_2op *a)
95
{
96
--
127
--
97
2.20.1
128
2.25.1
98
99
diff view generated by jsdifflib
1
From: Alexander Graf <agraf@csgraf.de>
1
From: Zongyuan Li <zongyuan.li@smartx.com>
2
2
3
We will need to install a migration helper for the ARM hvf backend.
3
Signed-off-by: Zongyuan Li <zongyuan.li@smartx.com>
4
Let's introduce an arch callback for the overall hvf init chain to
5
do so.
6
7
Signed-off-by: Alexander Graf <agraf@csgraf.de>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Message-id: 20210916155404.86958-4-agraf@csgraf.de
5
Message-id: 20220324181557.203805-2-zongyuan.li@smartx.com
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
7
---
12
include/sysemu/hvf_int.h | 1 +
8
hw/arm/realview.c | 33 ++++++++++++++++++++++++---------
13
accel/hvf/hvf-accel-ops.c | 3 ++-
9
1 file changed, 24 insertions(+), 9 deletions(-)
14
target/i386/hvf/hvf.c | 5 +++++
15
3 files changed, 8 insertions(+), 1 deletion(-)
16
10
17
diff --git a/include/sysemu/hvf_int.h b/include/sysemu/hvf_int.h
11
diff --git a/hw/arm/realview.c b/hw/arm/realview.c
18
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
19
--- a/include/sysemu/hvf_int.h
13
--- a/hw/arm/realview.c
20
+++ b/include/sysemu/hvf_int.h
14
+++ b/hw/arm/realview.c
21
@@ -XXX,XX +XXX,XX @@ struct hvf_vcpu_state {
15
@@ -XXX,XX +XXX,XX @@
16
#include "hw/sysbus.h"
17
#include "hw/arm/boot.h"
18
#include "hw/arm/primecell.h"
19
+#include "hw/core/split-irq.h"
20
#include "hw/net/lan9118.h"
21
#include "hw/net/smc91c111.h"
22
#include "hw/pci/pci.h"
23
+#include "hw/qdev-core.h"
24
#include "net/net.h"
25
#include "sysemu/sysemu.h"
26
#include "hw/boards.h"
27
@@ -XXX,XX +XXX,XX @@ static const int realview_board_id[] = {
28
0x76d
22
};
29
};
23
30
24
void assert_hvf_ok(hv_return_t ret);
31
+static void split_irq_from_named(DeviceState *src, const char* outname,
25
+int hvf_arch_init(void);
32
+ qemu_irq out1, qemu_irq out2) {
26
int hvf_arch_init_vcpu(CPUState *cpu);
33
+ DeviceState *splitter = qdev_new(TYPE_SPLIT_IRQ);
27
void hvf_arch_vcpu_destroy(CPUState *cpu);
28
int hvf_vcpu_exec(CPUState *);
29
diff --git a/accel/hvf/hvf-accel-ops.c b/accel/hvf/hvf-accel-ops.c
30
index XXXXXXX..XXXXXXX 100644
31
--- a/accel/hvf/hvf-accel-ops.c
32
+++ b/accel/hvf/hvf-accel-ops.c
33
@@ -XXX,XX +XXX,XX @@ static int hvf_accel_init(MachineState *ms)
34
35
hvf_state = s;
36
memory_listener_register(&hvf_memory_listener, &address_space_memory);
37
- return 0;
38
+
34
+
39
+ return hvf_arch_init();
35
+ qdev_prop_set_uint32(splitter, "num-lines", 2);
40
}
36
+
41
37
+ qdev_realize_and_unref(splitter, NULL, &error_fatal);
42
static void hvf_accel_class_init(ObjectClass *oc, void *data)
38
+
43
diff --git a/target/i386/hvf/hvf.c b/target/i386/hvf/hvf.c
39
+ qdev_connect_gpio_out(splitter, 0, out1);
44
index XXXXXXX..XXXXXXX 100644
40
+ qdev_connect_gpio_out(splitter, 1, out2);
45
--- a/target/i386/hvf/hvf.c
41
+ qdev_connect_gpio_out_named(src, outname, 0,
46
+++ b/target/i386/hvf/hvf.c
42
+ qdev_get_gpio_in(splitter, 0));
47
@@ -XXX,XX +XXX,XX @@ static inline bool apic_bus_freq_is_known(CPUX86State *env)
48
return env->apic_bus_freq != 0;
49
}
50
51
+int hvf_arch_init(void)
52
+{
53
+ return 0;
54
+}
43
+}
55
+
44
+
56
int hvf_arch_init_vcpu(CPUState *cpu)
45
static void realview_init(MachineState *machine,
46
enum realview_board_type board_type)
57
{
47
{
58
X86CPU *x86cpu = X86_CPU(cpu);
48
@@ -XXX,XX +XXX,XX @@ static void realview_init(MachineState *machine,
49
DeviceState *dev, *sysctl, *gpio2, *pl041;
50
SysBusDevice *busdev;
51
qemu_irq pic[64];
52
- qemu_irq mmc_irq[2];
53
PCIBus *pci_bus = NULL;
54
NICInfo *nd;
55
DriveInfo *dinfo;
56
@@ -XXX,XX +XXX,XX @@ static void realview_init(MachineState *machine,
57
* and the PL061 has them the other way about. Also the card
58
* detect line is inverted.
59
*/
60
- mmc_irq[0] = qemu_irq_split(
61
- qdev_get_gpio_in(sysctl, ARM_SYSCTL_GPIO_MMC_WPROT),
62
- qdev_get_gpio_in(gpio2, 1));
63
- mmc_irq[1] = qemu_irq_split(
64
- qdev_get_gpio_in(sysctl, ARM_SYSCTL_GPIO_MMC_CARDIN),
65
- qemu_irq_invert(qdev_get_gpio_in(gpio2, 0)));
66
- qdev_connect_gpio_out_named(dev, "card-read-only", 0, mmc_irq[0]);
67
- qdev_connect_gpio_out_named(dev, "card-inserted", 0, mmc_irq[1]);
68
+ split_irq_from_named(dev, "card-read-only",
69
+ qdev_get_gpio_in(sysctl, ARM_SYSCTL_GPIO_MMC_WPROT),
70
+ qdev_get_gpio_in(gpio2, 1));
71
+
72
+ split_irq_from_named(dev, "card-inserted",
73
+ qdev_get_gpio_in(sysctl, ARM_SYSCTL_GPIO_MMC_CARDIN),
74
+ qemu_irq_invert(qdev_get_gpio_in(gpio2, 0)));
75
+
76
dinfo = drive_get(IF_SD, 0, 0);
77
if (dinfo) {
78
DeviceState *card;
59
--
79
--
60
2.20.1
80
2.25.1
61
62
diff view generated by jsdifflib
New patch
1
From: Zongyuan Li <zongyuan.li@smartx.com>
1
2
3
Signed-off-by: Zongyuan Li <zongyuan.li@smartx.com>
4
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
5
Message-id: 20220324181557.203805-3-zongyuan.li@smartx.com
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
8
hw/arm/stellaris.c | 15 +++++++++++++--
9
1 file changed, 13 insertions(+), 2 deletions(-)
10
11
diff --git a/hw/arm/stellaris.c b/hw/arm/stellaris.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/hw/arm/stellaris.c
14
+++ b/hw/arm/stellaris.c
15
@@ -XXX,XX +XXX,XX @@
16
17
#include "qemu/osdep.h"
18
#include "qapi/error.h"
19
+#include "hw/core/split-irq.h"
20
#include "hw/sysbus.h"
21
#include "hw/sd/sd.h"
22
#include "hw/ssi/ssi.h"
23
@@ -XXX,XX +XXX,XX @@ static void stellaris_init(MachineState *ms, stellaris_board_info *board)
24
DeviceState *ssddev;
25
DriveInfo *dinfo;
26
DeviceState *carddev;
27
+ DeviceState *gpio_d_splitter;
28
BlockBackend *blk;
29
30
/*
31
@@ -XXX,XX +XXX,XX @@ static void stellaris_init(MachineState *ms, stellaris_board_info *board)
32
&error_fatal);
33
34
ssddev = ssi_create_peripheral(bus, "ssd0323");
35
- gpio_out[GPIO_D][0] = qemu_irq_split(
36
- qdev_get_gpio_in_named(sddev, SSI_GPIO_CS, 0),
37
+
38
+ gpio_d_splitter = qdev_new(TYPE_SPLIT_IRQ);
39
+ qdev_prop_set_uint32(gpio_d_splitter, "num-lines", 2);
40
+ qdev_realize_and_unref(gpio_d_splitter, NULL, &error_fatal);
41
+ qdev_connect_gpio_out(
42
+ gpio_d_splitter, 0,
43
+ qdev_get_gpio_in_named(sddev, SSI_GPIO_CS, 0));
44
+ qdev_connect_gpio_out(
45
+ gpio_d_splitter, 1,
46
qdev_get_gpio_in_named(ssddev, SSI_GPIO_CS, 0));
47
+ gpio_out[GPIO_D][0] = qdev_get_gpio_in(gpio_d_splitter, 0);
48
+
49
gpio_out[GPIO_C][7] = qdev_get_gpio_in(ssddev, 0);
50
51
/* Make sure the select pin is high. */
52
--
53
2.25.1
diff view generated by jsdifflib
1
From: Alexander Graf <agraf@csgraf.de>
1
From: Zongyuan Li <zongyuan.li@smartx.com>
2
2
3
We will need PMC register definitions in accel specific code later.
3
Signed-off-by: Zongyuan Li <zongyuan.li@smartx.com>
4
Move all constant definitions to common arm headers so we can reuse
5
them.
6
7
Signed-off-by: Alexander Graf <agraf@csgraf.de>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Message-id: 20210916155404.86958-2-agraf@csgraf.de
5
Message-id: 20220324181557.203805-5-zongyuan.li@smartx.com
6
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/811
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
8
---
12
target/arm/internals.h | 44 ++++++++++++++++++++++++++++++++++++++++++
9
include/hw/irq.h | 5 -----
13
target/arm/helper.c | 44 ------------------------------------------
10
hw/core/irq.c | 15 ---------------
14
2 files changed, 44 insertions(+), 44 deletions(-)
11
2 files changed, 20 deletions(-)
15
12
16
diff --git a/target/arm/internals.h b/target/arm/internals.h
13
diff --git a/include/hw/irq.h b/include/hw/irq.h
17
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/internals.h
15
--- a/include/hw/irq.h
19
+++ b/target/arm/internals.h
16
+++ b/include/hw/irq.h
20
@@ -XXX,XX +XXX,XX @@ enum MVEECIState {
17
@@ -XXX,XX +XXX,XX @@ void qemu_free_irq(qemu_irq irq);
21
/* All other values reserved */
18
/* Returns a new IRQ with opposite polarity. */
22
};
19
qemu_irq qemu_irq_invert(qemu_irq irq);
23
20
24
+/* Definitions for the PMU registers */
21
-/* Returns a new IRQ which feeds into both the passed IRQs.
25
+#define PMCRN_MASK 0xf800
22
- * It's probably better to use the TYPE_SPLIT_IRQ device instead.
26
+#define PMCRN_SHIFT 11
23
- */
27
+#define PMCRLC 0x40
24
-qemu_irq qemu_irq_split(qemu_irq irq1, qemu_irq irq2);
28
+#define PMCRDP 0x20
25
-
29
+#define PMCRX 0x10
26
/* For internal use in qtest. Similar to qemu_irq_split, but operating
30
+#define PMCRD 0x8
27
on an existing vector of qemu_irq. */
31
+#define PMCRC 0x4
28
void qemu_irq_intercept_in(qemu_irq *gpio_in, qemu_irq_handler handler, int n);
32
+#define PMCRP 0x2
29
diff --git a/hw/core/irq.c b/hw/core/irq.c
33
+#define PMCRE 0x1
34
+/*
35
+ * Mask of PMCR bits writeable by guest (not including WO bits like C, P,
36
+ * which can be written as 1 to trigger behaviour but which stay RAZ).
37
+ */
38
+#define PMCR_WRITEABLE_MASK (PMCRLC | PMCRDP | PMCRX | PMCRD | PMCRE)
39
+
40
+#define PMXEVTYPER_P 0x80000000
41
+#define PMXEVTYPER_U 0x40000000
42
+#define PMXEVTYPER_NSK 0x20000000
43
+#define PMXEVTYPER_NSU 0x10000000
44
+#define PMXEVTYPER_NSH 0x08000000
45
+#define PMXEVTYPER_M 0x04000000
46
+#define PMXEVTYPER_MT 0x02000000
47
+#define PMXEVTYPER_EVTCOUNT 0x0000ffff
48
+#define PMXEVTYPER_MASK (PMXEVTYPER_P | PMXEVTYPER_U | PMXEVTYPER_NSK | \
49
+ PMXEVTYPER_NSU | PMXEVTYPER_NSH | \
50
+ PMXEVTYPER_M | PMXEVTYPER_MT | \
51
+ PMXEVTYPER_EVTCOUNT)
52
+
53
+#define PMCCFILTR 0xf8000000
54
+#define PMCCFILTR_M PMXEVTYPER_M
55
+#define PMCCFILTR_EL0 (PMCCFILTR | PMCCFILTR_M)
56
+
57
+static inline uint32_t pmu_num_counters(CPUARMState *env)
58
+{
59
+ return (env->cp15.c9_pmcr & PMCRN_MASK) >> PMCRN_SHIFT;
60
+}
61
+
62
+/* Bits allowed to be set/cleared for PMCNTEN* and PMINTEN* */
63
+static inline uint64_t pmu_counter_mask(CPUARMState *env)
64
+{
65
+ return (1 << 31) | ((1 << pmu_num_counters(env)) - 1);
66
+}
67
+
68
#endif
69
diff --git a/target/arm/helper.c b/target/arm/helper.c
70
index XXXXXXX..XXXXXXX 100644
30
index XXXXXXX..XXXXXXX 100644
71
--- a/target/arm/helper.c
31
--- a/hw/core/irq.c
72
+++ b/target/arm/helper.c
32
+++ b/hw/core/irq.c
73
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo v6_cp_reginfo[] = {
33
@@ -XXX,XX +XXX,XX @@ qemu_irq qemu_irq_invert(qemu_irq irq)
74
REGINFO_SENTINEL
34
return qemu_allocate_irq(qemu_notirq, irq, 0);
75
};
35
}
76
36
77
-/* Definitions for the PMU registers */
37
-static void qemu_splitirq(void *opaque, int line, int level)
78
-#define PMCRN_MASK 0xf800
79
-#define PMCRN_SHIFT 11
80
-#define PMCRLC 0x40
81
-#define PMCRDP 0x20
82
-#define PMCRX 0x10
83
-#define PMCRD 0x8
84
-#define PMCRC 0x4
85
-#define PMCRP 0x2
86
-#define PMCRE 0x1
87
-/*
88
- * Mask of PMCR bits writeable by guest (not including WO bits like C, P,
89
- * which can be written as 1 to trigger behaviour but which stay RAZ).
90
- */
91
-#define PMCR_WRITEABLE_MASK (PMCRLC | PMCRDP | PMCRX | PMCRD | PMCRE)
92
-
93
-#define PMXEVTYPER_P 0x80000000
94
-#define PMXEVTYPER_U 0x40000000
95
-#define PMXEVTYPER_NSK 0x20000000
96
-#define PMXEVTYPER_NSU 0x10000000
97
-#define PMXEVTYPER_NSH 0x08000000
98
-#define PMXEVTYPER_M 0x04000000
99
-#define PMXEVTYPER_MT 0x02000000
100
-#define PMXEVTYPER_EVTCOUNT 0x0000ffff
101
-#define PMXEVTYPER_MASK (PMXEVTYPER_P | PMXEVTYPER_U | PMXEVTYPER_NSK | \
102
- PMXEVTYPER_NSU | PMXEVTYPER_NSH | \
103
- PMXEVTYPER_M | PMXEVTYPER_MT | \
104
- PMXEVTYPER_EVTCOUNT)
105
-
106
-#define PMCCFILTR 0xf8000000
107
-#define PMCCFILTR_M PMXEVTYPER_M
108
-#define PMCCFILTR_EL0 (PMCCFILTR | PMCCFILTR_M)
109
-
110
-static inline uint32_t pmu_num_counters(CPUARMState *env)
111
-{
38
-{
112
- return (env->cp15.c9_pmcr & PMCRN_MASK) >> PMCRN_SHIFT;
39
- struct IRQState **irq = opaque;
40
- irq[0]->handler(irq[0]->opaque, irq[0]->n, level);
41
- irq[1]->handler(irq[1]->opaque, irq[1]->n, level);
113
-}
42
-}
114
-
43
-
115
-/* Bits allowed to be set/cleared for PMCNTEN* and PMINTEN* */
44
-qemu_irq qemu_irq_split(qemu_irq irq1, qemu_irq irq2)
116
-static inline uint64_t pmu_counter_mask(CPUARMState *env)
117
-{
45
-{
118
- return (1 << 31) | ((1 << pmu_num_counters(env)) - 1);
46
- qemu_irq *s = g_new0(qemu_irq, 2);
47
- s[0] = irq1;
48
- s[1] = irq2;
49
- return qemu_allocate_irq(qemu_splitirq, s, 0);
119
-}
50
-}
120
-
51
-
121
typedef struct pm_event {
52
void qemu_irq_intercept_in(qemu_irq *gpio_in, qemu_irq_handler handler, int n)
122
uint16_t number; /* PMEVTYPER.evtCount is 16 bits wide */
53
{
123
/* If the event is supported on this CPU (used to generate PMCEID[01]) */
54
int i;
124
--
55
--
125
2.20.1
56
2.25.1
126
127
diff view generated by jsdifflib
1
From: Alexander Graf <agraf@csgraf.de>
1
From: Heinrich Schuchardt <heinrich.schuchardt@canonical.com>
2
2
3
Hvf's permission bitmap during and after dirty logging does not include
3
Describe that the gic-version influences the maximum number of CPUs.
4
the HV_MEMORY_EXEC permission. At least on Apple Silicon, this leads to
5
instruction faults once dirty logging was enabled.
6
4
7
Add the bit to make it work properly.
5
Signed-off-by: Heinrich Schuchardt <heinrich.schuchardt@canonical.com>
8
6
Message-id: 20220413231456.35811-1-heinrich.schuchardt@canonical.com
9
Signed-off-by: Alexander Graf <agraf@csgraf.de>
7
[PMM: minor punctuation tweaks]
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Message-id: 20210916155404.86958-3-agraf@csgraf.de
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
10
---
14
accel/hvf/hvf-accel-ops.c | 4 ++--
11
docs/system/arm/virt.rst | 4 ++--
15
1 file changed, 2 insertions(+), 2 deletions(-)
12
1 file changed, 2 insertions(+), 2 deletions(-)
16
13
17
diff --git a/accel/hvf/hvf-accel-ops.c b/accel/hvf/hvf-accel-ops.c
14
diff --git a/docs/system/arm/virt.rst b/docs/system/arm/virt.rst
18
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
19
--- a/accel/hvf/hvf-accel-ops.c
16
--- a/docs/system/arm/virt.rst
20
+++ b/accel/hvf/hvf-accel-ops.c
17
+++ b/docs/system/arm/virt.rst
21
@@ -XXX,XX +XXX,XX @@ static void hvf_set_dirty_tracking(MemoryRegionSection *section, bool on)
18
@@ -XXX,XX +XXX,XX @@ gic-version
22
if (on) {
19
Valid values are:
23
slot->flags |= HVF_SLOT_LOG;
20
24
hv_vm_protect((uintptr_t)slot->start, (size_t)slot->size,
21
``2``
25
- HV_MEMORY_READ);
22
- GICv2
26
+ HV_MEMORY_READ | HV_MEMORY_EXEC);
23
+ GICv2. Note that this limits the number of CPUs to 8.
27
/* stop tracking region*/
24
``3``
28
} else {
25
- GICv3
29
slot->flags &= ~HVF_SLOT_LOG;
26
+ GICv3. This allows up to 512 CPUs.
30
hv_vm_protect((uintptr_t)slot->start, (size_t)slot->size,
27
``host``
31
- HV_MEMORY_READ | HV_MEMORY_WRITE);
28
Use the same GIC version the host provides, when using KVM
32
+ HV_MEMORY_READ | HV_MEMORY_WRITE | HV_MEMORY_EXEC);
29
``max``
33
}
34
}
35
36
--
30
--
37
2.20.1
31
2.25.1
38
39
diff view generated by jsdifflib
1
From: Shashi Mallela <shashi.mallela@linaro.org>
1
From: Hao Wu <wuhaotsh@google.com>
2
2
3
During sbsa acs level 3 testing, it is seen that the GIC maintenance
3
Similar to the Aspeed code in include/misc/aspeed_scu.h, we define
4
interrupts are not triggered and the related test cases fail. This
4
the PWRON STRAP fields in their corresponding module for NPCM7XX.
5
is because we were incorrectly passing the value of the MISR register
6
(from maintenance_interrupt_state()) to qemu_set_irq() as the level
7
argument, whereas the device on the other end of this irq line
8
expects a 0/1 value.
9
5
10
Fix the logic to pass a 0/1 level indication, rather than a
6
Signed-off-by: Hao Wu <wuhaotsh@google.com>
11
0/not-0 value.
7
Reviewed-by: Patrick Venture <venture@google.com>
12
8
Message-id: 20220411165842.3912945-2-wuhaotsh@google.com
13
Fixes: c5fc89b36c0 ("hw/intc/arm_gicv3: Implement gicv3_cpuif_virt_update()")
14
Signed-off-by: Shashi Mallela <shashi.mallela@linaro.org>
15
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
16
Message-id: 20210915205809.59068-1-shashi.mallela@linaro.org
17
[PMM: tweaked commit message; collapsed nested if()s into one]
18
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
19
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
20
---
11
---
21
hw/intc/arm_gicv3_cpuif.c | 5 +++--
12
include/hw/misc/npcm7xx_gcr.h | 30 ++++++++++++++++++++++++++++++
22
1 file changed, 3 insertions(+), 2 deletions(-)
13
1 file changed, 30 insertions(+)
23
14
24
diff --git a/hw/intc/arm_gicv3_cpuif.c b/hw/intc/arm_gicv3_cpuif.c
15
diff --git a/include/hw/misc/npcm7xx_gcr.h b/include/hw/misc/npcm7xx_gcr.h
25
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
26
--- a/hw/intc/arm_gicv3_cpuif.c
17
--- a/include/hw/misc/npcm7xx_gcr.h
27
+++ b/hw/intc/arm_gicv3_cpuif.c
18
+++ b/include/hw/misc/npcm7xx_gcr.h
28
@@ -XXX,XX +XXX,XX @@ static void gicv3_cpuif_virt_update(GICv3CPUState *cs)
19
@@ -XXX,XX +XXX,XX @@
29
}
20
#include "exec/memory.h"
30
}
21
#include "hw/sysbus.h"
31
22
32
- if (cs->ich_hcr_el2 & ICH_HCR_EL2_EN) {
23
+/*
33
- maintlevel = maintenance_interrupt_state(cs);
24
+ * NPCM7XX PWRON STRAP bit fields
34
+ if ((cs->ich_hcr_el2 & ICH_HCR_EL2_EN) &&
25
+ * 12: SPI0 powered by VSBV3 at 1.8V
35
+ maintenance_interrupt_state(cs) != 0) {
26
+ * 11: System flash attached to BMC
36
+ maintlevel = 1;
27
+ * 10: BSP alternative pins.
37
}
28
+ * 9:8: Flash UART command route enabled.
38
29
+ * 7: Security enabled.
39
trace_gicv3_cpuif_virt_set_irqs(gicv3_redist_affid(cs), fiqlevel,
30
+ * 6: HI-Z state control.
31
+ * 5: ECC disabled.
32
+ * 4: Reserved
33
+ * 3: JTAG2 enabled.
34
+ * 2:0: CPU and DRAM clock frequency.
35
+ */
36
+#define NPCM7XX_PWRON_STRAP_SPI0F18 BIT(12)
37
+#define NPCM7XX_PWRON_STRAP_SFAB BIT(11)
38
+#define NPCM7XX_PWRON_STRAP_BSPA BIT(10)
39
+#define NPCM7XX_PWRON_STRAP_FUP(x) ((x) << 8)
40
+#define FUP_NORM_UART2 3
41
+#define FUP_PROG_UART3 2
42
+#define FUP_PROG_UART2 1
43
+#define FUP_NORM_UART3 0
44
+#define NPCM7XX_PWRON_STRAP_SECEN BIT(7)
45
+#define NPCM7XX_PWRON_STRAP_HIZ BIT(6)
46
+#define NPCM7XX_PWRON_STRAP_ECC BIT(5)
47
+#define NPCM7XX_PWRON_STRAP_RESERVE1 BIT(4)
48
+#define NPCM7XX_PWRON_STRAP_J2EN BIT(3)
49
+#define NPCM7XX_PWRON_STRAP_CKFRQ(x) (x)
50
+#define CKFRQ_SKIPINIT 0x000
51
+#define CKFRQ_DEFAULT 0x111
52
+
53
/*
54
* Number of registers in our device state structure. Don't change this without
55
* incrementing the version_id in the vmstate.
40
--
56
--
41
2.20.1
57
2.25.1
42
43
diff view generated by jsdifflib
1
Coverity points out that we aren't checking the return value
1
From: Hao Wu <wuhaotsh@google.com>
2
from curl_easy_setopt().
3
2
4
Fixes: Coverity CID 1458895
3
This patch uses the defined fields to describe PWRON STRAPs for
5
Inspired-by: Peter Maydell <peter.maydell@linaro.org>
4
better readability.
6
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
5
7
Reviewed-by: Viktor Prutyanov <viktor.prutyanov@phystech.edu>
6
Signed-off-by: Hao Wu <wuhaotsh@google.com>
8
Tested-by: Viktor Prutyanov <viktor.prutyanov@phystech.edu>
7
Reviewed-by: Patrick Venture <venture@google.com>
9
Message-id: 20210910170656.366592-2-philmd@redhat.com
8
Message-id: 20220411165842.3912945-3-wuhaotsh@google.com
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
11
---
12
contrib/elf2dmp/download.c | 22 ++++++++++------------
12
hw/arm/npcm7xx_boards.c | 24 +++++++++++++++++++-----
13
1 file changed, 10 insertions(+), 12 deletions(-)
13
1 file changed, 19 insertions(+), 5 deletions(-)
14
14
15
diff --git a/contrib/elf2dmp/download.c b/contrib/elf2dmp/download.c
15
diff --git a/hw/arm/npcm7xx_boards.c b/hw/arm/npcm7xx_boards.c
16
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
17
--- a/contrib/elf2dmp/download.c
17
--- a/hw/arm/npcm7xx_boards.c
18
+++ b/contrib/elf2dmp/download.c
18
+++ b/hw/arm/npcm7xx_boards.c
19
@@ -XXX,XX +XXX,XX @@ int download_url(const char *name, const char *url)
19
@@ -XXX,XX +XXX,XX @@
20
goto out_curl;
20
#include "sysemu/sysemu.h"
21
}
21
#include "sysemu/block-backend.h"
22
22
23
- curl_easy_setopt(curl, CURLOPT_URL, url);
23
-#define NPCM750_EVB_POWER_ON_STRAPS 0x00001ff7
24
- curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, NULL);
24
-#define QUANTA_GSJ_POWER_ON_STRAPS 0x00001fff
25
- curl_easy_setopt(curl, CURLOPT_WRITEDATA, file);
25
-#define QUANTA_GBS_POWER_ON_STRAPS 0x000017ff
26
- curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
26
-#define KUDO_BMC_POWER_ON_STRAPS 0x00001fff
27
- curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0);
27
-#define MORI_BMC_POWER_ON_STRAPS 0x00001fff
28
-
28
+#define NPCM7XX_POWER_ON_STRAPS_DEFAULT ( \
29
- if (curl_easy_perform(curl) != CURLE_OK) {
29
+ NPCM7XX_PWRON_STRAP_SPI0F18 | \
30
- err = 1;
30
+ NPCM7XX_PWRON_STRAP_SFAB | \
31
- fclose(file);
31
+ NPCM7XX_PWRON_STRAP_BSPA | \
32
+ if (curl_easy_setopt(curl, CURLOPT_URL, url) != CURLE_OK
32
+ NPCM7XX_PWRON_STRAP_FUP(FUP_NORM_UART2) | \
33
+ || curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, NULL) != CURLE_OK
33
+ NPCM7XX_PWRON_STRAP_SECEN | \
34
+ || curl_easy_setopt(curl, CURLOPT_WRITEDATA, file) != CURLE_OK
34
+ NPCM7XX_PWRON_STRAP_HIZ | \
35
+ || curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1) != CURLE_OK
35
+ NPCM7XX_PWRON_STRAP_ECC | \
36
+ || curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0) != CURLE_OK
36
+ NPCM7XX_PWRON_STRAP_RESERVE1 | \
37
+ || curl_easy_perform(curl) != CURLE_OK) {
37
+ NPCM7XX_PWRON_STRAP_J2EN | \
38
unlink(name);
38
+ NPCM7XX_PWRON_STRAP_CKFRQ(CKFRQ_DEFAULT))
39
- goto out_curl;
39
+
40
+ fclose(file);
40
+#define NPCM750_EVB_POWER_ON_STRAPS ( \
41
+ err = 1;
41
+ NPCM7XX_POWER_ON_STRAPS_DEFAULT & ~NPCM7XX_PWRON_STRAP_J2EN)
42
+ } else {
42
+#define QUANTA_GSJ_POWER_ON_STRAPS NPCM7XX_POWER_ON_STRAPS_DEFAULT
43
+ err = fclose(file);
43
+#define QUANTA_GBS_POWER_ON_STRAPS ( \
44
}
44
+ NPCM7XX_POWER_ON_STRAPS_DEFAULT & ~NPCM7XX_PWRON_STRAP_SFAB)
45
45
+#define KUDO_BMC_POWER_ON_STRAPS NPCM7XX_POWER_ON_STRAPS_DEFAULT
46
- err = fclose(file);
46
+#define MORI_BMC_POWER_ON_STRAPS NPCM7XX_POWER_ON_STRAPS_DEFAULT
47
-
47
48
out_curl:
48
static const char npcm7xx_default_bootrom[] = "npcm7xx_bootrom.bin";
49
curl_easy_cleanup(curl);
50
49
51
--
50
--
52
2.20.1
51
2.25.1
53
54
diff view generated by jsdifflib