1
First arm pullreq for 7.1. The bulk of this is the qemu_split_irq
1
Hi; here's a target-arm pullreq to go in before softfreeze.
2
removal.
2
This is actually pretty much entirely bugfixes (since the
3
3
SEL2 timers we implement here are a missing part of a feature
4
I have enough stuff in my to-review queue that I expect to do another
4
we claim to already implement).
5
pullreq early next week, but 31 patches is enough to not hang on to.
6
5
7
thanks
6
thanks
8
-- PMM
7
-- PMM
9
8
10
The following changes since commit 9c125d17e9402c232c46610802e5931b3639d77b:
9
The following changes since commit 98c7362b1efe651327385a25874a73e008c6549e:
11
10
12
Merge tag 'pull-tcg-20220420' of https://gitlab.com/rth7680/qemu into staging (2022-04-20 16:43:11 -0700)
11
Merge tag 'accel-cpus-20250306' of https://github.com/philmd/qemu into staging (2025-03-07 07:39:49 +0800)
13
12
14
are available in the Git repository at:
13
are available in the Git repository at:
15
14
16
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20220421
15
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20250307
17
16
18
for you to fetch changes up to 5b415dd61bdbf61fb4be0e9f1a7172b8bce682c6:
17
for you to fetch changes up to 0ce0739d46983e5e88fa9c149cb305689c9d8c6f:
19
18
20
hw/arm: Use bit fields for NPCM7XX PWRON STRAPs (2022-04-21 11:37:05 +0100)
19
target/rx: Remove TCG_CALL_NO_WG from helpers which write env (2025-03-07 15:03:20 +0000)
21
20
22
----------------------------------------------------------------
21
----------------------------------------------------------------
23
target-arm queue:
22
target-arm queue:
24
* hw/arm/virt: Check for attempt to use TrustZone with KVM or HVF
23
* hw/arm/smmu-common: Remove the repeated ttb field
25
* versal: Add the Cortex-R5s in the Real-Time Processing Unit (RPU) subsystem
24
* hw/gpio: npcm7xx: fixup out-of-bounds access
26
* versal: model enough of the Clock/Reset Low-power domain (CRL) to allow control of the Cortex-R5s
25
* tests/functional/test_arm_sx1: Check whether the serial console is working
27
* xlnx-zynqmp: Connect 4 TTC timers
26
* target/arm: Fix minor bugs in generic timer register handling
28
* exynos4210: Refactor GIC/combiner code to stop using qemu_split_irq
27
* target/arm: Implement SEL2 physical and virtual timers
29
* realview: replace 'qemu_split_irq' with 'TYPE_SPLIT_IRQ'
28
* target/arm: Correct STRD, LDRD atomicity and fault behaviour
30
* stellaris: replace 'qemu_split_irq' with 'TYPE_SPLIT_IRQ'
29
* target/arm: Make dummy debug registers RAZ, not NOP
31
* hw/core/irq: remove unused 'qemu_irq_split' function
30
* util/qemu-timer.c: Don't warp timer from timerlist_rearm()
32
* npcm7xx: use symbolic constants for PWRON STRAP bit fields
31
* include/exec/memop.h: Expand comment for MO_ATOM_SUBALIGN
33
* virt: document impact of gic-version on max CPUs
32
* hw/arm/smmu: Introduce smmu_configs_inv_sid_range() helper
33
* target/rx: Set exception vector base to 0xffffff80
34
* target/rx: Remove TCG_CALL_NO_WG from helpers which write env
34
35
35
----------------------------------------------------------------
36
----------------------------------------------------------------
36
Edgar E. Iglesias (6):
37
Alex Bennée (4):
37
timer: cadence_ttc: Break out header file to allow embedding
38
target/arm: Implement SEL2 physical and virtual timers
38
hw/arm/xlnx-zynqmp: Connect 4 TTC timers
39
target/arm: Document the architectural names of our GTIMERs
39
hw/arm: versal: Create an APU CPU Cluster
40
hw/arm: enable secure EL2 timers for virt machine
40
hw/arm: versal: Add the Cortex-R5Fs
41
hw/arm: enable secure EL2 timers for sbsa machine
41
hw/misc: Add a model of the Xilinx Versal CRL
42
hw/arm: versal: Connect the CRL
43
42
44
Hao Wu (2):
43
JianChunfu (2):
45
hw/misc: Add PWRON STRAP bit fields in GCR module
44
hw/arm/smmu-common: Remove the repeated ttb field
46
hw/arm: Use bit fields for NPCM7XX PWRON STRAPs
45
hw/arm/smmu: Introduce smmu_configs_inv_sid_range() helper
47
46
48
Heinrich Schuchardt (1):
47
Keith Packard (2):
49
hw/arm/virt: impact of gic-version on max CPUs
48
target/rx: Set exception vector base to 0xffffff80
49
target/rx: Remove TCG_CALL_NO_WG from helpers which write env
50
50
51
Peter Maydell (19):
51
Patrick Venture (1):
52
hw/arm/virt: Check for attempt to use TrustZone with KVM or HVF
52
hw/gpio: npcm7xx: fixup out-of-bounds access
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
71
53
72
Zongyuan Li (3):
54
Peter Maydell (11):
73
hw/arm/realview: replace 'qemu_split_irq' with 'TYPE_SPLIT_IRQ'
55
target/arm: Apply correct timer offset when calculating deadlines
74
hw/arm/stellaris: replace 'qemu_split_irq' with 'TYPE_SPLIT_IRQ'
56
target/arm: Don't apply CNTVOFF_EL2 for EL2_VIRT timer
75
hw/core/irq: remove unused 'qemu_irq_split' function
57
target/arm: Make CNTPS_* UNDEF from Secure EL1 when Secure EL2 is enabled
58
target/arm: Always apply CNTVOFF_EL2 for CNTV_TVAL_EL02 accesses
59
target/arm: Refactor handling of timer offset for direct register accesses
60
target/arm: Correct LDRD atomicity and fault behaviour
61
target/arm: Correct STRD atomicity
62
target/arm: Drop unused address_offset from op_addr_{rr, ri}_post()
63
target/arm: Make dummy debug registers RAZ, not NOP
64
util/qemu-timer.c: Don't warp timer from timerlist_rearm()
65
include/exec/memop.h: Expand comment for MO_ATOM_SUBALIGN
76
66
77
docs/system/arm/virt.rst | 4 +-
67
Thomas Huth (1):
78
include/hw/arm/exynos4210.h | 50 ++--
68
tests/functional/test_arm_sx1: Check whether the serial console is working
79
include/hw/arm/xlnx-versal.h | 16 ++
69
80
include/hw/arm/xlnx-zynqmp.h | 4 +
70
MAINTAINERS | 1 +
81
include/hw/intc/exynos4210_combiner.h | 57 +++++
71
hw/arm/smmu-internal.h | 5 -
82
include/hw/intc/exynos4210_gic.h | 43 ++++
72
include/exec/memop.h | 8 +-
83
include/hw/irq.h | 5 -
73
include/hw/arm/bsa.h | 2 +
84
include/hw/misc/npcm7xx_gcr.h | 30 +++
74
include/hw/arm/smmu-common.h | 7 +-
85
include/hw/misc/xlnx-versal-crl.h | 235 +++++++++++++++++++
75
target/arm/cpu.h | 2 +
86
include/hw/timer/cadence_ttc.h | 54 +++++
76
target/arm/gtimer.h | 14 +-
87
hw/arm/exynos4210.c | 430 ++++++++++++++++++++++++++++++----
77
target/arm/internals.h | 5 +-
88
hw/arm/npcm7xx_boards.c | 24 +-
78
target/rx/helper.h | 34 ++--
89
hw/arm/realview.c | 33 ++-
79
hw/arm/sbsa-ref.c | 2 +
90
hw/arm/stellaris.c | 15 +-
80
hw/arm/smmu-common.c | 21 +++
91
hw/arm/virt.c | 7 +
81
hw/arm/smmuv3.c | 19 +--
92
hw/arm/xlnx-versal-virt.c | 6 +-
82
hw/arm/virt.c | 2 +
93
hw/arm/xlnx-versal.c | 99 +++++++-
83
hw/gpio/npcm7xx_gpio.c | 3 +-
94
hw/arm/xlnx-zynqmp.c | 22 ++
84
target/arm/cpu.c | 4 +
95
hw/core/irq.c | 15 --
85
target/arm/debug_helper.c | 7 +-
96
hw/intc/exynos4210_combiner.c | 108 +--------
86
target/arm/helper.c | 324 ++++++++++++++++++++++++++++++++-------
97
hw/intc/exynos4210_gic.c | 344 +--------------------------
87
target/arm/tcg/op_helper.c | 8 +-
98
hw/misc/xlnx-versal-crl.c | 421 +++++++++++++++++++++++++++++++++
88
target/arm/tcg/translate.c | 147 +++++++++++-------
99
hw/timer/cadence_ttc.c | 32 +--
89
target/rx/helper.c | 2 +-
100
MAINTAINERS | 2 +-
90
util/qemu-timer.c | 4 -
101
hw/misc/meson.build | 1 +
91
hw/arm/trace-events | 3 +-
102
25 files changed, 1457 insertions(+), 600 deletions(-)
92
tests/functional/test_arm_sx1.py | 7 +-
103
create mode 100644 include/hw/intc/exynos4210_combiner.h
93
23 files changed, 455 insertions(+), 176 deletions(-)
104
create mode 100644 include/hw/intc/exynos4210_gic.h
94
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
From: Zongyuan Li <zongyuan.li@smartx.com>
1
From: JianChunfu <jansef.jian@hj-micro.com>
2
2
3
Signed-off-by: Zongyuan Li <zongyuan.li@smartx.com>
3
SMMUTransCfg->ttb is never used in QEMU, TT base address
4
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
can be accessed by SMMUTransCfg->tt[i]->ttb.
5
Message-id: 20220324181557.203805-5-zongyuan.li@smartx.com
5
6
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/811
6
Signed-off-by: JianChunfu <jansef.jian@hj-micro.com>
7
Reviewed-by: Eric Auger <eric.auger@redhat.com>
8
Message-id: 20250221031034.69822-1-jansef.jian@hj-micro.com
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
---
10
---
9
include/hw/irq.h | 5 -----
11
include/hw/arm/smmu-common.h | 1 -
10
hw/core/irq.c | 15 ---------------
12
1 file changed, 1 deletion(-)
11
2 files changed, 20 deletions(-)
12
13
13
diff --git a/include/hw/irq.h b/include/hw/irq.h
14
diff --git a/include/hw/arm/smmu-common.h b/include/hw/arm/smmu-common.h
14
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
15
--- a/include/hw/irq.h
16
--- a/include/hw/arm/smmu-common.h
16
+++ b/include/hw/irq.h
17
+++ b/include/hw/arm/smmu-common.h
17
@@ -XXX,XX +XXX,XX @@ void qemu_free_irq(qemu_irq irq);
18
@@ -XXX,XX +XXX,XX @@ typedef struct SMMUTransCfg {
18
/* Returns a new IRQ with opposite polarity. */
19
/* Used by stage-1 only. */
19
qemu_irq qemu_irq_invert(qemu_irq irq);
20
bool aa64; /* arch64 or aarch32 translation table */
20
21
bool record_faults; /* record fault events */
21
-/* Returns a new IRQ which feeds into both the passed IRQs.
22
- uint64_t ttb; /* TT base address */
22
- * It's probably better to use the TYPE_SPLIT_IRQ device instead.
23
uint8_t oas; /* output address width */
23
- */
24
uint8_t tbi; /* Top Byte Ignore */
24
-qemu_irq qemu_irq_split(qemu_irq irq1, qemu_irq irq2);
25
int asid;
25
-
26
/* For internal use in qtest. Similar to qemu_irq_split, but operating
27
on an existing vector of qemu_irq. */
28
void qemu_irq_intercept_in(qemu_irq *gpio_in, qemu_irq_handler handler, int n);
29
diff --git a/hw/core/irq.c b/hw/core/irq.c
30
index XXXXXXX..XXXXXXX 100644
31
--- a/hw/core/irq.c
32
+++ b/hw/core/irq.c
33
@@ -XXX,XX +XXX,XX @@ qemu_irq qemu_irq_invert(qemu_irq irq)
34
return qemu_allocate_irq(qemu_notirq, irq, 0);
35
}
36
37
-static void qemu_splitirq(void *opaque, int line, int level)
38
-{
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);
42
-}
43
-
44
-qemu_irq qemu_irq_split(qemu_irq irq1, qemu_irq irq2)
45
-{
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);
50
-}
51
-
52
void qemu_irq_intercept_in(qemu_irq *gpio_in, qemu_irq_handler handler, int n)
53
{
54
int i;
55
--
26
--
56
2.25.1
27
2.43.0
diff view generated by jsdifflib
1
From: Zongyuan Li <zongyuan.li@smartx.com>
1
From: Patrick Venture <venture@google.com>
2
2
3
Signed-off-by: Zongyuan Li <zongyuan.li@smartx.com>
3
The reg isn't validated to be a possible register before
4
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
it's dereferenced for one case. The mmio space registered
5
Message-id: 20220324181557.203805-3-zongyuan.li@smartx.com
5
for the gpio device is 4KiB but there aren't that many
6
registers in the struct.
7
8
Cc: qemu-stable@nongnu.org
9
Fixes: 526dbbe0874 ("hw/gpio: Add GPIO model for Nuvoton NPCM7xx")
10
Signed-off-by: Patrick Venture <venture@google.com>
11
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
12
Message-id: 20250226024603.493148-1-venture@google.com
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
14
---
8
hw/arm/stellaris.c | 15 +++++++++++++--
15
hw/gpio/npcm7xx_gpio.c | 3 +--
9
1 file changed, 13 insertions(+), 2 deletions(-)
16
1 file changed, 1 insertion(+), 2 deletions(-)
10
17
11
diff --git a/hw/arm/stellaris.c b/hw/arm/stellaris.c
18
diff --git a/hw/gpio/npcm7xx_gpio.c b/hw/gpio/npcm7xx_gpio.c
12
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
13
--- a/hw/arm/stellaris.c
20
--- a/hw/gpio/npcm7xx_gpio.c
14
+++ b/hw/arm/stellaris.c
21
+++ b/hw/gpio/npcm7xx_gpio.c
15
@@ -XXX,XX +XXX,XX @@
22
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_gpio_regs_write(void *opaque, hwaddr addr, uint64_t v,
16
23
return;
17
#include "qemu/osdep.h"
24
}
18
#include "qapi/error.h"
25
19
+#include "hw/core/split-irq.h"
26
- diff = s->regs[reg] ^ value;
20
#include "hw/sysbus.h"
27
-
21
#include "hw/sd/sd.h"
28
switch (reg) {
22
#include "hw/ssi/ssi.h"
29
case NPCM7XX_GPIO_TLOCK1:
23
@@ -XXX,XX +XXX,XX @@ static void stellaris_init(MachineState *ms, stellaris_board_info *board)
30
case NPCM7XX_GPIO_TLOCK2:
24
DeviceState *ssddev;
31
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_gpio_regs_write(void *opaque, hwaddr addr, uint64_t v,
25
DriveInfo *dinfo;
32
case NPCM7XX_GPIO_PU:
26
DeviceState *carddev;
33
case NPCM7XX_GPIO_PD:
27
+ DeviceState *gpio_d_splitter;
34
case NPCM7XX_GPIO_IEM:
28
BlockBackend *blk;
35
+ diff = s->regs[reg] ^ value;
29
36
s->regs[reg] = value;
30
/*
37
npcm7xx_gpio_update_pins(s, diff);
31
@@ -XXX,XX +XXX,XX @@ static void stellaris_init(MachineState *ms, stellaris_board_info *board)
38
break;
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
--
39
--
53
2.25.1
40
2.43.0
41
42
diff view generated by jsdifflib
1
Switch the creation of the external GIC to the new-style "embedded in
1
From: Thomas Huth <thuth@redhat.com>
2
state struct" approach, so we can easily refer to the object
3
elsewhere during realize.
4
2
3
The kernel that is used in the sx1 test prints the usual Linux log
4
onto the serial console, but this test currently ignores it. To
5
make sure that the serial device is working properly, let's check
6
for some strings in the output here.
7
8
While we're at it, also add the test to the corresponding section
9
in the MAINTAINERS file.
10
11
Signed-off-by: Thomas Huth <thuth@redhat.com>
12
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
13
Message-id: 20250226104833.1176253-1-thuth@redhat.com
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20220404154658.565020-9-peter.maydell@linaro.org
8
---
15
---
9
include/hw/arm/exynos4210.h | 2 ++
16
MAINTAINERS | 1 +
10
include/hw/intc/exynos4210_gic.h | 43 ++++++++++++++++++++++++++++++++
17
tests/functional/test_arm_sx1.py | 7 ++++---
11
hw/arm/exynos4210.c | 10 ++++----
18
2 files changed, 5 insertions(+), 3 deletions(-)
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
16
19
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
#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));
106
}
107
for (n = 0; n < EXYNOS4210_EXT_GIC_NIRQ; n++) {
108
- s->irqs.ext_gic_irq[n] = qdev_get_gpio_in(dev, n);
109
+ s->irqs.ext_gic_irq[n] = qdev_get_gpio_in(DEVICE(&s->ext_gic), n);
110
}
111
112
/* Internal Interrupt Combiner */
113
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init(Object *obj)
114
}
115
116
object_initialize_child(obj, "a9mpcore", &s->a9mpcore, TYPE_A9MPCORE_PRIV);
117
+ object_initialize_child(obj, "ext-gic", &s->ext_gic, TYPE_EXYNOS4210_GIC);
118
}
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)
139
-
140
-struct Exynos4210GicState {
141
- SysBusDevice parent_obj;
142
-
143
- MemoryRegion cpu_container;
144
- MemoryRegion dist_container;
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
20
diff --git a/MAINTAINERS b/MAINTAINERS
164
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
165
--- a/MAINTAINERS
22
--- a/MAINTAINERS
166
+++ b/MAINTAINERS
23
+++ b/MAINTAINERS
167
@@ -XXX,XX +XXX,XX @@ M: Peter Maydell <peter.maydell@linaro.org>
24
@@ -XXX,XX +XXX,XX @@ S: Maintained
168
L: qemu-arm@nongnu.org
25
F: hw/*/omap*
169
S: Odd Fixes
26
F: include/hw/arm/omap.h
170
F: hw/*/exynos*
27
F: docs/system/arm/sx1.rst
171
-F: include/hw/arm/exynos4210.h
28
+F: tests/functional/test_arm_sx1.py
172
+F: include/hw/*/exynos*
29
173
30
IPack
174
Calxeda Highbank
31
M: Alberto Garcia <berto@igalia.com>
175
M: Rob Herring <robh@kernel.org>
32
diff --git a/tests/functional/test_arm_sx1.py b/tests/functional/test_arm_sx1.py
33
index XXXXXXX..XXXXXXX 100755
34
--- a/tests/functional/test_arm_sx1.py
35
+++ b/tests/functional/test_arm_sx1.py
36
@@ -XXX,XX +XXX,XX @@ def test_arm_sx1_initrd(self):
37
self.vm.add_args('-append', f'kunit.enable=0 rdinit=/sbin/init {self.CONSOLE_ARGS}')
38
self.vm.add_args('-no-reboot')
39
self.launch_kernel(zimage_path,
40
- initrd=initrd_path)
41
+ initrd=initrd_path,
42
+ wait_for='Boot successful')
43
self.vm.wait(timeout=120)
44
45
def test_arm_sx1_sd(self):
46
@@ -XXX,XX +XXX,XX @@ def test_arm_sx1_sd(self):
47
self.vm.add_args('-no-reboot')
48
self.vm.add_args('-snapshot')
49
self.vm.add_args('-drive', f'format=raw,if=sd,file={sd_fs_path}')
50
- self.launch_kernel(zimage_path)
51
+ self.launch_kernel(zimage_path, wait_for='Boot successful')
52
self.vm.wait(timeout=120)
53
54
def test_arm_sx1_flash(self):
55
@@ -XXX,XX +XXX,XX @@ def test_arm_sx1_flash(self):
56
self.vm.add_args('-no-reboot')
57
self.vm.add_args('-snapshot')
58
self.vm.add_args('-drive', f'format=raw,if=pflash,file={flash_path}')
59
- self.launch_kernel(zimage_path)
60
+ self.launch_kernel(zimage_path, wait_for='Boot successful')
61
self.vm.wait(timeout=120)
62
63
if __name__ == '__main__':
176
--
64
--
177
2.25.1
65
2.43.0
66
67
diff view generated by jsdifflib
1
From: "Edgar E. Iglesias" <edgar.iglesias@amd.com>
1
When we are calculating timer deadlines, the correct definition of
2
whether or not to apply an offset to the physical count is described
3
in the Arm ARM DDI4087 rev L.a section D12.2.4.1. This is different
4
from when the offset should be applied for a direct read of the
5
counter sysreg.
2
6
3
Connect the 4 TTC timers on the ZynqMP.
7
We got this right for the EL1 physical timer and for the EL1 virtual
8
timer, but got all the rest wrong: they should be using a zero offset
9
always.
4
10
5
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>
11
Factor the offset calculation out into a function that has a comment
6
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
12
documenting exactly which offset it is calculating and which gets the
7
Reviewed-by: Luc Michel <luc@lmichel.fr>
13
HYP, SEC, and HYPVIRT cases right.
8
Reviewed-by: Francisco Iglesias <frasse.iglesias@gmail.com>
14
9
Message-id: 20220331222017.2914409-3-edgar.iglesias@gmail.com
15
Cc: qemu-stable@nongnu.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
18
Message-id: 20250204125009.2281315-2-peter.maydell@linaro.org
11
---
19
---
12
include/hw/arm/xlnx-zynqmp.h | 4 ++++
20
target/arm/helper.c | 29 +++++++++++++++++++++++++++--
13
hw/arm/xlnx-zynqmp.c | 22 ++++++++++++++++++++++
21
1 file changed, 27 insertions(+), 2 deletions(-)
14
2 files changed, 26 insertions(+)
15
22
16
diff --git a/include/hw/arm/xlnx-zynqmp.h b/include/hw/arm/xlnx-zynqmp.h
23
diff --git a/target/arm/helper.c b/target/arm/helper.c
17
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
18
--- a/include/hw/arm/xlnx-zynqmp.h
25
--- a/target/arm/helper.c
19
+++ b/include/hw/arm/xlnx-zynqmp.h
26
+++ b/target/arm/helper.c
20
@@ -XXX,XX +XXX,XX @@
27
@@ -XXX,XX +XXX,XX @@ static uint64_t gt_phys_cnt_offset(CPUARMState *env)
21
#include "hw/or-irq.h"
28
return gt_phys_raw_cnt_offset(env);
22
#include "hw/misc/xlnx-zynqmp-apu-ctrl.h"
23
#include "hw/misc/xlnx-zynqmp-crf.h"
24
+#include "hw/timer/cadence_ttc.h"
25
26
#define TYPE_XLNX_ZYNQMP "xlnx-zynqmp"
27
OBJECT_DECLARE_SIMPLE_TYPE(XlnxZynqMPState, XLNX_ZYNQMP)
28
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_SIMPLE_TYPE(XlnxZynqMPState, XLNX_ZYNQMP)
29
#define XLNX_ZYNQMP_MAX_RAM_SIZE (XLNX_ZYNQMP_MAX_LOW_RAM_SIZE + \
30
XLNX_ZYNQMP_MAX_HIGH_RAM_SIZE)
31
32
+#define XLNX_ZYNQMP_NUM_TTC 4
33
+
34
/*
35
* Unimplemented mmio regions needed to boot some images.
36
*/
37
@@ -XXX,XX +XXX,XX @@ struct XlnxZynqMPState {
38
qemu_or_irq qspi_irq_orgate;
39
XlnxZynqMPAPUCtrl apu_ctrl;
40
XlnxZynqMPCRF crf;
41
+ CadenceTTCState ttc[XLNX_ZYNQMP_NUM_TTC];
42
43
char *boot_cpu;
44
ARMCPU *boot_cpu_ptr;
45
diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c
46
index XXXXXXX..XXXXXXX 100644
47
--- a/hw/arm/xlnx-zynqmp.c
48
+++ b/hw/arm/xlnx-zynqmp.c
49
@@ -XXX,XX +XXX,XX @@
50
#define APU_ADDR 0xfd5c0000
51
#define APU_IRQ 153
52
53
+#define TTC0_ADDR 0xFF110000
54
+#define TTC0_IRQ 36
55
+
56
#define IPI_ADDR 0xFF300000
57
#define IPI_IRQ 64
58
59
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_create_crf(XlnxZynqMPState *s, qemu_irq *gic)
60
sysbus_connect_irq(sbd, 0, gic[CRF_IRQ]);
61
}
29
}
62
30
63
+static void xlnx_zynqmp_create_ttc(XlnxZynqMPState *s, qemu_irq *gic)
31
+static uint64_t gt_indirect_access_timer_offset(CPUARMState *env, int timeridx)
64
+{
32
+{
65
+ SysBusDevice *sbd;
33
+ /*
66
+ int i, irq;
34
+ * Return the timer offset to use for indirect accesses to the timer.
67
+
35
+ * This is the Offset value as defined in D12.2.4.1 "Operation of the
68
+ for (i = 0; i < XLNX_ZYNQMP_NUM_TTC; i++) {
36
+ * CompareValue views of the timers".
69
+ object_initialize_child(OBJECT(s), "ttc[*]", &s->ttc[i],
37
+ *
70
+ TYPE_CADENCE_TTC);
38
+ * The condition here is not always the same as the condition for
71
+ sbd = SYS_BUS_DEVICE(&s->ttc[i]);
39
+ * whether to apply an offset register when doing a direct read of
72
+
40
+ * the counter sysreg; those conditions are described in the
73
+ sysbus_realize(sbd, &error_fatal);
41
+ * access pseudocode for each counter register.
74
+ sysbus_mmio_map(sbd, 0, TTC0_ADDR + i * 0x10000);
42
+ */
75
+ for (irq = 0; irq < 3; irq++) {
43
+ switch (timeridx) {
76
+ sysbus_connect_irq(sbd, irq, gic[TTC0_IRQ + i * 3 + irq]);
44
+ case GTIMER_PHYS:
77
+ }
45
+ return gt_phys_raw_cnt_offset(env);
46
+ case GTIMER_VIRT:
47
+ return env->cp15.cntvoff_el2;
48
+ case GTIMER_HYP:
49
+ case GTIMER_SEC:
50
+ case GTIMER_HYPVIRT:
51
+ return 0;
52
+ default:
53
+ g_assert_not_reached();
78
+ }
54
+ }
79
+}
55
+}
80
+
56
+
81
static void xlnx_zynqmp_create_unimp_mmio(XlnxZynqMPState *s)
57
static void gt_recalc_timer(ARMCPU *cpu, int timeridx)
82
{
58
{
83
static const struct UnimpInfo {
59
ARMGenericTimer *gt = &cpu->env.cp15.c14_timer[timeridx];
84
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
60
@@ -XXX,XX +XXX,XX @@ static void gt_recalc_timer(ARMCPU *cpu, int timeridx)
85
xlnx_zynqmp_create_efuse(s, gic_spi);
61
* Timer enabled: calculate and set current ISTATUS, irq, and
86
xlnx_zynqmp_create_apu_ctrl(s, gic_spi);
62
* reset timer to when ISTATUS next has to change
87
xlnx_zynqmp_create_crf(s, gic_spi);
63
*/
88
+ xlnx_zynqmp_create_ttc(s, gic_spi);
64
- uint64_t offset = timeridx == GTIMER_VIRT ?
89
xlnx_zynqmp_create_unimp_mmio(s);
65
- cpu->env.cp15.cntvoff_el2 : gt_phys_raw_cnt_offset(&cpu->env);
90
66
+ uint64_t offset = gt_indirect_access_timer_offset(&cpu->env, timeridx);
91
for (i = 0; i < XLNX_ZYNQMP_NUM_GDMA_CH; i++) {
67
uint64_t count = gt_get_countervalue(&cpu->env);
68
/* Note that this must be unsigned 64 bit arithmetic: */
69
int istatus = count - offset >= gt->cval;
92
--
70
--
93
2.25.1
71
2.43.0
72
73
diff view generated by jsdifflib
1
From: Zongyuan Li <zongyuan.li@smartx.com>
1
The CNTVOFF_EL2 offset register should only be applied for accessses
2
to CNTVCT_EL0 and for the EL1 virtual timer (CNTV_*). We were
3
incorrectly applying it for the EL2 virtual timer (CNTHV_*).
2
4
3
Signed-off-by: Zongyuan Li <zongyuan.li@smartx.com>
5
Cc: qemu-stable@nongnu.org
4
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
5
Message-id: 20220324181557.203805-2-zongyuan.li@smartx.com
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
8
Message-id: 20250204125009.2281315-3-peter.maydell@linaro.org
7
---
9
---
8
hw/arm/realview.c | 33 ++++++++++++++++++++++++---------
10
target/arm/helper.c | 2 --
9
1 file changed, 24 insertions(+), 9 deletions(-)
11
1 file changed, 2 deletions(-)
10
12
11
diff --git a/hw/arm/realview.c b/hw/arm/realview.c
13
diff --git a/target/arm/helper.c b/target/arm/helper.c
12
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
13
--- a/hw/arm/realview.c
15
--- a/target/arm/helper.c
14
+++ b/hw/arm/realview.c
16
+++ b/target/arm/helper.c
15
@@ -XXX,XX +XXX,XX @@
17
@@ -XXX,XX +XXX,XX @@ static uint64_t gt_tval_read(CPUARMState *env, const ARMCPRegInfo *ri,
16
#include "hw/sysbus.h"
18
17
#include "hw/arm/boot.h"
19
switch (timeridx) {
18
#include "hw/arm/primecell.h"
20
case GTIMER_VIRT:
19
+#include "hw/core/split-irq.h"
21
- case GTIMER_HYPVIRT:
20
#include "hw/net/lan9118.h"
22
offset = gt_virt_cnt_offset(env);
21
#include "hw/net/smc91c111.h"
23
break;
22
#include "hw/pci/pci.h"
24
case GTIMER_PHYS:
23
+#include "hw/qdev-core.h"
25
@@ -XXX,XX +XXX,XX @@ static void gt_tval_write(CPUARMState *env, const ARMCPRegInfo *ri,
24
#include "net/net.h"
26
25
#include "sysemu/sysemu.h"
27
switch (timeridx) {
26
#include "hw/boards.h"
28
case GTIMER_VIRT:
27
@@ -XXX,XX +XXX,XX @@ static const int realview_board_id[] = {
29
- case GTIMER_HYPVIRT:
28
0x76d
30
offset = gt_virt_cnt_offset(env);
29
};
31
break;
30
32
case GTIMER_PHYS:
31
+static void split_irq_from_named(DeviceState *src, const char* outname,
32
+ qemu_irq out1, qemu_irq out2) {
33
+ DeviceState *splitter = qdev_new(TYPE_SPLIT_IRQ);
34
+
35
+ qdev_prop_set_uint32(splitter, "num-lines", 2);
36
+
37
+ qdev_realize_and_unref(splitter, NULL, &error_fatal);
38
+
39
+ qdev_connect_gpio_out(splitter, 0, out1);
40
+ qdev_connect_gpio_out(splitter, 1, out2);
41
+ qdev_connect_gpio_out_named(src, outname, 0,
42
+ qdev_get_gpio_in(splitter, 0));
43
+}
44
+
45
static void realview_init(MachineState *machine,
46
enum realview_board_type board_type)
47
{
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;
79
--
33
--
80
2.25.1
34
2.43.0
35
36
diff view generated by jsdifflib
1
The combiner_grp_to_gic_id[] array includes the EXT_GIC_ID_MCT_G0
1
When we added Secure EL2 support, we missed that this needs an update
2
and EXT_GIC_ID_MCT_G1 multiple times. This means that we will
2
to the access code for the EL3 physical timer registers. These are
3
connect multiple IRQs up to the same external GIC input, which
3
supposed to UNDEF from Secure EL1 when Secure EL2 is enabled.
4
is not permitted. We do the same thing in the code in
5
exynos4210_init_board_irqs() because the conditionals selecting
6
an irq_id in the first loop match multiple interrupt IDs.
7
4
8
Overall we do this for interrupt IDs
5
(Note for stable backporting: for backports to branches where
9
(1, 4), (12, 4), (35, 4), (51, 4), (53, 4) for EXT_GIC_ID_MCT_G0
6
CP_ACCESS_UNDEFINED is not defined, the old name to use instead
10
and
7
is CP_ACCESS_TRAP_UNCATEGORIZED.)
11
(1, 5), (12, 5), (35, 5), (51, 5), (53, 5) for EXT_GIC_ID_MCT_G1
12
8
13
These correspond to the cases for the multi-core timer that we are
9
Cc: qemu-stable@nongnu.org
14
wiring up to multiple inputs on the combiner in
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
exynos4210_combiner_get_gpioin(). That code already deals with all
11
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
16
these interrupt IDs being the same input source, so we don't need to
12
Message-id: 20250204125009.2281315-4-peter.maydell@linaro.org
17
connect the external GIC interrupt for any of them except the first
13
---
18
(1, 4) and (1, 5). Remove the array entries and conditionals which
14
target/arm/helper.c | 3 +++
19
were incorrectly causing us to wire up extra lines.
15
1 file changed, 3 insertions(+)
20
16
21
This bug didn't cause any visible effects, because we only connect
17
diff --git a/target/arm/helper.c b/target/arm/helper.c
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
25
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
26
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
27
Message-id: 20220404154658.565020-16-peter.maydell@linaro.org
28
---
29
include/hw/arm/exynos4210.h | 2 +-
30
hw/arm/exynos4210.c | 12 +++++-------
31
2 files changed, 6 insertions(+), 8 deletions(-)
32
33
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
34
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
35
--- a/include/hw/arm/exynos4210.h
19
--- a/target/arm/helper.c
36
+++ b/include/hw/arm/exynos4210.h
20
+++ b/target/arm/helper.c
37
@@ -XXX,XX +XXX,XX @@
21
@@ -XXX,XX +XXX,XX @@ static CPAccessResult gt_stimer_access(CPUARMState *env,
38
* one for every non-zero entry in combiner_grp_to_gic_id[].
22
if (!arm_is_secure(env)) {
39
* We'll assert in exynos4210_init_board_irqs() if this is wrong.
23
return CP_ACCESS_UNDEFINED;
40
*/
41
-#define EXYNOS4210_NUM_SPLITTERS (EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ + 60)
42
+#define EXYNOS4210_NUM_SPLITTERS (EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ + 54)
43
44
typedef struct Exynos4210Irq {
45
qemu_irq int_combiner_irq[EXYNOS4210_MAX_INT_COMBINER_IN_IRQ];
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 @@ combiner_grp_to_gic_id[64 - EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][8] = {
51
/* int combiner group 34 */
52
{ EXT_GIC_ID_ONENAND_AUDI, EXT_GIC_ID_NFC },
53
/* int combiner group 35 */
54
- { 0, 0, 0, EXT_GIC_ID_MCT_L1, EXT_GIC_ID_MCT_G0, EXT_GIC_ID_MCT_G1 },
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;
82
}
24
}
83
- if (n == EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 5) ||
25
+ if (arm_is_el2_enabled(env)) {
84
- n == EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 5)) {
26
+ return CP_ACCESS_UNDEFINED;
85
+ if (n == EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 5)) {
27
+ }
86
/* MCT_G1 is passed to External and GIC */
28
if (!(env->cp15.scr_el3 & SCR_ST)) {
87
irq_id = EXT_GIC_ID_MCT_G1;
29
return CP_ACCESS_TRAP_EL3;
88
}
30
}
89
--
31
--
90
2.25.1
32
2.43.0
33
34
diff view generated by jsdifflib
1
From: "Edgar E. Iglesias" <edgar.iglesias@amd.com>
1
Currently we handle CNTV_TVAL_EL02 by calling gt_tval_read() for the
2
EL1 virt timer. This is almost correct, but the underlying
3
CNTV_TVAL_EL0 register behaves slightly differently. CNTV_TVAL_EL02
4
always applies the CNTVOFF_EL2 offset; CNTV_TVAL_EL0 doesn't do so if
5
we're at EL2 and HCR_EL2.E2H is 1.
2
6
3
Add the Cortex-R5Fs of the Versal RPU (Real-time Processing Unit)
7
We were getting this wrong, because we ended up in
4
subsystem.
8
gt_virt_cnt_offset() and did the E2H check.
5
9
6
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>
10
Factor out the tval read/write calculation from the selection of the
7
Reviewed-by: Francisco Iglesias <francisco.iglesias@amd.com>
11
offset, so that we can special case gt_virt_tval_read() and
8
Message-id: 20220406174303.2022038-3-edgar.iglesias@xilinx.com
12
gt_virt_tval_write() to unconditionally pass CNTVOFF_EL2.
13
14
Cc: qemu-stable@nongnu.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
17
Message-id: 20250204125009.2281315-5-peter.maydell@linaro.org
10
---
18
---
11
include/hw/arm/xlnx-versal.h | 10 ++++++++++
19
target/arm/helper.c | 36 +++++++++++++++++++++++++++---------
12
hw/arm/xlnx-versal-virt.c | 6 +++---
20
1 file changed, 27 insertions(+), 9 deletions(-)
13
hw/arm/xlnx-versal.c | 36 ++++++++++++++++++++++++++++++++++++
14
3 files changed, 49 insertions(+), 3 deletions(-)
15
21
16
diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
22
diff --git a/target/arm/helper.c b/target/arm/helper.c
17
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
18
--- a/include/hw/arm/xlnx-versal.h
24
--- a/target/arm/helper.c
19
+++ b/include/hw/arm/xlnx-versal.h
25
+++ b/target/arm/helper.c
20
@@ -XXX,XX +XXX,XX @@
26
@@ -XXX,XX +XXX,XX @@ static void gt_cval_write(CPUARMState *env, const ARMCPRegInfo *ri,
21
OBJECT_DECLARE_SIMPLE_TYPE(Versal, XLNX_VERSAL)
27
gt_recalc_timer(env_archcpu(env), timeridx);
22
23
#define XLNX_VERSAL_NR_ACPUS 2
24
+#define XLNX_VERSAL_NR_RCPUS 2
25
#define XLNX_VERSAL_NR_UARTS 2
26
#define XLNX_VERSAL_NR_GEMS 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
}
28
}
61
diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
29
62
index XXXXXXX..XXXXXXX 100644
30
+static uint64_t do_tval_read(CPUARMState *env, int timeridx, uint64_t offset)
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)
74
}
75
}
76
77
+static void versal_create_rpu_cpus(Versal *s)
78
+{
31
+{
79
+ int i;
32
+ return (uint32_t)(env->cp15.c14_timer[timeridx].cval -
80
+
33
+ (gt_get_countervalue(env) - offset));
81
+ object_initialize_child(OBJECT(s), "rpu-cluster", &s->lpd.rpu.cluster,
82
+ TYPE_CPU_CLUSTER);
83
+ qdev_prop_set_uint32(DEVICE(&s->lpd.rpu.cluster), "cluster-id", 1);
84
+
85
+ for (i = 0; i < ARRAY_SIZE(s->lpd.rpu.cpu); i++) {
86
+ Object *obj;
87
+
88
+ object_initialize_child(OBJECT(&s->lpd.rpu.cluster),
89
+ "rpu-cpu[*]", &s->lpd.rpu.cpu[i],
90
+ XLNX_VERSAL_RCPU_TYPE);
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);
104
+}
34
+}
105
+
35
+
106
static void versal_create_uarts(Versal *s, qemu_irq *pic)
36
static uint64_t gt_tval_read(CPUARMState *env, const ARMCPRegInfo *ri,
37
int timeridx)
107
{
38
{
108
int i;
39
@@ -XXX,XX +XXX,XX @@ static uint64_t gt_tval_read(CPUARMState *env, const ARMCPRegInfo *ri,
109
@@ -XXX,XX +XXX,XX @@ static void versal_realize(DeviceState *dev, Error **errp)
40
break;
110
41
}
111
versal_create_apu_cpus(s);
42
112
versal_create_apu_gic(s, pic);
43
- return (uint32_t)(env->cp15.c14_timer[timeridx].cval -
113
+ versal_create_rpu_cpus(s);
44
- (gt_get_countervalue(env) - offset));
114
versal_create_uarts(s, pic);
45
+ return do_tval_read(env, timeridx, offset);
115
versal_create_usbs(s, pic);
46
+}
116
versal_create_gems(s, pic);
47
+
117
@@ -XXX,XX +XXX,XX @@ static void versal_realize(DeviceState *dev, Error **errp)
48
+static void do_tval_write(CPUARMState *env, int timeridx, uint64_t value,
118
49
+ uint64_t offset)
119
memory_region_add_subregion_overlap(&s->mr_ps, MM_OCM, &s->lpd.mr_ocm, 0);
50
+{
120
memory_region_add_subregion_overlap(&s->fpd.apu.mr, 0, &s->mr_ps, 0);
51
+ trace_arm_gt_tval_write(timeridx, value);
121
+ memory_region_add_subregion_overlap(&s->lpd.rpu.mr, 0,
52
+ env->cp15.c14_timer[timeridx].cval = gt_get_countervalue(env) - offset +
122
+ &s->lpd.rpu.mr_ps_alias, 0);
53
+ sextract64(value, 0, 32);
54
+ gt_recalc_timer(env_archcpu(env), timeridx);
123
}
55
}
124
56
125
static void versal_init(Object *obj)
57
static void gt_tval_write(CPUARMState *env, const ARMCPRegInfo *ri,
126
@@ -XXX,XX +XXX,XX @@ static void versal_init(Object *obj)
58
@@ -XXX,XX +XXX,XX @@ static void gt_tval_write(CPUARMState *env, const ARMCPRegInfo *ri,
127
Versal *s = XLNX_VERSAL(obj);
59
offset = gt_phys_cnt_offset(env);
128
60
break;
129
memory_region_init(&s->fpd.apu.mr, obj, "mr-apu", UINT64_MAX);
61
}
130
+ memory_region_init(&s->lpd.rpu.mr, obj, "mr-rpu", UINT64_MAX);
62
-
131
memory_region_init(&s->mr_ps, obj, "mr-ps-switch", UINT64_MAX);
63
- trace_arm_gt_tval_write(timeridx, value);
132
+ memory_region_init_alias(&s->lpd.rpu.mr_ps_alias, OBJECT(s),
64
- env->cp15.c14_timer[timeridx].cval = gt_get_countervalue(env) - offset +
133
+ "mr-rpu-ps-alias", &s->mr_ps, 0, UINT64_MAX);
65
- sextract64(value, 0, 32);
66
- gt_recalc_timer(env_archcpu(env), timeridx);
67
+ do_tval_write(env, timeridx, value, offset);
134
}
68
}
135
69
136
static Property versal_properties[] = {
70
static void gt_ctl_write(CPUARMState *env, const ARMCPRegInfo *ri,
71
@@ -XXX,XX +XXX,XX @@ static void gt_virt_cval_write(CPUARMState *env, const ARMCPRegInfo *ri,
72
73
static uint64_t gt_virt_tval_read(CPUARMState *env, const ARMCPRegInfo *ri)
74
{
75
- return gt_tval_read(env, ri, GTIMER_VIRT);
76
+ /*
77
+ * This is CNTV_TVAL_EL02; unlike the underlying CNTV_TVAL_EL0
78
+ * we always apply CNTVOFF_EL2. Special case that here rather
79
+ * than going into the generic gt_tval_read() and then having
80
+ * to re-detect that it's this register.
81
+ * Note that the accessfn/perms mean we know we're at EL2 or EL3 here.
82
+ */
83
+ return do_tval_read(env, GTIMER_VIRT, env->cp15.cntvoff_el2);
84
}
85
86
static void gt_virt_tval_write(CPUARMState *env, const ARMCPRegInfo *ri,
87
uint64_t value)
88
{
89
- gt_tval_write(env, ri, GTIMER_VIRT, value);
90
+ /* Similarly for writes to CNTV_TVAL_EL02 */
91
+ do_tval_write(env, GTIMER_VIRT, value, env->cp15.cntvoff_el2);
92
}
93
94
static void gt_virt_ctl_write(CPUARMState *env, const ARMCPRegInfo *ri,
137
--
95
--
138
2.25.1
96
2.43.0
97
98
diff view generated by jsdifflib
1
The function exynos4210_init_board_irqs() currently lives in
1
When reading or writing the timer registers, sometimes we need to
2
exynos4210_gic.c, but it isn't really part of the exynos4210.gic
2
apply one of the timer offsets. Specifically, this happens for
3
device -- it is a function that implements (some of) the wiring up of
3
direct reads of the counter registers CNTPCT_EL0 and CNTVCT_EL0 (and
4
interrupts between the SoC's GIC and combiner components. This means
4
their self-synchronized variants CNTVCTSS_EL0 and CNTPCTSS_EL0). It
5
it fits better in exynos4210.c, which is the SoC-level code. Move it
5
also applies for direct reads and writes of the CNT*_TVAL_EL*
6
there. Similarly, exynos4210_git_irq() is used almost only in the
6
registers that provide the 32-bit downcounting view of each timer.
7
SoC-level code, so move it too.
7
8
8
We currently do this with duplicated code in gt_tval_read() and
9
gt_tval_write() and a special-case in gt_virt_cnt_read() and
10
gt_cnt_read(). Refactor this so that we handle it all in a single
11
function gt_direct_access_timer_offset(), to parallel how we handle
12
the offset for indirect accesses.
13
14
The call in the WFIT helper previously to gt_virt_cnt_offset() is
15
now to gt_direct_access_timer_offset(); this is the correct
16
behaviour, but it's not immediately obvious that it shouldn't be
17
considered an indirect access, so we add an explanatory comment.
18
19
This commit should make no behavioural changes.
20
21
(Cc to stable because the following bugfix commit will
22
depend on this one.)
23
24
Cc: qemu-stable@nongnu.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
25
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
26
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
11
Message-id: 20220404154658.565020-8-peter.maydell@linaro.org
27
Message-id: 20250204125009.2281315-6-peter.maydell@linaro.org
12
---
28
---
13
include/hw/arm/exynos4210.h | 4 -
29
target/arm/internals.h | 5 +-
14
hw/arm/exynos4210.c | 202 +++++++++++++++++++++++++++++++++++
30
target/arm/helper.c | 103 +++++++++++++++++++------------------
15
hw/intc/exynos4210_gic.c | 204 ------------------------------------
31
target/arm/tcg/op_helper.c | 8 ++-
16
3 files changed, 202 insertions(+), 208 deletions(-)
32
3 files changed, 62 insertions(+), 54 deletions(-)
17
33
18
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
34
diff --git a/target/arm/internals.h b/target/arm/internals.h
19
index XXXXXXX..XXXXXXX 100644
35
index XXXXXXX..XXXXXXX 100644
20
--- a/include/hw/arm/exynos4210.h
36
--- a/target/arm/internals.h
21
+++ b/include/hw/arm/exynos4210.h
37
+++ b/target/arm/internals.h
22
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_SIMPLE_TYPE(Exynos4210State, EXYNOS4210_SOC)
38
@@ -XXX,XX +XXX,XX @@ int delete_hw_watchpoint(target_ulong addr, target_ulong len, int type);
23
void exynos4210_write_secondary(ARMCPU *cpu,
39
uint64_t gt_get_countervalue(CPUARMState *env);
24
const struct arm_boot_info *info);
40
/*
25
41
* Return the currently applicable offset between the system counter
26
-/* Initialize board IRQs.
42
- * and CNTVCT_EL0 (this will be either 0 or the value of CNTVOFF_EL2).
27
- * These IRQs contain splitted Int/External Combiner and External Gic IRQs */
43
+ * and the counter for the specified timer, as used for direct register
28
-void exynos4210_init_board_irqs(Exynos4210State *s);
44
+ * accesses.
29
-
45
*/
30
/* Get IRQ number from exynos4210 IRQ subsystem stub.
46
-uint64_t gt_virt_cnt_offset(CPUARMState *env);
31
* To identify IRQ source use internal combiner group and bit number
47
+uint64_t gt_direct_access_timer_offset(CPUARMState *env, int timeridx);
32
* grp - group number
48
33
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
49
/*
50
* Return mask of ARMMMUIdxBit values corresponding to an "invalidate
51
diff --git a/target/arm/helper.c b/target/arm/helper.c
34
index XXXXXXX..XXXXXXX 100644
52
index XXXXXXX..XXXXXXX 100644
35
--- a/hw/arm/exynos4210.c
53
--- a/target/arm/helper.c
36
+++ b/hw/arm/exynos4210.c
54
+++ b/target/arm/helper.c
37
@@ -XXX,XX +XXX,XX @@
55
@@ -XXX,XX +XXX,XX @@ static uint64_t gt_phys_raw_cnt_offset(CPUARMState *env)
38
#define EXYNOS4210_PL330_BASE1_ADDR 0x12690000
56
return 0;
39
#define EXYNOS4210_PL330_BASE2_ADDR 0x12850000
57
}
40
58
41
+enum ExtGicId {
59
-static uint64_t gt_phys_cnt_offset(CPUARMState *env)
42
+ EXT_GIC_ID_MDMA_LCD0 = 66,
60
-{
43
+ EXT_GIC_ID_PDMA0,
61
- if (arm_current_el(env) >= 2) {
44
+ EXT_GIC_ID_PDMA1,
62
- return 0;
45
+ EXT_GIC_ID_TIMER0,
63
- }
46
+ EXT_GIC_ID_TIMER1,
64
- return gt_phys_raw_cnt_offset(env);
47
+ EXT_GIC_ID_TIMER2,
65
-}
48
+ EXT_GIC_ID_TIMER3,
66
-
49
+ EXT_GIC_ID_TIMER4,
67
static uint64_t gt_indirect_access_timer_offset(CPUARMState *env, int timeridx)
50
+ EXT_GIC_ID_MCT_L0,
68
{
51
+ EXT_GIC_ID_WDT,
69
/*
52
+ EXT_GIC_ID_RTC_ALARM,
70
@@ -XXX,XX +XXX,XX @@ static uint64_t gt_indirect_access_timer_offset(CPUARMState *env, int timeridx)
53
+ EXT_GIC_ID_RTC_TIC,
71
}
54
+ EXT_GIC_ID_GPIO_XB,
72
}
55
+ EXT_GIC_ID_GPIO_XA,
73
56
+ EXT_GIC_ID_MCT_L1,
74
+uint64_t gt_direct_access_timer_offset(CPUARMState *env, int timeridx)
57
+ EXT_GIC_ID_IEM_APC,
75
+{
58
+ EXT_GIC_ID_IEM_IEC,
76
+ /*
59
+ EXT_GIC_ID_NFC,
77
+ * Return the timer offset to use for direct accesses to the
60
+ EXT_GIC_ID_UART0,
78
+ * counter registers CNTPCT and CNTVCT, and for direct accesses
61
+ EXT_GIC_ID_UART1,
79
+ * to the CNT*_TVAL registers.
62
+ EXT_GIC_ID_UART2,
80
+ *
63
+ EXT_GIC_ID_UART3,
81
+ * This isn't exactly the same as the indirect-access offset,
64
+ EXT_GIC_ID_UART4,
82
+ * because here we also care about what EL the register access
65
+ EXT_GIC_ID_MCT_G0,
83
+ * is being made from.
66
+ EXT_GIC_ID_I2C0,
84
+ *
67
+ EXT_GIC_ID_I2C1,
85
+ * This corresponds to the access pseudocode for the registers.
68
+ EXT_GIC_ID_I2C2,
86
+ */
69
+ EXT_GIC_ID_I2C3,
87
+ uint64_t hcr;
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
+
88
+
106
+enum ExtInt {
89
+ switch (timeridx) {
107
+ EXT_GIC_ID_EXTINT0 = 48,
90
+ case GTIMER_PHYS:
108
+ EXT_GIC_ID_EXTINT1,
91
+ if (arm_current_el(env) >= 2) {
109
+ EXT_GIC_ID_EXTINT2,
92
+ return 0;
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
+
125
+/*
126
+ * External GIC sources which are not from External Interrupt Combiner or
127
+ * External Interrupts are starting from EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ,
128
+ * which is INTG16 in Internal Interrupt Combiner.
129
+ */
130
+
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)
194
+{
195
+ uint32_t grp, bit, irq_id, n;
196
+ Exynos4210Irq *is = &s->irqs;
197
+
198
+ for (n = 0; n < EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ; n++) {
199
+ irq_id = 0;
200
+ if (n == EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 4) ||
201
+ n == EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 4)) {
202
+ /* MCT_G0 is passed to External GIC */
203
+ irq_id = EXT_GIC_ID_MCT_G0;
204
+ }
93
+ }
205
+ if (n == EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 5) ||
94
+ return gt_phys_raw_cnt_offset(env);
206
+ n == EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 5)) {
95
+ case GTIMER_VIRT:
207
+ /* MCT_G1 is passed to External and GIC */
96
+ switch (arm_current_el(env)) {
208
+ irq_id = EXT_GIC_ID_MCT_G1;
97
+ case 2:
98
+ hcr = arm_hcr_el2_eff(env);
99
+ if (hcr & HCR_E2H) {
100
+ return 0;
101
+ }
102
+ break;
103
+ case 0:
104
+ hcr = arm_hcr_el2_eff(env);
105
+ if ((hcr & (HCR_E2H | HCR_TGE)) == (HCR_E2H | HCR_TGE)) {
106
+ return 0;
107
+ }
108
+ break;
209
+ }
109
+ }
210
+ if (irq_id) {
110
+ return env->cp15.cntvoff_el2;
211
+ s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
111
+ case GTIMER_HYP:
212
+ is->ext_gic_irq[irq_id - 32]);
112
+ case GTIMER_SEC:
213
+ } else {
113
+ case GTIMER_HYPVIRT:
214
+ s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
114
+ return 0;
215
+ is->ext_combiner_irq[n]);
115
+ default:
216
+ }
116
+ g_assert_not_reached();
217
+ }
218
+ for (; n < EXYNOS4210_MAX_INT_COMBINER_IN_IRQ; n++) {
219
+ /* these IDs are passed to Internal Combiner and External GIC */
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
+ }
229
+ }
117
+ }
230
+}
118
+}
231
+
119
+
232
+/*
120
static void gt_recalc_timer(ARMCPU *cpu, int timeridx)
233
+ * Get IRQ number from exynos4210 IRQ subsystem stub.
121
{
234
+ * To identify IRQ source use internal combiner group and bit number
122
ARMGenericTimer *gt = &cpu->env.cp15.c14_timer[timeridx];
235
+ * grp - group number
123
@@ -XXX,XX +XXX,XX @@ static void gt_timer_reset(CPUARMState *env, const ARMCPRegInfo *ri,
236
+ * bit - bit number inside group
124
237
+ */
125
static uint64_t gt_cnt_read(CPUARMState *env, const ARMCPRegInfo *ri)
238
+uint32_t exynos4210_get_irq(uint32_t grp, uint32_t bit)
126
{
239
+{
127
- return gt_get_countervalue(env) - gt_phys_cnt_offset(env);
240
+ return EXYNOS4210_COMBINER_GET_IRQ_NUM(grp, bit);
128
-}
241
+}
129
-
242
+
130
-uint64_t gt_virt_cnt_offset(CPUARMState *env)
243
static uint8_t chipid_and_omr[] = { 0x11, 0x02, 0x21, 0x43,
131
-{
244
0x09, 0x00, 0x00, 0x00 };
132
- uint64_t hcr;
245
133
-
246
diff --git a/hw/intc/exynos4210_gic.c b/hw/intc/exynos4210_gic.c
134
- switch (arm_current_el(env)) {
135
- case 2:
136
- hcr = arm_hcr_el2_eff(env);
137
- if (hcr & HCR_E2H) {
138
- return 0;
139
- }
140
- break;
141
- case 0:
142
- hcr = arm_hcr_el2_eff(env);
143
- if ((hcr & (HCR_E2H | HCR_TGE)) == (HCR_E2H | HCR_TGE)) {
144
- return 0;
145
- }
146
- break;
147
- }
148
-
149
- return env->cp15.cntvoff_el2;
150
+ uint64_t offset = gt_direct_access_timer_offset(env, GTIMER_PHYS);
151
+ return gt_get_countervalue(env) - offset;
152
}
153
154
static uint64_t gt_virt_cnt_read(CPUARMState *env, const ARMCPRegInfo *ri)
155
{
156
- return gt_get_countervalue(env) - gt_virt_cnt_offset(env);
157
+ uint64_t offset = gt_direct_access_timer_offset(env, GTIMER_VIRT);
158
+ return gt_get_countervalue(env) - offset;
159
}
160
161
static void gt_cval_write(CPUARMState *env, const ARMCPRegInfo *ri,
162
@@ -XXX,XX +XXX,XX @@ static uint64_t do_tval_read(CPUARMState *env, int timeridx, uint64_t offset)
163
static uint64_t gt_tval_read(CPUARMState *env, const ARMCPRegInfo *ri,
164
int timeridx)
165
{
166
- uint64_t offset = 0;
167
-
168
- switch (timeridx) {
169
- case GTIMER_VIRT:
170
- offset = gt_virt_cnt_offset(env);
171
- break;
172
- case GTIMER_PHYS:
173
- offset = gt_phys_cnt_offset(env);
174
- break;
175
- }
176
+ uint64_t offset = gt_direct_access_timer_offset(env, timeridx);
177
178
return do_tval_read(env, timeridx, offset);
179
}
180
@@ -XXX,XX +XXX,XX @@ static void gt_tval_write(CPUARMState *env, const ARMCPRegInfo *ri,
181
int timeridx,
182
uint64_t value)
183
{
184
- uint64_t offset = 0;
185
+ uint64_t offset = gt_direct_access_timer_offset(env, timeridx);
186
187
- switch (timeridx) {
188
- case GTIMER_VIRT:
189
- offset = gt_virt_cnt_offset(env);
190
- break;
191
- case GTIMER_PHYS:
192
- offset = gt_phys_cnt_offset(env);
193
- break;
194
- }
195
do_tval_write(env, timeridx, value, offset);
196
}
197
198
diff --git a/target/arm/tcg/op_helper.c b/target/arm/tcg/op_helper.c
247
index XXXXXXX..XXXXXXX 100644
199
index XXXXXXX..XXXXXXX 100644
248
--- a/hw/intc/exynos4210_gic.c
200
--- a/target/arm/tcg/op_helper.c
249
+++ b/hw/intc/exynos4210_gic.c
201
+++ b/target/arm/tcg/op_helper.c
250
@@ -XXX,XX +XXX,XX @@
202
@@ -XXX,XX +XXX,XX @@ void HELPER(wfit)(CPUARMState *env, uint64_t timeout)
251
#include "hw/arm/exynos4210.h"
203
int target_el = check_wfx_trap(env, false, &excp);
252
#include "qom/object.h"
204
/* The WFIT should time out when CNTVCT_EL0 >= the specified value. */
253
205
uint64_t cntval = gt_get_countervalue(env);
254
-enum ExtGicId {
206
- uint64_t offset = gt_virt_cnt_offset(env);
255
- EXT_GIC_ID_MDMA_LCD0 = 66,
207
+ /*
256
- EXT_GIC_ID_PDMA0,
208
+ * We want the value that we would get if we read CNTVCT_EL0 from
257
- EXT_GIC_ID_PDMA1,
209
+ * the current exception level, so the direct_access offset, not
258
- EXT_GIC_ID_TIMER0,
210
+ * the indirect_access one. Compare the pseudocode LocalTimeoutEvent(),
259
- EXT_GIC_ID_TIMER1,
211
+ * which calls VirtualCounterTimer().
260
- EXT_GIC_ID_TIMER2,
212
+ */
261
- EXT_GIC_ID_TIMER3,
213
+ uint64_t offset = gt_direct_access_timer_offset(env, GTIMER_VIRT);
262
- EXT_GIC_ID_TIMER4,
214
uint64_t cntvct = cntval - offset;
263
- EXT_GIC_ID_MCT_L0,
215
uint64_t nexttick;
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
216
468
--
217
--
469
2.25.1
218
2.43.0
219
220
diff view generated by jsdifflib
1
The function exynos4210_combiner_get_gpioin() currently lives in
1
From: Alex Bennée <alex.bennee@linaro.org>
2
exynos4210_combiner.c, but it isn't really part of the combiner
2
3
device itself -- it is a function that implements the wiring up of
3
When FEAT_SEL2 was implemented the SEL2 timers were missed. This
4
some interrupt sources to multiple combiner inputs. Move it to live
4
shows up when building the latest Hafnium with SPMC_AT_EL=2. The
5
with the other SoC-level code in exynos4210.c, along with a few
5
actual implementation utilises the same logic as the rest of the
6
macros previously defined in exynos4210.h which are now used only
6
timers so all we need to do is:
7
in exynos4210.c.
7
8
8
- define the timers and their access functions
9
- conditionally add the correct system registers
10
- create a new accessfn as the rules are subtly different to the
11
existing secure timer
12
13
Fixes: e9152ee91c (target/arm: add ARMv8.4-SEL2 system registers)
14
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
16
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Message-id: 20220404154658.565020-11-peter.maydell@linaro.org
17
Message-id: 20250204125009.2281315-7-peter.maydell@linaro.org
18
Cc: qemu-stable@nongnu.org
19
Cc: Andrei Homescu <ahomescu@google.com>
20
Cc: Arve Hjønnevåg <arve@google.com>
21
Cc: Rémi Denis-Courmont <remi.denis.courmont@huawei.com>
22
[PMM: CP_ACCESS_TRAP_UNCATEGORIZED -> CP_ACCESS_UNDEFINED;
23
offset logic now in gt_{indirect,direct}_access_timer_offset() ]
24
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
25
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
26
---
13
include/hw/arm/exynos4210.h | 11 -----
27
include/hw/arm/bsa.h | 2 +
14
hw/arm/exynos4210.c | 82 +++++++++++++++++++++++++++++++++++
28
target/arm/cpu.h | 2 +
15
hw/intc/exynos4210_combiner.c | 77 --------------------------------
29
target/arm/gtimer.h | 4 +-
16
3 files changed, 82 insertions(+), 88 deletions(-)
30
target/arm/cpu.c | 4 ++
17
31
target/arm/helper.c | 163 +++++++++++++++++++++++++++++++++++++++++++
18
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
32
5 files changed, 174 insertions(+), 1 deletion(-)
19
index XXXXXXX..XXXXXXX 100644
33
20
--- a/include/hw/arm/exynos4210.h
34
diff --git a/include/hw/arm/bsa.h b/include/hw/arm/bsa.h
21
+++ b/include/hw/arm/exynos4210.h
35
index XXXXXXX..XXXXXXX 100644
36
--- a/include/hw/arm/bsa.h
37
+++ b/include/hw/arm/bsa.h
22
@@ -XXX,XX +XXX,XX @@
38
@@ -XXX,XX +XXX,XX @@
23
#define EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ \
39
#define QEMU_ARM_BSA_H
24
(EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ * 8)
40
25
41
/* These are architectural INTID values */
26
-#define EXYNOS4210_COMBINER_GET_IRQ_NUM(grp, bit) ((grp)*8 + (bit))
42
+#define ARCH_TIMER_S_EL2_VIRT_IRQ 19
27
-#define EXYNOS4210_COMBINER_GET_GRP_NUM(irq) ((irq) / 8)
43
+#define ARCH_TIMER_S_EL2_IRQ 20
28
-#define EXYNOS4210_COMBINER_GET_BIT_NUM(irq) \
44
#define VIRTUAL_PMU_IRQ 23
29
- ((irq) - 8 * EXYNOS4210_COMBINER_GET_GRP_NUM(irq))
45
#define ARCH_GIC_MAINT_IRQ 25
30
-
46
#define ARCH_TIMER_NS_EL2_IRQ 26
31
/* IRQs number for external and internal GIC */
47
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
32
#define EXYNOS4210_EXT_GIC_NIRQ (160-32)
48
index XXXXXXX..XXXXXXX 100644
33
#define EXYNOS4210_INT_GIC_NIRQ 64
49
--- a/target/arm/cpu.h
34
@@ -XXX,XX +XXX,XX @@ void exynos4210_write_secondary(ARMCPU *cpu,
50
+++ b/target/arm/cpu.h
35
* bit - bit number inside group */
51
@@ -XXX,XX +XXX,XX @@ void arm_gt_vtimer_cb(void *opaque);
36
uint32_t exynos4210_get_irq(uint32_t grp, uint32_t bit);
52
void arm_gt_htimer_cb(void *opaque);
37
53
void arm_gt_stimer_cb(void *opaque);
38
-/*
54
void arm_gt_hvtimer_cb(void *opaque);
39
- * Get Combiner input GPIO into irqs structure
55
+void arm_gt_sel2timer_cb(void *opaque);
40
- */
56
+void arm_gt_sel2vtimer_cb(void *opaque);
41
-void exynos4210_combiner_get_gpioin(Exynos4210Irq *irqs, DeviceState *dev,
57
42
- int ext);
58
unsigned int gt_cntfrq_period_ns(ARMCPU *cpu);
43
-
59
void gt_rme_post_el_change(ARMCPU *cpu, void *opaque);
44
/*
60
diff --git a/target/arm/gtimer.h b/target/arm/gtimer.h
45
* exynos4210 UART
61
index XXXXXXX..XXXXXXX 100644
46
*/
62
--- a/target/arm/gtimer.h
47
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
63
+++ b/target/arm/gtimer.h
48
index XXXXXXX..XXXXXXX 100644
64
@@ -XXX,XX +XXX,XX @@ enum {
49
--- a/hw/arm/exynos4210.c
65
GTIMER_HYP = 2,
50
+++ b/hw/arm/exynos4210.c
66
GTIMER_SEC = 3,
51
@@ -XXX,XX +XXX,XX @@ combiner_grp_to_gic_id[64 - EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][8] = {
67
GTIMER_HYPVIRT = 4,
52
{ }, { }, { }, { }, { }, { }, { }, { }, { }, { }
68
-#define NUM_GTIMERS 5
69
+ GTIMER_S_EL2_PHYS = 5, /* CNTHPS_* ; only if FEAT_SEL2 */
70
+ GTIMER_S_EL2_VIRT = 6, /* CNTHVS_* ; only if FEAT_SEL2 */
71
+#define NUM_GTIMERS 7
53
};
72
};
54
73
55
+#define EXYNOS4210_COMBINER_GET_IRQ_NUM(grp, bit) ((grp) * 8 + (bit))
74
#endif
56
+#define EXYNOS4210_COMBINER_GET_GRP_NUM(irq) ((irq) / 8)
75
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
57
+#define EXYNOS4210_COMBINER_GET_BIT_NUM(irq) \
76
index XXXXXXX..XXXXXXX 100644
58
+ ((irq) - 8 * EXYNOS4210_COMBINER_GET_GRP_NUM(irq))
77
--- a/target/arm/cpu.c
59
+
78
+++ b/target/arm/cpu.c
60
/*
79
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
61
* Initialize board IRQs.
80
arm_gt_stimer_cb, cpu);
62
* These IRQs contain splitted Int/External Combiner and External Gic IRQs.
81
cpu->gt_timer[GTIMER_HYPVIRT] = timer_new(QEMU_CLOCK_VIRTUAL, scale,
63
@@ -XXX,XX +XXX,XX @@ uint32_t exynos4210_get_irq(uint32_t grp, uint32_t bit)
82
arm_gt_hvtimer_cb, cpu);
64
return EXYNOS4210_COMBINER_GET_IRQ_NUM(grp, bit);
83
+ cpu->gt_timer[GTIMER_S_EL2_PHYS] = timer_new(QEMU_CLOCK_VIRTUAL, scale,
84
+ arm_gt_sel2timer_cb, cpu);
85
+ cpu->gt_timer[GTIMER_S_EL2_VIRT] = timer_new(QEMU_CLOCK_VIRTUAL, scale,
86
+ arm_gt_sel2vtimer_cb, cpu);
87
}
88
#endif
89
90
diff --git a/target/arm/helper.c b/target/arm/helper.c
91
index XXXXXXX..XXXXXXX 100644
92
--- a/target/arm/helper.c
93
+++ b/target/arm/helper.c
94
@@ -XXX,XX +XXX,XX @@ static CPAccessResult gt_stimer_access(CPUARMState *env,
95
}
65
}
96
}
66
97
67
+/*
98
+static CPAccessResult gt_sel2timer_access(CPUARMState *env,
68
+ * Get Combiner input GPIO into irqs structure
99
+ const ARMCPRegInfo *ri,
69
+ */
100
+ bool isread)
70
+static void exynos4210_combiner_get_gpioin(Exynos4210Irq *irqs,
101
+{
71
+ DeviceState *dev, int ext)
72
+{
73
+ int n;
74
+ int bit;
75
+ int max;
76
+ qemu_irq *irq;
77
+
78
+ max = ext ? EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ :
79
+ EXYNOS4210_MAX_INT_COMBINER_IN_IRQ;
80
+ irq = ext ? irqs->ext_combiner_irq : irqs->int_combiner_irq;
81
+
82
+ /*
102
+ /*
83
+ * Some IRQs of Int/External Combiner are going to two Combiners groups,
103
+ * The AArch64 register view of the secure EL2 timers are mostly
84
+ * so let split them.
104
+ * accessible from EL3 and EL2 although can also be trapped to EL2
105
+ * from EL1 depending on nested virt config.
85
+ */
106
+ */
86
+ for (n = 0; n < max; n++) {
107
+ switch (arm_current_el(env)) {
87
+
108
+ case 0: /* UNDEFINED */
88
+ bit = EXYNOS4210_COMBINER_GET_BIT_NUM(n);
109
+ return CP_ACCESS_UNDEFINED;
89
+
110
+ case 1:
90
+ switch (n) {
111
+ if (!arm_is_secure(env)) {
91
+ /* MDNIE_LCD1 INTG1 */
112
+ /* UNDEFINED */
92
+ case EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 0) ...
113
+ return CP_ACCESS_UNDEFINED;
93
+ EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 3):
114
+ } else if (arm_hcr_el2_eff(env) & HCR_NV) {
94
+ irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
115
+ /* Aarch64.SystemAccessTrap(EL2, 0x18) */
95
+ irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(0, bit + 4)]);
116
+ return CP_ACCESS_TRAP_EL2;
96
+ continue;
97
+
98
+ /* TMU INTG3 */
99
+ case EXYNOS4210_COMBINER_GET_IRQ_NUM(3, 4):
100
+ irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
101
+ irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(2, bit)]);
102
+ continue;
103
+
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
+ }
117
+ }
139
+
118
+ /* UNDEFINED */
140
+ irq[n] = qdev_get_gpio_in(dev, n);
119
+ return CP_ACCESS_UNDEFINED;
120
+ case 2:
121
+ if (!arm_is_secure(env)) {
122
+ /* UNDEFINED */
123
+ return CP_ACCESS_UNDEFINED;
124
+ }
125
+ return CP_ACCESS_OK;
126
+ case 3:
127
+ if (env->cp15.scr_el3 & SCR_EEL2) {
128
+ return CP_ACCESS_OK;
129
+ } else {
130
+ return CP_ACCESS_UNDEFINED;
131
+ }
132
+ default:
133
+ g_assert_not_reached();
141
+ }
134
+ }
142
+}
135
+}
143
+
136
+
144
static uint8_t chipid_and_omr[] = { 0x11, 0x02, 0x21, 0x43,
137
uint64_t gt_get_countervalue(CPUARMState *env)
145
0x09, 0x00, 0x00, 0x00 };
138
{
146
139
ARMCPU *cpu = env_archcpu(env);
147
diff --git a/hw/intc/exynos4210_combiner.c b/hw/intc/exynos4210_combiner.c
140
@@ -XXX,XX +XXX,XX @@ static uint64_t gt_indirect_access_timer_offset(CPUARMState *env, int timeridx)
148
index XXXXXXX..XXXXXXX 100644
141
case GTIMER_HYP:
149
--- a/hw/intc/exynos4210_combiner.c
142
case GTIMER_SEC:
150
+++ b/hw/intc/exynos4210_combiner.c
143
case GTIMER_HYPVIRT:
151
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_exynos4210_combiner = {
144
+ case GTIMER_S_EL2_PHYS:
152
}
145
+ case GTIMER_S_EL2_VIRT:
146
return 0;
147
default:
148
g_assert_not_reached();
149
@@ -XXX,XX +XXX,XX @@ uint64_t gt_direct_access_timer_offset(CPUARMState *env, int timeridx)
150
case GTIMER_HYP:
151
case GTIMER_SEC:
152
case GTIMER_HYPVIRT:
153
+ case GTIMER_S_EL2_PHYS:
154
+ case GTIMER_S_EL2_VIRT:
155
return 0;
156
default:
157
g_assert_not_reached();
158
@@ -XXX,XX +XXX,XX @@ static void gt_sec_ctl_write(CPUARMState *env, const ARMCPRegInfo *ri,
159
gt_ctl_write(env, ri, GTIMER_SEC, value);
160
}
161
162
+static void gt_sec_pel2_timer_reset(CPUARMState *env, const ARMCPRegInfo *ri)
163
+{
164
+ gt_timer_reset(env, ri, GTIMER_S_EL2_PHYS);
165
+}
166
+
167
+static void gt_sec_pel2_cval_write(CPUARMState *env, const ARMCPRegInfo *ri,
168
+ uint64_t value)
169
+{
170
+ gt_cval_write(env, ri, GTIMER_S_EL2_PHYS, value);
171
+}
172
+
173
+static uint64_t gt_sec_pel2_tval_read(CPUARMState *env, const ARMCPRegInfo *ri)
174
+{
175
+ return gt_tval_read(env, ri, GTIMER_S_EL2_PHYS);
176
+}
177
+
178
+static void gt_sec_pel2_tval_write(CPUARMState *env, const ARMCPRegInfo *ri,
179
+ uint64_t value)
180
+{
181
+ gt_tval_write(env, ri, GTIMER_S_EL2_PHYS, value);
182
+}
183
+
184
+static void gt_sec_pel2_ctl_write(CPUARMState *env, const ARMCPRegInfo *ri,
185
+ uint64_t value)
186
+{
187
+ gt_ctl_write(env, ri, GTIMER_S_EL2_PHYS, value);
188
+}
189
+
190
+static void gt_sec_vel2_timer_reset(CPUARMState *env, const ARMCPRegInfo *ri)
191
+{
192
+ gt_timer_reset(env, ri, GTIMER_S_EL2_VIRT);
193
+}
194
+
195
+static void gt_sec_vel2_cval_write(CPUARMState *env, const ARMCPRegInfo *ri,
196
+ uint64_t value)
197
+{
198
+ gt_cval_write(env, ri, GTIMER_S_EL2_VIRT, value);
199
+}
200
+
201
+static uint64_t gt_sec_vel2_tval_read(CPUARMState *env, const ARMCPRegInfo *ri)
202
+{
203
+ return gt_tval_read(env, ri, GTIMER_S_EL2_VIRT);
204
+}
205
+
206
+static void gt_sec_vel2_tval_write(CPUARMState *env, const ARMCPRegInfo *ri,
207
+ uint64_t value)
208
+{
209
+ gt_tval_write(env, ri, GTIMER_S_EL2_VIRT, value);
210
+}
211
+
212
+static void gt_sec_vel2_ctl_write(CPUARMState *env, const ARMCPRegInfo *ri,
213
+ uint64_t value)
214
+{
215
+ gt_ctl_write(env, ri, GTIMER_S_EL2_VIRT, value);
216
+}
217
+
218
static void gt_hv_timer_reset(CPUARMState *env, const ARMCPRegInfo *ri)
219
{
220
gt_timer_reset(env, ri, GTIMER_HYPVIRT);
221
@@ -XXX,XX +XXX,XX @@ void arm_gt_stimer_cb(void *opaque)
222
gt_recalc_timer(cpu, GTIMER_SEC);
223
}
224
225
+void arm_gt_sel2timer_cb(void *opaque)
226
+{
227
+ ARMCPU *cpu = opaque;
228
+
229
+ gt_recalc_timer(cpu, GTIMER_S_EL2_PHYS);
230
+}
231
+
232
+void arm_gt_sel2vtimer_cb(void *opaque)
233
+{
234
+ ARMCPU *cpu = opaque;
235
+
236
+ gt_recalc_timer(cpu, GTIMER_S_EL2_VIRT);
237
+}
238
+
239
void arm_gt_hvtimer_cb(void *opaque)
240
{
241
ARMCPU *cpu = opaque;
242
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo el2_sec_cp_reginfo[] = {
243
.access = PL2_RW, .accessfn = sel2_access,
244
.nv2_redirect_offset = 0x48,
245
.fieldoffset = offsetof(CPUARMState, cp15.vstcr_el2) },
246
+#ifndef CONFIG_USER_ONLY
247
+ /* Secure EL2 Physical Timer */
248
+ { .name = "CNTHPS_TVAL_EL2", .state = ARM_CP_STATE_AA64,
249
+ .opc0 = 3, .opc1 = 4, .crn = 14, .crm = 5, .opc2 = 0,
250
+ .type = ARM_CP_NO_RAW | ARM_CP_IO, .access = PL2_RW,
251
+ .accessfn = gt_sel2timer_access,
252
+ .readfn = gt_sec_pel2_tval_read,
253
+ .writefn = gt_sec_pel2_tval_write,
254
+ .resetfn = gt_sec_pel2_timer_reset,
255
+ },
256
+ { .name = "CNTHPS_CTL_EL2", .state = ARM_CP_STATE_AA64,
257
+ .opc0 = 3, .opc1 = 4, .crn = 14, .crm = 5, .opc2 = 1,
258
+ .type = ARM_CP_IO, .access = PL2_RW,
259
+ .accessfn = gt_sel2timer_access,
260
+ .fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_S_EL2_PHYS].ctl),
261
+ .resetvalue = 0,
262
+ .writefn = gt_sec_pel2_ctl_write, .raw_writefn = raw_write,
263
+ },
264
+ { .name = "CNTHPS_CVAL_EL2", .state = ARM_CP_STATE_AA64,
265
+ .opc0 = 3, .opc1 = 4, .crn = 14, .crm = 5, .opc2 = 2,
266
+ .type = ARM_CP_IO, .access = PL2_RW,
267
+ .accessfn = gt_sel2timer_access,
268
+ .fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_S_EL2_PHYS].cval),
269
+ .writefn = gt_sec_pel2_cval_write, .raw_writefn = raw_write,
270
+ },
271
+ /* Secure EL2 Virtual Timer */
272
+ { .name = "CNTHVS_TVAL_EL2", .state = ARM_CP_STATE_AA64,
273
+ .opc0 = 3, .opc1 = 4, .crn = 14, .crm = 4, .opc2 = 0,
274
+ .type = ARM_CP_NO_RAW | ARM_CP_IO, .access = PL2_RW,
275
+ .accessfn = gt_sel2timer_access,
276
+ .readfn = gt_sec_vel2_tval_read,
277
+ .writefn = gt_sec_vel2_tval_write,
278
+ .resetfn = gt_sec_vel2_timer_reset,
279
+ },
280
+ { .name = "CNTHVS_CTL_EL2", .state = ARM_CP_STATE_AA64,
281
+ .opc0 = 3, .opc1 = 4, .crn = 14, .crm = 4, .opc2 = 1,
282
+ .type = ARM_CP_IO, .access = PL2_RW,
283
+ .accessfn = gt_sel2timer_access,
284
+ .fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_S_EL2_VIRT].ctl),
285
+ .resetvalue = 0,
286
+ .writefn = gt_sec_vel2_ctl_write, .raw_writefn = raw_write,
287
+ },
288
+ { .name = "CNTHVS_CVAL_EL2", .state = ARM_CP_STATE_AA64,
289
+ .opc0 = 3, .opc1 = 4, .crn = 14, .crm = 4, .opc2 = 2,
290
+ .type = ARM_CP_IO, .access = PL2_RW,
291
+ .accessfn = gt_sel2timer_access,
292
+ .fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_S_EL2_VIRT].cval),
293
+ .writefn = gt_sec_vel2_cval_write, .raw_writefn = raw_write,
294
+ },
295
+#endif
153
};
296
};
154
297
155
-/*
298
static CPAccessResult nsacr_access(CPUARMState *env, const ARMCPRegInfo *ri,
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
{
235
--
299
--
236
2.25.1
300
2.43.0
301
302
diff view generated by jsdifflib
1
From: Hao Wu <wuhaotsh@google.com>
1
From: Alex Bennée <alex.bennee@linaro.org>
2
2
3
This patch uses the defined fields to describe PWRON STRAPs for
3
As we are about to add more physical and virtual timers let's make it
4
better readability.
4
clear what each timer does.
5
5
6
Signed-off-by: Hao Wu <wuhaotsh@google.com>
6
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
7
Reviewed-by: Patrick Venture <venture@google.com>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Message-id: 20220411165842.3912945-3-wuhaotsh@google.com
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Message-id: 20250204125009.2281315-8-peter.maydell@linaro.org
10
[PMM: Add timer register name prefix to each comment]
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
13
---
12
hw/arm/npcm7xx_boards.c | 24 +++++++++++++++++++-----
14
target/arm/gtimer.h | 10 +++++-----
13
1 file changed, 19 insertions(+), 5 deletions(-)
15
1 file changed, 5 insertions(+), 5 deletions(-)
14
16
15
diff --git a/hw/arm/npcm7xx_boards.c b/hw/arm/npcm7xx_boards.c
17
diff --git a/target/arm/gtimer.h b/target/arm/gtimer.h
16
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/arm/npcm7xx_boards.c
19
--- a/target/arm/gtimer.h
18
+++ b/hw/arm/npcm7xx_boards.c
20
+++ b/target/arm/gtimer.h
19
@@ -XXX,XX +XXX,XX @@
21
@@ -XXX,XX +XXX,XX @@
20
#include "sysemu/sysemu.h"
22
#define TARGET_ARM_GTIMER_H
21
#include "sysemu/block-backend.h"
23
22
24
enum {
23
-#define NPCM750_EVB_POWER_ON_STRAPS 0x00001ff7
25
- GTIMER_PHYS = 0,
24
-#define QUANTA_GSJ_POWER_ON_STRAPS 0x00001fff
26
- GTIMER_VIRT = 1,
25
-#define QUANTA_GBS_POWER_ON_STRAPS 0x000017ff
27
- GTIMER_HYP = 2,
26
-#define KUDO_BMC_POWER_ON_STRAPS 0x00001fff
28
- GTIMER_SEC = 3,
27
-#define MORI_BMC_POWER_ON_STRAPS 0x00001fff
29
- GTIMER_HYPVIRT = 4,
28
+#define NPCM7XX_POWER_ON_STRAPS_DEFAULT ( \
30
+ GTIMER_PHYS = 0, /* CNTP_* ; EL1 physical timer */
29
+ NPCM7XX_PWRON_STRAP_SPI0F18 | \
31
+ GTIMER_VIRT = 1, /* CNTV_* ; EL1 virtual timer */
30
+ NPCM7XX_PWRON_STRAP_SFAB | \
32
+ GTIMER_HYP = 2, /* CNTHP_* ; EL2 physical timer */
31
+ NPCM7XX_PWRON_STRAP_BSPA | \
33
+ GTIMER_SEC = 3, /* CNTPS_* ; EL3 physical timer */
32
+ NPCM7XX_PWRON_STRAP_FUP(FUP_NORM_UART2) | \
34
+ GTIMER_HYPVIRT = 4, /* CNTHV_* ; EL2 virtual timer ; only if FEAT_VHE */
33
+ NPCM7XX_PWRON_STRAP_SECEN | \
35
GTIMER_S_EL2_PHYS = 5, /* CNTHPS_* ; only if FEAT_SEL2 */
34
+ NPCM7XX_PWRON_STRAP_HIZ | \
36
GTIMER_S_EL2_VIRT = 6, /* CNTHVS_* ; only if FEAT_SEL2 */
35
+ NPCM7XX_PWRON_STRAP_ECC | \
37
#define NUM_GTIMERS 7
36
+ NPCM7XX_PWRON_STRAP_RESERVE1 | \
37
+ NPCM7XX_PWRON_STRAP_J2EN | \
38
+ NPCM7XX_PWRON_STRAP_CKFRQ(CKFRQ_DEFAULT))
39
+
40
+#define NPCM750_EVB_POWER_ON_STRAPS ( \
41
+ NPCM7XX_POWER_ON_STRAPS_DEFAULT & ~NPCM7XX_PWRON_STRAP_J2EN)
42
+#define QUANTA_GSJ_POWER_ON_STRAPS NPCM7XX_POWER_ON_STRAPS_DEFAULT
43
+#define QUANTA_GBS_POWER_ON_STRAPS ( \
44
+ NPCM7XX_POWER_ON_STRAPS_DEFAULT & ~NPCM7XX_PWRON_STRAP_SFAB)
45
+#define KUDO_BMC_POWER_ON_STRAPS NPCM7XX_POWER_ON_STRAPS_DEFAULT
46
+#define MORI_BMC_POWER_ON_STRAPS NPCM7XX_POWER_ON_STRAPS_DEFAULT
47
48
static const char npcm7xx_default_bootrom[] = "npcm7xx_bootrom.bin";
49
50
--
38
--
51
2.25.1
39
2.43.0
40
41
diff view generated by jsdifflib
1
It's not possible to provide the guest with the Security extensions
1
From: Alex Bennée <alex.bennee@linaro.org>
2
(TrustZone) when using KVM or HVF, because the hardware
3
virtualization extensions don't permit running EL3 guest code.
4
However, we weren't checking for this combination, with the result
5
that QEMU would assert if you tried it:
6
2
7
$ qemu-system-aarch64 -enable-kvm -machine virt,secure=on -cpu host -display none
3
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
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
19
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
20
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
21
Message-id: 20220404155301.566542-1-peter.maydell@linaro.org
6
Message-id: 20250204125009.2281315-9-peter.maydell@linaro.org
7
Cc: qemu-stable@nongnu.org
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
22
---
10
---
23
hw/arm/virt.c | 7 +++++++
11
hw/arm/virt.c | 2 ++
24
1 file changed, 7 insertions(+)
12
1 file changed, 2 insertions(+)
25
13
26
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
14
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
27
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
28
--- a/hw/arm/virt.c
16
--- a/hw/arm/virt.c
29
+++ b/hw/arm/virt.c
17
+++ b/hw/arm/virt.c
30
@@ -XXX,XX +XXX,XX @@ static void machvirt_init(MachineState *machine)
18
@@ -XXX,XX +XXX,XX @@ static void create_gic(VirtMachineState *vms, MemoryRegion *mem)
31
exit(1);
19
[GTIMER_HYP] = ARCH_TIMER_NS_EL2_IRQ,
32
}
20
[GTIMER_SEC] = ARCH_TIMER_S_EL1_IRQ,
33
21
[GTIMER_HYPVIRT] = ARCH_TIMER_NS_EL2_VIRT_IRQ,
34
+ if (vms->secure && (kvm_enabled() || hvf_enabled())) {
22
+ [GTIMER_S_EL2_PHYS] = ARCH_TIMER_S_EL2_IRQ,
35
+ error_report("mach-virt: %s does not support providing "
23
+ [GTIMER_S_EL2_VIRT] = ARCH_TIMER_S_EL2_VIRT_IRQ,
36
+ "Security extensions (TrustZone) to the guest CPU",
24
};
37
+ kvm_enabled() ? "KVM" : "HVF");
25
38
+ exit(1);
26
for (unsigned irq = 0; irq < ARRAY_SIZE(timer_irq); irq++) {
39
+ }
40
+
41
if (vms->virt && (kvm_enabled() || hvf_enabled())) {
42
error_report("mach-virt: %s does not support providing "
43
"Virtualization extensions to the guest CPU",
44
--
27
--
45
2.25.1
28
2.43.0
29
30
diff view generated by jsdifflib
Deleted patch
1
From: "Edgar E. Iglesias" <edgar.iglesias@amd.com>
2
1
3
Break out header file to allow embedding of the the TTC.
4
5
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>
6
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
7
Reviewed-by: Luc Michel <luc@lmichel.fr>
8
Reviewed-by: Francisco Iglesias <frasse.iglesias@gmail.com>
9
Message-id: 20220331222017.2914409-2-edgar.iglesias@gmail.com
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
include/hw/timer/cadence_ttc.h | 54 ++++++++++++++++++++++++++++++++++
13
hw/timer/cadence_ttc.c | 32 ++------------------
14
2 files changed, 56 insertions(+), 30 deletions(-)
15
create mode 100644 include/hw/timer/cadence_ttc.h
16
17
diff --git a/include/hw/timer/cadence_ttc.h b/include/hw/timer/cadence_ttc.h
18
new file mode 100644
19
index XXXXXXX..XXXXXXX
20
--- /dev/null
21
+++ b/include/hw/timer/cadence_ttc.h
22
@@ -XXX,XX +XXX,XX @@
23
+/*
24
+ * Xilinx Zynq cadence TTC model
25
+ *
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
78
index XXXXXXX..XXXXXXX 100644
79
--- a/hw/timer/cadence_ttc.c
80
+++ b/hw/timer/cadence_ttc.c
81
@@ -XXX,XX +XXX,XX @@
82
#include "qemu/timer.h"
83
#include "qom/object.h"
84
85
+#include "hw/timer/cadence_ttc.h"
86
+
87
#ifdef CADENCE_TTC_ERR_DEBUG
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));
127
--
128
2.25.1
diff view generated by jsdifflib
Deleted patch
1
From: "Edgar E. Iglesias" <edgar.iglesias@amd.com>
2
1
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
In exynos4210_init_board_irqs(), the loop that handles IRQ lines that
1
From: Alex Bennée <alex.bennee@linaro.org>
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
2
9
I don't have a reliable datasheet for this SoC, but since we do wire
3
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
10
up one interrupt line in this category (the HDMI I2C device on
4
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
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.
20
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
22
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20250204125009.2281315-10-peter.maydell@linaro.org
23
Message-id: 20220404154658.565020-14-peter.maydell@linaro.org
7
Cc: qemu-stable@nongnu.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
24
---
9
---
25
hw/arm/exynos4210.c | 2 ++
10
hw/arm/sbsa-ref.c | 2 ++
26
1 file changed, 2 insertions(+)
11
1 file changed, 2 insertions(+)
27
12
28
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
13
diff --git a/hw/arm/sbsa-ref.c b/hw/arm/sbsa-ref.c
29
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
30
--- a/hw/arm/exynos4210.c
15
--- a/hw/arm/sbsa-ref.c
31
+++ b/hw/arm/exynos4210.c
16
+++ b/hw/arm/sbsa-ref.c
32
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init_board_irqs(Exynos4210State *s)
17
@@ -XXX,XX +XXX,XX @@ static void create_gic(SBSAMachineState *sms, MemoryRegion *mem)
33
qdev_connect_gpio_out(splitter, 0, is->int_combiner_irq[n]);
18
[GTIMER_HYP] = ARCH_TIMER_NS_EL2_IRQ,
34
qdev_connect_gpio_out(splitter, 1,
19
[GTIMER_SEC] = ARCH_TIMER_S_EL1_IRQ,
35
qdev_get_gpio_in(extgicdev, irq_id - 32));
20
[GTIMER_HYPVIRT] = ARCH_TIMER_NS_EL2_VIRT_IRQ,
36
+ } else {
21
+ [GTIMER_S_EL2_PHYS] = ARCH_TIMER_S_EL2_IRQ,
37
+ s->irq_table[n] = is->int_combiner_irq[n];
22
+ [GTIMER_S_EL2_VIRT] = ARCH_TIMER_S_EL2_VIRT_IRQ,
38
}
23
};
39
}
24
40
/*
25
for (irq = 0; irq < ARRAY_SIZE(timer_irq); irq++) {
41
--
26
--
42
2.25.1
27
2.43.0
28
29
diff view generated by jsdifflib
1
The only time we use the int_combiner_irq[] and ext_combiner_irq[]
1
Our LDRD implementation is wrong in two respects:
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
2
10
Since these are the only two remaining elements of Exynos4210Irq,
3
* if the address is 4-aligned and the load crosses a page boundary
11
we can remove that struct entirely.
4
and the second load faults and the first load was to the
5
base register (as in cases like "ldrd r2, r3, [r2]", then we
6
must not update the base register before taking the fault
7
* if the address is 8-aligned the access must be a 64-bit
8
single-copy atomic access, not two 32-bit accesses
12
9
10
Rewrite the handling of the loads in LDRD to use a single
11
tcg_gen_qemu_ld_i64() and split the result into the destination
12
registers. This allows us to get the atomicity requirements
13
right, and also implicitly means that we won't update the
14
base register too early for the page-crossing case.
15
16
Note that because we no longer increment 'addr' by 4 in the course of
17
performing the LDRD we must change the adjustment value we pass to
18
op_addr_ri_post() and op_addr_rr_post(): it no longer needs to
19
subtract 4 to get the correct value to use if doing base register
20
writeback.
21
22
STRD has the same problem with not getting the atomicity right;
23
we will deal with that in the following commit.
24
25
Cc: qemu-stable@nongnu.org
26
Reported-by: Stu Grossman <stu.grossman@gmail.com>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
27
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
28
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
Message-id: 20220404154658.565020-19-peter.maydell@linaro.org
29
Message-id: 20250227142746.1698904-2-peter.maydell@linaro.org
16
---
30
---
17
include/hw/arm/exynos4210.h | 6 ------
31
target/arm/tcg/translate.c | 70 +++++++++++++++++++++++++-------------
18
hw/arm/exynos4210.c | 34 ++++++++--------------------------
32
1 file changed, 46 insertions(+), 24 deletions(-)
19
2 files changed, 8 insertions(+), 32 deletions(-)
20
33
21
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
34
diff --git a/target/arm/tcg/translate.c b/target/arm/tcg/translate.c
22
index XXXXXXX..XXXXXXX 100644
35
index XXXXXXX..XXXXXXX 100644
23
--- a/include/hw/arm/exynos4210.h
36
--- a/target/arm/tcg/translate.c
24
+++ b/include/hw/arm/exynos4210.h
37
+++ b/target/arm/tcg/translate.c
25
@@ -XXX,XX +XXX,XX @@
38
@@ -XXX,XX +XXX,XX @@ static bool op_store_rr(DisasContext *s, arg_ldst_rr *a,
26
*/
39
return true;
27
#define EXYNOS4210_NUM_SPLITTERS (EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ + 38)
40
}
28
41
29
-typedef struct Exynos4210Irq {
42
+static void do_ldrd_load(DisasContext *s, TCGv_i32 addr, int rt, int rt2)
30
- qemu_irq int_combiner_irq[EXYNOS4210_MAX_INT_COMBINER_IN_IRQ];
43
+{
31
- qemu_irq ext_combiner_irq[EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ];
44
+ /*
32
-} Exynos4210Irq;
45
+ * LDRD is required to be an atomic 64-bit access if the
46
+ * address is 8-aligned, two atomic 32-bit accesses if
47
+ * it's only 4-aligned, and to give an alignment fault
48
+ * if it's not 4-aligned. This is MO_ALIGN_4 | MO_ATOM_SUBALIGN.
49
+ * Rt is always the word from the lower address, and Rt2 the
50
+ * data from the higher address, regardless of endianness.
51
+ * So (like gen_load_exclusive) we avoid gen_aa32_ld_i64()
52
+ * so we don't get its SCTLR_B check, and instead do a 64-bit access
53
+ * using MO_BE if appropriate and then split the two halves.
54
+ *
55
+ * For M-profile, and for A-profile before LPAE, the 64-bit
56
+ * atomicity is not required. We could model that using
57
+ * the looser MO_ATOM_IFALIGN_PAIR, but providing a higher
58
+ * level of atomicity than required is harmless (we would not
59
+ * currently generate better code for IFALIGN_PAIR here).
60
+ *
61
+ * This also gives us the correct behaviour of not updating
62
+ * rt if the load of rt2 faults; this is required for cases
63
+ * like "ldrd r2, r3, [r2]" where rt is also the base register.
64
+ */
65
+ int mem_idx = get_mem_index(s);
66
+ MemOp opc = MO_64 | MO_ALIGN_4 | MO_ATOM_SUBALIGN | s->be_data;
67
+ TCGv taddr = gen_aa32_addr(s, addr, opc);
68
+ TCGv_i64 t64 = tcg_temp_new_i64();
69
+ TCGv_i32 tmp = tcg_temp_new_i32();
70
+ TCGv_i32 tmp2 = tcg_temp_new_i32();
71
+
72
+ tcg_gen_qemu_ld_i64(t64, taddr, mem_idx, opc);
73
+ if (s->be_data == MO_BE) {
74
+ tcg_gen_extr_i64_i32(tmp2, tmp, t64);
75
+ } else {
76
+ tcg_gen_extr_i64_i32(tmp, tmp2, t64);
77
+ }
78
+ store_reg(s, rt, tmp);
79
+ store_reg(s, rt2, tmp2);
80
+}
81
+
82
static bool trans_LDRD_rr(DisasContext *s, arg_ldst_rr *a)
83
{
84
- int mem_idx = get_mem_index(s);
85
- TCGv_i32 addr, tmp;
86
+ TCGv_i32 addr;
87
88
if (!ENABLE_ARCH_5TE) {
89
return false;
90
@@ -XXX,XX +XXX,XX @@ static bool trans_LDRD_rr(DisasContext *s, arg_ldst_rr *a)
91
}
92
addr = op_addr_rr_pre(s, a);
93
94
- tmp = tcg_temp_new_i32();
95
- gen_aa32_ld_i32(s, tmp, addr, mem_idx, MO_UL | MO_ALIGN);
96
- store_reg(s, a->rt, tmp);
33
-
97
-
34
struct Exynos4210State {
98
- tcg_gen_addi_i32(addr, addr, 4);
35
/*< private >*/
99
-
36
SysBusDevice parent_obj;
100
- tmp = tcg_temp_new_i32();
37
/*< public >*/
101
- gen_aa32_ld_i32(s, tmp, addr, mem_idx, MO_UL | MO_ALIGN);
38
ARMCPU *cpu[EXYNOS4210_NCPUS];
102
- store_reg(s, a->rt + 1, tmp);
39
- Exynos4210Irq irqs;
103
+ do_ldrd_load(s, addr, a->rt, a->rt + 1);
40
qemu_irq irq_table[EXYNOS4210_MAX_INT_COMBINER_IN_IRQ];
104
41
105
/* LDRD w/ base writeback is undefined if the registers overlap. */
42
MemoryRegion chipid_mem;
106
- op_addr_rr_post(s, a, addr, -4);
43
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
107
+ op_addr_rr_post(s, a, addr, 0);
44
index XXXXXXX..XXXXXXX 100644
108
return true;
45
--- a/hw/arm/exynos4210.c
109
}
46
+++ b/hw/arm/exynos4210.c
110
47
@@ -XXX,XX +XXX,XX @@ static int mapline_size(const int *mapline)
111
@@ -XXX,XX +XXX,XX @@ static bool op_store_ri(DisasContext *s, arg_ldst_ri *a,
48
static void exynos4210_init_board_irqs(Exynos4210State *s)
112
113
static bool op_ldrd_ri(DisasContext *s, arg_ldst_ri *a, int rt2)
49
{
114
{
50
uint32_t grp, bit, irq_id, n;
115
- int mem_idx = get_mem_index(s);
51
- Exynos4210Irq *is = &s->irqs;
116
- TCGv_i32 addr, tmp;
52
DeviceState *extgicdev = DEVICE(&s->ext_gic);
117
+ TCGv_i32 addr;
53
+ DeviceState *intcdev = DEVICE(&s->int_combiner);
118
54
+ DeviceState *extcdev = DEVICE(&s->ext_combiner);
119
addr = op_addr_ri_pre(s, a);
55
int splitcount = 0;
120
56
DeviceState *splitter;
121
- tmp = tcg_temp_new_i32();
57
const int *mapline;
122
- gen_aa32_ld_i32(s, tmp, addr, mem_idx, MO_UL | MO_ALIGN);
58
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init_board_irqs(Exynos4210State *s)
123
- store_reg(s, a->rt, tmp);
59
splitin = 0;
124
-
60
for (;;) {
125
- tcg_gen_addi_i32(addr, addr, 4);
61
s->irq_table[in] = qdev_get_gpio_in(splitter, 0);
126
-
62
- qdev_connect_gpio_out(splitter, splitin, is->int_combiner_irq[in]);
127
- tmp = tcg_temp_new_i32();
63
- qdev_connect_gpio_out(splitter, splitin + 1, is->ext_combiner_irq[in]);
128
- gen_aa32_ld_i32(s, tmp, addr, mem_idx, MO_UL | MO_ALIGN);
64
+ qdev_connect_gpio_out(splitter, splitin,
129
- store_reg(s, rt2, tmp);
65
+ qdev_get_gpio_in(intcdev, in));
130
+ do_ldrd_load(s, addr, a->rt, rt2);
66
+ qdev_connect_gpio_out(splitter, splitin + 1,
131
67
+ qdev_get_gpio_in(extcdev, in));
132
/* LDRD w/ base writeback is undefined if the registers overlap. */
68
splitin += 2;
133
- op_addr_ri_post(s, a, addr, -4);
69
if (!mapline) {
134
+ op_addr_ri_post(s, a, addr, 0);
70
break;
135
return true;
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);
87
}
136
}
88
137
89
-/*
90
- * Get Combiner input GPIO into irqs structure
91
- */
92
-static void exynos4210_combiner_get_gpioin(Exynos4210Irq *irqs,
93
- DeviceState *dev, int ext)
94
-{
95
- int n;
96
- int max;
97
- qemu_irq *irq;
98
-
99
- max = ext ? EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ :
100
- EXYNOS4210_MAX_INT_COMBINER_IN_IRQ;
101
- irq = ext ? irqs->ext_combiner_irq : irqs->int_combiner_irq;
102
-
103
- for (n = 0; n < max; n++) {
104
- irq[n] = qdev_get_gpio_in(dev, n);
105
- }
106
-}
107
-
108
static uint8_t chipid_and_omr[] = { 0x11, 0x02, 0x21, 0x43,
109
0x09, 0x00, 0x00, 0x00 };
110
111
@@ -XXX,XX +XXX,XX @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
112
sysbus_connect_irq(busdev, n,
113
qdev_get_gpio_in(DEVICE(&s->a9mpcore), n));
114
}
115
- exynos4210_combiner_get_gpioin(&s->irqs, DEVICE(&s->int_combiner), 0);
116
sysbus_mmio_map(busdev, 0, EXYNOS4210_INT_COMBINER_BASE_ADDR);
117
118
/* External Interrupt Combiner */
119
@@ -XXX,XX +XXX,XX @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
120
for (n = 0; n < EXYNOS4210_MAX_INT_COMBINER_OUT_IRQ; n++) {
121
sysbus_connect_irq(busdev, n, qdev_get_gpio_in(DEVICE(&s->ext_gic), n));
122
}
123
- exynos4210_combiner_get_gpioin(&s->irqs, DEVICE(&s->ext_combiner), 1);
124
sysbus_mmio_map(busdev, 0, EXYNOS4210_EXT_COMBINER_BASE_ADDR);
125
126
/* Initialize board IRQs. */
127
--
138
--
128
2.25.1
139
2.43.0
diff view generated by jsdifflib
1
At this point, the function exynos4210_init_board_irqs() splits input
1
Our STRD implementation doesn't correctly implement the requirement:
2
IRQ lines to connect them to the input combiner, output combiner and
2
* if the address is 8-aligned the access must be a 64-bit
3
external GIC. The function exynos4210_combiner_get_gpioin() splits
3
single-copy atomic access, not two 32-bit accesses
4
some of the combiner input lines further to connect them to multiple
5
different inputs on the combiner.
6
4
7
Because (unlike qemu_irq_split()) the TYPE_SPLIT_IRQ device has a
5
Rewrite the handling of STRD to use a single tcg_gen_qemu_st_i64()
8
configurable number of outputs, we can do all this in one place, by
6
of a value produced by concatenating the two 32 bit source registers.
9
making exynos4210_init_board_irqs() add extra outputs to the splitter
7
This allows us to get the atomicity right.
10
device when it must be connected to more than one input on each
11
combiner.
12
8
13
We do this with a new data structure, the combinermap, which is an
9
As with the LDRD change, now that we don't update 'addr' in the
14
array each of whose elements is a list of the interrupt IDs on the
10
course of performing the store we need to adjust the offset
15
combiner which must be tied together. As we loop through each
11
we pass to op_addr_ri_post() and op_addr_rr_post().
16
interrupt ID, if we find that it is the first one in one of these
17
lists, we configure the splitter device with eonugh extra outputs and
18
wire them up to the other interrupt IDs in the list.
19
12
20
Conveniently, for all the cases where this is necessary, the
13
Cc: qemu-stable@nongnu.org
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.
38
39
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
40
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
41
Message-id: 20220404154658.565020-17-peter.maydell@linaro.org
16
Message-id: 20250227142746.1698904-3-peter.maydell@linaro.org
42
---
17
---
43
include/hw/arm/exynos4210.h | 6 +-
18
target/arm/tcg/translate.c | 59 +++++++++++++++++++++++++-------------
44
hw/arm/exynos4210.c | 178 +++++++++++++++++++++++-------------
19
1 file changed, 39 insertions(+), 20 deletions(-)
45
2 files changed, 119 insertions(+), 65 deletions(-)
46
20
47
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
21
diff --git a/target/arm/tcg/translate.c b/target/arm/tcg/translate.c
48
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
49
--- a/include/hw/arm/exynos4210.h
23
--- a/target/arm/tcg/translate.c
50
+++ b/include/hw/arm/exynos4210.h
24
+++ b/target/arm/tcg/translate.c
51
@@ -XXX,XX +XXX,XX @@
25
@@ -XXX,XX +XXX,XX @@ static bool trans_LDRD_rr(DisasContext *s, arg_ldst_rr *a)
52
26
return true;
53
/*
27
}
54
* We need one splitter for every external combiner input, plus
28
55
- * one for every non-zero entry in combiner_grp_to_gic_id[].
29
+static void do_strd_store(DisasContext *s, TCGv_i32 addr, int rt, int rt2)
56
+ * one for every non-zero entry in combiner_grp_to_gic_id[],
57
+ * minus one for every external combiner ID in second or later
58
+ * places in a combinermap[] line.
59
* We'll assert in exynos4210_init_board_irqs() if this is wrong.
60
*/
61
-#define EXYNOS4210_NUM_SPLITTERS (EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ + 54)
62
+#define EXYNOS4210_NUM_SPLITTERS (EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ + 38)
63
64
typedef struct Exynos4210Irq {
65
qemu_irq int_combiner_irq[EXYNOS4210_MAX_INT_COMBINER_IN_IRQ];
66
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
67
index XXXXXXX..XXXXXXX 100644
68
--- a/hw/arm/exynos4210.c
69
+++ b/hw/arm/exynos4210.c
70
@@ -XXX,XX +XXX,XX @@ combiner_grp_to_gic_id[64 - EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][8] = {
71
#define EXYNOS4210_COMBINER_GET_BIT_NUM(irq) \
72
((irq) - 8 * EXYNOS4210_COMBINER_GET_GRP_NUM(irq))
73
74
+/*
75
+ * Some interrupt lines go to multiple combiner inputs.
76
+ * This data structure defines those: each array element is
77
+ * a list of combiner inputs which are connected together;
78
+ * the one with the smallest interrupt ID value must be first.
79
+ * As with combiner_grp_to_gic_id[], we rely on (0, 0) not being
80
+ * wired to anything so we can use 0 as a terminator.
81
+ */
82
+#define IRQNO(G, B) EXYNOS4210_COMBINER_GET_IRQ_NUM(G, B)
83
+#define IRQNONE 0
84
+
85
+#define COMBINERMAP_SIZE 16
86
+
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)
113
+{
30
+{
114
+ /*
31
+ /*
115
+ * If the interrupt number passed in is the first entry in some
32
+ * STRD is required to be an atomic 64-bit access if the
116
+ * line of the combinermap, return a pointer to that line;
33
+ * address is 8-aligned, two atomic 32-bit accesses if
117
+ * otherwise return NULL.
34
+ * it's only 4-aligned, and to give an alignment fault
35
+ * if it's not 4-aligned.
36
+ * Rt is always the word from the lower address, and Rt2 the
37
+ * data from the higher address, regardless of endianness.
38
+ * So (like gen_store_exclusive) we avoid gen_aa32_ld_i64()
39
+ * so we don't get its SCTLR_B check, and instead do a 64-bit access
40
+ * using MO_BE if appropriate, using a value constructed
41
+ * by putting the two halves together in the right order.
42
+ *
43
+ * As with LDRD, the 64-bit atomicity is not required for
44
+ * M-profile, or for A-profile before LPAE, and we provide
45
+ * the higher guarantee always for simplicity.
118
+ */
46
+ */
119
+ int i;
47
+ int mem_idx = get_mem_index(s);
120
+ for (i = 0; i < COMBINERMAP_SIZE; i++) {
48
+ MemOp opc = MO_64 | MO_ALIGN_4 | MO_ATOM_SUBALIGN | s->be_data;
121
+ if (combinermap[i][0] == irq) {
49
+ TCGv taddr = gen_aa32_addr(s, addr, opc);
122
+ return combinermap[i];
50
+ TCGv_i32 t1 = load_reg(s, rt);
123
+ }
51
+ TCGv_i32 t2 = load_reg(s, rt2);
52
+ TCGv_i64 t64 = tcg_temp_new_i64();
53
+
54
+ if (s->be_data == MO_BE) {
55
+ tcg_gen_concat_i32_i64(t64, t2, t1);
56
+ } else {
57
+ tcg_gen_concat_i32_i64(t64, t1, t2);
124
+ }
58
+ }
125
+ return NULL;
59
+ tcg_gen_qemu_st_i64(t64, taddr, mem_idx, opc);
126
+}
60
+}
127
+
61
+
128
+static int mapline_size(const int *mapline)
62
static bool trans_STRD_rr(DisasContext *s, arg_ldst_rr *a)
129
+{
63
{
130
+ /* Return number of entries in this mapline in total */
64
- int mem_idx = get_mem_index(s);
131
+ int i = 0;
65
- TCGv_i32 addr, tmp;
132
+
66
+ TCGv_i32 addr;
133
+ if (!mapline) {
67
134
+ /* Not in the map? IRQ goes to exactly one combiner input */
68
if (!ENABLE_ARCH_5TE) {
135
+ return 1;
69
return false;
136
+ }
70
@@ -XXX,XX +XXX,XX @@ static bool trans_STRD_rr(DisasContext *s, arg_ldst_rr *a)
137
+ while (*mapline != IRQNONE) {
138
+ mapline++;
139
+ i++;
140
+ }
141
+ return i;
142
+}
143
+
144
/*
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
}
71
}
208
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init_board_irqs(Exynos4210State *s)
72
addr = op_addr_rr_pre(s, a);
209
irq_id = combiner_grp_to_gic_id[grp -
73
210
EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][bit];
74
- tmp = load_reg(s, a->rt);
211
75
- gen_aa32_st_i32(s, tmp, addr, mem_idx, MO_UL | MO_ALIGN);
212
+ if (s->irq_table[n]) {
76
+ do_strd_store(s, addr, a->rt, a->rt + 1);
213
+ /*
77
214
+ * This must be some non-first entry in a combinermap line,
78
- tcg_gen_addi_i32(addr, addr, 4);
215
+ * and we've already filled it in.
79
-
216
+ */
80
- tmp = load_reg(s, a->rt + 1);
217
+ continue;
81
- gen_aa32_st_i32(s, tmp, addr, mem_idx, MO_UL | MO_ALIGN);
218
+ }
82
-
219
+
83
- op_addr_rr_post(s, a, addr, -4);
220
if (irq_id) {
84
+ op_addr_rr_post(s, a, addr, 0);
221
assert(splitcount < EXYNOS4210_NUM_SPLITTERS);
85
return true;
222
splitter = DEVICE(&s->splitter[splitcount]);
86
}
223
@@ -XXX,XX +XXX,XX @@ static void exynos4210_combiner_get_gpioin(Exynos4210Irq *irqs,
87
224
DeviceState *dev, int ext)
88
@@ -XXX,XX +XXX,XX @@ static bool trans_LDRD_ri_t32(DisasContext *s, arg_ldst_ri2 *a)
89
90
static bool op_strd_ri(DisasContext *s, arg_ldst_ri *a, int rt2)
225
{
91
{
226
int n;
92
- int mem_idx = get_mem_index(s);
227
- int bit;
93
- TCGv_i32 addr, tmp;
228
int max;
94
+ TCGv_i32 addr;
229
qemu_irq *irq;
95
230
96
addr = op_addr_ri_pre(s, a);
231
@@ -XXX,XX +XXX,XX @@ static void exynos4210_combiner_get_gpioin(Exynos4210Irq *irqs,
97
232
EXYNOS4210_MAX_INT_COMBINER_IN_IRQ;
98
- tmp = load_reg(s, a->rt);
233
irq = ext ? irqs->ext_combiner_irq : irqs->int_combiner_irq;
99
- gen_aa32_st_i32(s, tmp, addr, mem_idx, MO_UL | MO_ALIGN);
234
100
+ do_strd_store(s, addr, a->rt, rt2);
235
- /*
101
236
- * Some IRQs of Int/External Combiner are going to two Combiners groups,
102
- tcg_gen_addi_i32(addr, addr, 4);
237
- * so let split them.
238
- */
239
for (n = 0; n < max; n++) {
240
-
103
-
241
- bit = EXYNOS4210_COMBINER_GET_BIT_NUM(n);
104
- tmp = load_reg(s, rt2);
105
- gen_aa32_st_i32(s, tmp, addr, mem_idx, MO_UL | MO_ALIGN);
242
-
106
-
243
- switch (n) {
107
- op_addr_ri_post(s, a, addr, -4);
244
- /* MDNIE_LCD1 INTG1 */
108
+ op_addr_ri_post(s, a, addr, 0);
245
- case EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 0) ...
109
return true;
246
- EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 3):
247
- irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
248
- irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(0, bit + 4)]);
249
- continue;
250
-
251
- /* TMU INTG3 */
252
- case EXYNOS4210_COMBINER_GET_IRQ_NUM(3, 4):
253
- irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
254
- irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(2, bit)]);
255
- continue;
256
-
257
- /* LCD1 INTG12 */
258
- case EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 0) ...
259
- EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 3):
260
- irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
261
- irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(11, bit + 4)]);
262
- continue;
263
-
264
- /* Multi-Core Timer INTG12 */
265
- case EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 4) ...
266
- EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 8):
267
- irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
268
- irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(1, bit + 4)]);
269
- continue;
270
-
271
- /* Multi-Core Timer INTG35 */
272
- case EXYNOS4210_COMBINER_GET_IRQ_NUM(35, 4) ...
273
- EXYNOS4210_COMBINER_GET_IRQ_NUM(35, 8):
274
- irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
275
- irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(1, bit + 4)]);
276
- continue;
277
-
278
- /* Multi-Core Timer INTG51 */
279
- case EXYNOS4210_COMBINER_GET_IRQ_NUM(51, 4) ...
280
- EXYNOS4210_COMBINER_GET_IRQ_NUM(51, 8):
281
- irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
282
- irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(1, bit + 4)]);
283
- continue;
284
-
285
- /* Multi-Core Timer INTG53 */
286
- case EXYNOS4210_COMBINER_GET_IRQ_NUM(53, 4) ...
287
- EXYNOS4210_COMBINER_GET_IRQ_NUM(53, 8):
288
- irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
289
- irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(1, bit + 4)]);
290
- continue;
291
- }
292
-
293
irq[n] = qdev_get_gpio_in(dev, n);
294
}
295
}
110
}
111
296
--
112
--
297
2.25.1
113
2.43.0
diff view generated by jsdifflib
1
Switch the creation of the combiner devices to the new-style
1
All the callers of op_addr_rr_post() and op_addr_ri_post() now pass in
2
"embedded in state struct" approach, so we can easily refer
2
zero for the address_offset, so we can remove that argument.
3
to the object elsewhere during realize.
4
3
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20220404154658.565020-18-peter.maydell@linaro.org
6
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
7
Message-id: 20250227142746.1698904-4-peter.maydell@linaro.org
8
---
8
---
9
include/hw/arm/exynos4210.h | 3 ++
9
target/arm/tcg/translate.c | 26 +++++++++++++-------------
10
include/hw/intc/exynos4210_combiner.h | 57 +++++++++++++++++++++++++++
10
1 file changed, 13 insertions(+), 13 deletions(-)
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
15
11
16
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
12
diff --git a/target/arm/tcg/translate.c b/target/arm/tcg/translate.c
17
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
18
--- a/include/hw/arm/exynos4210.h
14
--- a/target/arm/tcg/translate.c
19
+++ b/include/hw/arm/exynos4210.h
15
+++ b/target/arm/tcg/translate.c
20
@@ -XXX,XX +XXX,XX @@
16
@@ -XXX,XX +XXX,XX @@ static TCGv_i32 op_addr_rr_pre(DisasContext *s, arg_ldst_rr *a)
21
#include "hw/sysbus.h"
17
}
22
#include "hw/cpu/a9mpcore.h"
18
23
#include "hw/intc/exynos4210_gic.h"
19
static void op_addr_rr_post(DisasContext *s, arg_ldst_rr *a,
24
+#include "hw/intc/exynos4210_combiner.h"
20
- TCGv_i32 addr, int address_offset)
25
#include "hw/core/split-irq.h"
21
+ TCGv_i32 addr)
26
#include "target/arm/cpu-qom.h"
22
{
27
#include "qom/object.h"
23
if (!a->p) {
28
@@ -XXX,XX +XXX,XX @@ struct Exynos4210State {
24
TCGv_i32 ofs = load_reg(s, a->rm);
29
qemu_or_irq cpu_irq_orgate[EXYNOS4210_NCPUS];
25
@@ -XXX,XX +XXX,XX @@ static void op_addr_rr_post(DisasContext *s, arg_ldst_rr *a,
30
A9MPPrivState a9mpcore;
26
} else if (!a->w) {
31
Exynos4210GicState ext_gic;
27
return;
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
39
index XXXXXXX..XXXXXXX
40
--- /dev/null
41
+++ b/include/hw/intc/exynos4210_combiner.h
42
@@ -XXX,XX +XXX,XX @@
43
+/*
44
+ * Samsung exynos4210 Interrupt Combiner
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
+
65
+#ifndef HW_INTC_EXYNOS4210_COMBINER
66
+#define HW_INTC_EXYNOS4210_COMBINER
67
+
68
+#include "hw/sysbus.h"
69
+
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
+};
98
+
99
+#endif
100
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
101
index XXXXXXX..XXXXXXX 100644
102
--- a/hw/arm/exynos4210.c
103
+++ b/hw/arm/exynos4210.c
104
@@ -XXX,XX +XXX,XX @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
105
}
28
}
106
29
- tcg_gen_addi_i32(addr, addr, address_offset);
107
/* Internal Interrupt Combiner */
30
store_reg(s, a->rn, addr);
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
}
31
}
146
32
147
static void exynos4210_class_init(ObjectClass *klass, void *data)
33
@@ -XXX,XX +XXX,XX @@ static bool op_load_rr(DisasContext *s, arg_ldst_rr *a,
148
diff --git a/hw/intc/exynos4210_combiner.c b/hw/intc/exynos4210_combiner.c
34
* Perform base writeback before the loaded value to
149
index XXXXXXX..XXXXXXX 100644
35
* ensure correct behavior with overlapping index registers.
150
--- a/hw/intc/exynos4210_combiner.c
36
*/
151
+++ b/hw/intc/exynos4210_combiner.c
37
- op_addr_rr_post(s, a, addr, 0);
152
@@ -XXX,XX +XXX,XX @@
38
+ op_addr_rr_post(s, a, addr);
153
#include "hw/sysbus.h"
39
store_reg_from_load(s, a->rt, tmp);
154
#include "migration/vmstate.h"
40
return true;
155
#include "qemu/module.h"
41
}
156
-
42
@@ -XXX,XX +XXX,XX @@ static bool op_store_rr(DisasContext *s, arg_ldst_rr *a,
157
+#include "hw/intc/exynos4210_combiner.h"
43
gen_aa32_st_i32(s, tmp, addr, mem_idx, mop);
158
#include "hw/arm/exynos4210.h"
44
disas_set_da_iss(s, mop, issinfo);
159
#include "hw/hw.h"
45
160
#include "hw/irq.h"
46
- op_addr_rr_post(s, a, addr, 0);
161
@@ -XXX,XX +XXX,XX @@
47
+ op_addr_rr_post(s, a, addr);
162
#define DPRINTF(fmt, ...) do {} while (0)
48
return true;
163
#endif
49
}
164
50
165
-#define IIC_NGRP 64 /* Internal Interrupt Combiner
51
@@ -XXX,XX +XXX,XX @@ static bool trans_LDRD_rr(DisasContext *s, arg_ldst_rr *a)
166
- Groups number */
52
do_ldrd_load(s, addr, a->rt, a->rt + 1);
167
-#define IIC_NIRQ (IIC_NGRP * 8)/* Internal Interrupt Combiner
53
168
- Interrupts number */
54
/* LDRD w/ base writeback is undefined if the registers overlap. */
169
#define IIC_REGION_SIZE 0x108 /* Size of memory mapped region */
55
- op_addr_rr_post(s, a, addr, 0);
170
-#define IIC_REGSET_SIZE 0x41
56
+ op_addr_rr_post(s, a, addr);
171
-
57
return true;
172
-/*
58
}
173
- * State for each output signal of internal combiner
59
174
- */
60
@@ -XXX,XX +XXX,XX @@ static bool trans_STRD_rr(DisasContext *s, arg_ldst_rr *a)
175
-typedef struct CombinerGroupState {
61
176
- uint8_t src_mask; /* 1 - source enabled, 0 - disabled */
62
do_strd_store(s, addr, a->rt, a->rt + 1);
177
- uint8_t src_pending; /* Pending source interrupts before masking */
63
178
-} CombinerGroupState;
64
- op_addr_rr_post(s, a, addr, 0);
179
-
65
+ op_addr_rr_post(s, a, addr);
180
-#define TYPE_EXYNOS4210_COMBINER "exynos4210.combiner"
66
return true;
181
-OBJECT_DECLARE_SIMPLE_TYPE(Exynos4210CombinerState, EXYNOS4210_COMBINER)
67
}
182
-
68
183
-struct Exynos4210CombinerState {
69
@@ -XXX,XX +XXX,XX @@ static TCGv_i32 op_addr_ri_pre(DisasContext *s, arg_ldst_ri *a)
184
- SysBusDevice parent_obj;
70
}
185
-
71
186
- MemoryRegion iomem;
72
static void op_addr_ri_post(DisasContext *s, arg_ldst_ri *a,
187
-
73
- TCGv_i32 addr, int address_offset)
188
- struct CombinerGroupState group[IIC_NGRP];
74
+ TCGv_i32 addr)
189
- uint32_t reg_set[IIC_REGSET_SIZE];
75
{
190
- uint32_t icipsr[2];
76
+ int address_offset = 0;
191
- uint32_t external; /* 1 means that this combiner is external */
77
if (!a->p) {
192
-
78
if (a->u) {
193
- qemu_irq output_irq[IIC_NGRP];
79
- address_offset += a->imm;
194
-};
80
+ address_offset = a->imm;
195
81
} else {
196
static const VMStateDescription vmstate_exynos4210_combiner_group_state = {
82
- address_offset -= a->imm;
197
.name = "exynos4210.combiner.groupstate",
83
+ address_offset = -a->imm;
84
}
85
} else if (!a->w) {
86
return;
87
@@ -XXX,XX +XXX,XX @@ static bool op_load_ri(DisasContext *s, arg_ldst_ri *a,
88
* Perform base writeback before the loaded value to
89
* ensure correct behavior with overlapping index registers.
90
*/
91
- op_addr_ri_post(s, a, addr, 0);
92
+ op_addr_ri_post(s, a, addr);
93
store_reg_from_load(s, a->rt, tmp);
94
return true;
95
}
96
@@ -XXX,XX +XXX,XX @@ static bool op_store_ri(DisasContext *s, arg_ldst_ri *a,
97
gen_aa32_st_i32(s, tmp, addr, mem_idx, mop);
98
disas_set_da_iss(s, mop, issinfo);
99
100
- op_addr_ri_post(s, a, addr, 0);
101
+ op_addr_ri_post(s, a, addr);
102
return true;
103
}
104
105
@@ -XXX,XX +XXX,XX @@ static bool op_ldrd_ri(DisasContext *s, arg_ldst_ri *a, int rt2)
106
do_ldrd_load(s, addr, a->rt, rt2);
107
108
/* LDRD w/ base writeback is undefined if the registers overlap. */
109
- op_addr_ri_post(s, a, addr, 0);
110
+ op_addr_ri_post(s, a, addr);
111
return true;
112
}
113
114
@@ -XXX,XX +XXX,XX @@ static bool op_strd_ri(DisasContext *s, arg_ldst_ri *a, int rt2)
115
116
do_strd_store(s, addr, a->rt, rt2);
117
118
- op_addr_ri_post(s, a, addr, 0);
119
+ op_addr_ri_post(s, a, addr);
120
return true;
121
}
122
198
--
123
--
199
2.25.1
124
2.43.0
125
126
diff view generated by jsdifflib
1
In exynos4210_init_board_irqs(), use the TYPE_SPLIT_IRQ device
1
In debug_helper.c we provide a few dummy versions of
2
instead of qemu_irq_split().
2
debug registers:
3
* DBGVCR (AArch32 only): enable bits for vector-catch
4
debug events
5
* MDCCINT_EL1: interrupt enable bits for the DCC
6
debug communications channel
7
* DBGVCR32_EL2: the AArch64 accessor for the state in
8
DBGVCR
3
9
10
We implemented these only to stop Linux crashing on startup,
11
but we chose to implement them as ARM_CP_NOP. This worked
12
for Linux where it only cares about trying to write to these
13
registers, but is very confusing behaviour for anything that
14
wants to read the registers (perhaps for context state switches),
15
because the destination register will be left with whatever
16
random value it happened to have before the read.
17
18
Model these registers instead as RAZ.
19
20
Fixes: 5e8b12ffbb8c68 ("target-arm: Implement minimal DBGVCR, OSDLR_EL1, MDCCSR_EL0")
21
Fixes: 5dbdc4342f479d ("target-arm: Implement dummy MDCCINT_EL1")
22
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2708
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
23
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
24
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20220404154658.565020-13-peter.maydell@linaro.org
25
Message-id: 20250228162424.1917269-1-peter.maydell@linaro.org
7
---
26
---
8
include/hw/arm/exynos4210.h | 9 ++++++++
27
target/arm/debug_helper.c | 7 ++++---
9
hw/arm/exynos4210.c | 41 +++++++++++++++++++++++++++++--------
28
1 file changed, 4 insertions(+), 3 deletions(-)
10
2 files changed, 42 insertions(+), 8 deletions(-)
11
29
12
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
30
diff --git a/target/arm/debug_helper.c b/target/arm/debug_helper.c
13
index XXXXXXX..XXXXXXX 100644
31
index XXXXXXX..XXXXXXX 100644
14
--- a/include/hw/arm/exynos4210.h
32
--- a/target/arm/debug_helper.c
15
+++ b/include/hw/arm/exynos4210.h
33
+++ b/target/arm/debug_helper.c
16
@@ -XXX,XX +XXX,XX @@
34
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo debug_cp_reginfo[] = {
17
#include "hw/sysbus.h"
35
{ .name = "DBGVCR",
18
#include "hw/cpu/a9mpcore.h"
36
.cp = 14, .opc1 = 0, .crn = 0, .crm = 7, .opc2 = 0,
19
#include "hw/intc/exynos4210_gic.h"
37
.access = PL1_RW, .accessfn = access_tda,
20
+#include "hw/core/split-irq.h"
38
- .type = ARM_CP_NOP },
21
#include "target/arm/cpu-qom.h"
39
+ .type = ARM_CP_CONST, .resetvalue = 0 },
22
#include "qom/object.h"
40
/*
23
41
* Dummy MDCCINT_EL1, since we don't implement the Debug Communications
24
@@ -XXX,XX +XXX,XX @@
42
* Channel but Linux may try to access this register. The 32-bit
25
43
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo debug_cp_reginfo[] = {
26
#define EXYNOS4210_NUM_DMA 3
44
{ .name = "MDCCINT_EL1", .state = ARM_CP_STATE_BOTH,
27
45
.cp = 14, .opc0 = 2, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 0,
28
+/*
46
.access = PL1_RW, .accessfn = access_tdcc,
29
+ * We need one splitter for every external combiner input, plus
47
- .type = ARM_CP_NOP },
30
+ * one for every non-zero entry in combiner_grp_to_gic_id[].
48
+ .type = ARM_CP_CONST, .resetvalue = 0 },
31
+ * We'll assert in exynos4210_init_board_irqs() if this is wrong.
49
/*
32
+ */
50
* Dummy DBGCLAIM registers.
33
+#define EXYNOS4210_NUM_SPLITTERS (EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ + 60)
51
* "The architecture does not define any functionality for the CLAIM tag bits.",
34
+
52
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo debug_aa32_el1_reginfo[] = {
35
typedef struct Exynos4210Irq {
53
{ .name = "DBGVCR32_EL2", .state = ARM_CP_STATE_AA64,
36
qemu_irq int_combiner_irq[EXYNOS4210_MAX_INT_COMBINER_IN_IRQ];
54
.opc0 = 2, .opc1 = 4, .crn = 0, .crm = 7, .opc2 = 0,
37
qemu_irq ext_combiner_irq[EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ];
55
.access = PL2_RW, .accessfn = access_dbgvcr32,
38
@@ -XXX,XX +XXX,XX @@ struct Exynos4210State {
56
- .type = ARM_CP_NOP | ARM_CP_EL3_NO_EL2_KEEP },
39
qemu_or_irq cpu_irq_orgate[EXYNOS4210_NCPUS];
57
+ .type = ARM_CP_CONST | ARM_CP_EL3_NO_EL2_KEEP,
40
A9MPPrivState a9mpcore;
58
+ .resetvalue = 0 },
41
Exynos4210GicState ext_gic;
42
+ SplitIRQ splitter[EXYNOS4210_NUM_SPLITTERS];
43
};
59
};
44
60
45
#define TYPE_EXYNOS4210_SOC "exynos4210"
61
static const ARMCPRegInfo debug_lpae_cp_reginfo[] = {
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);
108
}
109
110
/*
111
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init(Object *obj)
112
object_initialize_child(obj, name, &s->cpu_irq_orgate[i], TYPE_OR_IRQ);
113
}
114
115
+ for (i = 0; i < ARRAY_SIZE(s->splitter); i++) {
116
+ g_autofree char *name = g_strdup_printf("irq-splitter%d", i);
117
+ object_initialize_child(obj, name, &s->splitter[i], TYPE_SPLIT_IRQ);
118
+ }
119
+
120
object_initialize_child(obj, "a9mpcore", &s->a9mpcore, TYPE_A9MPCORE_PRIV);
121
object_initialize_child(obj, "ext-gic", &s->ext_gic, TYPE_EXYNOS4210_GIC);
122
}
123
--
62
--
124
2.25.1
63
2.43.0
diff view generated by jsdifflib
1
Delete a couple of #defines which are never used.
1
Currently we call icount_start_warp_timer() from timerlist_rearm().
2
This produces incorrect behaviour, because timerlist_rearm() is
3
called, for instance, when a timer callback modifies its timer. We
4
cannot decide here to warp the timer forwards to the next timer
5
deadline merely because all_cpu_threads_idle() is true, because the
6
timer callback we were called from (or some other callback later in
7
the list of callbacks being invoked) may be about to raise a CPU
8
interrupt and move a CPU from idle to ready.
2
9
10
The only valid place to choose to warp the timer forward is from the
11
main loop, when we know we have no outstanding IO or timer callbacks
12
that might be about to wake up a CPU.
13
14
For Arm guests, this bug was mostly latent until the refactoring
15
commit f6fc36deef6abc ("target/arm/helper: Implement
16
CNTHCTL_EL2.CNT[VP]MASK"), which exposed it because it refactored a
17
timer callback so that it happened to call timer_mod() first and
18
raise the interrupt second, when it had previously raised the
19
interrupt first and called timer_mod() afterwards.
20
21
This call seems to have originally derived from the
22
pre-record-and-replay icount code, which (as of e.g. commit
23
db1a49726c3c in 2010) in this location did a call to
24
qemu_notify_event(), necessary to get the icount code in the vCPU
25
round-robin thread to stop and recalculate the icount deadline when a
26
timer was reprogrammed from the IO thread. In current QEMU,
27
everything is done on the vCPU thread when we are in icount mode, so
28
there's no need to try to notify another thread here.
29
30
I suspect that the other reason why this call was doing icount timer
31
warping is that it pre-dates commit efab87cf79077a from 2015, which
32
added a call to icount_start_warp_timer() to main_loop_wait(). Once
33
the call in timerlist_rearm() has been removed, if the timer
34
callbacks don't cause any CPU to be woken up then we will end up
35
calling icount_start_warp_timer() from main_loop_wait() when the rr
36
main loop code calls rr_wait_io_event().
37
38
Remove the incorrect call from timerlist_rearm().
39
40
Cc: qemu-stable@nongnu.org
41
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2703
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
42
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
43
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20220404154658.565020-12-peter.maydell@linaro.org
44
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
45
Tested-by: Alex Bennée <alex.bennee@linaro.org>
46
Message-id: 20250210135804.3526943-1-peter.maydell@linaro.org
6
---
47
---
7
include/hw/arm/exynos4210.h | 4 ----
48
util/qemu-timer.c | 4 ----
8
1 file changed, 4 deletions(-)
49
1 file changed, 4 deletions(-)
9
50
10
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
51
diff --git a/util/qemu-timer.c b/util/qemu-timer.c
11
index XXXXXXX..XXXXXXX 100644
52
index XXXXXXX..XXXXXXX 100644
12
--- a/include/hw/arm/exynos4210.h
53
--- a/util/qemu-timer.c
13
+++ b/include/hw/arm/exynos4210.h
54
+++ b/util/qemu-timer.c
14
@@ -XXX,XX +XXX,XX @@
55
@@ -XXX,XX +XXX,XX @@ static bool timer_mod_ns_locked(QEMUTimerList *timer_list,
15
#define EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ \
56
16
(EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ * 8)
57
static void timerlist_rearm(QEMUTimerList *timer_list)
17
58
{
18
-/* IRQs number for external and internal GIC */
59
- /* Interrupt execution to force deadline recalculation. */
19
-#define EXYNOS4210_EXT_GIC_NIRQ (160-32)
60
- if (icount_enabled() && timer_list->clock->type == QEMU_CLOCK_VIRTUAL) {
20
-#define EXYNOS4210_INT_GIC_NIRQ 64
61
- icount_start_warp_timer();
21
-
62
- }
22
#define EXYNOS4210_I2C_NUMBER 9
63
timerlist_notify(timer_list);
23
64
}
24
#define EXYNOS4210_NUM_DMA 3
65
25
--
66
--
26
2.25.1
67
2.43.0
68
69
diff view generated by jsdifflib
1
Currently for the interrupts MCT_G0 and MCT_G1 which are
1
Expand the example in the comment documenting MO_ATOM_SUBALIGN,
2
the only ones in the input range of the external combiner
2
to be clearer about the atomicity guarantees it represents.
3
and which are also wired to the external GIC, we connect
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.)
10
11
Wire these interrupts up to both combiners, like the rest.
12
3
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
Message-id: 20220404154658.565020-15-peter.maydell@linaro.org
6
Message-id: 20250228103222.1838913-1-peter.maydell@linaro.org
16
---
7
---
17
hw/arm/exynos4210.c | 7 +++----
8
include/exec/memop.h | 8 ++++++--
18
1 file changed, 3 insertions(+), 4 deletions(-)
9
1 file changed, 6 insertions(+), 2 deletions(-)
19
10
20
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
11
diff --git a/include/exec/memop.h b/include/exec/memop.h
21
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
22
--- a/hw/arm/exynos4210.c
13
--- a/include/exec/memop.h
23
+++ b/hw/arm/exynos4210.c
14
+++ b/include/exec/memop.h
24
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init_board_irqs(Exynos4210State *s)
15
@@ -XXX,XX +XXX,XX @@ typedef enum MemOp {
25
16
* Depending on alignment, one or both will be single-copy atomic.
26
assert(splitcount < EXYNOS4210_NUM_SPLITTERS);
17
* This is the atomicity e.g. of Arm FEAT_LSE2 LDP.
27
splitter = DEVICE(&s->splitter[splitcount]);
18
* MO_ATOM_SUBALIGN: the operation is single-copy atomic by parts
28
- qdev_prop_set_uint16(splitter, "num-lines", 2);
19
- * by the alignment. E.g. if the address is 0 mod 4, then each
29
+ qdev_prop_set_uint16(splitter, "num-lines", irq_id ? 3 : 2);
20
- * 4-byte subobject is single-copy atomic.
30
qdev_realize(splitter, NULL, &error_abort);
21
+ * by the alignment. E.g. if an 8-byte value is accessed at an
31
splitcount++;
22
+ * address which is 0 mod 8, then the whole 8-byte access is
32
s->irq_table[n] = qdev_get_gpio_in(splitter, 0);
23
+ * single-copy atomic; otherwise, if it is accessed at 0 mod 4
33
qdev_connect_gpio_out(splitter, 0, is->int_combiner_irq[n]);
24
+ * then each 4-byte subobject is single-copy atomic; otherwise
34
+ qdev_connect_gpio_out(splitter, 1, is->ext_combiner_irq[n]);
25
+ * if it is accessed at 0 mod 2 then the four 2-byte subobjects
35
if (irq_id) {
26
+ * are single-copy atomic.
36
- qdev_connect_gpio_out(splitter, 1,
27
* This is the atomicity e.g. of IBM Power.
37
+ qdev_connect_gpio_out(splitter, 2,
28
* MO_ATOM_NONE: the operation has no atomicity requirements.
38
qdev_get_gpio_in(extgicdev, irq_id - 32));
29
*
39
- } else {
40
- qdev_connect_gpio_out(splitter, 1, is->ext_combiner_irq[n]);
41
}
42
}
43
for (; n < EXYNOS4210_MAX_INT_COMBINER_IN_IRQ; n++) {
44
--
30
--
45
2.25.1
31
2.43.0
diff view generated by jsdifflib
1
From: "Edgar E. Iglesias" <edgar.iglesias@amd.com>
1
From: JianChunfu <jansef.jian@hj-micro.com>
2
2
3
Add a model of the Xilinx Versal CRL.
3
Use a similar terminology smmu_hash_remove_by_sid_range() as the one
4
being used for other hash table matching functions since
5
smmuv3_invalidate_ste() name is not self explanatory, and introduce a
6
helper that invokes the g_hash_table_foreach_remove.
4
7
5
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>
8
No functional change intended.
6
Reviewed-by: Frederic Konrad <fkonrad@amd.com>
9
7
Reviewed-by: Francisco Iglesias <francisco.iglesias@amd.com>
10
Signed-off-by: JianChunfu <jansef.jian@hj-micro.com>
8
Message-id: 20220406174303.2022038-4-edgar.iglesias@xilinx.com
11
Reviewed-by: Eric Auger <eric.auger@redhat.com>
12
Message-id: 20250228031438.3916-1-jansef.jian@hj-micro.com
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
14
---
11
include/hw/misc/xlnx-versal-crl.h | 235 +++++++++++++++++
15
hw/arm/smmu-internal.h | 5 -----
12
hw/misc/xlnx-versal-crl.c | 421 ++++++++++++++++++++++++++++++
16
include/hw/arm/smmu-common.h | 6 ++++++
13
hw/misc/meson.build | 1 +
17
hw/arm/smmu-common.c | 21 +++++++++++++++++++++
14
3 files changed, 657 insertions(+)
18
hw/arm/smmuv3.c | 19 ++-----------------
15
create mode 100644 include/hw/misc/xlnx-versal-crl.h
19
hw/arm/trace-events | 3 ++-
16
create mode 100644 hw/misc/xlnx-versal-crl.c
20
5 files changed, 31 insertions(+), 23 deletions(-)
17
21
18
diff --git a/include/hw/misc/xlnx-versal-crl.h b/include/hw/misc/xlnx-versal-crl.h
22
diff --git a/hw/arm/smmu-internal.h b/hw/arm/smmu-internal.h
19
new file mode 100644
23
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX
24
--- a/hw/arm/smmu-internal.h
21
--- /dev/null
25
+++ b/hw/arm/smmu-internal.h
22
+++ b/include/hw/misc/xlnx-versal-crl.h
26
@@ -XXX,XX +XXX,XX @@ typedef struct SMMUIOTLBPageInvInfo {
23
@@ -XXX,XX +XXX,XX @@
27
uint64_t mask;
24
+/*
28
} SMMUIOTLBPageInvInfo;
25
+ * QEMU model of the Clock-Reset-LPD (CRL).
29
26
+ *
30
-typedef struct SMMUSIDRange {
27
+ * Copyright (c) 2022 Xilinx Inc.
31
- uint32_t start;
28
+ * SPDX-License-Identifier: GPL-2.0-or-later
32
- uint32_t end;
29
+ *
33
-} SMMUSIDRange;
30
+ * Written by Edgar E. Iglesias <edgar.iglesias@xilinx.com>
34
-
31
+ */
35
#endif
32
+#ifndef HW_MISC_XLNX_VERSAL_CRL_H
36
diff --git a/include/hw/arm/smmu-common.h b/include/hw/arm/smmu-common.h
33
+#define HW_MISC_XLNX_VERSAL_CRL_H
37
index XXXXXXX..XXXXXXX 100644
38
--- a/include/hw/arm/smmu-common.h
39
+++ b/include/hw/arm/smmu-common.h
40
@@ -XXX,XX +XXX,XX @@ typedef struct SMMUIOTLBKey {
41
uint8_t level;
42
} SMMUIOTLBKey;
43
44
+typedef struct SMMUSIDRange {
45
+ uint32_t start;
46
+ uint32_t end;
47
+} SMMUSIDRange;
34
+
48
+
35
+#include "hw/sysbus.h"
49
struct SMMUState {
36
+#include "hw/register.h"
50
/* <private> */
37
+#include "target/arm/cpu.h"
51
SysBusDevice dev;
52
@@ -XXX,XX +XXX,XX @@ void smmu_iotlb_inv_iova(SMMUState *s, int asid, int vmid, dma_addr_t iova,
53
uint8_t tg, uint64_t num_pages, uint8_t ttl);
54
void smmu_iotlb_inv_ipa(SMMUState *s, int vmid, dma_addr_t ipa, uint8_t tg,
55
uint64_t num_pages, uint8_t ttl);
56
+void smmu_configs_inv_sid_range(SMMUState *s, SMMUSIDRange sid_range);
57
/* Unmap the range of all the notifiers registered to any IOMMU mr */
58
void smmu_inv_notifiers_all(SMMUState *s);
59
60
diff --git a/hw/arm/smmu-common.c b/hw/arm/smmu-common.c
61
index XXXXXXX..XXXXXXX 100644
62
--- a/hw/arm/smmu-common.c
63
+++ b/hw/arm/smmu-common.c
64
@@ -XXX,XX +XXX,XX @@ static gboolean smmu_hash_remove_by_vmid_ipa(gpointer key, gpointer value,
65
((entry->iova & ~info->mask) == info->iova);
66
}
67
68
+static gboolean
69
+smmu_hash_remove_by_sid_range(gpointer key, gpointer value, gpointer user_data)
70
+{
71
+ SMMUDevice *sdev = (SMMUDevice *)key;
72
+ uint32_t sid = smmu_get_sid(sdev);
73
+ SMMUSIDRange *sid_range = (SMMUSIDRange *)user_data;
38
+
74
+
39
+#define TYPE_XLNX_VERSAL_CRL "xlnx,versal-crl"
75
+ if (sid < sid_range->start || sid > sid_range->end) {
40
+OBJECT_DECLARE_SIMPLE_TYPE(XlnxVersalCRL, XLNX_VERSAL_CRL)
76
+ return false;
41
+
77
+ }
42
+REG32(ERR_CTRL, 0x0)
78
+ trace_smmu_config_cache_inv(sid);
43
+ FIELD(ERR_CTRL, SLVERR_ENABLE, 0, 1)
79
+ return true;
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
+ */
273
+
274
+#include "qemu/osdep.h"
275
+#include "qapi/error.h"
276
+#include "qemu/log.h"
277
+#include "qemu/bitops.h"
278
+#include "migration/vmstate.h"
279
+#include "hw/qdev-properties.h"
280
+#include "hw/sysbus.h"
281
+#include "hw/irq.h"
282
+#include "hw/register.h"
283
+#include "hw/resettable.h"
284
+
285
+#include "target/arm/arm-powerctl.h"
286
+#include "hw/misc/xlnx-versal-crl.h"
287
+
288
+#ifndef XLNX_VERSAL_CRL_ERR_DEBUG
289
+#define XLNX_VERSAL_CRL_ERR_DEBUG 0
290
+#endif
291
+
292
+static void crl_update_irq(XlnxVersalCRL *s)
293
+{
294
+ bool pending = s->regs[R_IR_STATUS] & ~s->regs[R_IR_MASK];
295
+ qemu_set_irq(s->irq, pending);
296
+}
80
+}
297
+
81
+
298
+static void crl_status_postw(RegisterInfo *reg, uint64_t val64)
82
+void smmu_configs_inv_sid_range(SMMUState *s, SMMUSIDRange sid_range)
299
+{
83
+{
300
+ XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque);
84
+ trace_smmu_configs_inv_sid_range(sid_range.start, sid_range.end);
301
+ crl_update_irq(s);
85
+ g_hash_table_foreach_remove(s->configs, smmu_hash_remove_by_sid_range,
86
+ &sid_range);
302
+}
87
+}
303
+
88
+
304
+static uint64_t crl_enable_prew(RegisterInfo *reg, uint64_t val64)
89
void smmu_iotlb_inv_iova(SMMUState *s, int asid, int vmid, dma_addr_t iova,
305
+{
90
uint8_t tg, uint64_t num_pages, uint8_t ttl)
306
+ XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque);
91
{
307
+ uint32_t val = val64;
92
diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c
308
+
309
+ s->regs[R_IR_MASK] &= ~val;
310
+ crl_update_irq(s);
311
+ return 0;
312
+}
313
+
314
+static uint64_t crl_disable_prew(RegisterInfo *reg, uint64_t val64)
315
+{
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
+ }
565
+};
566
+
567
+static void crl_reset_enter(Object *obj, ResetType type)
568
+{
569
+ XlnxVersalCRL *s = XLNX_VERSAL_CRL(obj);
570
+ unsigned int i;
571
+
572
+ for (i = 0; i < ARRAY_SIZE(s->regs_info); ++i) {
573
+ register_reset(&s->regs_info[i]);
574
+ }
575
+}
576
+
577
+static void crl_reset_hold(Object *obj)
578
+{
579
+ XlnxVersalCRL *s = XLNX_VERSAL_CRL(obj);
580
+
581
+ crl_update_irq(s);
582
+}
583
+
584
+static const MemoryRegionOps crl_ops = {
585
+ .read = register_read_memory,
586
+ .write = register_write_memory,
587
+ .endianness = DEVICE_LITTLE_ENDIAN,
588
+ .valid = {
589
+ .min_access_size = 4,
590
+ .max_access_size = 4,
591
+ },
592
+};
593
+
594
+static void crl_init(Object *obj)
595
+{
596
+ XlnxVersalCRL *s = XLNX_VERSAL_CRL(obj);
597
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
598
+ int i;
599
+
600
+ s->reg_array =
601
+ register_init_block32(DEVICE(obj), crl_regs_info,
602
+ ARRAY_SIZE(crl_regs_info),
603
+ s->regs_info, s->regs,
604
+ &crl_ops,
605
+ XLNX_VERSAL_CRL_ERR_DEBUG,
606
+ CRL_R_MAX * 4);
607
+ sysbus_init_mmio(sbd, &s->reg_array->mem);
608
+ sysbus_init_irq(sbd, &s->irq);
609
+
610
+ for (i = 0; i < ARRAY_SIZE(s->cfg.cpu_r5); ++i) {
611
+ object_property_add_link(obj, "cpu_r5[*]", TYPE_ARM_CPU,
612
+ (Object **)&s->cfg.cpu_r5[i],
613
+ qdev_prop_allow_set_link_before_realize,
614
+ OBJ_PROP_LINK_STRONG);
615
+ }
616
+
617
+ for (i = 0; i < ARRAY_SIZE(s->cfg.adma); ++i) {
618
+ object_property_add_link(obj, "adma[*]", TYPE_DEVICE,
619
+ (Object **)&s->cfg.adma[i],
620
+ qdev_prop_allow_set_link_before_realize,
621
+ OBJ_PROP_LINK_STRONG);
622
+ }
623
+
624
+ for (i = 0; i < ARRAY_SIZE(s->cfg.uart); ++i) {
625
+ object_property_add_link(obj, "uart[*]", TYPE_DEVICE,
626
+ (Object **)&s->cfg.uart[i],
627
+ qdev_prop_allow_set_link_before_realize,
628
+ OBJ_PROP_LINK_STRONG);
629
+ }
630
+
631
+ for (i = 0; i < ARRAY_SIZE(s->cfg.gem); ++i) {
632
+ object_property_add_link(obj, "gem[*]", TYPE_DEVICE,
633
+ (Object **)&s->cfg.gem[i],
634
+ qdev_prop_allow_set_link_before_realize,
635
+ OBJ_PROP_LINK_STRONG);
636
+ }
637
+
638
+ object_property_add_link(obj, "usb", TYPE_DEVICE,
639
+ (Object **)&s->cfg.gem[i],
640
+ qdev_prop_allow_set_link_before_realize,
641
+ OBJ_PROP_LINK_STRONG);
642
+}
643
+
644
+static void crl_finalize(Object *obj)
645
+{
646
+ XlnxVersalCRL *s = XLNX_VERSAL_CRL(obj);
647
+ register_finalize_block(s->reg_array);
648
+}
649
+
650
+static const VMStateDescription vmstate_crl = {
651
+ .name = TYPE_XLNX_VERSAL_CRL,
652
+ .version_id = 1,
653
+ .minimum_version_id = 1,
654
+ .fields = (VMStateField[]) {
655
+ VMSTATE_UINT32_ARRAY(regs, XlnxVersalCRL, CRL_R_MAX),
656
+ VMSTATE_END_OF_LIST(),
657
+ }
658
+};
659
+
660
+static void crl_class_init(ObjectClass *klass, void *data)
661
+{
662
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
663
+ DeviceClass *dc = DEVICE_CLASS(klass);
664
+
665
+ dc->vmsd = &vmstate_crl;
666
+
667
+ rc->phases.enter = crl_reset_enter;
668
+ rc->phases.hold = crl_reset_hold;
669
+}
670
+
671
+static const TypeInfo crl_info = {
672
+ .name = TYPE_XLNX_VERSAL_CRL,
673
+ .parent = TYPE_SYS_BUS_DEVICE,
674
+ .instance_size = sizeof(XlnxVersalCRL),
675
+ .class_init = crl_class_init,
676
+ .instance_init = crl_init,
677
+ .instance_finalize = crl_finalize,
678
+};
679
+
680
+static void crl_register_types(void)
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
687
index XXXXXXX..XXXXXXX 100644
93
index XXXXXXX..XXXXXXX 100644
688
--- a/hw/misc/meson.build
94
--- a/hw/arm/smmuv3.c
689
+++ b/hw/misc/meson.build
95
+++ b/hw/arm/smmuv3.c
690
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_SLAVIO', if_true: files('slavio_misc.c'))
96
@@ -XXX,XX +XXX,XX @@ static void smmuv3_flush_config(SMMUDevice *sdev)
691
softmmu_ss.add(when: 'CONFIG_ZYNQ', if_true: files('zynq_slcr.c'))
97
SMMUv3State *s = sdev->smmu;
692
specific_ss.add(when: 'CONFIG_XLNX_ZYNQMP_ARM', if_true: files('xlnx-zynqmp-crf.c'))
98
SMMUState *bc = &s->smmu_state;
693
specific_ss.add(when: 'CONFIG_XLNX_ZYNQMP_ARM', if_true: files('xlnx-zynqmp-apu-ctrl.c'))
99
694
+specific_ss.add(when: 'CONFIG_XLNX_VERSAL', if_true: files('xlnx-versal-crl.c'))
100
- trace_smmuv3_config_cache_inv(smmu_get_sid(sdev));
695
softmmu_ss.add(when: 'CONFIG_XLNX_VERSAL', if_true: files(
101
+ trace_smmu_config_cache_inv(smmu_get_sid(sdev));
696
'xlnx-versal-xramc.c',
102
g_hash_table_remove(bc->configs, sdev);
697
'xlnx-versal-pmc-iou-slcr.c',
103
}
104
105
@@ -XXX,XX +XXX,XX @@ static void smmuv3_range_inval(SMMUState *s, Cmd *cmd, SMMUStage stage)
106
}
107
}
108
109
-static gboolean
110
-smmuv3_invalidate_ste(gpointer key, gpointer value, gpointer user_data)
111
-{
112
- SMMUDevice *sdev = (SMMUDevice *)key;
113
- uint32_t sid = smmu_get_sid(sdev);
114
- SMMUSIDRange *sid_range = (SMMUSIDRange *)user_data;
115
-
116
- if (sid < sid_range->start || sid > sid_range->end) {
117
- return false;
118
- }
119
- trace_smmuv3_config_cache_inv(sid);
120
- return true;
121
-}
122
-
123
static int smmuv3_cmdq_consume(SMMUv3State *s)
124
{
125
SMMUState *bs = ARM_SMMU(s);
126
@@ -XXX,XX +XXX,XX @@ static int smmuv3_cmdq_consume(SMMUv3State *s)
127
sid_range.end = sid_range.start + mask;
128
129
trace_smmuv3_cmdq_cfgi_ste_range(sid_range.start, sid_range.end);
130
- g_hash_table_foreach_remove(bs->configs, smmuv3_invalidate_ste,
131
- &sid_range);
132
+ smmu_configs_inv_sid_range(bs, sid_range);
133
break;
134
}
135
case SMMU_CMD_CFGI_CD:
136
diff --git a/hw/arm/trace-events b/hw/arm/trace-events
137
index XXXXXXX..XXXXXXX 100644
138
--- a/hw/arm/trace-events
139
+++ b/hw/arm/trace-events
140
@@ -XXX,XX +XXX,XX @@ smmu_iotlb_inv_asid_vmid(int asid, int vmid) "IOTLB invalidate asid=%d vmid=%d"
141
smmu_iotlb_inv_vmid(int vmid) "IOTLB invalidate vmid=%d"
142
smmu_iotlb_inv_vmid_s1(int vmid) "IOTLB invalidate vmid=%d"
143
smmu_iotlb_inv_iova(int asid, uint64_t addr) "IOTLB invalidate asid=%d addr=0x%"PRIx64
144
+smmu_configs_inv_sid_range(uint32_t start, uint32_t end) "Config cache INV SID range from 0x%x to 0x%x"
145
+smmu_config_cache_inv(uint32_t sid) "Config cache INV for sid=0x%x"
146
smmu_inv_notifiers_mr(const char *name) "iommu mr=%s"
147
smmu_iotlb_lookup_hit(int asid, int vmid, uint64_t addr, uint32_t hit, uint32_t miss, uint32_t p) "IOTLB cache HIT asid=%d vmid=%d addr=0x%"PRIx64" hit=%d miss=%d hit rate=%d"
148
smmu_iotlb_lookup_miss(int asid, int vmid, uint64_t addr, uint32_t hit, uint32_t miss, uint32_t p) "IOTLB cache MISS asid=%d vmid=%d addr=0x%"PRIx64" hit=%d miss=%d hit rate=%d"
149
@@ -XXX,XX +XXX,XX @@ smmuv3_cmdq_tlbi_nh(int vmid) "vmid=%d"
150
smmuv3_cmdq_tlbi_nsnh(void) ""
151
smmuv3_cmdq_tlbi_nh_asid(int asid) "asid=%d"
152
smmuv3_cmdq_tlbi_s12_vmid(int vmid) "vmid=%d"
153
-smmuv3_config_cache_inv(uint32_t sid) "Config cache INV for sid=0x%x"
154
smmuv3_notify_flag_add(const char *iommu) "ADD SMMUNotifier node for iommu mr=%s"
155
smmuv3_notify_flag_del(const char *iommu) "DEL SMMUNotifier node for iommu mr=%s"
156
smmuv3_inv_notifiers_iova(const char *name, int asid, int vmid, uint64_t iova, uint8_t tg, uint64_t num_pages, int stage) "iommu mr=%s asid=%d vmid=%d iova=0x%"PRIx64" tg=%d num_pages=0x%"PRIx64" stage=%d"
698
--
157
--
699
2.25.1
158
2.43.0
diff view generated by jsdifflib
Deleted patch
1
From: "Edgar E. Iglesias" <edgar.iglesias@amd.com>
2
1
3
Connect the CRL (Clock Reset LPD) to the Versal SoC.
4
5
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>
6
Reviewed-by: Frederic Konrad <fkonrad@amd.com>
7
Reviewed-by: Francisco Iglesias <francisco.iglesias@amd.com>
8
Message-id: 20220406174303.2022038-5-edgar.iglesias@xilinx.com
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
include/hw/arm/xlnx-versal.h | 4 +++
12
hw/arm/xlnx-versal.c | 54 ++++++++++++++++++++++++++++++++++--
13
2 files changed, 56 insertions(+), 2 deletions(-)
14
15
diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
16
index XXXXXXX..XXXXXXX 100644
17
--- a/include/hw/arm/xlnx-versal.h
18
+++ b/include/hw/arm/xlnx-versal.h
19
@@ -XXX,XX +XXX,XX @@
20
#include "hw/nvram/xlnx-versal-efuse.h"
21
#include "hw/ssi/xlnx-versal-ospi.h"
22
#include "hw/dma/xlnx_csu_dma.h"
23
+#include "hw/misc/xlnx-versal-crl.h"
24
#include "hw/misc/xlnx-versal-pmc-iou-slcr.h"
25
26
#define TYPE_XLNX_VERSAL "xlnx-versal"
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
45
index XXXXXXX..XXXXXXX 100644
46
--- a/hw/arm/xlnx-versal.c
47
+++ b/hw/arm/xlnx-versal.c
48
@@ -XXX,XX +XXX,XX @@ static void versal_create_ospi(Versal *s, qemu_irq *pic)
49
qdev_connect_gpio_out(orgate, 0, pic[VERSAL_OSPI_IRQ]);
50
}
51
52
+static void versal_create_crl(Versal *s, qemu_irq *pic)
53
+{
54
+ SysBusDevice *sbd;
55
+ int i;
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);
67
+ }
68
+
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]);
101
+}
102
+
103
/* This takes the board allocated linear DDR memory and creates aliases
104
* for each split DDR range/aperture on the Versal address map.
105
*/
106
@@ -XXX,XX +XXX,XX @@ static void versal_unimp(Versal *s)
107
108
versal_unimp_area(s, "psm", &s->mr_ps,
109
MM_PSM_START, MM_PSM_END - MM_PSM_START);
110
- versal_unimp_area(s, "crl", &s->mr_ps,
111
- MM_CRL, MM_CRL_SIZE);
112
versal_unimp_area(s, "crf", &s->mr_ps,
113
MM_FPD_CRF, MM_FPD_CRF_SIZE);
114
versal_unimp_area(s, "apu", &s->mr_ps,
115
@@ -XXX,XX +XXX,XX @@ static void versal_realize(DeviceState *dev, Error **errp)
116
versal_create_efuse(s, pic);
117
versal_create_pmc_iou_slcr(s, pic);
118
versal_create_ospi(s, pic);
119
+ versal_create_crl(s, pic);
120
versal_map_ddr(s);
121
versal_unimp(s);
122
123
--
124
2.25.1
diff view generated by jsdifflib
Deleted patch
1
The Exynos4210 SoC device currently uses a custom device
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
1
6
(This is a migration compatibility break, but that is OK for this
7
machine type.)
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-2-peter.maydell@linaro.org
12
---
13
include/hw/arm/exynos4210.h | 1 +
14
hw/arm/exynos4210.c | 31 ++++++++++++++++---------------
15
2 files changed, 17 insertions(+), 15 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 @@ struct Exynos4210State {
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
+ }
96
}
97
98
static void exynos4210_class_init(ObjectClass *klass, void *data)
99
--
100
2.25.1
diff view generated by jsdifflib
Deleted patch
1
Now we have removed the only use of TYPE_EXYNOS4210_IRQ_GATE we can
2
delete the device entirely.
3
1
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Francisco Iglesias <frasse.iglesias@gmail.com>
6
Message-id: 20220404154658.565020-3-peter.maydell@linaro.org
7
---
8
hw/intc/exynos4210_gic.c | 107 ---------------------------------------
9
1 file changed, 107 deletions(-)
10
11
diff --git a/hw/intc/exynos4210_gic.c b/hw/intc/exynos4210_gic.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/hw/intc/exynos4210_gic.c
14
+++ b/hw/intc/exynos4210_gic.c
15
@@ -XXX,XX +XXX,XX @@ static void exynos4210_gic_register_types(void)
16
}
17
18
type_init(exynos4210_gic_register_types)
19
-
20
-/* IRQ OR Gate struct.
21
- *
22
- * This device models an OR gate. There are n_in input qdev gpio lines and one
23
- * output sysbus IRQ line. The output IRQ level is formed as OR between all
24
- * gpio inputs.
25
- */
26
-
27
-#define TYPE_EXYNOS4210_IRQ_GATE "exynos4210.irq_gate"
28
-OBJECT_DECLARE_SIMPLE_TYPE(Exynos4210IRQGateState, EXYNOS4210_IRQ_GATE)
29
-
30
-struct Exynos4210IRQGateState {
31
- SysBusDevice parent_obj;
32
-
33
- uint32_t n_in; /* inputs amount */
34
- uint32_t *level; /* input levels */
35
- qemu_irq out; /* output IRQ */
36
-};
37
-
38
-static Property exynos4210_irq_gate_properties[] = {
39
- DEFINE_PROP_UINT32("n_in", Exynos4210IRQGateState, n_in, 1),
40
- DEFINE_PROP_END_OF_LIST(),
41
-};
42
-
43
-static const VMStateDescription vmstate_exynos4210_irq_gate = {
44
- .name = "exynos4210.irq_gate",
45
- .version_id = 2,
46
- .minimum_version_id = 2,
47
- .fields = (VMStateField[]) {
48
- VMSTATE_VBUFFER_UINT32(level, Exynos4210IRQGateState, 1, NULL, n_in),
49
- VMSTATE_END_OF_LIST()
50
- }
51
-};
52
-
53
-/* Process a change in IRQ input. */
54
-static void exynos4210_irq_gate_handler(void *opaque, int irq, int level)
55
-{
56
- Exynos4210IRQGateState *s = (Exynos4210IRQGateState *)opaque;
57
- uint32_t i;
58
-
59
- assert(irq < s->n_in);
60
-
61
- s->level[irq] = level;
62
-
63
- for (i = 0; i < s->n_in; i++) {
64
- if (s->level[i] >= 1) {
65
- qemu_irq_raise(s->out);
66
- return;
67
- }
68
- }
69
-
70
- qemu_irq_lower(s->out);
71
-}
72
-
73
-static void exynos4210_irq_gate_reset(DeviceState *d)
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)
126
--
127
2.25.1
diff view generated by jsdifflib
Deleted patch
1
The exynos4210 SoC mostly creates its child devices as if it were
2
board code. This includes the a9mpcore object. Switch that to a
3
new-style "embedded in the state struct" creation, because in the
4
next commit we're going to want to refer to the object again further
5
down in the exynos4210_realize() function.
6
1
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20220404154658.565020-4-peter.maydell@linaro.org
10
---
11
include/hw/arm/exynos4210.h | 2 ++
12
hw/arm/exynos4210.c | 11 ++++++-----
13
2 files changed, 8 insertions(+), 5 deletions(-)
14
15
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
16
index XXXXXXX..XXXXXXX 100644
17
--- a/include/hw/arm/exynos4210.h
18
+++ b/include/hw/arm/exynos4210.h
19
@@ -XXX,XX +XXX,XX @@
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)
40
}
41
42
/* Private memory region and Internal GIC */
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
}
65
+
66
+ object_initialize_child(obj, "a9mpcore", &s->a9mpcore, TYPE_A9MPCORE_PRIV);
67
}
68
69
static void exynos4210_class_init(ObjectClass *klass, void *data)
70
--
71
2.25.1
diff view generated by jsdifflib
Deleted 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.
8
1
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
Deleted patch
1
The exynos4210 code currently has two very similar arrays of IRQs:
2
1
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.
14
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
17
Message-id: 20220404154658.565020-6-peter.maydell@linaro.org
18
---
19
include/hw/arm/exynos4210.h | 8 ++------
20
hw/arm/exynos4210.c | 6 +-----
21
hw/intc/exynos4210_gic.c | 32 ++++++++------------------------
22
3 files changed, 11 insertions(+), 35 deletions(-)
23
24
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
25
index XXXXXXX..XXXXXXX 100644
26
--- a/include/hw/arm/exynos4210.h
27
+++ b/include/hw/arm/exynos4210.h
28
@@ -XXX,XX +XXX,XX @@ typedef struct Exynos4210Irq {
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);
65
}
66
67
- /*** IRQs ***/
68
-
69
- s->irq_table = exynos4210_init_irq(&s->irqs);
70
-
71
/* IRQ Gate */
72
for (i = 0; i < EXYNOS4210_NCPUS; i++) {
73
DeviceState *orgate = DEVICE(&s->cpu_irq_orgate[i]);
74
@@ -XXX,XX +XXX,XX @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
75
sysbus_mmio_map(busdev, 0, EXYNOS4210_EXT_COMBINER_BASE_ADDR);
76
77
/* Initialize board IRQs. */
78
- exynos4210_init_board_irqs(&s->irqs);
79
+ exynos4210_init_board_irqs(s);
80
81
/*** Memory ***/
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
}
147
--
148
2.25.1
diff view generated by jsdifflib
Deleted patch
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.
5
1
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20220404154658.565020-7-peter.maydell@linaro.org
9
---
10
hw/intc/exynos4210_gic.c | 2 +-
11
1 file changed, 1 insertion(+), 1 deletion(-)
12
13
diff --git a/hw/intc/exynos4210_gic.c b/hw/intc/exynos4210_gic.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/intc/exynos4210_gic.c
16
+++ b/hw/intc/exynos4210_gic.c
17
@@ -XXX,XX +XXX,XX @@ enum ExtInt {
18
*/
19
20
static const uint32_t
21
-combiner_grp_to_gic_id[64-EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][8] = {
22
+combiner_grp_to_gic_id[64 - EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][8] = {
23
/* int combiner groups 16-19 */
24
{ }, { }, { }, { },
25
/* int combiner group 20 */
26
--
27
2.25.1
diff view generated by jsdifflib
Deleted patch
1
The only time we use the ext_gic_irq[] array in the Exynos4210Irq
2
struct is during realize of the SoC -- we initialize it with the
3
input IRQs of the external GIC device, and then connect those to
4
outputs of other devices further on in realize (including in the
5
exynos4210_init_board_irqs() function). Now that the ext_gic object
6
is easily accessible as s->ext_gic we can make the connections
7
directly from one device to the other without going via this array.
8
1
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20220404154658.565020-10-peter.maydell@linaro.org
12
---
13
include/hw/arm/exynos4210.h | 1 -
14
hw/arm/exynos4210.c | 12 ++++++------
15
2 files changed, 6 insertions(+), 7 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 ext_gic_irq[EXYNOS4210_EXT_GIC_NIRQ];
26
} Exynos4210Irq;
27
28
struct Exynos4210State {
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_init_board_irqs(Exynos4210State *s)
34
{
35
uint32_t grp, bit, irq_id, n;
36
Exynos4210Irq *is = &s->irqs;
37
+ DeviceState *extgicdev = DEVICE(&s->ext_gic);
38
39
for (n = 0; n < EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ; n++) {
40
irq_id = 0;
41
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init_board_irqs(Exynos4210State *s)
42
}
43
if (irq_id) {
44
s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
45
- is->ext_gic_irq[irq_id - 32]);
46
+ qdev_get_gpio_in(extgicdev,
47
+ irq_id - 32));
48
} else {
49
s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
50
is->ext_combiner_irq[n]);
51
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init_board_irqs(Exynos4210State *s)
52
53
if (irq_id) {
54
s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
55
- is->ext_gic_irq[irq_id - 32]);
56
+ qdev_get_gpio_in(extgicdev,
57
+ irq_id - 32));
58
}
59
}
60
}
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);
80
--
81
2.25.1
diff view generated by jsdifflib
1
From: Hao Wu <wuhaotsh@google.com>
1
From: Keith Packard <keithp@keithp.com>
2
2
3
Similar to the Aspeed code in include/misc/aspeed_scu.h, we define
3
The documentation says the vector is at 0xffffff80, instead of the
4
the PWRON STRAP fields in their corresponding module for NPCM7XX.
4
previous value of 0xffffffc0. That value must have been a bug because
5
the standard vector values (20, 21, 23, 25, 30) were all
6
past the end of the array.
5
7
6
Signed-off-by: Hao Wu <wuhaotsh@google.com>
8
Signed-off-by: Keith Packard <keithp@keithp.com>
7
Reviewed-by: Patrick Venture <venture@google.com>
8
Message-id: 20220411165842.3912945-2-wuhaotsh@google.com
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
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
include/hw/misc/npcm7xx_gcr.h | 30 ++++++++++++++++++++++++++++++
12
target/rx/helper.c | 2 +-
13
1 file changed, 30 insertions(+)
13
1 file changed, 1 insertion(+), 1 deletion(-)
14
14
15
diff --git a/include/hw/misc/npcm7xx_gcr.h b/include/hw/misc/npcm7xx_gcr.h
15
diff --git a/target/rx/helper.c b/target/rx/helper.c
16
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
17
--- a/include/hw/misc/npcm7xx_gcr.h
17
--- a/target/rx/helper.c
18
+++ b/include/hw/misc/npcm7xx_gcr.h
18
+++ b/target/rx/helper.c
19
@@ -XXX,XX +XXX,XX @@
19
@@ -XXX,XX +XXX,XX @@ void rx_cpu_do_interrupt(CPUState *cs)
20
#include "exec/memory.h"
20
cpu_stl_data(env, env->isp, env->pc);
21
#include "hw/sysbus.h"
21
22
22
if (vec < 0x100) {
23
+/*
23
- env->pc = cpu_ldl_data(env, 0xffffffc0 + vec * 4);
24
+ * NPCM7XX PWRON STRAP bit fields
24
+ env->pc = cpu_ldl_data(env, 0xffffff80 + vec * 4);
25
+ * 12: SPI0 powered by VSBV3 at 1.8V
25
} else {
26
+ * 11: System flash attached to BMC
26
env->pc = cpu_ldl_data(env, env->intb + (vec & 0xff) * 4);
27
+ * 10: BSP alternative pins.
27
}
28
+ * 9:8: Flash UART command route enabled.
29
+ * 7: Security enabled.
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.
56
--
28
--
57
2.25.1
29
2.43.0
diff view generated by jsdifflib
1
From: Heinrich Schuchardt <heinrich.schuchardt@canonical.com>
1
From: Keith Packard <keithp@keithp.com>
2
2
3
Describe that the gic-version influences the maximum number of CPUs.
3
Functions which modify TCG globals must not be marked TCG_CALL_NO_WG,
4
as that tells the optimizer that TCG global values already loaded in
5
machine registers are still valid, and so any changes which these
6
helpers make to the CPU state may be ignored.
4
7
5
Signed-off-by: Heinrich Schuchardt <heinrich.schuchardt@canonical.com>
8
The target/rx code chooses to put (among other things) all the PSW
6
Message-id: 20220413231456.35811-1-heinrich.schuchardt@canonical.com
9
bits and also ACC into globals, so the NO_WG flag on various
7
[PMM: minor punctuation tweaks]
10
functions that touch the PSW or ACC is incorrect and must be removed.
11
This includes all the floating point helper functions, because
12
update_fpsw() will update PSW Z and S.
13
14
Signed-off-by: Keith Packard <keithp@keithp.com>
15
[PMM: Clarified commit message]
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
16
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
18
---
11
docs/system/arm/virt.rst | 4 ++--
19
target/rx/helper.h | 34 +++++++++++++++++-----------------
12
1 file changed, 2 insertions(+), 2 deletions(-)
20
1 file changed, 17 insertions(+), 17 deletions(-)
13
21
14
diff --git a/docs/system/arm/virt.rst b/docs/system/arm/virt.rst
22
diff --git a/target/rx/helper.h b/target/rx/helper.h
15
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
16
--- a/docs/system/arm/virt.rst
24
--- a/target/rx/helper.h
17
+++ b/docs/system/arm/virt.rst
25
+++ b/target/rx/helper.h
18
@@ -XXX,XX +XXX,XX @@ gic-version
26
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_1(raise_privilege_violation, noreturn, env)
19
Valid values are:
27
DEF_HELPER_1(wait, noreturn, env)
20
28
DEF_HELPER_2(rxint, noreturn, env, i32)
21
``2``
29
DEF_HELPER_1(rxbrk, noreturn, env)
22
- GICv2
30
-DEF_HELPER_FLAGS_3(fadd, TCG_CALL_NO_WG, f32, env, f32, f32)
23
+ GICv2. Note that this limits the number of CPUs to 8.
31
-DEF_HELPER_FLAGS_3(fsub, TCG_CALL_NO_WG, f32, env, f32, f32)
24
``3``
32
-DEF_HELPER_FLAGS_3(fmul, TCG_CALL_NO_WG, f32, env, f32, f32)
25
- GICv3
33
-DEF_HELPER_FLAGS_3(fdiv, TCG_CALL_NO_WG, f32, env, f32, f32)
26
+ GICv3. This allows up to 512 CPUs.
34
-DEF_HELPER_FLAGS_3(fcmp, TCG_CALL_NO_WG, void, env, f32, f32)
27
``host``
35
-DEF_HELPER_FLAGS_2(ftoi, TCG_CALL_NO_WG, i32, env, f32)
28
Use the same GIC version the host provides, when using KVM
36
-DEF_HELPER_FLAGS_2(round, TCG_CALL_NO_WG, i32, env, f32)
29
``max``
37
-DEF_HELPER_FLAGS_2(itof, TCG_CALL_NO_WG, f32, env, i32)
38
+DEF_HELPER_3(fadd, f32, env, f32, f32)
39
+DEF_HELPER_3(fsub, f32, env, f32, f32)
40
+DEF_HELPER_3(fmul, f32, env, f32, f32)
41
+DEF_HELPER_3(fdiv, f32, env, f32, f32)
42
+DEF_HELPER_3(fcmp, void, env, f32, f32)
43
+DEF_HELPER_2(ftoi, i32, env, f32)
44
+DEF_HELPER_2(round, i32, env, f32)
45
+DEF_HELPER_2(itof, f32, env, i32)
46
DEF_HELPER_2(set_fpsw, void, env, i32)
47
-DEF_HELPER_FLAGS_2(racw, TCG_CALL_NO_WG, void, env, i32)
48
-DEF_HELPER_FLAGS_2(set_psw_rte, TCG_CALL_NO_WG, void, env, i32)
49
-DEF_HELPER_FLAGS_2(set_psw, TCG_CALL_NO_WG, void, env, i32)
50
+DEF_HELPER_2(racw, void, env, i32)
51
+DEF_HELPER_2(set_psw_rte, void, env, i32)
52
+DEF_HELPER_2(set_psw, void, env, i32)
53
DEF_HELPER_1(pack_psw, i32, env)
54
-DEF_HELPER_FLAGS_3(div, TCG_CALL_NO_WG, i32, env, i32, i32)
55
-DEF_HELPER_FLAGS_3(divu, TCG_CALL_NO_WG, i32, env, i32, i32)
56
-DEF_HELPER_FLAGS_1(scmpu, TCG_CALL_NO_WG, void, env)
57
+DEF_HELPER_3(div, i32, env, i32, i32)
58
+DEF_HELPER_3(divu, i32, env, i32, i32)
59
+DEF_HELPER_1(scmpu, void, env)
60
DEF_HELPER_1(smovu, void, env)
61
DEF_HELPER_1(smovf, void, env)
62
DEF_HELPER_1(smovb, void, env)
63
DEF_HELPER_2(sstr, void, env, i32)
64
-DEF_HELPER_FLAGS_2(swhile, TCG_CALL_NO_WG, void, env, i32)
65
-DEF_HELPER_FLAGS_2(suntil, TCG_CALL_NO_WG, void, env, i32)
66
-DEF_HELPER_FLAGS_2(rmpa, TCG_CALL_NO_WG, void, env, i32)
67
+DEF_HELPER_2(swhile, void, env, i32)
68
+DEF_HELPER_2(suntil, void, env, i32)
69
+DEF_HELPER_2(rmpa, void, env, i32)
70
DEF_HELPER_1(satr, void, env)
30
--
71
--
31
2.25.1
72
2.43.0
diff view generated by jsdifflib