1
First arm pullreq for 7.1. The bulk of this is the qemu_split_irq
1
Hi; here's the latest arm pullreq. This is mostly patches from
2
removal.
2
RTH, plus a couple of other more minor things. Switching to
3
3
PCREL is the big one, hopefully should improve performance.
4
I have enough stuff in my to-review queue that I expect to do another
5
pullreq early next week, but 31 patches is enough to not hang on to.
6
4
7
thanks
5
thanks
8
-- PMM
6
-- PMM
9
7
10
The following changes since commit 9c125d17e9402c232c46610802e5931b3639d77b:
8
The following changes since commit 214a8da23651f2472b296b3293e619fd58d9e212:
11
9
12
Merge tag 'pull-tcg-20220420' of https://gitlab.com/rth7680/qemu into staging (2022-04-20 16:43:11 -0700)
10
Merge tag 'for-upstream' of https://gitlab.com/bonzini/qemu into staging (2022-10-18 11:14:31 -0400)
13
11
14
are available in the Git repository at:
12
are available in the Git repository at:
15
13
16
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20220421
14
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20221020
17
15
18
for you to fetch changes up to 5b415dd61bdbf61fb4be0e9f1a7172b8bce682c6:
16
for you to fetch changes up to 5db899303799e49209016a93289b8694afa1449e:
19
17
20
hw/arm: Use bit fields for NPCM7XX PWRON STRAPs (2022-04-21 11:37:05 +0100)
18
hw/ide/microdrive: Use device_cold_reset() for self-resets (2022-10-20 12:11:53 +0100)
21
19
22
----------------------------------------------------------------
20
----------------------------------------------------------------
23
target-arm queue:
21
target-arm queue:
24
* hw/arm/virt: Check for attempt to use TrustZone with KVM or HVF
22
* Switch to TARGET_TB_PCREL
25
* versal: Add the Cortex-R5s in the Real-Time Processing Unit (RPU) subsystem
23
* More pagetable-walk refactoring preparatory to HAFDBS
26
* versal: model enough of the Clock/Reset Low-power domain (CRL) to allow control of the Cortex-R5s
24
* update the cortex-a15 MIDR to latest rev
27
* xlnx-zynqmp: Connect 4 TTC timers
25
* hw/char/pl011: fix baud rate calculation
28
* exynos4210: Refactor GIC/combiner code to stop using qemu_split_irq
26
* hw/ide/microdrive: Use device_cold_reset() for self-resets
29
* realview: replace 'qemu_split_irq' with 'TYPE_SPLIT_IRQ'
30
* stellaris: replace 'qemu_split_irq' with 'TYPE_SPLIT_IRQ'
31
* hw/core/irq: remove unused 'qemu_irq_split' function
32
* npcm7xx: use symbolic constants for PWRON STRAP bit fields
33
* virt: document impact of gic-version on max CPUs
34
27
35
----------------------------------------------------------------
28
----------------------------------------------------------------
36
Edgar E. Iglesias (6):
29
Alex Bennée (1):
37
timer: cadence_ttc: Break out header file to allow embedding
30
target/arm: update the cortex-a15 MIDR to latest rev
38
hw/arm/xlnx-zynqmp: Connect 4 TTC timers
39
hw/arm: versal: Create an APU CPU Cluster
40
hw/arm: versal: Add the Cortex-R5Fs
41
hw/misc: Add a model of the Xilinx Versal CRL
42
hw/arm: versal: Connect the CRL
43
31
44
Hao Wu (2):
32
Baruch Siach (1):
45
hw/misc: Add PWRON STRAP bit fields in GCR module
33
hw/char/pl011: fix baud rate calculation
46
hw/arm: Use bit fields for NPCM7XX PWRON STRAPs
47
34
48
Heinrich Schuchardt (1):
35
Peter Maydell (1):
49
hw/arm/virt: impact of gic-version on max CPUs
36
hw/ide/microdrive: Use device_cold_reset() for self-resets
50
37
51
Peter Maydell (19):
38
Richard Henderson (21):
52
hw/arm/virt: Check for attempt to use TrustZone with KVM or HVF
39
target/arm: Enable TARGET_PAGE_ENTRY_EXTRA
53
hw/arm/exynos4210: Use TYPE_OR_IRQ instead of custom OR-gate device
40
target/arm: Use probe_access_full for MTE
54
hw/intc/exynos4210_gic: Remove unused TYPE_EXYNOS4210_IRQ_GATE
41
target/arm: Use probe_access_full for BTI
55
hw/arm/exynos4210: Put a9mpcore device into state struct
42
target/arm: Add ARMMMUIdx_Phys_{S,NS}
56
hw/arm/exynos4210: Drop int_gic_irq[] from Exynos4210Irq struct
43
target/arm: Move ARMMMUIdx_Stage2 to a real tlb mmu_idx
57
hw/arm/exynos4210: Coalesce board_irqs and irq_table
44
target/arm: Restrict tlb flush from vttbr_write to vmid change
58
hw/arm/exynos4210: Fix code style nit in combiner_grp_to_gic_id[]
45
target/arm: Split out S1Translate type
59
hw/arm/exynos4210: Move exynos4210_init_board_irqs() into exynos4210.c
46
target/arm: Plumb debug into S1Translate
60
hw/arm/exynos4210: Put external GIC into state struct
47
target/arm: Move be test for regime into S1TranslateResult
61
hw/arm/exynos4210: Drop ext_gic_irq[] from Exynos4210Irq struct
48
target/arm: Use softmmu tlbs for page table walking
62
hw/arm/exynos4210: Move exynos4210_combiner_get_gpioin() into exynos4210.c
49
target/arm: Split out get_phys_addr_twostage
63
hw/arm/exynos4210: Delete unused macro definitions
50
target/arm: Use bool consistently for get_phys_addr subroutines
64
hw/arm/exynos4210: Use TYPE_SPLIT_IRQ in exynos4210_init_board_irqs()
51
target/arm: Introduce curr_insn_len
65
hw/arm/exynos4210: Fill in irq_table[] for internal-combiner-only IRQ lines
52
target/arm: Change gen_goto_tb to work on displacements
66
hw/arm/exynos4210: Connect MCT_G0 and MCT_G1 to both combiners
53
target/arm: Change gen_*set_pc_im to gen_*update_pc
67
hw/arm/exynos4210: Don't connect multiple lines to external GIC inputs
54
target/arm: Change gen_exception_insn* to work on displacements
68
hw/arm/exynos4210: Fold combiner splits into exynos4210_init_board_irqs()
55
target/arm: Remove gen_exception_internal_insn pc argument
69
hw/arm/exynos4210: Put combiners into state struct
56
target/arm: Change gen_jmp* to work on displacements
70
hw/arm/exynos4210: Drop Exynos4210Irq struct
57
target/arm: Introduce gen_pc_plus_diff for aarch64
58
target/arm: Introduce gen_pc_plus_diff for aarch32
59
target/arm: Enable TARGET_TB_PCREL
71
60
72
Zongyuan Li (3):
61
target/arm/cpu-param.h | 17 +-
73
hw/arm/realview: replace 'qemu_split_irq' with 'TYPE_SPLIT_IRQ'
62
target/arm/cpu.h | 47 ++--
74
hw/arm/stellaris: replace 'qemu_split_irq' with 'TYPE_SPLIT_IRQ'
63
target/arm/internals.h | 1 +
75
hw/core/irq: remove unused 'qemu_irq_split' function
64
target/arm/sve_ldst_internal.h | 1 +
65
target/arm/translate-a32.h | 2 +-
66
target/arm/translate.h | 66 ++++-
67
hw/char/pl011.c | 2 +-
68
hw/ide/microdrive.c | 8 +-
69
target/arm/cpu.c | 23 +-
70
target/arm/cpu_tcg.c | 4 +-
71
target/arm/helper.c | 155 +++++++++---
72
target/arm/mte_helper.c | 62 ++---
73
target/arm/ptw.c | 535 +++++++++++++++++++++++++----------------
74
target/arm/sve_helper.c | 54 ++---
75
target/arm/tlb_helper.c | 24 +-
76
target/arm/translate-a64.c | 220 ++++++++++-------
77
target/arm/translate-m-nocp.c | 8 +-
78
target/arm/translate-mve.c | 2 +-
79
target/arm/translate-vfp.c | 10 +-
80
target/arm/translate.c | 284 +++++++++++++---------
81
20 files changed, 918 insertions(+), 607 deletions(-)
76
82
77
docs/system/arm/virt.rst | 4 +-
78
include/hw/arm/exynos4210.h | 50 ++--
79
include/hw/arm/xlnx-versal.h | 16 ++
80
include/hw/arm/xlnx-zynqmp.h | 4 +
81
include/hw/intc/exynos4210_combiner.h | 57 +++++
82
include/hw/intc/exynos4210_gic.h | 43 ++++
83
include/hw/irq.h | 5 -
84
include/hw/misc/npcm7xx_gcr.h | 30 +++
85
include/hw/misc/xlnx-versal-crl.h | 235 +++++++++++++++++++
86
include/hw/timer/cadence_ttc.h | 54 +++++
87
hw/arm/exynos4210.c | 430 ++++++++++++++++++++++++++++++----
88
hw/arm/npcm7xx_boards.c | 24 +-
89
hw/arm/realview.c | 33 ++-
90
hw/arm/stellaris.c | 15 +-
91
hw/arm/virt.c | 7 +
92
hw/arm/xlnx-versal-virt.c | 6 +-
93
hw/arm/xlnx-versal.c | 99 +++++++-
94
hw/arm/xlnx-zynqmp.c | 22 ++
95
hw/core/irq.c | 15 --
96
hw/intc/exynos4210_combiner.c | 108 +--------
97
hw/intc/exynos4210_gic.c | 344 +--------------------------
98
hw/misc/xlnx-versal-crl.c | 421 +++++++++++++++++++++++++++++++++
99
hw/timer/cadence_ttc.c | 32 +--
100
MAINTAINERS | 2 +-
101
hw/misc/meson.build | 1 +
102
25 files changed, 1457 insertions(+), 600 deletions(-)
103
create mode 100644 include/hw/intc/exynos4210_combiner.h
104
create mode 100644 include/hw/intc/exynos4210_gic.h
105
create mode 100644 include/hw/misc/xlnx-versal-crl.h
106
create mode 100644 include/hw/timer/cadence_ttc.h
107
create mode 100644 hw/misc/xlnx-versal-crl.c
diff view generated by jsdifflib
Deleted patch
1
It's not possible to provide the guest with the Security extensions
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
1
7
$ qemu-system-aarch64 -enable-kvm -machine virt,secure=on -cpu host -display none
8
Unexpected error in object_property_find_err() at ../../qom/object.c:1304:
9
qemu-system-aarch64: Property 'host-arm-cpu.secure-memory' not found
10
Aborted
11
12
Check for this combination of options and report an error, in the
13
same way we already do for attempts to give a KVM or HVF guest the
14
Virtualization or MTE extensions. Now we will report:
15
16
qemu-system-aarch64: mach-virt: KVM does not support providing Security extensions (TrustZone) to the guest CPU
17
18
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/961
19
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
20
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
21
Message-id: 20220404155301.566542-1-peter.maydell@linaro.org
22
---
23
hw/arm/virt.c | 7 +++++++
24
1 file changed, 7 insertions(+)
25
26
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
27
index XXXXXXX..XXXXXXX 100644
28
--- a/hw/arm/virt.c
29
+++ b/hw/arm/virt.c
30
@@ -XXX,XX +XXX,XX @@ static void machvirt_init(MachineState *machine)
31
exit(1);
32
}
33
34
+ if (vms->secure && (kvm_enabled() || hvf_enabled())) {
35
+ error_report("mach-virt: %s does not support providing "
36
+ "Security extensions (TrustZone) to the guest CPU",
37
+ kvm_enabled() ? "KVM" : "HVF");
38
+ exit(1);
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
--
45
2.25.1
diff view generated by jsdifflib
1
From: Hao Wu <wuhaotsh@google.com>
1
From: Baruch Siach <baruch@tkos.co.il>
2
2
3
This patch uses the defined fields to describe PWRON STRAPs for
3
The PL011 TRM says that "UARTIBRD = 0 is invalid and UARTFBRD is ignored
4
better readability.
4
when this is the case". But the code looks at FBRD for the invalid case.
5
Fix this.
5
6
6
Signed-off-by: Hao Wu <wuhaotsh@google.com>
7
Signed-off-by: Baruch Siach <baruch@tkos.co.il>
7
Reviewed-by: Patrick Venture <venture@google.com>
8
Message-id: 1408f62a2e45665816527d4845ffde650957d5ab.1665051588.git.baruchs-c@neureality.ai
8
Message-id: 20220411165842.3912945-3-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
hw/arm/npcm7xx_boards.c | 24 +++++++++++++++++++-----
12
hw/char/pl011.c | 2 +-
13
1 file changed, 19 insertions(+), 5 deletions(-)
13
1 file changed, 1 insertion(+), 1 deletion(-)
14
14
15
diff --git a/hw/arm/npcm7xx_boards.c b/hw/arm/npcm7xx_boards.c
15
diff --git a/hw/char/pl011.c b/hw/char/pl011.c
16
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/arm/npcm7xx_boards.c
17
--- a/hw/char/pl011.c
18
+++ b/hw/arm/npcm7xx_boards.c
18
+++ b/hw/char/pl011.c
19
@@ -XXX,XX +XXX,XX @@
19
@@ -XXX,XX +XXX,XX @@ static unsigned int pl011_get_baudrate(const PL011State *s)
20
#include "sysemu/sysemu.h"
20
{
21
#include "sysemu/block-backend.h"
21
uint64_t clk;
22
22
23
-#define NPCM750_EVB_POWER_ON_STRAPS 0x00001ff7
23
- if (s->fbrd == 0) {
24
-#define QUANTA_GSJ_POWER_ON_STRAPS 0x00001fff
24
+ if (s->ibrd == 0) {
25
-#define QUANTA_GBS_POWER_ON_STRAPS 0x000017ff
25
return 0;
26
-#define KUDO_BMC_POWER_ON_STRAPS 0x00001fff
26
}
27
-#define MORI_BMC_POWER_ON_STRAPS 0x00001fff
28
+#define NPCM7XX_POWER_ON_STRAPS_DEFAULT ( \
29
+ NPCM7XX_PWRON_STRAP_SPI0F18 | \
30
+ NPCM7XX_PWRON_STRAP_SFAB | \
31
+ NPCM7XX_PWRON_STRAP_BSPA | \
32
+ NPCM7XX_PWRON_STRAP_FUP(FUP_NORM_UART2) | \
33
+ NPCM7XX_PWRON_STRAP_SECEN | \
34
+ NPCM7XX_PWRON_STRAP_HIZ | \
35
+ NPCM7XX_PWRON_STRAP_ECC | \
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
27
50
--
28
--
51
2.25.1
29
2.25.1
diff view generated by jsdifflib
1
From: Hao Wu <wuhaotsh@google.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Similar to the Aspeed code in include/misc/aspeed_scu.h, we define
3
The CPUTLBEntryFull structure now stores the original pte attributes, as
4
the PWRON STRAP fields in their corresponding module for NPCM7XX.
4
well as the physical address. Therefore, we no longer need a separate
5
bit in MemTxAttrs, nor do we need to walk the tree of memory regions.
5
6
6
Signed-off-by: Hao Wu <wuhaotsh@google.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>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20221011031911.2408754-3-richard.henderson@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/arm/cpu.h | 1 -
13
1 file changed, 30 insertions(+)
13
target/arm/sve_ldst_internal.h | 1 +
14
target/arm/mte_helper.c | 62 ++++++++++------------------------
15
target/arm/sve_helper.c | 54 ++++++++++-------------------
16
target/arm/tlb_helper.c | 4 ---
17
5 files changed, 36 insertions(+), 86 deletions(-)
14
18
15
diff --git a/include/hw/misc/npcm7xx_gcr.h b/include/hw/misc/npcm7xx_gcr.h
19
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
16
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
17
--- a/include/hw/misc/npcm7xx_gcr.h
21
--- a/target/arm/cpu.h
18
+++ b/include/hw/misc/npcm7xx_gcr.h
22
+++ b/target/arm/cpu.h
19
@@ -XXX,XX +XXX,XX @@
23
@@ -XXX,XX +XXX,XX @@ static inline MemTxAttrs *typecheck_memtxattrs(MemTxAttrs *x)
20
#include "exec/memory.h"
24
* generic target bits directly.
21
#include "hw/sysbus.h"
25
*/
22
26
#define arm_tlb_bti_gp(x) (typecheck_memtxattrs(x)->target_tlb_bit0)
23
+/*
27
-#define arm_tlb_mte_tagged(x) (typecheck_memtxattrs(x)->target_tlb_bit1)
24
+ * NPCM7XX PWRON STRAP bit fields
28
25
+ * 12: SPI0 powered by VSBV3 at 1.8V
29
/*
26
+ * 11: System flash attached to BMC
30
* AArch64 usage of the PAGE_TARGET_* bits for linux-user.
27
+ * 10: BSP alternative pins.
31
diff --git a/target/arm/sve_ldst_internal.h b/target/arm/sve_ldst_internal.h
28
+ * 9:8: Flash UART command route enabled.
32
index XXXXXXX..XXXXXXX 100644
29
+ * 7: Security enabled.
33
--- a/target/arm/sve_ldst_internal.h
30
+ * 6: HI-Z state control.
34
+++ b/target/arm/sve_ldst_internal.h
31
+ * 5: ECC disabled.
35
@@ -XXX,XX +XXX,XX @@ typedef struct {
32
+ * 4: Reserved
36
void *host;
33
+ * 3: JTAG2 enabled.
37
int flags;
34
+ * 2:0: CPU and DRAM clock frequency.
38
MemTxAttrs attrs;
35
+ */
39
+ bool tagged;
36
+#define NPCM7XX_PWRON_STRAP_SPI0F18 BIT(12)
40
} SVEHostPage;
37
+#define NPCM7XX_PWRON_STRAP_SFAB BIT(11)
41
38
+#define NPCM7XX_PWRON_STRAP_BSPA BIT(10)
42
bool sve_probe_page(SVEHostPage *info, bool nofault, CPUARMState *env,
39
+#define NPCM7XX_PWRON_STRAP_FUP(x) ((x) << 8)
43
diff --git a/target/arm/mte_helper.c b/target/arm/mte_helper.c
40
+#define FUP_NORM_UART2 3
44
index XXXXXXX..XXXXXXX 100644
41
+#define FUP_PROG_UART3 2
45
--- a/target/arm/mte_helper.c
42
+#define FUP_PROG_UART2 1
46
+++ b/target/arm/mte_helper.c
43
+#define FUP_NORM_UART3 0
47
@@ -XXX,XX +XXX,XX @@ static uint8_t *allocation_tag_mem(CPUARMState *env, int ptr_mmu_idx,
44
+#define NPCM7XX_PWRON_STRAP_SECEN BIT(7)
48
TARGET_PAGE_BITS - LOG2_TAG_GRANULE - 1);
45
+#define NPCM7XX_PWRON_STRAP_HIZ BIT(6)
49
return tags + index;
46
+#define NPCM7XX_PWRON_STRAP_ECC BIT(5)
50
#else
47
+#define NPCM7XX_PWRON_STRAP_RESERVE1 BIT(4)
51
- uintptr_t index;
48
+#define NPCM7XX_PWRON_STRAP_J2EN BIT(3)
52
CPUTLBEntryFull *full;
49
+#define NPCM7XX_PWRON_STRAP_CKFRQ(x) (x)
53
+ MemTxAttrs attrs;
50
+#define CKFRQ_SKIPINIT 0x000
54
int in_page, flags;
51
+#define CKFRQ_DEFAULT 0x111
55
- ram_addr_t ptr_ra;
56
hwaddr ptr_paddr, tag_paddr, xlat;
57
MemoryRegion *mr;
58
ARMASIdx tag_asi;
59
@@ -XXX,XX +XXX,XX @@ static uint8_t *allocation_tag_mem(CPUARMState *env, int ptr_mmu_idx,
60
* valid. Indicate to probe_access_flags no-fault, then assert that
61
* we received a valid page.
62
*/
63
- flags = probe_access_flags(env, ptr, ptr_access, ptr_mmu_idx,
64
- ra == 0, &host, ra);
65
+ flags = probe_access_full(env, ptr, ptr_access, ptr_mmu_idx,
66
+ ra == 0, &host, &full, ra);
67
assert(!(flags & TLB_INVALID_MASK));
68
69
- /*
70
- * Find the CPUTLBEntryFull for ptr. This *must* be present in the TLB
71
- * because we just found the mapping.
72
- * TODO: Perhaps there should be a cputlb helper that returns a
73
- * matching tlb entry + iotlb entry.
74
- */
75
- index = tlb_index(env, ptr_mmu_idx, ptr);
76
-# ifdef CONFIG_DEBUG_TCG
77
- {
78
- CPUTLBEntry *entry = tlb_entry(env, ptr_mmu_idx, ptr);
79
- target_ulong comparator = (ptr_access == MMU_DATA_LOAD
80
- ? entry->addr_read
81
- : tlb_addr_write(entry));
82
- g_assert(tlb_hit(comparator, ptr));
83
- }
84
-# endif
85
- full = &env_tlb(env)->d[ptr_mmu_idx].fulltlb[index];
86
-
87
/* If the virtual page MemAttr != Tagged, access unchecked. */
88
- if (!arm_tlb_mte_tagged(&full->attrs)) {
89
+ if (full->pte_attrs != 0xf0) {
90
return NULL;
91
}
92
93
@@ -XXX,XX +XXX,XX @@ static uint8_t *allocation_tag_mem(CPUARMState *env, int ptr_mmu_idx,
94
return NULL;
95
}
96
97
+ /*
98
+ * Remember these values across the second lookup below,
99
+ * which may invalidate this pointer via tlb resize.
100
+ */
101
+ ptr_paddr = full->phys_addr;
102
+ attrs = full->attrs;
103
+ full = NULL;
52
+
104
+
53
/*
105
/*
54
* Number of registers in our device state structure. Don't change this without
106
* The Normal memory access can extend to the next page. E.g. a single
55
* incrementing the version_id in the vmstate.
107
* 8-byte access to the last byte of a page will check only the last
108
@@ -XXX,XX +XXX,XX @@ static uint8_t *allocation_tag_mem(CPUARMState *env, int ptr_mmu_idx,
109
*/
110
in_page = -(ptr | TARGET_PAGE_MASK);
111
if (unlikely(ptr_size > in_page)) {
112
- void *ignore;
113
- flags |= probe_access_flags(env, ptr + in_page, ptr_access,
114
- ptr_mmu_idx, ra == 0, &ignore, ra);
115
+ flags |= probe_access_full(env, ptr + in_page, ptr_access,
116
+ ptr_mmu_idx, ra == 0, &host, &full, ra);
117
assert(!(flags & TLB_INVALID_MASK));
118
}
119
120
@@ -XXX,XX +XXX,XX @@ static uint8_t *allocation_tag_mem(CPUARMState *env, int ptr_mmu_idx,
121
if (unlikely(flags & TLB_WATCHPOINT)) {
122
int wp = ptr_access == MMU_DATA_LOAD ? BP_MEM_READ : BP_MEM_WRITE;
123
assert(ra != 0);
124
- cpu_check_watchpoint(env_cpu(env), ptr, ptr_size,
125
- full->attrs, wp, ra);
126
+ cpu_check_watchpoint(env_cpu(env), ptr, ptr_size, attrs, wp, ra);
127
}
128
129
- /*
130
- * Find the physical address within the normal mem space.
131
- * The memory region lookup must succeed because TLB_MMIO was
132
- * not set in the cputlb lookup above.
133
- */
134
- mr = memory_region_from_host(host, &ptr_ra);
135
- tcg_debug_assert(mr != NULL);
136
- tcg_debug_assert(memory_region_is_ram(mr));
137
- ptr_paddr = ptr_ra;
138
- do {
139
- ptr_paddr += mr->addr;
140
- mr = mr->container;
141
- } while (mr);
142
-
143
/* Convert to the physical address in tag space. */
144
tag_paddr = ptr_paddr >> (LOG2_TAG_GRANULE + 1);
145
146
/* Look up the address in tag space. */
147
- tag_asi = full->attrs.secure ? ARMASIdx_TagS : ARMASIdx_TagNS;
148
+ tag_asi = attrs.secure ? ARMASIdx_TagS : ARMASIdx_TagNS;
149
tag_as = cpu_get_address_space(env_cpu(env), tag_asi);
150
mr = address_space_translate(tag_as, tag_paddr, &xlat, NULL,
151
- tag_access == MMU_DATA_STORE,
152
- full->attrs);
153
+ tag_access == MMU_DATA_STORE, attrs);
154
155
/*
156
* Note that @mr will never be NULL. If there is nothing in the address
157
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
158
index XXXXXXX..XXXXXXX 100644
159
--- a/target/arm/sve_helper.c
160
+++ b/target/arm/sve_helper.c
161
@@ -XXX,XX +XXX,XX @@ bool sve_probe_page(SVEHostPage *info, bool nofault, CPUARMState *env,
162
*/
163
addr = useronly_clean_ptr(addr);
164
165
+#ifdef CONFIG_USER_ONLY
166
flags = probe_access_flags(env, addr, access_type, mmu_idx, nofault,
167
&info->host, retaddr);
168
+ memset(&info->attrs, 0, sizeof(info->attrs));
169
+ /* Require both ANON and MTE; see allocation_tag_mem(). */
170
+ info->tagged = (flags & PAGE_ANON) && (flags & PAGE_MTE);
171
+#else
172
+ CPUTLBEntryFull *full;
173
+ flags = probe_access_full(env, addr, access_type, mmu_idx, nofault,
174
+ &info->host, &full, retaddr);
175
+ info->attrs = full->attrs;
176
+ info->tagged = full->pte_attrs == 0xf0;
177
+#endif
178
info->flags = flags;
179
180
if (flags & TLB_INVALID_MASK) {
181
@@ -XXX,XX +XXX,XX @@ bool sve_probe_page(SVEHostPage *info, bool nofault, CPUARMState *env,
182
183
/* Ensure that info->host[] is relative to addr, not addr + mem_off. */
184
info->host -= mem_off;
185
-
186
-#ifdef CONFIG_USER_ONLY
187
- memset(&info->attrs, 0, sizeof(info->attrs));
188
- /* Require both MAP_ANON and PROT_MTE -- see allocation_tag_mem. */
189
- arm_tlb_mte_tagged(&info->attrs) =
190
- (flags & PAGE_ANON) && (flags & PAGE_MTE);
191
-#else
192
- /*
193
- * Find the iotlbentry for addr and return the transaction attributes.
194
- * This *must* be present in the TLB because we just found the mapping.
195
- */
196
- {
197
- uintptr_t index = tlb_index(env, mmu_idx, addr);
198
-
199
-# ifdef CONFIG_DEBUG_TCG
200
- CPUTLBEntry *entry = tlb_entry(env, mmu_idx, addr);
201
- target_ulong comparator = (access_type == MMU_DATA_LOAD
202
- ? entry->addr_read
203
- : tlb_addr_write(entry));
204
- g_assert(tlb_hit(comparator, addr));
205
-# endif
206
-
207
- CPUTLBEntryFull *full = &env_tlb(env)->d[mmu_idx].fulltlb[index];
208
- info->attrs = full->attrs;
209
- }
210
-#endif
211
-
212
return true;
213
}
214
215
@@ -XXX,XX +XXX,XX @@ void sve_cont_ldst_mte_check(SVEContLdSt *info, CPUARMState *env,
216
intptr_t mem_off, reg_off, reg_last;
217
218
/* Process the page only if MemAttr == Tagged. */
219
- if (arm_tlb_mte_tagged(&info->page[0].attrs)) {
220
+ if (info->page[0].tagged) {
221
mem_off = info->mem_off_first[0];
222
reg_off = info->reg_off_first[0];
223
reg_last = info->reg_off_split;
224
@@ -XXX,XX +XXX,XX @@ void sve_cont_ldst_mte_check(SVEContLdSt *info, CPUARMState *env,
225
}
226
227
mem_off = info->mem_off_first[1];
228
- if (mem_off >= 0 && arm_tlb_mte_tagged(&info->page[1].attrs)) {
229
+ if (mem_off >= 0 && info->page[1].tagged) {
230
reg_off = info->reg_off_first[1];
231
reg_last = info->reg_off_last[1];
232
233
@@ -XXX,XX +XXX,XX @@ void sve_ldnfff1_r(CPUARMState *env, void *vg, const target_ulong addr,
234
* Disable MTE checking if the Tagged bit is not set. Since TBI must
235
* be set within MTEDESC for MTE, !mtedesc => !mte_active.
236
*/
237
- if (!arm_tlb_mte_tagged(&info.page[0].attrs)) {
238
+ if (!info.page[0].tagged) {
239
mtedesc = 0;
240
}
241
242
@@ -XXX,XX +XXX,XX @@ void sve_ld1_z(CPUARMState *env, void *vd, uint64_t *vg, void *vm,
243
cpu_check_watchpoint(env_cpu(env), addr, msize,
244
info.attrs, BP_MEM_READ, retaddr);
245
}
246
- if (mtedesc && arm_tlb_mte_tagged(&info.attrs)) {
247
+ if (mtedesc && info.tagged) {
248
mte_check(env, mtedesc, addr, retaddr);
249
}
250
if (unlikely(info.flags & TLB_MMIO)) {
251
@@ -XXX,XX +XXX,XX @@ void sve_ld1_z(CPUARMState *env, void *vd, uint64_t *vg, void *vm,
252
msize, info.attrs,
253
BP_MEM_READ, retaddr);
254
}
255
- if (mtedesc && arm_tlb_mte_tagged(&info.attrs)) {
256
+ if (mtedesc && info.tagged) {
257
mte_check(env, mtedesc, addr, retaddr);
258
}
259
tlb_fn(env, &scratch, reg_off, addr, retaddr);
260
@@ -XXX,XX +XXX,XX @@ void sve_ldff1_z(CPUARMState *env, void *vd, uint64_t *vg, void *vm,
261
(env_cpu(env), addr, msize) & BP_MEM_READ)) {
262
goto fault;
263
}
264
- if (mtedesc &&
265
- arm_tlb_mte_tagged(&info.attrs) &&
266
- !mte_probe(env, mtedesc, addr)) {
267
+ if (mtedesc && info.tagged && !mte_probe(env, mtedesc, addr)) {
268
goto fault;
269
}
270
271
@@ -XXX,XX +XXX,XX @@ void sve_st1_z(CPUARMState *env, void *vd, uint64_t *vg, void *vm,
272
info.attrs, BP_MEM_WRITE, retaddr);
273
}
274
275
- if (mtedesc && arm_tlb_mte_tagged(&info.attrs)) {
276
+ if (mtedesc && info.tagged) {
277
mte_check(env, mtedesc, addr, retaddr);
278
}
279
}
280
diff --git a/target/arm/tlb_helper.c b/target/arm/tlb_helper.c
281
index XXXXXXX..XXXXXXX 100644
282
--- a/target/arm/tlb_helper.c
283
+++ b/target/arm/tlb_helper.c
284
@@ -XXX,XX +XXX,XX @@ bool arm_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
285
res.f.phys_addr &= TARGET_PAGE_MASK;
286
address &= TARGET_PAGE_MASK;
287
}
288
- /* Notice and record tagged memory. */
289
- if (cpu_isar_feature(aa64_mte, cpu) && res.cacheattrs.attrs == 0xf0) {
290
- arm_tlb_mte_tagged(&res.f.attrs) = true;
291
- }
292
293
res.f.pte_attrs = res.cacheattrs.attrs;
294
res.f.shareability = res.cacheattrs.shareability;
56
--
295
--
57
2.25.1
296
2.25.1
diff view generated by jsdifflib
1
The exynos4210 code currently has two very similar arrays of IRQs:
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
* board_irqs is a field of the Exynos4210Irq struct which is filled
3
Add a field to TARGET_PAGE_ENTRY_EXTRA to hold the guarded bit.
4
in by exynos4210_init_board_irqs() with the appropriate qemu_irqs
4
In is_guarded_page, use probe_access_full instead of just guessing
5
for each IRQ the board/SoC can assert
5
that the tlb entry is still present. Also handles the FIXME about
6
* irq_table is a set of qemu_irqs pointed to from the
6
executing from device memory.
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
7
11
The extra indirection through irq_table is unnecessary, so coalesce
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
these into a single irq_table[] array as a direct field in
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
13
Exynos4210State which exynos4210_init_board_irqs() fills in.
10
Message-id: 20221011031911.2408754-4-richard.henderson@linaro.org
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
13
target/arm/cpu-param.h | 9 +++++----
14
target/arm/cpu.h | 13 -------------
15
target/arm/internals.h | 1 +
16
target/arm/ptw.c | 7 ++++---
17
target/arm/translate-a64.c | 21 ++++++++++-----------
18
5 files changed, 20 insertions(+), 31 deletions(-)
14
19
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
20
diff --git a/target/arm/cpu-param.h b/target/arm/cpu-param.h
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
21
index XXXXXXX..XXXXXXX 100644
26
--- a/include/hw/arm/exynos4210.h
22
--- a/target/arm/cpu-param.h
27
+++ b/include/hw/arm/exynos4210.h
23
+++ b/target/arm/cpu-param.h
28
@@ -XXX,XX +XXX,XX @@ typedef struct Exynos4210Irq {
24
@@ -XXX,XX +XXX,XX @@
29
qemu_irq int_combiner_irq[EXYNOS4210_MAX_INT_COMBINER_IN_IRQ];
25
*
30
qemu_irq ext_combiner_irq[EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ];
26
* For ARMMMUIdx_Stage2*, pte_attrs is the S2 descriptor bits [5:2].
31
qemu_irq ext_gic_irq[EXYNOS4210_EXT_GIC_NIRQ];
27
* Otherwise, pte_attrs is the same as the MAIR_EL1 8-bit format.
32
- qemu_irq board_irqs[EXYNOS4210_MAX_INT_COMBINER_IN_IRQ];
28
- * For shareability, as in the SH field of the VMSAv8-64 PTEs.
33
} Exynos4210Irq;
29
+ * For shareability and guarded, as in the SH and GP fields respectively
34
30
+ * of the VMSAv8-64 PTEs.
35
struct Exynos4210State {
31
*/
36
@@ -XXX,XX +XXX,XX @@ struct Exynos4210State {
32
# define TARGET_PAGE_ENTRY_EXTRA \
37
/*< public >*/
33
- uint8_t pte_attrs; \
38
ARMCPU *cpu[EXYNOS4210_NCPUS];
34
- uint8_t shareability;
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
-
35
-
52
/* Initialize board IRQs.
36
+ uint8_t pte_attrs; \
53
* These IRQs contain splitted Int/External Combiner and External Gic IRQs */
37
+ uint8_t shareability; \
54
-void exynos4210_init_board_irqs(Exynos4210Irq *s);
38
+ bool guarded;
55
+void exynos4210_init_board_irqs(Exynos4210State *s);
39
#endif
56
40
57
/* Get IRQ number from exynos4210 IRQ subsystem stub.
41
#define NB_MMU_MODES 8
58
* To identify IRQ source use internal combiner group and bit number
42
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
59
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
60
index XXXXXXX..XXXXXXX 100644
43
index XXXXXXX..XXXXXXX 100644
61
--- a/hw/arm/exynos4210.c
44
--- a/target/arm/cpu.h
62
+++ b/hw/arm/exynos4210.c
45
+++ b/target/arm/cpu.h
63
@@ -XXX,XX +XXX,XX @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
46
@@ -XXX,XX +XXX,XX @@ static inline uint64_t *aa64_vfp_qreg(CPUARMState *env, unsigned regno)
64
qdev_realize(DEVICE(cpuobj), NULL, &error_fatal);
47
/* Shared between translate-sve.c and sve_helper.c. */
65
}
48
extern const uint64_t pred_esz_masks[5];
66
49
67
- /*** IRQs ***/
50
-/* Helper for the macros below, validating the argument type. */
68
-
51
-static inline MemTxAttrs *typecheck_memtxattrs(MemTxAttrs *x)
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
-{
52
-{
93
- Exynos4210Irq *s = (Exynos4210Irq *)opaque;
53
- return x;
94
-
95
- /* Bypass */
96
- qemu_set_irq(s->board_irqs[irq], level);
97
-}
54
-}
98
-
55
-
99
-/*
56
-/*
100
- * Initialize exynos4210 IRQ subsystem stub.
57
- * Lvalue macros for ARM TLB bits that we must cache in the TCG TLB.
58
- * Using these should be a bit more self-documenting than using the
59
- * generic target bits directly.
101
- */
60
- */
102
-qemu_irq *exynos4210_init_irq(Exynos4210Irq *s)
61
-#define arm_tlb_bti_gp(x) (typecheck_memtxattrs(x)->target_tlb_bit0)
103
-{
104
- return qemu_allocate_irqs(exynos4210_irq_handler, s,
105
- EXYNOS4210_MAX_INT_COMBINER_IN_IRQ);
106
-}
107
-
62
-
108
/*
63
/*
109
* Initialize board IRQs.
64
* AArch64 usage of the PAGE_TARGET_* bits for linux-user.
110
* These IRQs contain splitted Int/External Combiner and External Gic IRQs.
65
* Note that with the Linux kernel, PROT_MTE may not be cleared by mprotect
111
*/
66
diff --git a/target/arm/internals.h b/target/arm/internals.h
112
-void exynos4210_init_board_irqs(Exynos4210Irq *s)
67
index XXXXXXX..XXXXXXX 100644
113
+void exynos4210_init_board_irqs(Exynos4210State *s)
68
--- a/target/arm/internals.h
114
{
69
+++ b/target/arm/internals.h
115
uint32_t grp, bit, irq_id, n;
70
@@ -XXX,XX +XXX,XX @@ typedef struct ARMCacheAttrs {
116
+ Exynos4210Irq *is = &s->irqs;
71
unsigned int attrs:8;
117
72
unsigned int shareability:2; /* as in the SH field of the VMSAv8-64 PTEs */
118
for (n = 0; n < EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ; n++) {
73
bool is_s2_format:1;
119
irq_id = 0;
74
+ bool guarded:1; /* guarded bit of the v8-64 PTE */
120
@@ -XXX,XX +XXX,XX @@ void exynos4210_init_board_irqs(Exynos4210Irq *s)
75
} ARMCacheAttrs;
121
irq_id = EXT_GIC_ID_MCT_G1;
76
122
}
77
/* Fields that are valid upon success. */
123
if (irq_id) {
78
diff --git a/target/arm/ptw.c b/target/arm/ptw.c
124
- s->board_irqs[n] = qemu_irq_split(s->int_combiner_irq[n],
79
index XXXXXXX..XXXXXXX 100644
125
- s->ext_gic_irq[irq_id-32]);
80
--- a/target/arm/ptw.c
126
+ s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
81
+++ b/target/arm/ptw.c
127
+ is->ext_gic_irq[irq_id - 32]);
82
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, uint64_t address,
128
} else {
83
*/
129
- s->board_irqs[n] = qemu_irq_split(s->int_combiner_irq[n],
84
result->f.attrs.secure = false;
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
}
85
}
135
for (; n < EXYNOS4210_MAX_INT_COMBINER_IN_IRQ; n++) {
86
- /* When in aarch64 mode, and BTI is enabled, remember GP in the IOTLB. */
136
@@ -XXX,XX +XXX,XX @@ void exynos4210_init_board_irqs(Exynos4210Irq *s)
87
- if (aarch64 && guarded && cpu_isar_feature(aa64_bti, cpu)) {
137
EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][bit];
88
- arm_tlb_bti_gp(&result->f.attrs) = true;
138
89
+
139
if (irq_id) {
90
+ /* When in aarch64 mode, and BTI is enabled, remember GP in the TLB. */
140
- s->board_irqs[n] = qemu_irq_split(s->int_combiner_irq[n],
91
+ if (aarch64 && cpu_isar_feature(aa64_bti, cpu)) {
141
- s->ext_gic_irq[irq_id-32]);
92
+ result->f.guarded = guarded;
142
+ s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
143
+ is->ext_gic_irq[irq_id - 32]);
144
}
145
}
93
}
94
95
if (mmu_idx == ARMMMUIdx_Stage2 || mmu_idx == ARMMMUIdx_Stage2_S) {
96
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
97
index XXXXXXX..XXXXXXX 100644
98
--- a/target/arm/translate-a64.c
99
+++ b/target/arm/translate-a64.c
100
@@ -XXX,XX +XXX,XX @@ static bool is_guarded_page(CPUARMState *env, DisasContext *s)
101
#ifdef CONFIG_USER_ONLY
102
return page_get_flags(addr) & PAGE_BTI;
103
#else
104
+ CPUTLBEntryFull *full;
105
+ void *host;
106
int mmu_idx = arm_to_core_mmu_idx(s->mmu_idx);
107
- unsigned int index = tlb_index(env, mmu_idx, addr);
108
- CPUTLBEntry *entry = tlb_entry(env, mmu_idx, addr);
109
+ int flags;
110
111
/*
112
* We test this immediately after reading an insn, which means
113
- * that any normal page must be in the TLB. The only exception
114
- * would be for executing from flash or device memory, which
115
- * does not retain the TLB entry.
116
- *
117
- * FIXME: Assume false for those, for now. We could use
118
- * arm_cpu_get_phys_page_attrs_debug to re-read the page
119
- * table entry even for that case.
120
+ * that the TLB entry must be present and valid, and thus this
121
+ * access will never raise an exception.
122
*/
123
- return (tlb_hit(entry->addr_code, addr) &&
124
- arm_tlb_bti_gp(&env_tlb(env)->d[mmu_idx].fulltlb[index].attrs));
125
+ flags = probe_access_full(env, addr, MMU_INST_FETCH, mmu_idx,
126
+ false, &host, &full, 0);
127
+ assert(!(flags & TLB_INVALID_MASK));
128
+
129
+ return full->guarded;
130
#endif
146
}
131
}
132
147
--
133
--
148
2.25.1
134
2.25.1
diff view generated by jsdifflib
1
Switch the creation of the external GIC to the new-style "embedded in
1
From: Richard Henderson <richard.henderson@linaro.org>
2
state struct" approach, so we can easily refer to the object
3
elsewhere during realize.
4
2
3
Not yet used, but add mmu indexes for 1-1 mapping
4
to physical addresses.
5
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20221011031911.2408754-5-richard.henderson@linaro.org
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20220404154658.565020-9-peter.maydell@linaro.org
8
---
10
---
9
include/hw/arm/exynos4210.h | 2 ++
11
target/arm/cpu-param.h | 2 +-
10
include/hw/intc/exynos4210_gic.h | 43 ++++++++++++++++++++++++++++++++
12
target/arm/cpu.h | 7 ++++++-
11
hw/arm/exynos4210.c | 10 ++++----
13
target/arm/ptw.c | 19 +++++++++++++++++--
12
hw/intc/exynos4210_gic.c | 17 ++-----------
14
3 files changed, 24 insertions(+), 4 deletions(-)
13
MAINTAINERS | 2 +-
14
5 files changed, 53 insertions(+), 21 deletions(-)
15
create mode 100644 include/hw/intc/exynos4210_gic.h
16
15
17
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
16
diff --git a/target/arm/cpu-param.h b/target/arm/cpu-param.h
18
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
19
--- a/include/hw/arm/exynos4210.h
18
--- a/target/arm/cpu-param.h
20
+++ b/include/hw/arm/exynos4210.h
19
+++ b/target/arm/cpu-param.h
21
@@ -XXX,XX +XXX,XX @@
20
@@ -XXX,XX +XXX,XX @@
22
#include "hw/or-irq.h"
21
bool guarded;
23
#include "hw/sysbus.h"
22
#endif
24
#include "hw/cpu/a9mpcore.h"
23
25
+#include "hw/intc/exynos4210_gic.h"
24
-#define NB_MMU_MODES 8
26
#include "target/arm/cpu-qom.h"
25
+#define NB_MMU_MODES 10
27
#include "qom/object.h"
26
28
27
#endif
29
@@ -XXX,XX +XXX,XX @@ struct Exynos4210State {
28
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
30
qemu_or_irq pl330_irq_orgate[EXYNOS4210_NUM_DMA];
29
index XXXXXXX..XXXXXXX 100644
31
qemu_or_irq cpu_irq_orgate[EXYNOS4210_NCPUS];
30
--- a/target/arm/cpu.h
32
A9MPPrivState a9mpcore;
31
+++ b/target/arm/cpu.h
33
+ Exynos4210GicState ext_gic;
32
@@ -XXX,XX +XXX,XX @@ bool write_cpustate_to_list(ARMCPU *cpu, bool kvm_sync);
34
};
33
* EL2 EL2&0 +PAN
35
34
* EL2 (aka NS PL2)
36
#define TYPE_EXYNOS4210_SOC "exynos4210"
35
* EL3 (aka S PL1)
37
diff --git a/include/hw/intc/exynos4210_gic.h b/include/hw/intc/exynos4210_gic.h
36
+ * Physical (NS & S)
38
new file mode 100644
37
*
39
index XXXXXXX..XXXXXXX
38
- * for a total of 8 different mmu_idx.
40
--- /dev/null
39
+ * for a total of 10 different mmu_idx.
41
+++ b/include/hw/intc/exynos4210_gic.h
40
*
42
@@ -XXX,XX +XXX,XX @@
41
* R profile CPUs have an MPU, but can use the same set of MMU indexes
43
+/*
42
* as A profile. They only need to distinguish EL0 and EL1 (and
44
+ * Samsung exynos4210 GIC implementation. Based on hw/arm_gic.c
43
@@ -XXX,XX +XXX,XX @@ typedef enum ARMMMUIdx {
45
+ *
44
ARMMMUIdx_E2 = 6 | ARM_MMU_IDX_A,
46
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd.
45
ARMMMUIdx_E3 = 7 | ARM_MMU_IDX_A,
47
+ * All rights reserved.
46
48
+ *
47
+ /* TLBs with 1-1 mapping to the physical address spaces. */
49
+ * Evgeny Voevodin <e.voevodin@samsung.com>
48
+ ARMMMUIdx_Phys_NS = 8 | ARM_MMU_IDX_A,
50
+ *
49
+ ARMMMUIdx_Phys_S = 9 | ARM_MMU_IDX_A,
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
+
50
+
67
+#include "hw/sysbus.h"
51
/*
52
* These are not allocated TLBs and are used only for AT system
53
* instructions or for the first stage of an S12 page table walk.
54
diff --git a/target/arm/ptw.c b/target/arm/ptw.c
55
index XXXXXXX..XXXXXXX 100644
56
--- a/target/arm/ptw.c
57
+++ b/target/arm/ptw.c
58
@@ -XXX,XX +XXX,XX @@ static bool regime_translation_disabled(CPUARMState *env, ARMMMUIdx mmu_idx,
59
case ARMMMUIdx_E3:
60
break;
61
62
+ case ARMMMUIdx_Phys_NS:
63
+ case ARMMMUIdx_Phys_S:
64
+ /* No translation for physical address spaces. */
65
+ return true;
68
+
66
+
69
+#define TYPE_EXYNOS4210_GIC "exynos4210.gic"
67
default:
70
+OBJECT_DECLARE_SIMPLE_TYPE(Exynos4210GicState, EXYNOS4210_GIC)
68
g_assert_not_reached();
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
}
69
}
107
for (n = 0; n < EXYNOS4210_EXT_GIC_NIRQ; n++) {
70
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_disabled(CPUARMState *env, target_ulong address,
108
- s->irqs.ext_gic_irq[n] = qdev_get_gpio_in(dev, n);
71
{
109
+ s->irqs.ext_gic_irq[n] = qdev_get_gpio_in(DEVICE(&s->ext_gic), n);
72
uint8_t memattr = 0x00; /* Device nGnRnE */
73
uint8_t shareability = 0; /* non-sharable */
74
+ int r_el;
75
76
- if (mmu_idx != ARMMMUIdx_Stage2 && mmu_idx != ARMMMUIdx_Stage2_S) {
77
- int r_el = regime_el(env, mmu_idx);
78
+ switch (mmu_idx) {
79
+ case ARMMMUIdx_Stage2:
80
+ case ARMMMUIdx_Stage2_S:
81
+ case ARMMMUIdx_Phys_NS:
82
+ case ARMMMUIdx_Phys_S:
83
+ break;
84
85
+ default:
86
+ r_el = regime_el(env, mmu_idx);
87
if (arm_el_is_aa64(env, r_el)) {
88
int pamax = arm_pamax(env_archcpu(env));
89
uint64_t tcr = env->cp15.tcr_el[r_el];
90
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_disabled(CPUARMState *env, target_ulong address,
91
shareability = 2; /* outer sharable */
92
}
93
result->cacheattrs.is_s2_format = false;
94
+ break;
110
}
95
}
111
96
112
/* Internal Interrupt Combiner */
97
result->f.phys_addr = address;
113
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init(Object *obj)
98
@@ -XXX,XX +XXX,XX @@ bool get_phys_addr(CPUARMState *env, target_ulong address,
114
}
99
is_secure = arm_is_secure_below_el3(env);
115
100
break;
116
object_initialize_child(obj, "a9mpcore", &s->a9mpcore, TYPE_A9MPCORE_PRIV);
101
case ARMMMUIdx_Stage2:
117
+ object_initialize_child(obj, "ext-gic", &s->ext_gic, TYPE_EXYNOS4210_GIC);
102
+ case ARMMMUIdx_Phys_NS:
118
}
103
case ARMMMUIdx_MPrivNegPri:
119
104
case ARMMMUIdx_MUserNegPri:
120
static void exynos4210_class_init(ObjectClass *klass, void *data)
105
case ARMMMUIdx_MPriv:
121
diff --git a/hw/intc/exynos4210_gic.c b/hw/intc/exynos4210_gic.c
106
@@ -XXX,XX +XXX,XX @@ bool get_phys_addr(CPUARMState *env, target_ulong address,
122
index XXXXXXX..XXXXXXX 100644
107
break;
123
--- a/hw/intc/exynos4210_gic.c
108
case ARMMMUIdx_E3:
124
+++ b/hw/intc/exynos4210_gic.c
109
case ARMMMUIdx_Stage2_S:
125
@@ -XXX,XX +XXX,XX @@
110
+ case ARMMMUIdx_Phys_S:
126
#include "qemu/module.h"
111
case ARMMMUIdx_MSPrivNegPri:
127
#include "hw/irq.h"
112
case ARMMMUIdx_MSUserNegPri:
128
#include "hw/qdev-properties.h"
113
case ARMMMUIdx_MSPriv:
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
164
index XXXXXXX..XXXXXXX 100644
165
--- a/MAINTAINERS
166
+++ b/MAINTAINERS
167
@@ -XXX,XX +XXX,XX @@ M: Peter Maydell <peter.maydell@linaro.org>
168
L: qemu-arm@nongnu.org
169
S: Odd Fixes
170
F: hw/*/exynos*
171
-F: include/hw/arm/exynos4210.h
172
+F: include/hw/*/exynos*
173
174
Calxeda Highbank
175
M: Rob Herring <robh@kernel.org>
176
--
114
--
177
2.25.1
115
2.25.1
diff view generated by jsdifflib
1
From: "Edgar E. Iglesias" <edgar.iglesias@amd.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Add a model of the Xilinx Versal CRL.
3
We had been marking this ARM_MMU_IDX_NOTLB, move it to a real tlb.
4
Flush the tlb when invalidating stage 1+2 translations. Re-use
5
alle1_tlbmask() for other instances of EL1&0 + Stage2.
4
6
5
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Frederic Konrad <fkonrad@amd.com>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Francisco Iglesias <francisco.iglesias@amd.com>
9
Message-id: 20221011031911.2408754-6-richard.henderson@linaro.org
8
Message-id: 20220406174303.2022038-4-edgar.iglesias@xilinx.com
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
---
11
include/hw/misc/xlnx-versal-crl.h | 235 +++++++++++++++++
12
target/arm/cpu-param.h | 2 +-
12
hw/misc/xlnx-versal-crl.c | 421 ++++++++++++++++++++++++++++++
13
target/arm/cpu.h | 23 ++++---
13
hw/misc/meson.build | 1 +
14
target/arm/helper.c | 151 ++++++++++++++++++++++++++++++-----------
14
3 files changed, 657 insertions(+)
15
3 files changed, 127 insertions(+), 49 deletions(-)
15
create mode 100644 include/hw/misc/xlnx-versal-crl.h
16
create mode 100644 hw/misc/xlnx-versal-crl.c
17
16
18
diff --git a/include/hw/misc/xlnx-versal-crl.h b/include/hw/misc/xlnx-versal-crl.h
17
diff --git a/target/arm/cpu-param.h b/target/arm/cpu-param.h
19
new file mode 100644
18
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX
19
--- a/target/arm/cpu-param.h
21
--- /dev/null
20
+++ b/target/arm/cpu-param.h
22
+++ b/include/hw/misc/xlnx-versal-crl.h
23
@@ -XXX,XX +XXX,XX @@
21
@@ -XXX,XX +XXX,XX @@
24
+/*
22
bool guarded;
25
+ * QEMU model of the Clock-Reset-LPD (CRL).
23
#endif
26
+ *
24
27
+ * Copyright (c) 2022 Xilinx Inc.
25
-#define NB_MMU_MODES 10
28
+ * SPDX-License-Identifier: GPL-2.0-or-later
26
+#define NB_MMU_MODES 12
29
+ *
27
30
+ * Written by Edgar E. Iglesias <edgar.iglesias@xilinx.com>
28
#endif
31
+ */
29
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
32
+#ifndef HW_MISC_XLNX_VERSAL_CRL_H
30
index XXXXXXX..XXXXXXX 100644
33
+#define HW_MISC_XLNX_VERSAL_CRL_H
31
--- a/target/arm/cpu.h
34
+
32
+++ b/target/arm/cpu.h
35
+#include "hw/sysbus.h"
33
@@ -XXX,XX +XXX,XX @@ bool write_cpustate_to_list(ARMCPU *cpu, bool kvm_sync);
36
+#include "hw/register.h"
34
* EL2 (aka NS PL2)
37
+#include "target/arm/cpu.h"
35
* EL3 (aka S PL1)
38
+
36
* Physical (NS & S)
39
+#define TYPE_XLNX_VERSAL_CRL "xlnx,versal-crl"
37
+ * Stage2 (NS & S)
40
+OBJECT_DECLARE_SIMPLE_TYPE(XlnxVersalCRL, XLNX_VERSAL_CRL)
38
*
41
+
39
- * for a total of 10 different mmu_idx.
42
+REG32(ERR_CTRL, 0x0)
40
+ * for a total of 12 different mmu_idx.
43
+ FIELD(ERR_CTRL, SLVERR_ENABLE, 0, 1)
41
*
44
+REG32(IR_STATUS, 0x4)
42
* R profile CPUs have an MPU, but can use the same set of MMU indexes
45
+ FIELD(IR_STATUS, ADDR_DECODE_ERR, 0, 1)
43
* as A profile. They only need to distinguish EL0 and EL1 (and
46
+REG32(IR_MASK, 0x8)
44
@@ -XXX,XX +XXX,XX @@ typedef enum ARMMMUIdx {
47
+ FIELD(IR_MASK, ADDR_DECODE_ERR, 0, 1)
45
ARMMMUIdx_Phys_NS = 8 | ARM_MMU_IDX_A,
48
+REG32(IR_ENABLE, 0xc)
46
ARMMMUIdx_Phys_S = 9 | ARM_MMU_IDX_A,
49
+ FIELD(IR_ENABLE, ADDR_DECODE_ERR, 0, 1)
47
50
+REG32(IR_DISABLE, 0x10)
48
+ /*
51
+ FIELD(IR_DISABLE, ADDR_DECODE_ERR, 0, 1)
49
+ * Used for second stage of an S12 page table walk, or for descriptor
52
+REG32(WPROT, 0x1c)
50
+ * loads during first stage of an S1 page table walk. Note that both
53
+ FIELD(WPROT, ACTIVE, 0, 1)
51
+ * are in use simultaneously for SecureEL2: the security state for
54
+REG32(PLL_CLK_OTHER_DMN, 0x20)
52
+ * the S2 ptw is selected by the NS bit from the S1 ptw.
55
+ FIELD(PLL_CLK_OTHER_DMN, APLL_BYPASS, 0, 1)
53
+ */
56
+REG32(RPLL_CTRL, 0x40)
54
+ ARMMMUIdx_Stage2 = 10 | ARM_MMU_IDX_A,
57
+ FIELD(RPLL_CTRL, POST_SRC, 24, 3)
55
+ ARMMMUIdx_Stage2_S = 11 | ARM_MMU_IDX_A,
58
+ FIELD(RPLL_CTRL, PRE_SRC, 20, 3)
56
+
59
+ FIELD(RPLL_CTRL, CLKOUTDIV, 16, 2)
57
/*
60
+ FIELD(RPLL_CTRL, FBDIV, 8, 8)
58
* These are not allocated TLBs and are used only for AT system
61
+ FIELD(RPLL_CTRL, BYPASS, 3, 1)
59
* instructions or for the first stage of an S12 page table walk.
62
+ FIELD(RPLL_CTRL, RESET, 0, 1)
60
@@ -XXX,XX +XXX,XX @@ typedef enum ARMMMUIdx {
63
+REG32(RPLL_CFG, 0x44)
61
ARMMMUIdx_Stage1_E0 = 0 | ARM_MMU_IDX_NOTLB,
64
+ FIELD(RPLL_CFG, LOCK_DLY, 25, 7)
62
ARMMMUIdx_Stage1_E1 = 1 | ARM_MMU_IDX_NOTLB,
65
+ FIELD(RPLL_CFG, LOCK_CNT, 13, 10)
63
ARMMMUIdx_Stage1_E1_PAN = 2 | ARM_MMU_IDX_NOTLB,
66
+ FIELD(RPLL_CFG, LFHF, 10, 2)
64
- /*
67
+ FIELD(RPLL_CFG, CP, 5, 4)
65
- * Not allocated a TLB: used only for second stage of an S12 page
68
+ FIELD(RPLL_CFG, RES, 0, 4)
66
- * table walk, or for descriptor loads during first stage of an S1
69
+REG32(RPLL_FRAC_CFG, 0x48)
67
- * page table walk. Note that if we ever want to have a TLB for this
70
+ FIELD(RPLL_FRAC_CFG, ENABLED, 31, 1)
68
- * then various TLB flush insns which currently are no-ops or flush
71
+ FIELD(RPLL_FRAC_CFG, SEED, 22, 3)
69
- * only stage 1 MMU indexes will need to change to flush stage 2.
72
+ FIELD(RPLL_FRAC_CFG, ALGRTHM, 19, 1)
70
- */
73
+ FIELD(RPLL_FRAC_CFG, ORDER, 18, 1)
71
- ARMMMUIdx_Stage2 = 3 | ARM_MMU_IDX_NOTLB,
74
+ FIELD(RPLL_FRAC_CFG, DATA, 0, 16)
72
- ARMMMUIdx_Stage2_S = 4 | ARM_MMU_IDX_NOTLB,
75
+REG32(PLL_STATUS, 0x50)
73
76
+ FIELD(PLL_STATUS, RPLL_STABLE, 2, 1)
74
/*
77
+ FIELD(PLL_STATUS, RPLL_LOCK, 0, 1)
75
* M-profile.
78
+REG32(RPLL_TO_XPD_CTRL, 0x100)
76
@@ -XXX,XX +XXX,XX @@ typedef enum ARMMMUIdxBit {
79
+ FIELD(RPLL_TO_XPD_CTRL, CLKACT, 25, 1)
77
TO_CORE_BIT(E20_2),
80
+ FIELD(RPLL_TO_XPD_CTRL, DIVISOR0, 8, 10)
78
TO_CORE_BIT(E20_2_PAN),
81
+REG32(LPD_TOP_SWITCH_CTRL, 0x104)
79
TO_CORE_BIT(E3),
82
+ FIELD(LPD_TOP_SWITCH_CTRL, CLKACT_ADMA, 26, 1)
80
+ TO_CORE_BIT(Stage2),
83
+ FIELD(LPD_TOP_SWITCH_CTRL, CLKACT, 25, 1)
81
+ TO_CORE_BIT(Stage2_S),
84
+ FIELD(LPD_TOP_SWITCH_CTRL, DIVISOR0, 8, 10)
82
85
+ FIELD(LPD_TOP_SWITCH_CTRL, SRCSEL, 0, 3)
83
TO_CORE_BIT(MUser),
86
+REG32(LPD_LSBUS_CTRL, 0x108)
84
TO_CORE_BIT(MPriv),
87
+ FIELD(LPD_LSBUS_CTRL, CLKACT, 25, 1)
85
diff --git a/target/arm/helper.c b/target/arm/helper.c
88
+ FIELD(LPD_LSBUS_CTRL, DIVISOR0, 8, 10)
86
index XXXXXXX..XXXXXXX 100644
89
+ FIELD(LPD_LSBUS_CTRL, SRCSEL, 0, 3)
87
--- a/target/arm/helper.c
90
+REG32(CPU_R5_CTRL, 0x10c)
88
+++ b/target/arm/helper.c
91
+ FIELD(CPU_R5_CTRL, CLKACT_OCM2, 28, 1)
89
@@ -XXX,XX +XXX,XX @@ static void contextidr_write(CPUARMState *env, const ARMCPRegInfo *ri,
92
+ FIELD(CPU_R5_CTRL, CLKACT_OCM, 27, 1)
90
raw_write(env, ri, value);
93
+ FIELD(CPU_R5_CTRL, CLKACT_CORE, 26, 1)
91
}
94
+ FIELD(CPU_R5_CTRL, CLKACT, 25, 1)
92
95
+ FIELD(CPU_R5_CTRL, DIVISOR0, 8, 10)
93
+static int alle1_tlbmask(CPUARMState *env)
96
+ FIELD(CPU_R5_CTRL, SRCSEL, 0, 3)
94
+{
97
+REG32(IOU_SWITCH_CTRL, 0x114)
95
+ /*
98
+ FIELD(IOU_SWITCH_CTRL, CLKACT, 25, 1)
96
+ * Note that the 'ALL' scope must invalidate both stage 1 and
99
+ FIELD(IOU_SWITCH_CTRL, DIVISOR0, 8, 10)
97
+ * stage 2 translations, whereas most other scopes only invalidate
100
+ FIELD(IOU_SWITCH_CTRL, SRCSEL, 0, 3)
98
+ * stage 1 translations.
101
+REG32(GEM0_REF_CTRL, 0x118)
99
+ */
102
+ FIELD(GEM0_REF_CTRL, CLKACT_RX, 27, 1)
100
+ return (ARMMMUIdxBit_E10_1 |
103
+ FIELD(GEM0_REF_CTRL, CLKACT_TX, 26, 1)
101
+ ARMMMUIdxBit_E10_1_PAN |
104
+ FIELD(GEM0_REF_CTRL, CLKACT, 25, 1)
102
+ ARMMMUIdxBit_E10_0 |
105
+ FIELD(GEM0_REF_CTRL, DIVISOR0, 8, 10)
103
+ ARMMMUIdxBit_Stage2 |
106
+ FIELD(GEM0_REF_CTRL, SRCSEL, 0, 3)
104
+ ARMMMUIdxBit_Stage2_S);
107
+REG32(GEM1_REF_CTRL, 0x11c)
105
+}
108
+ FIELD(GEM1_REF_CTRL, CLKACT_RX, 27, 1)
106
+
109
+ FIELD(GEM1_REF_CTRL, CLKACT_TX, 26, 1)
107
+
110
+ FIELD(GEM1_REF_CTRL, CLKACT, 25, 1)
108
/* IS variants of TLB operations must affect all cores */
111
+ FIELD(GEM1_REF_CTRL, DIVISOR0, 8, 10)
109
static void tlbiall_is_write(CPUARMState *env, const ARMCPRegInfo *ri,
112
+ FIELD(GEM1_REF_CTRL, SRCSEL, 0, 3)
110
uint64_t value)
113
+REG32(GEM_TSU_REF_CTRL, 0x120)
111
@@ -XXX,XX +XXX,XX @@ static void tlbiall_nsnh_write(CPUARMState *env, const ARMCPRegInfo *ri,
114
+ FIELD(GEM_TSU_REF_CTRL, CLKACT, 25, 1)
112
{
115
+ FIELD(GEM_TSU_REF_CTRL, DIVISOR0, 8, 10)
113
CPUState *cs = env_cpu(env);
116
+ FIELD(GEM_TSU_REF_CTRL, SRCSEL, 0, 3)
114
117
+REG32(USB0_BUS_REF_CTRL, 0x124)
115
- tlb_flush_by_mmuidx(cs,
118
+ FIELD(USB0_BUS_REF_CTRL, CLKACT, 25, 1)
116
- ARMMMUIdxBit_E10_1 |
119
+ FIELD(USB0_BUS_REF_CTRL, DIVISOR0, 8, 10)
117
- ARMMMUIdxBit_E10_1_PAN |
120
+ FIELD(USB0_BUS_REF_CTRL, SRCSEL, 0, 3)
118
- ARMMMUIdxBit_E10_0);
121
+REG32(UART0_REF_CTRL, 0x128)
119
+ tlb_flush_by_mmuidx(cs, alle1_tlbmask(env));
122
+ FIELD(UART0_REF_CTRL, CLKACT, 25, 1)
120
}
123
+ FIELD(UART0_REF_CTRL, DIVISOR0, 8, 10)
121
124
+ FIELD(UART0_REF_CTRL, SRCSEL, 0, 3)
122
static void tlbiall_nsnh_is_write(CPUARMState *env, const ARMCPRegInfo *ri,
125
+REG32(UART1_REF_CTRL, 0x12c)
123
@@ -XXX,XX +XXX,XX @@ static void tlbiall_nsnh_is_write(CPUARMState *env, const ARMCPRegInfo *ri,
126
+ FIELD(UART1_REF_CTRL, CLKACT, 25, 1)
124
{
127
+ FIELD(UART1_REF_CTRL, DIVISOR0, 8, 10)
125
CPUState *cs = env_cpu(env);
128
+ FIELD(UART1_REF_CTRL, SRCSEL, 0, 3)
126
129
+REG32(SPI0_REF_CTRL, 0x130)
127
- tlb_flush_by_mmuidx_all_cpus_synced(cs,
130
+ FIELD(SPI0_REF_CTRL, CLKACT, 25, 1)
128
- ARMMMUIdxBit_E10_1 |
131
+ FIELD(SPI0_REF_CTRL, DIVISOR0, 8, 10)
129
- ARMMMUIdxBit_E10_1_PAN |
132
+ FIELD(SPI0_REF_CTRL, SRCSEL, 0, 3)
130
- ARMMMUIdxBit_E10_0);
133
+REG32(SPI1_REF_CTRL, 0x134)
131
+ tlb_flush_by_mmuidx_all_cpus_synced(cs, alle1_tlbmask(env));
134
+ FIELD(SPI1_REF_CTRL, CLKACT, 25, 1)
132
}
135
+ FIELD(SPI1_REF_CTRL, DIVISOR0, 8, 10)
133
136
+ FIELD(SPI1_REF_CTRL, SRCSEL, 0, 3)
134
137
+REG32(CAN0_REF_CTRL, 0x138)
135
@@ -XXX,XX +XXX,XX @@ static void tlbimva_hyp_is_write(CPUARMState *env, const ARMCPRegInfo *ri,
138
+ FIELD(CAN0_REF_CTRL, CLKACT, 25, 1)
136
ARMMMUIdxBit_E2);
139
+ FIELD(CAN0_REF_CTRL, DIVISOR0, 8, 10)
137
}
140
+ FIELD(CAN0_REF_CTRL, SRCSEL, 0, 3)
138
141
+REG32(CAN1_REF_CTRL, 0x13c)
139
+static void tlbiipas2_hyp_write(CPUARMState *env, const ARMCPRegInfo *ri,
142
+ FIELD(CAN1_REF_CTRL, CLKACT, 25, 1)
140
+ uint64_t value)
143
+ FIELD(CAN1_REF_CTRL, DIVISOR0, 8, 10)
141
+{
144
+ FIELD(CAN1_REF_CTRL, SRCSEL, 0, 3)
142
+ CPUState *cs = env_cpu(env);
145
+REG32(I2C0_REF_CTRL, 0x140)
143
+ uint64_t pageaddr = (value & MAKE_64BIT_MASK(0, 28)) << 12;
146
+ FIELD(I2C0_REF_CTRL, CLKACT, 25, 1)
144
+
147
+ FIELD(I2C0_REF_CTRL, DIVISOR0, 8, 10)
145
+ tlb_flush_page_by_mmuidx(cs, pageaddr, ARMMMUIdxBit_Stage2);
148
+ FIELD(I2C0_REF_CTRL, SRCSEL, 0, 3)
146
+}
149
+REG32(I2C1_REF_CTRL, 0x144)
147
+
150
+ FIELD(I2C1_REF_CTRL, CLKACT, 25, 1)
148
+static void tlbiipas2is_hyp_write(CPUARMState *env, const ARMCPRegInfo *ri,
151
+ FIELD(I2C1_REF_CTRL, DIVISOR0, 8, 10)
149
+ uint64_t value)
152
+ FIELD(I2C1_REF_CTRL, SRCSEL, 0, 3)
150
+{
153
+REG32(DBG_LPD_CTRL, 0x148)
151
+ CPUState *cs = env_cpu(env);
154
+ FIELD(DBG_LPD_CTRL, CLKACT, 25, 1)
152
+ uint64_t pageaddr = (value & MAKE_64BIT_MASK(0, 28)) << 12;
155
+ FIELD(DBG_LPD_CTRL, DIVISOR0, 8, 10)
153
+
156
+ FIELD(DBG_LPD_CTRL, SRCSEL, 0, 3)
154
+ tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr, ARMMMUIdxBit_Stage2);
157
+REG32(TIMESTAMP_REF_CTRL, 0x14c)
155
+}
158
+ FIELD(TIMESTAMP_REF_CTRL, CLKACT, 25, 1)
156
+
159
+ FIELD(TIMESTAMP_REF_CTRL, DIVISOR0, 8, 10)
157
static const ARMCPRegInfo cp_reginfo[] = {
160
+ FIELD(TIMESTAMP_REF_CTRL, SRCSEL, 0, 3)
158
/* Define the secure and non-secure FCSE identifier CP registers
161
+REG32(CRL_SAFETY_CHK, 0x150)
159
* separately because there is no secure bank in V8 (no _EL3). This allows
162
+REG32(PSM_REF_CTRL, 0x154)
160
@@ -XXX,XX +XXX,XX @@ static void vttbr_write(CPUARMState *env, const ARMCPRegInfo *ri,
163
+ FIELD(PSM_REF_CTRL, DIVISOR0, 8, 10)
161
164
+ FIELD(PSM_REF_CTRL, SRCSEL, 0, 3)
162
/*
165
+REG32(DBG_TSTMP_CTRL, 0x158)
163
* A change in VMID to the stage2 page table (Stage2) invalidates
166
+ FIELD(DBG_TSTMP_CTRL, CLKACT, 25, 1)
164
- * the combined stage 1&2 tlbs (EL10_1 and EL10_0).
167
+ FIELD(DBG_TSTMP_CTRL, DIVISOR0, 8, 10)
165
+ * the stage2 and combined stage 1&2 tlbs (EL10_1 and EL10_0).
168
+ FIELD(DBG_TSTMP_CTRL, SRCSEL, 0, 3)
166
*/
169
+REG32(CPM_TOPSW_REF_CTRL, 0x15c)
167
if (raw_read(env, ri) != value) {
170
+ FIELD(CPM_TOPSW_REF_CTRL, CLKACT, 25, 1)
168
- uint16_t mask = ARMMMUIdxBit_E10_1 |
171
+ FIELD(CPM_TOPSW_REF_CTRL, DIVISOR0, 8, 10)
169
- ARMMMUIdxBit_E10_1_PAN |
172
+ FIELD(CPM_TOPSW_REF_CTRL, SRCSEL, 0, 3)
170
- ARMMMUIdxBit_E10_0;
173
+REG32(USB3_DUAL_REF_CTRL, 0x160)
171
- tlb_flush_by_mmuidx(cs, mask);
174
+ FIELD(USB3_DUAL_REF_CTRL, CLKACT, 25, 1)
172
+ tlb_flush_by_mmuidx(cs, alle1_tlbmask(env));
175
+ FIELD(USB3_DUAL_REF_CTRL, DIVISOR0, 8, 10)
173
raw_write(env, ri, value);
176
+ FIELD(USB3_DUAL_REF_CTRL, SRCSEL, 0, 3)
174
}
177
+REG32(RST_CPU_R5, 0x300)
175
}
178
+ FIELD(RST_CPU_R5, RESET_PGE, 4, 1)
176
@@ -XXX,XX +XXX,XX @@ static void tlbi_aa64_vmalle1_write(CPUARMState *env, const ARMCPRegInfo *ri,
179
+ FIELD(RST_CPU_R5, RESET_AMBA, 2, 1)
177
}
180
+ FIELD(RST_CPU_R5, RESET_CPU1, 1, 1)
178
}
181
+ FIELD(RST_CPU_R5, RESET_CPU0, 0, 1)
179
182
+REG32(RST_ADMA, 0x304)
180
-static int alle1_tlbmask(CPUARMState *env)
183
+ FIELD(RST_ADMA, RESET, 0, 1)
181
-{
184
+REG32(RST_GEM0, 0x308)
182
- /*
185
+ FIELD(RST_GEM0, RESET, 0, 1)
183
- * Note that the 'ALL' scope must invalidate both stage 1 and
186
+REG32(RST_GEM1, 0x30c)
184
- * stage 2 translations, whereas most other scopes only invalidate
187
+ FIELD(RST_GEM1, RESET, 0, 1)
185
- * stage 1 translations.
188
+REG32(RST_SPARE, 0x310)
186
- */
189
+ FIELD(RST_SPARE, RESET, 0, 1)
187
- return (ARMMMUIdxBit_E10_1 |
190
+REG32(RST_USB0, 0x314)
188
- ARMMMUIdxBit_E10_1_PAN |
191
+ FIELD(RST_USB0, RESET, 0, 1)
189
- ARMMMUIdxBit_E10_0);
192
+REG32(RST_UART0, 0x318)
190
-}
193
+ FIELD(RST_UART0, RESET, 0, 1)
191
-
194
+REG32(RST_UART1, 0x31c)
192
static int e2_tlbmask(CPUARMState *env)
195
+ FIELD(RST_UART1, RESET, 0, 1)
193
{
196
+REG32(RST_SPI0, 0x320)
194
return (ARMMMUIdxBit_E20_0 |
197
+ FIELD(RST_SPI0, RESET, 0, 1)
195
@@ -XXX,XX +XXX,XX @@ static void tlbi_aa64_vae3is_write(CPUARMState *env, const ARMCPRegInfo *ri,
198
+REG32(RST_SPI1, 0x324)
196
ARMMMUIdxBit_E3, bits);
199
+ FIELD(RST_SPI1, RESET, 0, 1)
197
}
200
+REG32(RST_CAN0, 0x328)
198
201
+ FIELD(RST_CAN0, RESET, 0, 1)
199
+static int ipas2e1_tlbmask(CPUARMState *env, int64_t value)
202
+REG32(RST_CAN1, 0x32c)
200
+{
203
+ FIELD(RST_CAN1, RESET, 0, 1)
201
+ /*
204
+REG32(RST_I2C0, 0x330)
202
+ * The MSB of value is the NS field, which only applies if SEL2
205
+ FIELD(RST_I2C0, RESET, 0, 1)
203
+ * is implemented and SCR_EL3.NS is not set (i.e. in secure mode).
206
+REG32(RST_I2C1, 0x334)
204
+ */
207
+ FIELD(RST_I2C1, RESET, 0, 1)
205
+ return (value >= 0
208
+REG32(RST_DBG_LPD, 0x338)
206
+ && cpu_isar_feature(aa64_sel2, env_archcpu(env))
209
+ FIELD(RST_DBG_LPD, RPU_DBG1_RESET, 5, 1)
207
+ && arm_is_secure_below_el3(env)
210
+ FIELD(RST_DBG_LPD, RPU_DBG0_RESET, 4, 1)
208
+ ? ARMMMUIdxBit_Stage2_S
211
+ FIELD(RST_DBG_LPD, RESET_HSDP, 1, 1)
209
+ : ARMMMUIdxBit_Stage2);
212
+ FIELD(RST_DBG_LPD, RESET, 0, 1)
210
+}
213
+REG32(RST_GPIO, 0x33c)
211
+
214
+ FIELD(RST_GPIO, RESET, 0, 1)
212
+static void tlbi_aa64_ipas2e1_write(CPUARMState *env, const ARMCPRegInfo *ri,
215
+REG32(RST_TTC, 0x344)
213
+ uint64_t value)
216
+ FIELD(RST_TTC, TTC3_RESET, 3, 1)
214
+{
217
+ FIELD(RST_TTC, TTC2_RESET, 2, 1)
215
+ CPUState *cs = env_cpu(env);
218
+ FIELD(RST_TTC, TTC1_RESET, 1, 1)
216
+ int mask = ipas2e1_tlbmask(env, value);
219
+ FIELD(RST_TTC, TTC0_RESET, 0, 1)
217
+ uint64_t pageaddr = sextract64(value << 12, 0, 56);
220
+REG32(RST_TIMESTAMP, 0x348)
218
+
221
+ FIELD(RST_TIMESTAMP, RESET, 0, 1)
219
+ if (tlb_force_broadcast(env)) {
222
+REG32(RST_SWDT, 0x34c)
220
+ tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr, mask);
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
+}
297
+
298
+static void crl_status_postw(RegisterInfo *reg, uint64_t val64)
299
+{
300
+ XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque);
301
+ crl_update_irq(s);
302
+}
303
+
304
+static uint64_t crl_enable_prew(RegisterInfo *reg, uint64_t val64)
305
+{
306
+ XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque);
307
+ uint32_t val = val64;
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 {
221
+ } else {
336
+ arm_set_cpu_on_and_reset(armcpu->mp_affinity);
222
+ tlb_flush_page_by_mmuidx(cs, pageaddr, mask);
337
+ }
223
+ }
338
+}
224
+}
339
+
225
+
340
+#define REGFIELD_RESET(type, s, reg, f, new_val, dev) { \
226
+static void tlbi_aa64_ipas2e1is_write(CPUARMState *env, const ARMCPRegInfo *ri,
341
+ bool old_f = ARRAY_FIELD_EX32((s)->regs, reg, f); \
227
+ uint64_t value)
342
+ bool new_f = FIELD_EX32(new_val, reg, f); \
228
+{
343
+ \
229
+ CPUState *cs = env_cpu(env);
344
+ /* Detect edges. */ \
230
+ int mask = ipas2e1_tlbmask(env, value);
345
+ if (dev && old_f != new_f) { \
231
+ uint64_t pageaddr = sextract64(value << 12, 0, 56);
346
+ crl_reset_ ## type(s, dev, old_f, new_f); \
232
+
347
+ } \
233
+ tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr, mask);
348
+}
234
+}
349
+
235
+
350
+static uint64_t crl_rst_r5_prew(RegisterInfo *reg, uint64_t val64)
236
#ifdef TARGET_AARCH64
351
+{
237
typedef struct {
352
+ XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque);
238
uint64_t base;
353
+
239
@@ -XXX,XX +XXX,XX @@ static void tlbi_aa64_rvae3is_write(CPUARMState *env,
354
+ REGFIELD_RESET(cpu, s, RST_CPU_R5, RESET_CPU0, val64, s->cfg.cpu_r5[0]);
240
355
+ REGFIELD_RESET(cpu, s, RST_CPU_R5, RESET_CPU1, val64, s->cfg.cpu_r5[1]);
241
do_rvae_write(env, value, ARMMMUIdxBit_E3, true);
356
+ return val64;
242
}
357
+}
243
+
358
+
244
+static void tlbi_aa64_ripas2e1_write(CPUARMState *env, const ARMCPRegInfo *ri,
359
+static uint64_t crl_rst_adma_prew(RegisterInfo *reg, uint64_t val64)
245
+ uint64_t value)
360
+{
246
+{
361
+ XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque);
247
+ do_rvae_write(env, value, ipas2e1_tlbmask(env, value),
362
+ int i;
248
+ tlb_force_broadcast(env));
363
+
249
+}
364
+ /* A single register fans out to all ADMA reset inputs. */
250
+
365
+ for (i = 0; i < ARRAY_SIZE(s->cfg.adma); i++) {
251
+static void tlbi_aa64_ripas2e1is_write(CPUARMState *env,
366
+ REGFIELD_RESET(dev, s, RST_ADMA, RESET, val64, s->cfg.adma[i]);
252
+ const ARMCPRegInfo *ri,
367
+ }
253
+ uint64_t value)
368
+ return val64;
254
+{
369
+}
255
+ do_rvae_write(env, value, ipas2e1_tlbmask(env, value), true);
370
+
256
+}
371
+static uint64_t crl_rst_uart0_prew(RegisterInfo *reg, uint64_t val64)
257
#endif
372
+{
258
373
+ XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque);
259
static CPAccessResult aa64_zva_access(CPUARMState *env, const ARMCPRegInfo *ri,
374
+
260
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo v8_cp_reginfo[] = {
375
+ REGFIELD_RESET(dev, s, RST_UART0, RESET, val64, s->cfg.uart[0]);
261
.writefn = tlbi_aa64_vae1_write },
376
+ return val64;
262
{ .name = "TLBI_IPAS2E1IS", .state = ARM_CP_STATE_AA64,
377
+}
263
.opc0 = 1, .opc1 = 4, .crn = 8, .crm = 0, .opc2 = 1,
378
+
264
- .access = PL2_W, .type = ARM_CP_NOP },
379
+static uint64_t crl_rst_uart1_prew(RegisterInfo *reg, uint64_t val64)
265
+ .access = PL2_W, .type = ARM_CP_NO_RAW,
380
+{
266
+ .writefn = tlbi_aa64_ipas2e1is_write },
381
+ XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque);
267
{ .name = "TLBI_IPAS2LE1IS", .state = ARM_CP_STATE_AA64,
382
+
268
.opc0 = 1, .opc1 = 4, .crn = 8, .crm = 0, .opc2 = 5,
383
+ REGFIELD_RESET(dev, s, RST_UART1, RESET, val64, s->cfg.uart[1]);
269
- .access = PL2_W, .type = ARM_CP_NOP },
384
+ return val64;
270
+ .access = PL2_W, .type = ARM_CP_NO_RAW,
385
+}
271
+ .writefn = tlbi_aa64_ipas2e1is_write },
386
+
272
{ .name = "TLBI_ALLE1IS", .state = ARM_CP_STATE_AA64,
387
+static uint64_t crl_rst_gem0_prew(RegisterInfo *reg, uint64_t val64)
273
.opc0 = 1, .opc1 = 4, .crn = 8, .crm = 3, .opc2 = 4,
388
+{
274
.access = PL2_W, .type = ARM_CP_NO_RAW,
389
+ XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque);
275
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo v8_cp_reginfo[] = {
390
+
276
.writefn = tlbi_aa64_alle1is_write },
391
+ REGFIELD_RESET(dev, s, RST_GEM0, RESET, val64, s->cfg.gem[0]);
277
{ .name = "TLBI_IPAS2E1", .state = ARM_CP_STATE_AA64,
392
+ return val64;
278
.opc0 = 1, .opc1 = 4, .crn = 8, .crm = 4, .opc2 = 1,
393
+}
279
- .access = PL2_W, .type = ARM_CP_NOP },
394
+
280
+ .access = PL2_W, .type = ARM_CP_NO_RAW,
395
+static uint64_t crl_rst_gem1_prew(RegisterInfo *reg, uint64_t val64)
281
+ .writefn = tlbi_aa64_ipas2e1_write },
396
+{
282
{ .name = "TLBI_IPAS2LE1", .state = ARM_CP_STATE_AA64,
397
+ XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque);
283
.opc0 = 1, .opc1 = 4, .crn = 8, .crm = 4, .opc2 = 5,
398
+
284
- .access = PL2_W, .type = ARM_CP_NOP },
399
+ REGFIELD_RESET(dev, s, RST_GEM1, RESET, val64, s->cfg.gem[1]);
285
+ .access = PL2_W, .type = ARM_CP_NO_RAW,
400
+ return val64;
286
+ .writefn = tlbi_aa64_ipas2e1_write },
401
+}
287
{ .name = "TLBI_ALLE1", .state = ARM_CP_STATE_AA64,
402
+
288
.opc0 = 1, .opc1 = 4, .crn = 8, .crm = 7, .opc2 = 4,
403
+static uint64_t crl_rst_usb_prew(RegisterInfo *reg, uint64_t val64)
289
.access = PL2_W, .type = ARM_CP_NO_RAW,
404
+{
290
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo v8_cp_reginfo[] = {
405
+ XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque);
291
.writefn = tlbimva_hyp_is_write },
406
+
292
{ .name = "TLBIIPAS2",
407
+ REGFIELD_RESET(dev, s, RST_USB0, RESET, val64, s->cfg.usb);
293
.cp = 15, .opc1 = 4, .crn = 8, .crm = 4, .opc2 = 1,
408
+ return val64;
294
- .type = ARM_CP_NOP, .access = PL2_W },
409
+}
295
+ .type = ARM_CP_NO_RAW, .access = PL2_W,
410
+
296
+ .writefn = tlbiipas2_hyp_write },
411
+static const RegisterAccessInfo crl_regs_info[] = {
297
{ .name = "TLBIIPAS2IS",
412
+ { .name = "ERR_CTRL", .addr = A_ERR_CTRL,
298
.cp = 15, .opc1 = 4, .crn = 8, .crm = 0, .opc2 = 1,
413
+ },{ .name = "IR_STATUS", .addr = A_IR_STATUS,
299
- .type = ARM_CP_NOP, .access = PL2_W },
414
+ .w1c = 0x1,
300
+ .type = ARM_CP_NO_RAW, .access = PL2_W,
415
+ .post_write = crl_status_postw,
301
+ .writefn = tlbiipas2is_hyp_write },
416
+ },{ .name = "IR_MASK", .addr = A_IR_MASK,
302
{ .name = "TLBIIPAS2L",
417
+ .reset = 0x1,
303
.cp = 15, .opc1 = 4, .crn = 8, .crm = 4, .opc2 = 5,
418
+ .ro = 0x1,
304
- .type = ARM_CP_NOP, .access = PL2_W },
419
+ },{ .name = "IR_ENABLE", .addr = A_IR_ENABLE,
305
+ .type = ARM_CP_NO_RAW, .access = PL2_W,
420
+ .pre_write = crl_enable_prew,
306
+ .writefn = tlbiipas2_hyp_write },
421
+ },{ .name = "IR_DISABLE", .addr = A_IR_DISABLE,
307
{ .name = "TLBIIPAS2LIS",
422
+ .pre_write = crl_disable_prew,
308
.cp = 15, .opc1 = 4, .crn = 8, .crm = 0, .opc2 = 5,
423
+ },{ .name = "WPROT", .addr = A_WPROT,
309
- .type = ARM_CP_NOP, .access = PL2_W },
424
+ },{ .name = "PLL_CLK_OTHER_DMN", .addr = A_PLL_CLK_OTHER_DMN,
310
+ .type = ARM_CP_NO_RAW, .access = PL2_W,
425
+ .reset = 0x1,
311
+ .writefn = tlbiipas2is_hyp_write },
426
+ .rsvd = 0xe,
312
/* 32 bit cache operations */
427
+ },{ .name = "RPLL_CTRL", .addr = A_RPLL_CTRL,
313
{ .name = "ICIALLUIS", .cp = 15, .opc1 = 0, .crn = 7, .crm = 1, .opc2 = 0,
428
+ .reset = 0x24809,
314
.type = ARM_CP_NOP, .access = PL1_W, .accessfn = aa64_cacheop_pou_access },
429
+ .rsvd = 0xf88c00f6,
315
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo tlbirange_reginfo[] = {
430
+ },{ .name = "RPLL_CFG", .addr = A_RPLL_CFG,
316
.writefn = tlbi_aa64_rvae1_write },
431
+ .reset = 0x2000000,
317
{ .name = "TLBI_RIPAS2E1IS", .state = ARM_CP_STATE_AA64,
432
+ .rsvd = 0x1801210,
318
.opc0 = 1, .opc1 = 4, .crn = 8, .crm = 0, .opc2 = 2,
433
+ },{ .name = "RPLL_FRAC_CFG", .addr = A_RPLL_FRAC_CFG,
319
- .access = PL2_W, .type = ARM_CP_NOP },
434
+ .rsvd = 0x7e330000,
320
+ .access = PL2_W, .type = ARM_CP_NO_RAW,
435
+ },{ .name = "PLL_STATUS", .addr = A_PLL_STATUS,
321
+ .writefn = tlbi_aa64_ripas2e1is_write },
436
+ .reset = R_PLL_STATUS_RPLL_STABLE_MASK |
322
{ .name = "TLBI_RIPAS2LE1IS", .state = ARM_CP_STATE_AA64,
437
+ R_PLL_STATUS_RPLL_LOCK_MASK,
323
.opc0 = 1, .opc1 = 4, .crn = 8, .crm = 0, .opc2 = 6,
438
+ .rsvd = 0xfa,
324
- .access = PL2_W, .type = ARM_CP_NOP },
439
+ .ro = 0x5,
325
+ .access = PL2_W, .type = ARM_CP_NO_RAW,
440
+ },{ .name = "RPLL_TO_XPD_CTRL", .addr = A_RPLL_TO_XPD_CTRL,
326
+ .writefn = tlbi_aa64_ripas2e1is_write },
441
+ .reset = 0x2000100,
327
{ .name = "TLBI_RVAE2IS", .state = ARM_CP_STATE_AA64,
442
+ .rsvd = 0xfdfc00ff,
328
.opc0 = 1, .opc1 = 4, .crn = 8, .crm = 2, .opc2 = 1,
443
+ },{ .name = "LPD_TOP_SWITCH_CTRL", .addr = A_LPD_TOP_SWITCH_CTRL,
329
.access = PL2_W, .type = ARM_CP_NO_RAW | ARM_CP_EL3_NO_EL2_UNDEF,
444
+ .reset = 0x6000300,
330
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo tlbirange_reginfo[] = {
445
+ .rsvd = 0xf9fc00f8,
331
.writefn = tlbi_aa64_rvae2is_write },
446
+ },{ .name = "LPD_LSBUS_CTRL", .addr = A_LPD_LSBUS_CTRL,
332
{ .name = "TLBI_RIPAS2E1", .state = ARM_CP_STATE_AA64,
447
+ .reset = 0x2000800,
333
.opc0 = 1, .opc1 = 4, .crn = 8, .crm = 4, .opc2 = 2,
448
+ .rsvd = 0xfdfc00f8,
334
- .access = PL2_W, .type = ARM_CP_NOP },
449
+ },{ .name = "CPU_R5_CTRL", .addr = A_CPU_R5_CTRL,
335
- { .name = "TLBI_RIPAS2LE1", .state = ARM_CP_STATE_AA64,
450
+ .reset = 0xe000300,
336
+ .access = PL2_W, .type = ARM_CP_NO_RAW,
451
+ .rsvd = 0xe1fc00f8,
337
+ .writefn = tlbi_aa64_ripas2e1_write },
452
+ },{ .name = "IOU_SWITCH_CTRL", .addr = A_IOU_SWITCH_CTRL,
338
+ { .name = "TLBI_RIPAS2LE1", .state = ARM_CP_STATE_AA64,
453
+ .reset = 0x2000500,
339
.opc0 = 1, .opc1 = 4, .crn = 8, .crm = 4, .opc2 = 6,
454
+ .rsvd = 0xfdfc00f8,
340
- .access = PL2_W, .type = ARM_CP_NOP },
455
+ },{ .name = "GEM0_REF_CTRL", .addr = A_GEM0_REF_CTRL,
341
+ .access = PL2_W, .type = ARM_CP_NO_RAW,
456
+ .reset = 0xe000a00,
342
+ .writefn = tlbi_aa64_ripas2e1_write },
457
+ .rsvd = 0xf1fc00f8,
343
{ .name = "TLBI_RVAE2OS", .state = ARM_CP_STATE_AA64,
458
+ },{ .name = "GEM1_REF_CTRL", .addr = A_GEM1_REF_CTRL,
344
.opc0 = 1, .opc1 = 4, .crn = 8, .crm = 5, .opc2 = 1,
459
+ .reset = 0xe000a00,
345
.access = PL2_W, .type = ARM_CP_NO_RAW | ARM_CP_EL3_NO_EL2_UNDEF,
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
688
--- a/hw/misc/meson.build
689
+++ b/hw/misc/meson.build
690
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_SLAVIO', if_true: files('slavio_misc.c'))
691
softmmu_ss.add(when: 'CONFIG_ZYNQ', if_true: files('zynq_slcr.c'))
692
specific_ss.add(when: 'CONFIG_XLNX_ZYNQMP_ARM', if_true: files('xlnx-zynqmp-crf.c'))
693
specific_ss.add(when: 'CONFIG_XLNX_ZYNQMP_ARM', if_true: files('xlnx-zynqmp-apu-ctrl.c'))
694
+specific_ss.add(when: 'CONFIG_XLNX_VERSAL', if_true: files('xlnx-versal-crl.c'))
695
softmmu_ss.add(when: 'CONFIG_XLNX_VERSAL', if_true: files(
696
'xlnx-versal-xramc.c',
697
'xlnx-versal-pmc-iou-slcr.c',
698
--
346
--
699
2.25.1
347
2.25.1
diff view generated by jsdifflib
1
From: Heinrich Schuchardt <heinrich.schuchardt@canonical.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Describe that the gic-version influences the maximum number of CPUs.
3
Compare only the VMID field when considering whether we need to flush.
4
4
5
Signed-off-by: Heinrich Schuchardt <heinrich.schuchardt@canonical.com>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20220413231456.35811-1-heinrich.schuchardt@canonical.com
7
[PMM: minor punctuation tweaks]
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Message-id: 20221011031911.2408754-7-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
9
---
11
docs/system/arm/virt.rst | 4 ++--
10
target/arm/helper.c | 4 ++--
12
1 file changed, 2 insertions(+), 2 deletions(-)
11
1 file changed, 2 insertions(+), 2 deletions(-)
13
12
14
diff --git a/docs/system/arm/virt.rst b/docs/system/arm/virt.rst
13
diff --git a/target/arm/helper.c b/target/arm/helper.c
15
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
16
--- a/docs/system/arm/virt.rst
15
--- a/target/arm/helper.c
17
+++ b/docs/system/arm/virt.rst
16
+++ b/target/arm/helper.c
18
@@ -XXX,XX +XXX,XX @@ gic-version
17
@@ -XXX,XX +XXX,XX @@ static void vttbr_write(CPUARMState *env, const ARMCPRegInfo *ri,
19
Valid values are:
18
* A change in VMID to the stage2 page table (Stage2) invalidates
20
19
* the stage2 and combined stage 1&2 tlbs (EL10_1 and EL10_0).
21
``2``
20
*/
22
- GICv2
21
- if (raw_read(env, ri) != value) {
23
+ GICv2. Note that this limits the number of CPUs to 8.
22
+ if (extract64(raw_read(env, ri) ^ value, 48, 16) != 0) {
24
``3``
23
tlb_flush_by_mmuidx(cs, alle1_tlbmask(env));
25
- GICv3
24
- raw_write(env, ri, value);
26
+ GICv3. This allows up to 512 CPUs.
25
}
27
``host``
26
+ raw_write(env, ri, value);
28
Use the same GIC version the host provides, when using KVM
27
}
29
``max``
28
29
static const ARMCPRegInfo vmsa_pmsa_cp_reginfo[] = {
30
--
30
--
31
2.25.1
31
2.25.1
diff view generated by jsdifflib
1
From: Zongyuan Li <zongyuan.li@smartx.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Signed-off-by: Zongyuan Li <zongyuan.li@smartx.com>
3
Consolidate most of the inputs and outputs of S1_ptw_translate
4
into a single structure. Plumb this through arm_ld*_ptw from
5
the controlling get_phys_addr_* routine.
6
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
4
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
5
Message-id: 20220324181557.203805-3-zongyuan.li@smartx.com
9
Message-id: 20221011031911.2408754-8-richard.henderson@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
11
---
8
hw/arm/stellaris.c | 15 +++++++++++++--
12
target/arm/ptw.c | 140 ++++++++++++++++++++++++++---------------------
9
1 file changed, 13 insertions(+), 2 deletions(-)
13
1 file changed, 79 insertions(+), 61 deletions(-)
10
14
11
diff --git a/hw/arm/stellaris.c b/hw/arm/stellaris.c
15
diff --git a/target/arm/ptw.c b/target/arm/ptw.c
12
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
13
--- a/hw/arm/stellaris.c
17
--- a/target/arm/ptw.c
14
+++ b/hw/arm/stellaris.c
18
+++ b/target/arm/ptw.c
15
@@ -XXX,XX +XXX,XX @@
19
@@ -XXX,XX +XXX,XX @@
16
20
#include "idau.h"
17
#include "qemu/osdep.h"
21
18
#include "qapi/error.h"
22
19
+#include "hw/core/split-irq.h"
23
-static bool get_phys_addr_lpae(CPUARMState *env, uint64_t address,
20
#include "hw/sysbus.h"
24
- MMUAccessType access_type, ARMMMUIdx mmu_idx,
21
#include "hw/sd/sd.h"
25
- bool is_secure, bool s1_is_el0,
22
#include "hw/ssi/ssi.h"
26
+typedef struct S1Translate {
23
@@ -XXX,XX +XXX,XX @@ static void stellaris_init(MachineState *ms, stellaris_board_info *board)
27
+ ARMMMUIdx in_mmu_idx;
24
DeviceState *ssddev;
28
+ bool in_secure;
25
DriveInfo *dinfo;
29
+ bool out_secure;
26
DeviceState *carddev;
30
+ hwaddr out_phys;
27
+ DeviceState *gpio_d_splitter;
31
+} S1Translate;
28
BlockBackend *blk;
32
+
33
+static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
34
+ uint64_t address,
35
+ MMUAccessType access_type, bool s1_is_el0,
36
GetPhysAddrResult *result, ARMMMUFaultInfo *fi)
37
__attribute__((nonnull));
38
39
@@ -XXX,XX +XXX,XX @@ static bool ptw_attrs_are_device(uint64_t hcr, ARMCacheAttrs cacheattrs)
40
}
41
42
/* Translate a S1 pagetable walk through S2 if needed. */
43
-static hwaddr S1_ptw_translate(CPUARMState *env, ARMMMUIdx mmu_idx,
44
- hwaddr addr, bool *is_secure_ptr,
45
- ARMMMUFaultInfo *fi)
46
+static bool S1_ptw_translate(CPUARMState *env, S1Translate *ptw,
47
+ hwaddr addr, ARMMMUFaultInfo *fi)
48
{
49
- bool is_secure = *is_secure_ptr;
50
+ bool is_secure = ptw->in_secure;
51
ARMMMUIdx s2_mmu_idx = is_secure ? ARMMMUIdx_Stage2_S : ARMMMUIdx_Stage2;
52
53
- if (arm_mmu_idx_is_stage1_of_2(mmu_idx) &&
54
+ if (arm_mmu_idx_is_stage1_of_2(ptw->in_mmu_idx) &&
55
!regime_translation_disabled(env, s2_mmu_idx, is_secure)) {
56
GetPhysAddrResult s2 = {};
57
+ S1Translate s2ptw = {
58
+ .in_mmu_idx = s2_mmu_idx,
59
+ .in_secure = is_secure,
60
+ };
61
uint64_t hcr;
62
int ret;
63
64
- ret = get_phys_addr_lpae(env, addr, MMU_DATA_LOAD, s2_mmu_idx,
65
- is_secure, false, &s2, fi);
66
+ ret = get_phys_addr_lpae(env, &s2ptw, addr, MMU_DATA_LOAD,
67
+ false, &s2, fi);
68
if (ret) {
69
assert(fi->type != ARMFault_None);
70
fi->s2addr = addr;
71
fi->stage2 = true;
72
fi->s1ptw = true;
73
fi->s1ns = !is_secure;
74
- return ~0;
75
+ return false;
76
}
77
78
hcr = arm_hcr_el2_eff_secstate(env, is_secure);
79
@@ -XXX,XX +XXX,XX @@ static hwaddr S1_ptw_translate(CPUARMState *env, ARMMMUIdx mmu_idx,
80
fi->stage2 = true;
81
fi->s1ptw = true;
82
fi->s1ns = !is_secure;
83
- return ~0;
84
+ return false;
85
}
86
87
if (arm_is_secure_below_el3(env)) {
88
@@ -XXX,XX +XXX,XX @@ static hwaddr S1_ptw_translate(CPUARMState *env, ARMMMUIdx mmu_idx,
89
} else {
90
is_secure = !(env->cp15.vtcr_el2 & VTCR_NSW);
91
}
92
- *is_secure_ptr = is_secure;
93
} else {
94
assert(!is_secure);
95
}
96
97
addr = s2.f.phys_addr;
98
}
99
- return addr;
100
+
101
+ ptw->out_secure = is_secure;
102
+ ptw->out_phys = addr;
103
+ return true;
104
}
105
106
/* All loads done in the course of a page table walk go through here. */
107
-static uint32_t arm_ldl_ptw(CPUARMState *env, hwaddr addr, bool is_secure,
108
- ARMMMUIdx mmu_idx, ARMMMUFaultInfo *fi)
109
+static uint32_t arm_ldl_ptw(CPUARMState *env, S1Translate *ptw, hwaddr addr,
110
+ ARMMMUFaultInfo *fi)
111
{
112
CPUState *cs = env_cpu(env);
113
MemTxAttrs attrs = {};
114
@@ -XXX,XX +XXX,XX @@ static uint32_t arm_ldl_ptw(CPUARMState *env, hwaddr addr, bool is_secure,
115
AddressSpace *as;
116
uint32_t data;
117
118
- addr = S1_ptw_translate(env, mmu_idx, addr, &is_secure, fi);
119
- attrs.secure = is_secure;
120
- as = arm_addressspace(cs, attrs);
121
- if (fi->s1ptw) {
122
+ if (!S1_ptw_translate(env, ptw, addr, fi)) {
123
return 0;
124
}
125
- if (regime_translation_big_endian(env, mmu_idx)) {
126
+ addr = ptw->out_phys;
127
+ attrs.secure = ptw->out_secure;
128
+ as = arm_addressspace(cs, attrs);
129
+ if (regime_translation_big_endian(env, ptw->in_mmu_idx)) {
130
data = address_space_ldl_be(as, addr, attrs, &result);
131
} else {
132
data = address_space_ldl_le(as, addr, attrs, &result);
133
@@ -XXX,XX +XXX,XX @@ static uint32_t arm_ldl_ptw(CPUARMState *env, hwaddr addr, bool is_secure,
134
return 0;
135
}
136
137
-static uint64_t arm_ldq_ptw(CPUARMState *env, hwaddr addr, bool is_secure,
138
- ARMMMUIdx mmu_idx, ARMMMUFaultInfo *fi)
139
+static uint64_t arm_ldq_ptw(CPUARMState *env, S1Translate *ptw, hwaddr addr,
140
+ ARMMMUFaultInfo *fi)
141
{
142
CPUState *cs = env_cpu(env);
143
MemTxAttrs attrs = {};
144
@@ -XXX,XX +XXX,XX @@ static uint64_t arm_ldq_ptw(CPUARMState *env, hwaddr addr, bool is_secure,
145
AddressSpace *as;
146
uint64_t data;
147
148
- addr = S1_ptw_translate(env, mmu_idx, addr, &is_secure, fi);
149
- attrs.secure = is_secure;
150
- as = arm_addressspace(cs, attrs);
151
- if (fi->s1ptw) {
152
+ if (!S1_ptw_translate(env, ptw, addr, fi)) {
153
return 0;
154
}
155
- if (regime_translation_big_endian(env, mmu_idx)) {
156
+ addr = ptw->out_phys;
157
+ attrs.secure = ptw->out_secure;
158
+ as = arm_addressspace(cs, attrs);
159
+ if (regime_translation_big_endian(env, ptw->in_mmu_idx)) {
160
data = address_space_ldq_be(as, addr, attrs, &result);
161
} else {
162
data = address_space_ldq_le(as, addr, attrs, &result);
163
@@ -XXX,XX +XXX,XX @@ static int simple_ap_to_rw_prot(CPUARMState *env, ARMMMUIdx mmu_idx, int ap)
164
return simple_ap_to_rw_prot_is_user(ap, regime_is_user(env, mmu_idx));
165
}
166
167
-static bool get_phys_addr_v5(CPUARMState *env, uint32_t address,
168
- MMUAccessType access_type, ARMMMUIdx mmu_idx,
169
- bool is_secure, GetPhysAddrResult *result,
170
- ARMMMUFaultInfo *fi)
171
+static bool get_phys_addr_v5(CPUARMState *env, S1Translate *ptw,
172
+ uint32_t address, MMUAccessType access_type,
173
+ GetPhysAddrResult *result, ARMMMUFaultInfo *fi)
174
{
175
int level = 1;
176
uint32_t table;
177
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_v5(CPUARMState *env, uint32_t address,
178
179
/* Pagetable walk. */
180
/* Lookup l1 descriptor. */
181
- if (!get_level1_table_address(env, mmu_idx, &table, address)) {
182
+ if (!get_level1_table_address(env, ptw->in_mmu_idx, &table, address)) {
183
/* Section translation fault if page walk is disabled by PD0 or PD1 */
184
fi->type = ARMFault_Translation;
185
goto do_fault;
186
}
187
- desc = arm_ldl_ptw(env, table, is_secure, mmu_idx, fi);
188
+ desc = arm_ldl_ptw(env, ptw, table, fi);
189
if (fi->type != ARMFault_None) {
190
goto do_fault;
191
}
192
type = (desc & 3);
193
domain = (desc >> 5) & 0x0f;
194
- if (regime_el(env, mmu_idx) == 1) {
195
+ if (regime_el(env, ptw->in_mmu_idx) == 1) {
196
dacr = env->cp15.dacr_ns;
197
} else {
198
dacr = env->cp15.dacr_s;
199
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_v5(CPUARMState *env, uint32_t address,
200
/* Fine pagetable. */
201
table = (desc & 0xfffff000) | ((address >> 8) & 0xffc);
202
}
203
- desc = arm_ldl_ptw(env, table, is_secure, mmu_idx, fi);
204
+ desc = arm_ldl_ptw(env, ptw, table, fi);
205
if (fi->type != ARMFault_None) {
206
goto do_fault;
207
}
208
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_v5(CPUARMState *env, uint32_t address,
209
g_assert_not_reached();
210
}
211
}
212
- result->f.prot = ap_to_rw_prot(env, mmu_idx, ap, domain_prot);
213
+ result->f.prot = ap_to_rw_prot(env, ptw->in_mmu_idx, ap, domain_prot);
214
result->f.prot |= result->f.prot ? PAGE_EXEC : 0;
215
if (!(result->f.prot & (1 << access_type))) {
216
/* Access permission fault. */
217
@@ -XXX,XX +XXX,XX @@ do_fault:
218
return true;
219
}
220
221
-static bool get_phys_addr_v6(CPUARMState *env, uint32_t address,
222
- MMUAccessType access_type, ARMMMUIdx mmu_idx,
223
- bool is_secure, GetPhysAddrResult *result,
224
- ARMMMUFaultInfo *fi)
225
+static bool get_phys_addr_v6(CPUARMState *env, S1Translate *ptw,
226
+ uint32_t address, MMUAccessType access_type,
227
+ GetPhysAddrResult *result, ARMMMUFaultInfo *fi)
228
{
229
ARMCPU *cpu = env_archcpu(env);
230
+ ARMMMUIdx mmu_idx = ptw->in_mmu_idx;
231
int level = 1;
232
uint32_t table;
233
uint32_t desc;
234
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_v6(CPUARMState *env, uint32_t address,
235
fi->type = ARMFault_Translation;
236
goto do_fault;
237
}
238
- desc = arm_ldl_ptw(env, table, is_secure, mmu_idx, fi);
239
+ desc = arm_ldl_ptw(env, ptw, table, fi);
240
if (fi->type != ARMFault_None) {
241
goto do_fault;
242
}
243
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_v6(CPUARMState *env, uint32_t address,
244
ns = extract32(desc, 3, 1);
245
/* Lookup l2 entry. */
246
table = (desc & 0xfffffc00) | ((address >> 10) & 0x3fc);
247
- desc = arm_ldl_ptw(env, table, is_secure, mmu_idx, fi);
248
+ desc = arm_ldl_ptw(env, ptw, table, fi);
249
if (fi->type != ARMFault_None) {
250
goto do_fault;
251
}
252
@@ -XXX,XX +XXX,XX @@ static bool check_s2_mmu_setup(ARMCPU *cpu, bool is_aa64, int level,
253
* the WnR bit is never set (the caller must do this).
254
*
255
* @env: CPUARMState
256
+ * @ptw: Current and next stage parameters for the walk.
257
* @address: virtual address to get physical address for
258
* @access_type: MMU_DATA_LOAD, MMU_DATA_STORE or MMU_INST_FETCH
259
- * @mmu_idx: MMU index indicating required translation regime
260
- * @s1_is_el0: if @mmu_idx is ARMMMUIdx_Stage2 (so this is a stage 2 page
261
- * table walk), must be true if this is stage 2 of a stage 1+2
262
+ * @s1_is_el0: if @ptw->in_mmu_idx is ARMMMUIdx_Stage2
263
+ * (so this is a stage 2 page table walk),
264
+ * must be true if this is stage 2 of a stage 1+2
265
* walk for an EL0 access. If @mmu_idx is anything else,
266
* @s1_is_el0 is ignored.
267
* @result: set on translation success,
268
* @fi: set to fault info if the translation fails
269
*/
270
-static bool get_phys_addr_lpae(CPUARMState *env, uint64_t address,
271
- MMUAccessType access_type, ARMMMUIdx mmu_idx,
272
- bool is_secure, bool s1_is_el0,
273
+static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
274
+ uint64_t address,
275
+ MMUAccessType access_type, bool s1_is_el0,
276
GetPhysAddrResult *result, ARMMMUFaultInfo *fi)
277
{
278
ARMCPU *cpu = env_archcpu(env);
279
+ ARMMMUIdx mmu_idx = ptw->in_mmu_idx;
280
+ bool is_secure = ptw->in_secure;
281
/* Read an LPAE long-descriptor translation table. */
282
ARMFaultType fault_type = ARMFault_Translation;
283
uint32_t level;
284
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, uint64_t address,
285
descaddr |= (address >> (stride * (4 - level))) & indexmask;
286
descaddr &= ~7ULL;
287
nstable = extract32(tableattrs, 4, 1);
288
- descriptor = arm_ldq_ptw(env, descaddr, !nstable, mmu_idx, fi);
289
+ ptw->in_secure = !nstable;
290
+ descriptor = arm_ldq_ptw(env, ptw, descaddr, fi);
291
if (fi->type != ARMFault_None) {
292
goto do_fault;
293
}
294
@@ -XXX,XX +XXX,XX @@ bool get_phys_addr_with_secure(CPUARMState *env, target_ulong address,
295
ARMMMUFaultInfo *fi)
296
{
297
ARMMMUIdx s1_mmu_idx = stage_1_mmu_idx(mmu_idx);
298
+ S1Translate ptw;
299
300
if (mmu_idx != s1_mmu_idx) {
301
/*
302
@@ -XXX,XX +XXX,XX @@ bool get_phys_addr_with_secure(CPUARMState *env, target_ulong address,
303
int ret;
304
bool ipa_secure, s2walk_secure;
305
ARMCacheAttrs cacheattrs1;
306
- ARMMMUIdx s2_mmu_idx;
307
bool is_el0;
308
uint64_t hcr;
309
310
@@ -XXX,XX +XXX,XX @@ bool get_phys_addr_with_secure(CPUARMState *env, target_ulong address,
311
s2walk_secure = false;
312
}
313
314
- s2_mmu_idx = (s2walk_secure
315
- ? ARMMMUIdx_Stage2_S : ARMMMUIdx_Stage2);
316
+ ptw.in_mmu_idx =
317
+ s2walk_secure ? ARMMMUIdx_Stage2_S : ARMMMUIdx_Stage2;
318
+ ptw.in_secure = s2walk_secure;
319
is_el0 = mmu_idx == ARMMMUIdx_E10_0;
29
320
30
/*
321
/*
31
@@ -XXX,XX +XXX,XX @@ static void stellaris_init(MachineState *ms, stellaris_board_info *board)
322
@@ -XXX,XX +XXX,XX @@ bool get_phys_addr_with_secure(CPUARMState *env, target_ulong address,
32
&error_fatal);
323
cacheattrs1 = result->cacheattrs;
33
324
memset(result, 0, sizeof(*result));
34
ssddev = ssi_create_peripheral(bus, "ssd0323");
325
35
- gpio_out[GPIO_D][0] = qemu_irq_split(
326
- ret = get_phys_addr_lpae(env, ipa, access_type, s2_mmu_idx,
36
- qdev_get_gpio_in_named(sddev, SSI_GPIO_CS, 0),
327
- s2walk_secure, is_el0, result, fi);
328
+ ret = get_phys_addr_lpae(env, &ptw, ipa, access_type,
329
+ is_el0, result, fi);
330
fi->s2addr = ipa;
331
332
/* Combine the S1 and S2 perms. */
333
@@ -XXX,XX +XXX,XX @@ bool get_phys_addr_with_secure(CPUARMState *env, target_ulong address,
334
return get_phys_addr_disabled(env, address, access_type, mmu_idx,
335
is_secure, result, fi);
336
}
37
+
337
+
38
+ gpio_d_splitter = qdev_new(TYPE_SPLIT_IRQ);
338
+ ptw.in_mmu_idx = mmu_idx;
39
+ qdev_prop_set_uint32(gpio_d_splitter, "num-lines", 2);
339
+ ptw.in_secure = is_secure;
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
+
340
+
49
gpio_out[GPIO_C][7] = qdev_get_gpio_in(ssddev, 0);
341
if (regime_using_lpae_format(env, mmu_idx)) {
50
342
- return get_phys_addr_lpae(env, address, access_type, mmu_idx,
51
/* Make sure the select pin is high. */
343
- is_secure, false, result, fi);
344
+ return get_phys_addr_lpae(env, &ptw, address, access_type, false,
345
+ result, fi);
346
} else if (regime_sctlr(env, mmu_idx) & SCTLR_XP) {
347
- return get_phys_addr_v6(env, address, access_type, mmu_idx,
348
- is_secure, result, fi);
349
+ return get_phys_addr_v6(env, &ptw, address, access_type, result, fi);
350
} else {
351
- return get_phys_addr_v5(env, address, access_type, mmu_idx,
352
- is_secure, result, fi);
353
+ return get_phys_addr_v5(env, &ptw, address, access_type, result, fi);
354
}
355
}
356
52
--
357
--
53
2.25.1
358
2.25.1
diff view generated by jsdifflib
1
From: Zongyuan Li <zongyuan.li@smartx.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Signed-off-by: Zongyuan Li <zongyuan.li@smartx.com>
3
Before using softmmu page tables for the ptw, plumb down
4
a debug parameter so that we can query page table entries
5
from gdbstub without modifying cpu state.
6
4
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
5
Message-id: 20220324181557.203805-2-zongyuan.li@smartx.com
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20221011031911.2408754-9-richard.henderson@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
11
---
8
hw/arm/realview.c | 33 ++++++++++++++++++++++++---------
12
target/arm/ptw.c | 55 ++++++++++++++++++++++++++++++++----------------
9
1 file changed, 24 insertions(+), 9 deletions(-)
13
1 file changed, 37 insertions(+), 18 deletions(-)
10
14
11
diff --git a/hw/arm/realview.c b/hw/arm/realview.c
15
diff --git a/target/arm/ptw.c b/target/arm/ptw.c
12
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
13
--- a/hw/arm/realview.c
17
--- a/target/arm/ptw.c
14
+++ b/hw/arm/realview.c
18
+++ b/target/arm/ptw.c
15
@@ -XXX,XX +XXX,XX @@
19
@@ -XXX,XX +XXX,XX @@
16
#include "hw/sysbus.h"
20
typedef struct S1Translate {
17
#include "hw/arm/boot.h"
21
ARMMMUIdx in_mmu_idx;
18
#include "hw/arm/primecell.h"
22
bool in_secure;
19
+#include "hw/core/split-irq.h"
23
+ bool in_debug;
20
#include "hw/net/lan9118.h"
24
bool out_secure;
21
#include "hw/net/smc91c111.h"
25
hwaddr out_phys;
22
#include "hw/pci/pci.h"
26
} S1Translate;
23
+#include "hw/qdev-core.h"
27
@@ -XXX,XX +XXX,XX @@ static bool S1_ptw_translate(CPUARMState *env, S1Translate *ptw,
24
#include "net/net.h"
28
S1Translate s2ptw = {
25
#include "sysemu/sysemu.h"
29
.in_mmu_idx = s2_mmu_idx,
26
#include "hw/boards.h"
30
.in_secure = is_secure,
27
@@ -XXX,XX +XXX,XX @@ static const int realview_board_id[] = {
31
+ .in_debug = ptw->in_debug,
28
0x76d
32
};
29
};
33
uint64_t hcr;
30
34
int ret;
31
+static void split_irq_from_named(DeviceState *src, const char* outname,
35
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_disabled(CPUARMState *env, target_ulong address,
32
+ qemu_irq out1, qemu_irq out2) {
36
return 0;
33
+ DeviceState *splitter = qdev_new(TYPE_SPLIT_IRQ);
37
}
34
+
38
35
+ qdev_prop_set_uint32(splitter, "num-lines", 2);
39
-bool get_phys_addr_with_secure(CPUARMState *env, target_ulong address,
36
+
40
- MMUAccessType access_type, ARMMMUIdx mmu_idx,
37
+ qdev_realize_and_unref(splitter, NULL, &error_fatal);
41
- bool is_secure, GetPhysAddrResult *result,
38
+
42
- ARMMMUFaultInfo *fi)
39
+ qdev_connect_gpio_out(splitter, 0, out1);
43
+static bool get_phys_addr_with_struct(CPUARMState *env, S1Translate *ptw,
40
+ qdev_connect_gpio_out(splitter, 1, out2);
44
+ target_ulong address,
41
+ qdev_connect_gpio_out_named(src, outname, 0,
45
+ MMUAccessType access_type,
42
+ qdev_get_gpio_in(splitter, 0));
46
+ GetPhysAddrResult *result,
47
+ ARMMMUFaultInfo *fi)
48
{
49
+ ARMMMUIdx mmu_idx = ptw->in_mmu_idx;
50
ARMMMUIdx s1_mmu_idx = stage_1_mmu_idx(mmu_idx);
51
- S1Translate ptw;
52
+ bool is_secure = ptw->in_secure;
53
54
if (mmu_idx != s1_mmu_idx) {
55
/*
56
@@ -XXX,XX +XXX,XX @@ bool get_phys_addr_with_secure(CPUARMState *env, target_ulong address,
57
bool is_el0;
58
uint64_t hcr;
59
60
- ret = get_phys_addr_with_secure(env, address, access_type,
61
- s1_mmu_idx, is_secure, result, fi);
62
+ ptw->in_mmu_idx = s1_mmu_idx;
63
+ ret = get_phys_addr_with_struct(env, ptw, address, access_type,
64
+ result, fi);
65
66
/* If S1 fails or S2 is disabled, return early. */
67
if (ret || regime_translation_disabled(env, ARMMMUIdx_Stage2,
68
@@ -XXX,XX +XXX,XX @@ bool get_phys_addr_with_secure(CPUARMState *env, target_ulong address,
69
s2walk_secure = false;
70
}
71
72
- ptw.in_mmu_idx =
73
+ ptw->in_mmu_idx =
74
s2walk_secure ? ARMMMUIdx_Stage2_S : ARMMMUIdx_Stage2;
75
- ptw.in_secure = s2walk_secure;
76
+ ptw->in_secure = s2walk_secure;
77
is_el0 = mmu_idx == ARMMMUIdx_E10_0;
78
79
/*
80
@@ -XXX,XX +XXX,XX @@ bool get_phys_addr_with_secure(CPUARMState *env, target_ulong address,
81
cacheattrs1 = result->cacheattrs;
82
memset(result, 0, sizeof(*result));
83
84
- ret = get_phys_addr_lpae(env, &ptw, ipa, access_type,
85
+ ret = get_phys_addr_lpae(env, ptw, ipa, access_type,
86
is_el0, result, fi);
87
fi->s2addr = ipa;
88
89
@@ -XXX,XX +XXX,XX @@ bool get_phys_addr_with_secure(CPUARMState *env, target_ulong address,
90
is_secure, result, fi);
91
}
92
93
- ptw.in_mmu_idx = mmu_idx;
94
- ptw.in_secure = is_secure;
95
-
96
if (regime_using_lpae_format(env, mmu_idx)) {
97
- return get_phys_addr_lpae(env, &ptw, address, access_type, false,
98
+ return get_phys_addr_lpae(env, ptw, address, access_type, false,
99
result, fi);
100
} else if (regime_sctlr(env, mmu_idx) & SCTLR_XP) {
101
- return get_phys_addr_v6(env, &ptw, address, access_type, result, fi);
102
+ return get_phys_addr_v6(env, ptw, address, access_type, result, fi);
103
} else {
104
- return get_phys_addr_v5(env, &ptw, address, access_type, result, fi);
105
+ return get_phys_addr_v5(env, ptw, address, access_type, result, fi);
106
}
107
}
108
109
+bool get_phys_addr_with_secure(CPUARMState *env, target_ulong address,
110
+ MMUAccessType access_type, ARMMMUIdx mmu_idx,
111
+ bool is_secure, GetPhysAddrResult *result,
112
+ ARMMMUFaultInfo *fi)
113
+{
114
+ S1Translate ptw = {
115
+ .in_mmu_idx = mmu_idx,
116
+ .in_secure = is_secure,
117
+ };
118
+ return get_phys_addr_with_struct(env, &ptw, address, access_type,
119
+ result, fi);
43
+}
120
+}
44
+
121
+
45
static void realview_init(MachineState *machine,
122
bool get_phys_addr(CPUARMState *env, target_ulong address,
46
enum realview_board_type board_type)
123
MMUAccessType access_type, ARMMMUIdx mmu_idx,
124
GetPhysAddrResult *result, ARMMMUFaultInfo *fi)
125
@@ -XXX,XX +XXX,XX @@ hwaddr arm_cpu_get_phys_page_attrs_debug(CPUState *cs, vaddr addr,
47
{
126
{
48
@@ -XXX,XX +XXX,XX @@ static void realview_init(MachineState *machine,
127
ARMCPU *cpu = ARM_CPU(cs);
49
DeviceState *dev, *sysctl, *gpio2, *pl041;
128
CPUARMState *env = &cpu->env;
50
SysBusDevice *busdev;
129
+ S1Translate ptw = {
51
qemu_irq pic[64];
130
+ .in_mmu_idx = arm_mmu_idx(env),
52
- qemu_irq mmc_irq[2];
131
+ .in_secure = arm_is_secure(env),
53
PCIBus *pci_bus = NULL;
132
+ .in_debug = true,
54
NICInfo *nd;
133
+ };
55
DriveInfo *dinfo;
134
GetPhysAddrResult res = {};
56
@@ -XXX,XX +XXX,XX @@ static void realview_init(MachineState *machine,
135
ARMMMUFaultInfo fi = {};
57
* and the PL061 has them the other way about. Also the card
136
- ARMMMUIdx mmu_idx = arm_mmu_idx(env);
58
* detect line is inverted.
137
bool ret;
59
*/
138
60
- mmc_irq[0] = qemu_irq_split(
139
- ret = get_phys_addr(env, addr, MMU_DATA_LOAD, mmu_idx, &res, &fi);
61
- qdev_get_gpio_in(sysctl, ARM_SYSCTL_GPIO_MMC_WPROT),
140
+ ret = get_phys_addr_with_struct(env, &ptw, addr, MMU_DATA_LOAD, &res, &fi);
62
- qdev_get_gpio_in(gpio2, 1));
141
*attrs = res.f.attrs;
63
- mmc_irq[1] = qemu_irq_split(
142
64
- qdev_get_gpio_in(sysctl, ARM_SYSCTL_GPIO_MMC_CARDIN),
143
if (ret) {
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
--
144
--
80
2.25.1
145
2.25.1
diff view generated by jsdifflib
1
The only time we use the int_combiner_irq[] and ext_combiner_irq[]
1
From: Richard Henderson <richard.henderson@linaro.org>
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
Hoist this test out of arm_ld[lq]_ptw into S1_ptw_translate.
11
we can remove that struct entirely.
12
4
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20221011031911.2408754-10-richard.henderson@linaro.org
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
Message-id: 20220404154658.565020-19-peter.maydell@linaro.org
16
---
9
---
17
include/hw/arm/exynos4210.h | 6 ------
10
target/arm/ptw.c | 6 ++++--
18
hw/arm/exynos4210.c | 34 ++++++++--------------------------
11
1 file changed, 4 insertions(+), 2 deletions(-)
19
2 files changed, 8 insertions(+), 32 deletions(-)
20
12
21
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
13
diff --git a/target/arm/ptw.c b/target/arm/ptw.c
22
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
23
--- a/include/hw/arm/exynos4210.h
15
--- a/target/arm/ptw.c
24
+++ b/include/hw/arm/exynos4210.h
16
+++ b/target/arm/ptw.c
25
@@ -XXX,XX +XXX,XX @@
17
@@ -XXX,XX +XXX,XX @@ typedef struct S1Translate {
26
*/
18
bool in_secure;
27
#define EXYNOS4210_NUM_SPLITTERS (EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ + 38)
19
bool in_debug;
28
20
bool out_secure;
29
-typedef struct Exynos4210Irq {
21
+ bool out_be;
30
- qemu_irq int_combiner_irq[EXYNOS4210_MAX_INT_COMBINER_IN_IRQ];
22
hwaddr out_phys;
31
- qemu_irq ext_combiner_irq[EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ];
23
} S1Translate;
32
-} Exynos4210Irq;
24
33
-
25
@@ -XXX,XX +XXX,XX @@ static bool S1_ptw_translate(CPUARMState *env, S1Translate *ptw,
34
struct Exynos4210State {
26
35
/*< private >*/
27
ptw->out_secure = is_secure;
36
SysBusDevice parent_obj;
28
ptw->out_phys = addr;
37
/*< public >*/
29
+ ptw->out_be = regime_translation_big_endian(env, ptw->in_mmu_idx);
38
ARMCPU *cpu[EXYNOS4210_NCPUS];
30
return true;
39
- Exynos4210Irq irqs;
40
qemu_irq irq_table[EXYNOS4210_MAX_INT_COMBINER_IN_IRQ];
41
42
MemoryRegion chipid_mem;
43
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
44
index XXXXXXX..XXXXXXX 100644
45
--- a/hw/arm/exynos4210.c
46
+++ b/hw/arm/exynos4210.c
47
@@ -XXX,XX +XXX,XX @@ static int mapline_size(const int *mapline)
48
static void exynos4210_init_board_irqs(Exynos4210State *s)
49
{
50
uint32_t grp, bit, irq_id, n;
51
- Exynos4210Irq *is = &s->irqs;
52
DeviceState *extgicdev = DEVICE(&s->ext_gic);
53
+ DeviceState *intcdev = DEVICE(&s->int_combiner);
54
+ DeviceState *extcdev = DEVICE(&s->ext_combiner);
55
int splitcount = 0;
56
DeviceState *splitter;
57
const int *mapline;
58
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init_board_irqs(Exynos4210State *s)
59
splitin = 0;
60
for (;;) {
61
s->irq_table[in] = qdev_get_gpio_in(splitter, 0);
62
- qdev_connect_gpio_out(splitter, splitin, is->int_combiner_irq[in]);
63
- qdev_connect_gpio_out(splitter, splitin + 1, is->ext_combiner_irq[in]);
64
+ qdev_connect_gpio_out(splitter, splitin,
65
+ qdev_get_gpio_in(intcdev, in));
66
+ qdev_connect_gpio_out(splitter, splitin + 1,
67
+ qdev_get_gpio_in(extcdev, in));
68
splitin += 2;
69
if (!mapline) {
70
break;
71
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init_board_irqs(Exynos4210State *s)
72
qdev_realize(splitter, NULL, &error_abort);
73
splitcount++;
74
s->irq_table[n] = qdev_get_gpio_in(splitter, 0);
75
- qdev_connect_gpio_out(splitter, 0, is->int_combiner_irq[n]);
76
+ qdev_connect_gpio_out(splitter, 0, qdev_get_gpio_in(intcdev, n));
77
qdev_connect_gpio_out(splitter, 1,
78
qdev_get_gpio_in(extgicdev, irq_id - 32));
79
} else {
80
- s->irq_table[n] = is->int_combiner_irq[n];
81
+ s->irq_table[n] = qdev_get_gpio_in(intcdev, n);
82
}
83
}
84
/*
85
@@ -XXX,XX +XXX,XX @@ uint32_t exynos4210_get_irq(uint32_t grp, uint32_t bit)
86
return EXYNOS4210_COMBINER_GET_IRQ_NUM(grp, bit);
87
}
31
}
88
32
89
-/*
33
@@ -XXX,XX +XXX,XX @@ static uint32_t arm_ldl_ptw(CPUARMState *env, S1Translate *ptw, hwaddr addr,
90
- * Get Combiner input GPIO into irqs structure
34
addr = ptw->out_phys;
91
- */
35
attrs.secure = ptw->out_secure;
92
-static void exynos4210_combiner_get_gpioin(Exynos4210Irq *irqs,
36
as = arm_addressspace(cs, attrs);
93
- DeviceState *dev, int ext)
37
- if (regime_translation_big_endian(env, ptw->in_mmu_idx)) {
94
-{
38
+ if (ptw->out_be) {
95
- int n;
39
data = address_space_ldl_be(as, addr, attrs, &result);
96
- int max;
40
} else {
97
- qemu_irq *irq;
41
data = address_space_ldl_le(as, addr, attrs, &result);
98
-
42
@@ -XXX,XX +XXX,XX @@ static uint64_t arm_ldq_ptw(CPUARMState *env, S1Translate *ptw, hwaddr addr,
99
- max = ext ? EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ :
43
addr = ptw->out_phys;
100
- EXYNOS4210_MAX_INT_COMBINER_IN_IRQ;
44
attrs.secure = ptw->out_secure;
101
- irq = ext ? irqs->ext_combiner_irq : irqs->int_combiner_irq;
45
as = arm_addressspace(cs, attrs);
102
-
46
- if (regime_translation_big_endian(env, ptw->in_mmu_idx)) {
103
- for (n = 0; n < max; n++) {
47
+ if (ptw->out_be) {
104
- irq[n] = qdev_get_gpio_in(dev, n);
48
data = address_space_ldq_be(as, addr, attrs, &result);
105
- }
49
} else {
106
-}
50
data = address_space_ldq_le(as, addr, attrs, &result);
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
--
51
--
128
2.25.1
52
2.25.1
diff view generated by jsdifflib
1
In exynos4210_init_board_irqs(), use the TYPE_SPLIT_IRQ device
1
From: Richard Henderson <richard.henderson@linaro.org>
2
instead of qemu_irq_split().
3
2
3
So far, limit the change to S1_ptw_translate, arm_ldl_ptw, and
4
arm_ldq_ptw. Use probe_access_full to find the host address,
5
and if so use a host load. If the probe fails, we've got our
6
fault info already. On the off chance that page tables are not
7
in RAM, continue to use the address_space_ld* functions.
8
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20221011031911.2408754-11-richard.henderson@linaro.org
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20220404154658.565020-13-peter.maydell@linaro.org
7
---
13
---
8
include/hw/arm/exynos4210.h | 9 ++++++++
14
target/arm/cpu.h | 5 +
9
hw/arm/exynos4210.c | 41 +++++++++++++++++++++++++++++--------
15
target/arm/ptw.c | 196 +++++++++++++++++++++++++---------------
10
2 files changed, 42 insertions(+), 8 deletions(-)
16
target/arm/tlb_helper.c | 17 +++-
17
3 files changed, 144 insertions(+), 74 deletions(-)
11
18
12
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
19
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
13
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
14
--- a/include/hw/arm/exynos4210.h
21
--- a/target/arm/cpu.h
15
+++ b/include/hw/arm/exynos4210.h
22
+++ b/target/arm/cpu.h
23
@@ -XXX,XX +XXX,XX @@ typedef struct CPUARMTBFlags {
24
target_ulong flags2;
25
} CPUARMTBFlags;
26
27
+typedef struct ARMMMUFaultInfo ARMMMUFaultInfo;
28
+
29
typedef struct CPUArchState {
30
/* Regs for current mode. */
31
uint32_t regs[16];
32
@@ -XXX,XX +XXX,XX @@ typedef struct CPUArchState {
33
struct CPUBreakpoint *cpu_breakpoint[16];
34
struct CPUWatchpoint *cpu_watchpoint[16];
35
36
+ /* Optional fault info across tlb lookup. */
37
+ ARMMMUFaultInfo *tlb_fi;
38
+
39
/* Fields up to this point are cleared by a CPU reset */
40
struct {} end_reset_fields;
41
42
diff --git a/target/arm/ptw.c b/target/arm/ptw.c
43
index XXXXXXX..XXXXXXX 100644
44
--- a/target/arm/ptw.c
45
+++ b/target/arm/ptw.c
16
@@ -XXX,XX +XXX,XX @@
46
@@ -XXX,XX +XXX,XX @@
17
#include "hw/sysbus.h"
47
#include "qemu/osdep.h"
18
#include "hw/cpu/a9mpcore.h"
48
#include "qemu/log.h"
19
#include "hw/intc/exynos4210_gic.h"
49
#include "qemu/range.h"
20
+#include "hw/core/split-irq.h"
50
+#include "exec/exec-all.h"
21
#include "target/arm/cpu-qom.h"
51
#include "cpu.h"
22
#include "qom/object.h"
52
#include "internals.h"
23
53
#include "idau.h"
24
@@ -XXX,XX +XXX,XX @@
54
@@ -XXX,XX +XXX,XX @@ typedef struct S1Translate {
25
55
bool out_secure;
26
#define EXYNOS4210_NUM_DMA 3
56
bool out_be;
27
57
hwaddr out_phys;
28
+/*
58
+ void *out_host;
29
+ * We need one splitter for every external combiner input, plus
59
} S1Translate;
30
+ * one for every non-zero entry in combiner_grp_to_gic_id[].
60
31
+ * We'll assert in exynos4210_init_board_irqs() if this is wrong.
61
static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
32
+ */
62
@@ -XXX,XX +XXX,XX @@ static bool regime_translation_disabled(CPUARMState *env, ARMMMUIdx mmu_idx,
33
+#define EXYNOS4210_NUM_SPLITTERS (EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ + 60)
63
return (regime_sctlr(env, mmu_idx) & SCTLR_M) == 0;
34
+
64
}
35
typedef struct Exynos4210Irq {
65
36
qemu_irq int_combiner_irq[EXYNOS4210_MAX_INT_COMBINER_IN_IRQ];
66
-static bool ptw_attrs_are_device(uint64_t hcr, ARMCacheAttrs cacheattrs)
37
qemu_irq ext_combiner_irq[EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ];
67
+static bool S2_attrs_are_device(uint64_t hcr, uint8_t attrs)
38
@@ -XXX,XX +XXX,XX @@ struct Exynos4210State {
68
{
39
qemu_or_irq cpu_irq_orgate[EXYNOS4210_NCPUS];
69
/*
40
A9MPPrivState a9mpcore;
70
* For an S1 page table walk, the stage 1 attributes are always
41
Exynos4210GicState ext_gic;
71
@@ -XXX,XX +XXX,XX @@ static bool ptw_attrs_are_device(uint64_t hcr, ARMCacheAttrs cacheattrs)
42
+ SplitIRQ splitter[EXYNOS4210_NUM_SPLITTERS];
72
* With HCR_EL2.FWB == 1 this is when descriptor bit [4] is 0, ie
43
};
73
* when cacheattrs.attrs bit [2] is 0.
44
74
*/
45
#define TYPE_EXYNOS4210_SOC "exynos4210"
75
- assert(cacheattrs.is_s2_format);
46
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
76
if (hcr & HCR_FWB) {
77
- return (cacheattrs.attrs & 0x4) == 0;
78
+ return (attrs & 0x4) == 0;
79
} else {
80
- return (cacheattrs.attrs & 0xc) == 0;
81
+ return (attrs & 0xc) == 0;
82
}
83
}
84
85
@@ -XXX,XX +XXX,XX @@ static bool S1_ptw_translate(CPUARMState *env, S1Translate *ptw,
86
hwaddr addr, ARMMMUFaultInfo *fi)
87
{
88
bool is_secure = ptw->in_secure;
89
+ ARMMMUIdx mmu_idx = ptw->in_mmu_idx;
90
ARMMMUIdx s2_mmu_idx = is_secure ? ARMMMUIdx_Stage2_S : ARMMMUIdx_Stage2;
91
+ bool s2_phys = false;
92
+ uint8_t pte_attrs;
93
+ bool pte_secure;
94
95
- if (arm_mmu_idx_is_stage1_of_2(ptw->in_mmu_idx) &&
96
- !regime_translation_disabled(env, s2_mmu_idx, is_secure)) {
97
- GetPhysAddrResult s2 = {};
98
- S1Translate s2ptw = {
99
- .in_mmu_idx = s2_mmu_idx,
100
- .in_secure = is_secure,
101
- .in_debug = ptw->in_debug,
102
- };
103
- uint64_t hcr;
104
- int ret;
105
+ if (!arm_mmu_idx_is_stage1_of_2(mmu_idx)
106
+ || regime_translation_disabled(env, s2_mmu_idx, is_secure)) {
107
+ s2_mmu_idx = is_secure ? ARMMMUIdx_Phys_S : ARMMMUIdx_Phys_NS;
108
+ s2_phys = true;
109
+ }
110
111
- ret = get_phys_addr_lpae(env, &s2ptw, addr, MMU_DATA_LOAD,
112
- false, &s2, fi);
113
- if (ret) {
114
- assert(fi->type != ARMFault_None);
115
- fi->s2addr = addr;
116
- fi->stage2 = true;
117
- fi->s1ptw = true;
118
- fi->s1ns = !is_secure;
119
- return false;
120
+ if (unlikely(ptw->in_debug)) {
121
+ /*
122
+ * From gdbstub, do not use softmmu so that we don't modify the
123
+ * state of the cpu at all, including softmmu tlb contents.
124
+ */
125
+ if (s2_phys) {
126
+ ptw->out_phys = addr;
127
+ pte_attrs = 0;
128
+ pte_secure = is_secure;
129
+ } else {
130
+ S1Translate s2ptw = {
131
+ .in_mmu_idx = s2_mmu_idx,
132
+ .in_secure = is_secure,
133
+ .in_debug = true,
134
+ };
135
+ GetPhysAddrResult s2 = { };
136
+ if (!get_phys_addr_lpae(env, &s2ptw, addr, MMU_DATA_LOAD,
137
+ false, &s2, fi)) {
138
+ goto fail;
139
+ }
140
+ ptw->out_phys = s2.f.phys_addr;
141
+ pte_attrs = s2.cacheattrs.attrs;
142
+ pte_secure = s2.f.attrs.secure;
143
}
144
+ ptw->out_host = NULL;
145
+ } else {
146
+ CPUTLBEntryFull *full;
147
+ int flags;
148
149
- hcr = arm_hcr_el2_eff_secstate(env, is_secure);
150
- if ((hcr & HCR_PTW) && ptw_attrs_are_device(hcr, s2.cacheattrs)) {
151
+ env->tlb_fi = fi;
152
+ flags = probe_access_full(env, addr, MMU_DATA_LOAD,
153
+ arm_to_core_mmu_idx(s2_mmu_idx),
154
+ true, &ptw->out_host, &full, 0);
155
+ env->tlb_fi = NULL;
156
+
157
+ if (unlikely(flags & TLB_INVALID_MASK)) {
158
+ goto fail;
159
+ }
160
+ ptw->out_phys = full->phys_addr;
161
+ pte_attrs = full->pte_attrs;
162
+ pte_secure = full->attrs.secure;
163
+ }
164
+
165
+ if (!s2_phys) {
166
+ uint64_t hcr = arm_hcr_el2_eff_secstate(env, is_secure);
167
+
168
+ if ((hcr & HCR_PTW) && S2_attrs_are_device(hcr, pte_attrs)) {
169
/*
170
* PTW set and S1 walk touched S2 Device memory:
171
* generate Permission fault.
172
@@ -XXX,XX +XXX,XX @@ static bool S1_ptw_translate(CPUARMState *env, S1Translate *ptw,
173
fi->s1ns = !is_secure;
174
return false;
175
}
176
-
177
- if (arm_is_secure_below_el3(env)) {
178
- /* Check if page table walk is to secure or non-secure PA space. */
179
- if (is_secure) {
180
- is_secure = !(env->cp15.vstcr_el2 & VSTCR_SW);
181
- } else {
182
- is_secure = !(env->cp15.vtcr_el2 & VTCR_NSW);
183
- }
184
- } else {
185
- assert(!is_secure);
186
- }
187
-
188
- addr = s2.f.phys_addr;
189
}
190
191
- ptw->out_secure = is_secure;
192
- ptw->out_phys = addr;
193
- ptw->out_be = regime_translation_big_endian(env, ptw->in_mmu_idx);
194
+ /* Check if page table walk is to secure or non-secure PA space. */
195
+ ptw->out_secure = (is_secure
196
+ && !(pte_secure
197
+ ? env->cp15.vstcr_el2 & VSTCR_SW
198
+ : env->cp15.vtcr_el2 & VTCR_NSW));
199
+ ptw->out_be = regime_translation_big_endian(env, mmu_idx);
200
return true;
201
+
202
+ fail:
203
+ assert(fi->type != ARMFault_None);
204
+ fi->s2addr = addr;
205
+ fi->stage2 = true;
206
+ fi->s1ptw = true;
207
+ fi->s1ns = !is_secure;
208
+ return false;
209
}
210
211
/* All loads done in the course of a page table walk go through here. */
212
@@ -XXX,XX +XXX,XX @@ static uint32_t arm_ldl_ptw(CPUARMState *env, S1Translate *ptw, hwaddr addr,
213
ARMMMUFaultInfo *fi)
214
{
215
CPUState *cs = env_cpu(env);
216
- MemTxAttrs attrs = {};
217
- MemTxResult result = MEMTX_OK;
218
- AddressSpace *as;
219
uint32_t data;
220
221
if (!S1_ptw_translate(env, ptw, addr, fi)) {
222
+ /* Failure. */
223
+ assert(fi->s1ptw);
224
return 0;
225
}
226
- addr = ptw->out_phys;
227
- attrs.secure = ptw->out_secure;
228
- as = arm_addressspace(cs, attrs);
229
- if (ptw->out_be) {
230
- data = address_space_ldl_be(as, addr, attrs, &result);
231
+
232
+ if (likely(ptw->out_host)) {
233
+ /* Page tables are in RAM, and we have the host address. */
234
+ if (ptw->out_be) {
235
+ data = ldl_be_p(ptw->out_host);
236
+ } else {
237
+ data = ldl_le_p(ptw->out_host);
238
+ }
239
} else {
240
- data = address_space_ldl_le(as, addr, attrs, &result);
241
+ /* Page tables are in MMIO. */
242
+ MemTxAttrs attrs = { .secure = ptw->out_secure };
243
+ AddressSpace *as = arm_addressspace(cs, attrs);
244
+ MemTxResult result = MEMTX_OK;
245
+
246
+ if (ptw->out_be) {
247
+ data = address_space_ldl_be(as, ptw->out_phys, attrs, &result);
248
+ } else {
249
+ data = address_space_ldl_le(as, ptw->out_phys, attrs, &result);
250
+ }
251
+ if (unlikely(result != MEMTX_OK)) {
252
+ fi->type = ARMFault_SyncExternalOnWalk;
253
+ fi->ea = arm_extabort_type(result);
254
+ return 0;
255
+ }
256
}
257
- if (result == MEMTX_OK) {
258
- return data;
259
- }
260
- fi->type = ARMFault_SyncExternalOnWalk;
261
- fi->ea = arm_extabort_type(result);
262
- return 0;
263
+ return data;
264
}
265
266
static uint64_t arm_ldq_ptw(CPUARMState *env, S1Translate *ptw, hwaddr addr,
267
ARMMMUFaultInfo *fi)
268
{
269
CPUState *cs = env_cpu(env);
270
- MemTxAttrs attrs = {};
271
- MemTxResult result = MEMTX_OK;
272
- AddressSpace *as;
273
uint64_t data;
274
275
if (!S1_ptw_translate(env, ptw, addr, fi)) {
276
+ /* Failure. */
277
+ assert(fi->s1ptw);
278
return 0;
279
}
280
- addr = ptw->out_phys;
281
- attrs.secure = ptw->out_secure;
282
- as = arm_addressspace(cs, attrs);
283
- if (ptw->out_be) {
284
- data = address_space_ldq_be(as, addr, attrs, &result);
285
+
286
+ if (likely(ptw->out_host)) {
287
+ /* Page tables are in RAM, and we have the host address. */
288
+ if (ptw->out_be) {
289
+ data = ldq_be_p(ptw->out_host);
290
+ } else {
291
+ data = ldq_le_p(ptw->out_host);
292
+ }
293
} else {
294
- data = address_space_ldq_le(as, addr, attrs, &result);
295
+ /* Page tables are in MMIO. */
296
+ MemTxAttrs attrs = { .secure = ptw->out_secure };
297
+ AddressSpace *as = arm_addressspace(cs, attrs);
298
+ MemTxResult result = MEMTX_OK;
299
+
300
+ if (ptw->out_be) {
301
+ data = address_space_ldq_be(as, ptw->out_phys, attrs, &result);
302
+ } else {
303
+ data = address_space_ldq_le(as, ptw->out_phys, attrs, &result);
304
+ }
305
+ if (unlikely(result != MEMTX_OK)) {
306
+ fi->type = ARMFault_SyncExternalOnWalk;
307
+ fi->ea = arm_extabort_type(result);
308
+ return 0;
309
+ }
310
}
311
- if (result == MEMTX_OK) {
312
- return data;
313
- }
314
- fi->type = ARMFault_SyncExternalOnWalk;
315
- fi->ea = arm_extabort_type(result);
316
- return 0;
317
+ return data;
318
}
319
320
static bool get_level1_table_address(CPUARMState *env, ARMMMUIdx mmu_idx,
321
diff --git a/target/arm/tlb_helper.c b/target/arm/tlb_helper.c
47
index XXXXXXX..XXXXXXX 100644
322
index XXXXXXX..XXXXXXX 100644
48
--- a/hw/arm/exynos4210.c
323
--- a/target/arm/tlb_helper.c
49
+++ b/hw/arm/exynos4210.c
324
+++ b/target/arm/tlb_helper.c
50
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init_board_irqs(Exynos4210State *s)
325
@@ -XXX,XX +XXX,XX @@ bool arm_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
51
uint32_t grp, bit, irq_id, n;
326
bool probe, uintptr_t retaddr)
52
Exynos4210Irq *is = &s->irqs;
327
{
53
DeviceState *extgicdev = DEVICE(&s->ext_gic);
328
ARMCPU *cpu = ARM_CPU(cs);
54
+ int splitcount = 0;
329
- ARMMMUFaultInfo fi = {};
55
+ DeviceState *splitter;
330
GetPhysAddrResult res = {};
56
331
+ ARMMMUFaultInfo local_fi, *fi;
57
for (n = 0; n < EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ; n++) {
332
int ret;
58
irq_id = 0;
333
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
+ /*
334
+ /*
103
+ * We check this here to avoid a more obscure assert later when
335
+ * Allow S1_ptw_translate to see any fault generated here.
104
+ * qdev_assert_realized_properly() checks that we realized every
336
+ * Since this may recurse, read and clear.
105
+ * child object we initialized.
106
+ */
337
+ */
107
+ assert(splitcount == EXYNOS4210_NUM_SPLITTERS);
338
+ fi = cpu->env.tlb_fi;
108
}
339
+ if (fi) {
109
340
+ cpu->env.tlb_fi = NULL;
110
/*
341
+ } else {
111
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init(Object *obj)
342
+ fi = memset(&local_fi, 0, sizeof(local_fi));
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
+ }
343
+ }
119
+
344
+
120
object_initialize_child(obj, "a9mpcore", &s->a9mpcore, TYPE_A9MPCORE_PRIV);
345
/*
121
object_initialize_child(obj, "ext-gic", &s->ext_gic, TYPE_EXYNOS4210_GIC);
346
* Walk the page table and (if the mapping exists) add the page
122
}
347
* to the TLB. On success, return true. Otherwise, if probing,
348
@@ -XXX,XX +XXX,XX @@ bool arm_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
349
*/
350
ret = get_phys_addr(&cpu->env, address, access_type,
351
core_to_arm_mmu_idx(&cpu->env, mmu_idx),
352
- &res, &fi);
353
+ &res, fi);
354
if (likely(!ret)) {
355
/*
356
* Map a single [sub]page. Regions smaller than our declared
357
@@ -XXX,XX +XXX,XX @@ bool arm_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
358
} else {
359
/* now we have a real cpu fault */
360
cpu_restore_state(cs, retaddr, true);
361
- arm_deliver_fault(cpu, address, access_type, mmu_idx, &fi);
362
+ arm_deliver_fault(cpu, address, access_type, mmu_idx, fi);
363
}
364
}
365
#else
123
--
366
--
124
2.25.1
367
2.25.1
diff view generated by jsdifflib
1
The function exynos4210_combiner_get_gpioin() currently lives in
1
From: Richard Henderson <richard.henderson@linaro.org>
2
exynos4210_combiner.c, but it isn't really part of the combiner
3
device itself -- it is a function that implements the wiring up of
4
some interrupt sources to multiple combiner inputs. Move it to live
5
with the other SoC-level code in exynos4210.c, along with a few
6
macros previously defined in exynos4210.h which are now used only
7
in exynos4210.c.
8
2
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20221011031911.2408754-12-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20220404154658.565020-11-peter.maydell@linaro.org
12
---
7
---
13
include/hw/arm/exynos4210.h | 11 -----
8
target/arm/ptw.c | 191 +++++++++++++++++++++++++----------------------
14
hw/arm/exynos4210.c | 82 +++++++++++++++++++++++++++++++++++
9
1 file changed, 100 insertions(+), 91 deletions(-)
15
hw/intc/exynos4210_combiner.c | 77 --------------------------------
16
3 files changed, 82 insertions(+), 88 deletions(-)
17
10
18
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
11
diff --git a/target/arm/ptw.c b/target/arm/ptw.c
19
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
20
--- a/include/hw/arm/exynos4210.h
13
--- a/target/arm/ptw.c
21
+++ b/include/hw/arm/exynos4210.h
14
+++ b/target/arm/ptw.c
22
@@ -XXX,XX +XXX,XX @@
15
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
23
#define EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ \
16
GetPhysAddrResult *result, ARMMMUFaultInfo *fi)
24
(EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ * 8)
17
__attribute__((nonnull));
25
18
26
-#define EXYNOS4210_COMBINER_GET_IRQ_NUM(grp, bit) ((grp)*8 + (bit))
19
+static bool get_phys_addr_with_struct(CPUARMState *env, S1Translate *ptw,
27
-#define EXYNOS4210_COMBINER_GET_GRP_NUM(irq) ((irq) / 8)
20
+ target_ulong address,
28
-#define EXYNOS4210_COMBINER_GET_BIT_NUM(irq) \
21
+ MMUAccessType access_type,
29
- ((irq) - 8 * EXYNOS4210_COMBINER_GET_GRP_NUM(irq))
22
+ GetPhysAddrResult *result,
30
-
23
+ ARMMMUFaultInfo *fi)
31
/* IRQs number for external and internal GIC */
24
+ __attribute__((nonnull));
32
#define EXYNOS4210_EXT_GIC_NIRQ (160-32)
25
+
33
#define EXYNOS4210_INT_GIC_NIRQ 64
26
/* This mapping is common between ID_AA64MMFR0.PARANGE and TCR_ELx.{I}PS. */
34
@@ -XXX,XX +XXX,XX @@ void exynos4210_write_secondary(ARMCPU *cpu,
27
static const uint8_t pamax_map[] = {
35
* bit - bit number inside group */
28
[0] = 32,
36
uint32_t exynos4210_get_irq(uint32_t grp, uint32_t bit);
29
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_disabled(CPUARMState *env, target_ulong address,
37
30
return 0;
38
-/*
39
- * Get Combiner input GPIO into irqs structure
40
- */
41
-void exynos4210_combiner_get_gpioin(Exynos4210Irq *irqs, DeviceState *dev,
42
- int ext);
43
-
44
/*
45
* exynos4210 UART
46
*/
47
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
48
index XXXXXXX..XXXXXXX 100644
49
--- a/hw/arm/exynos4210.c
50
+++ b/hw/arm/exynos4210.c
51
@@ -XXX,XX +XXX,XX @@ combiner_grp_to_gic_id[64 - EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][8] = {
52
{ }, { }, { }, { }, { }, { }, { }, { }, { }, { }
53
};
54
55
+#define EXYNOS4210_COMBINER_GET_IRQ_NUM(grp, bit) ((grp) * 8 + (bit))
56
+#define EXYNOS4210_COMBINER_GET_GRP_NUM(irq) ((irq) / 8)
57
+#define EXYNOS4210_COMBINER_GET_BIT_NUM(irq) \
58
+ ((irq) - 8 * EXYNOS4210_COMBINER_GET_GRP_NUM(irq))
59
+
60
/*
61
* Initialize board IRQs.
62
* These IRQs contain splitted Int/External Combiner and External Gic IRQs.
63
@@ -XXX,XX +XXX,XX @@ uint32_t exynos4210_get_irq(uint32_t grp, uint32_t bit)
64
return EXYNOS4210_COMBINER_GET_IRQ_NUM(grp, bit);
65
}
31
}
66
32
67
+/*
33
+static bool get_phys_addr_twostage(CPUARMState *env, S1Translate *ptw,
68
+ * Get Combiner input GPIO into irqs structure
34
+ target_ulong address,
69
+ */
35
+ MMUAccessType access_type,
70
+static void exynos4210_combiner_get_gpioin(Exynos4210Irq *irqs,
36
+ GetPhysAddrResult *result,
71
+ DeviceState *dev, int ext)
37
+ ARMMMUFaultInfo *fi)
72
+{
38
+{
73
+ int n;
39
+ hwaddr ipa;
74
+ int bit;
40
+ int s1_prot;
75
+ int max;
41
+ int ret;
76
+ qemu_irq *irq;
42
+ bool is_secure = ptw->in_secure;
77
+
43
+ bool ipa_secure, s2walk_secure;
78
+ max = ext ? EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ :
44
+ ARMCacheAttrs cacheattrs1;
79
+ EXYNOS4210_MAX_INT_COMBINER_IN_IRQ;
45
+ bool is_el0;
80
+ irq = ext ? irqs->ext_combiner_irq : irqs->int_combiner_irq;
46
+ uint64_t hcr;
47
+
48
+ ret = get_phys_addr_with_struct(env, ptw, address, access_type, result, fi);
49
+
50
+ /* If S1 fails or S2 is disabled, return early. */
51
+ if (ret || regime_translation_disabled(env, ARMMMUIdx_Stage2, is_secure)) {
52
+ return ret;
53
+ }
54
+
55
+ ipa = result->f.phys_addr;
56
+ ipa_secure = result->f.attrs.secure;
57
+ if (is_secure) {
58
+ /* Select TCR based on the NS bit from the S1 walk. */
59
+ s2walk_secure = !(ipa_secure
60
+ ? env->cp15.vstcr_el2 & VSTCR_SW
61
+ : env->cp15.vtcr_el2 & VTCR_NSW);
62
+ } else {
63
+ assert(!ipa_secure);
64
+ s2walk_secure = false;
65
+ }
66
+
67
+ is_el0 = ptw->in_mmu_idx == ARMMMUIdx_Stage1_E0;
68
+ ptw->in_mmu_idx = s2walk_secure ? ARMMMUIdx_Stage2_S : ARMMMUIdx_Stage2;
69
+ ptw->in_secure = s2walk_secure;
81
+
70
+
82
+ /*
71
+ /*
83
+ * Some IRQs of Int/External Combiner are going to two Combiners groups,
72
+ * S1 is done, now do S2 translation.
84
+ * so let split them.
73
+ * Save the stage1 results so that we may merge prot and cacheattrs later.
85
+ */
74
+ */
86
+ for (n = 0; n < max; n++) {
75
+ s1_prot = result->f.prot;
87
+
76
+ cacheattrs1 = result->cacheattrs;
88
+ bit = EXYNOS4210_COMBINER_GET_BIT_NUM(n);
77
+ memset(result, 0, sizeof(*result));
89
+
78
+
90
+ switch (n) {
79
+ ret = get_phys_addr_lpae(env, ptw, ipa, access_type, is_el0, result, fi);
91
+ /* MDNIE_LCD1 INTG1 */
80
+ fi->s2addr = ipa;
92
+ case EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 0) ...
81
+
93
+ EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 3):
82
+ /* Combine the S1 and S2 perms. */
94
+ irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
83
+ result->f.prot &= s1_prot;
95
+ irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(0, bit + 4)]);
84
+
96
+ continue;
85
+ /* If S2 fails, return early. */
97
+
86
+ if (ret) {
98
+ /* TMU INTG3 */
87
+ return ret;
99
+ case EXYNOS4210_COMBINER_GET_IRQ_NUM(3, 4):
88
+ }
100
+ irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
89
+
101
+ irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(2, bit)]);
90
+ /* Combine the S1 and S2 cache attributes. */
102
+ continue;
91
+ hcr = arm_hcr_el2_eff_secstate(env, is_secure);
103
+
92
+ if (hcr & HCR_DC) {
104
+ /* LCD1 INTG12 */
93
+ /*
105
+ case EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 0) ...
94
+ * HCR.DC forces the first stage attributes to
106
+ EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 3):
95
+ * Normal Non-Shareable,
107
+ irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
96
+ * Inner Write-Back Read-Allocate Write-Allocate,
108
+ irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(11, bit + 4)]);
97
+ * Outer Write-Back Read-Allocate Write-Allocate.
109
+ continue;
98
+ * Do not overwrite Tagged within attrs.
110
+
99
+ */
111
+ /* Multi-Core Timer INTG12 */
100
+ if (cacheattrs1.attrs != 0xf0) {
112
+ case EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 4) ...
101
+ cacheattrs1.attrs = 0xff;
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
+ }
102
+ }
139
+
103
+ cacheattrs1.shareability = 0;
140
+ irq[n] = qdev_get_gpio_in(dev, n);
104
+ }
141
+ }
105
+ result->cacheattrs = combine_cacheattrs(hcr, cacheattrs1,
106
+ result->cacheattrs);
107
+
108
+ /*
109
+ * Check if IPA translates to secure or non-secure PA space.
110
+ * Note that VSTCR overrides VTCR and {N}SW overrides {N}SA.
111
+ */
112
+ result->f.attrs.secure =
113
+ (is_secure
114
+ && !(env->cp15.vstcr_el2 & (VSTCR_SA | VSTCR_SW))
115
+ && (ipa_secure
116
+ || !(env->cp15.vtcr_el2 & (VTCR_NSA | VTCR_NSW))));
117
+
118
+ return 0;
142
+}
119
+}
143
+
120
+
144
static uint8_t chipid_and_omr[] = { 0x11, 0x02, 0x21, 0x43,
121
static bool get_phys_addr_with_struct(CPUARMState *env, S1Translate *ptw,
145
0x09, 0x00, 0x00, 0x00 };
122
target_ulong address,
146
123
MMUAccessType access_type,
147
diff --git a/hw/intc/exynos4210_combiner.c b/hw/intc/exynos4210_combiner.c
124
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_with_struct(CPUARMState *env, S1Translate *ptw,
148
index XXXXXXX..XXXXXXX 100644
125
if (mmu_idx != s1_mmu_idx) {
149
--- a/hw/intc/exynos4210_combiner.c
126
/*
150
+++ b/hw/intc/exynos4210_combiner.c
127
* Call ourselves recursively to do the stage 1 and then stage 2
151
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_exynos4210_combiner = {
128
- * translations if mmu_idx is a two-stage regime.
129
+ * translations if mmu_idx is a two-stage regime, and EL2 present.
130
+ * Otherwise, a stage1+stage2 translation is just stage 1.
131
*/
132
+ ptw->in_mmu_idx = mmu_idx = s1_mmu_idx;
133
if (arm_feature(env, ARM_FEATURE_EL2)) {
134
- hwaddr ipa;
135
- int s1_prot;
136
- int ret;
137
- bool ipa_secure, s2walk_secure;
138
- ARMCacheAttrs cacheattrs1;
139
- bool is_el0;
140
- uint64_t hcr;
141
-
142
- ptw->in_mmu_idx = s1_mmu_idx;
143
- ret = get_phys_addr_with_struct(env, ptw, address, access_type,
144
- result, fi);
145
-
146
- /* If S1 fails or S2 is disabled, return early. */
147
- if (ret || regime_translation_disabled(env, ARMMMUIdx_Stage2,
148
- is_secure)) {
149
- return ret;
150
- }
151
-
152
- ipa = result->f.phys_addr;
153
- ipa_secure = result->f.attrs.secure;
154
- if (is_secure) {
155
- /* Select TCR based on the NS bit from the S1 walk. */
156
- s2walk_secure = !(ipa_secure
157
- ? env->cp15.vstcr_el2 & VSTCR_SW
158
- : env->cp15.vtcr_el2 & VTCR_NSW);
159
- } else {
160
- assert(!ipa_secure);
161
- s2walk_secure = false;
162
- }
163
-
164
- ptw->in_mmu_idx =
165
- s2walk_secure ? ARMMMUIdx_Stage2_S : ARMMMUIdx_Stage2;
166
- ptw->in_secure = s2walk_secure;
167
- is_el0 = mmu_idx == ARMMMUIdx_E10_0;
168
-
169
- /*
170
- * S1 is done, now do S2 translation.
171
- * Save the stage1 results so that we may merge
172
- * prot and cacheattrs later.
173
- */
174
- s1_prot = result->f.prot;
175
- cacheattrs1 = result->cacheattrs;
176
- memset(result, 0, sizeof(*result));
177
-
178
- ret = get_phys_addr_lpae(env, ptw, ipa, access_type,
179
- is_el0, result, fi);
180
- fi->s2addr = ipa;
181
-
182
- /* Combine the S1 and S2 perms. */
183
- result->f.prot &= s1_prot;
184
-
185
- /* If S2 fails, return early. */
186
- if (ret) {
187
- return ret;
188
- }
189
-
190
- /* Combine the S1 and S2 cache attributes. */
191
- hcr = arm_hcr_el2_eff_secstate(env, is_secure);
192
- if (hcr & HCR_DC) {
193
- /*
194
- * HCR.DC forces the first stage attributes to
195
- * Normal Non-Shareable,
196
- * Inner Write-Back Read-Allocate Write-Allocate,
197
- * Outer Write-Back Read-Allocate Write-Allocate.
198
- * Do not overwrite Tagged within attrs.
199
- */
200
- if (cacheattrs1.attrs != 0xf0) {
201
- cacheattrs1.attrs = 0xff;
202
- }
203
- cacheattrs1.shareability = 0;
204
- }
205
- result->cacheattrs = combine_cacheattrs(hcr, cacheattrs1,
206
- result->cacheattrs);
207
-
208
- /*
209
- * Check if IPA translates to secure or non-secure PA space.
210
- * Note that VSTCR overrides VTCR and {N}SW overrides {N}SA.
211
- */
212
- result->f.attrs.secure =
213
- (is_secure
214
- && !(env->cp15.vstcr_el2 & (VSTCR_SA | VSTCR_SW))
215
- && (ipa_secure
216
- || !(env->cp15.vtcr_el2 & (VTCR_NSA | VTCR_NSW))));
217
-
218
- return 0;
219
- } else {
220
- /*
221
- * For non-EL2 CPUs a stage1+stage2 translation is just stage 1.
222
- */
223
- mmu_idx = stage_1_mmu_idx(mmu_idx);
224
+ return get_phys_addr_twostage(env, ptw, address, access_type,
225
+ result, fi);
226
}
152
}
227
}
153
};
228
154
155
-/*
156
- * Get Combiner input GPIO into irqs structure
157
- */
158
-void exynos4210_combiner_get_gpioin(Exynos4210Irq *irqs, DeviceState *dev,
159
- int ext)
160
-{
161
- int n;
162
- int bit;
163
- int max;
164
- qemu_irq *irq;
165
-
166
- max = ext ? EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ :
167
- EXYNOS4210_MAX_INT_COMBINER_IN_IRQ;
168
- irq = ext ? irqs->ext_combiner_irq : irqs->int_combiner_irq;
169
-
170
- /*
171
- * Some IRQs of Int/External Combiner are going to two Combiners groups,
172
- * so let split them.
173
- */
174
- for (n = 0; n < max; n++) {
175
-
176
- bit = EXYNOS4210_COMBINER_GET_BIT_NUM(n);
177
-
178
- switch (n) {
179
- /* MDNIE_LCD1 INTG1 */
180
- case EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 0) ...
181
- EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 3):
182
- irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
183
- irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(0, bit + 4)]);
184
- continue;
185
-
186
- /* TMU INTG3 */
187
- case EXYNOS4210_COMBINER_GET_IRQ_NUM(3, 4):
188
- irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
189
- irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(2, bit)]);
190
- continue;
191
-
192
- /* LCD1 INTG12 */
193
- case EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 0) ...
194
- EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 3):
195
- irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
196
- irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(11, bit + 4)]);
197
- continue;
198
-
199
- /* Multi-Core Timer INTG12 */
200
- case EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 4) ...
201
- EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 8):
202
- irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
203
- irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(1, bit + 4)]);
204
- continue;
205
-
206
- /* Multi-Core Timer INTG35 */
207
- case EXYNOS4210_COMBINER_GET_IRQ_NUM(35, 4) ...
208
- EXYNOS4210_COMBINER_GET_IRQ_NUM(35, 8):
209
- irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
210
- irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(1, bit + 4)]);
211
- continue;
212
-
213
- /* Multi-Core Timer INTG51 */
214
- case EXYNOS4210_COMBINER_GET_IRQ_NUM(51, 4) ...
215
- EXYNOS4210_COMBINER_GET_IRQ_NUM(51, 8):
216
- irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
217
- irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(1, bit + 4)]);
218
- continue;
219
-
220
- /* Multi-Core Timer INTG53 */
221
- case EXYNOS4210_COMBINER_GET_IRQ_NUM(53, 4) ...
222
- EXYNOS4210_COMBINER_GET_IRQ_NUM(53, 8):
223
- irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
224
- irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(1, bit + 4)]);
225
- continue;
226
- }
227
-
228
- irq[n] = qdev_get_gpio_in(dev, n);
229
- }
230
-}
231
-
232
static uint64_t
233
exynos4210_combiner_read(void *opaque, hwaddr offset, unsigned size)
234
{
235
--
229
--
236
2.25.1
230
2.25.1
diff view generated by jsdifflib
1
From: "Edgar E. Iglesias" <edgar.iglesias@amd.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Create an APU CPU Cluster. This is in preparation to add the RPU.
3
The return type of the functions is already bool, but in a few
4
instances we used an integer type with the return statement.
4
5
5
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Francisco Iglesias <francisco.iglesias@amd.com>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20220406174303.2022038-2-edgar.iglesias@xilinx.com
8
Message-id: 20221011031911.2408754-13-richard.henderson@linaro.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
---
10
include/hw/arm/xlnx-versal.h | 2 ++
11
target/arm/ptw.c | 7 +++----
11
hw/arm/xlnx-versal.c | 9 ++++++++-
12
1 file changed, 3 insertions(+), 4 deletions(-)
12
2 files changed, 10 insertions(+), 1 deletion(-)
13
13
14
diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
14
diff --git a/target/arm/ptw.c b/target/arm/ptw.c
15
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
16
--- a/include/hw/arm/xlnx-versal.h
16
--- a/target/arm/ptw.c
17
+++ b/include/hw/arm/xlnx-versal.h
17
+++ b/target/arm/ptw.c
18
@@ -XXX,XX +XXX,XX @@
18
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_disabled(CPUARMState *env, target_ulong address,
19
19
result->f.lg_page_size = TARGET_PAGE_BITS;
20
#include "hw/sysbus.h"
20
result->cacheattrs.shareability = shareability;
21
#include "hw/arm/boot.h"
21
result->cacheattrs.attrs = memattr;
22
+#include "hw/cpu/cluster.h"
22
- return 0;
23
#include "hw/or-irq.h"
23
+ return false;
24
#include "hw/sd/sdhci.h"
24
}
25
#include "hw/intc/arm_gicv3.h"
25
26
@@ -XXX,XX +XXX,XX @@ struct Versal {
26
static bool get_phys_addr_twostage(CPUARMState *env, S1Translate *ptw,
27
struct {
27
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_twostage(CPUARMState *env, S1Translate *ptw,
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
{
28
{
40
int i;
29
hwaddr ipa;
41
30
int s1_prot;
42
+ object_initialize_child(OBJECT(s), "apu-cluster", &s->fpd.apu.cluster,
31
- int ret;
43
+ TYPE_CPU_CLUSTER);
32
bool is_secure = ptw->in_secure;
44
+ qdev_prop_set_uint32(DEVICE(&s->fpd.apu.cluster), "cluster-id", 0);
33
- bool ipa_secure, s2walk_secure;
45
+
34
+ bool ret, ipa_secure, s2walk_secure;
46
for (i = 0; i < ARRAY_SIZE(s->fpd.apu.cpu); i++) {
35
ARMCacheAttrs cacheattrs1;
47
Object *obj;
36
bool is_el0;
48
37
uint64_t hcr;
49
- object_initialize_child(OBJECT(s), "apu-cpu[*]", &s->fpd.apu.cpu[i],
38
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_twostage(CPUARMState *env, S1Translate *ptw,
50
+ object_initialize_child(OBJECT(&s->fpd.apu.cluster),
39
&& (ipa_secure
51
+ "apu-cpu[*]", &s->fpd.apu.cpu[i],
40
|| !(env->cp15.vtcr_el2 & (VTCR_NSA | VTCR_NSW))));
52
XLNX_VERSAL_ACPU_TYPE);
41
53
obj = OBJECT(&s->fpd.apu.cpu[i]);
42
- return 0;
54
if (i) {
43
+ return false;
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
}
44
}
62
45
63
static void versal_create_apu_gic(Versal *s, qemu_irq *pic)
46
static bool get_phys_addr_with_struct(CPUARMState *env, S1Translate *ptw,
64
--
47
--
65
2.25.1
48
2.25.1
diff view generated by jsdifflib
1
From: "Edgar E. Iglesias" <edgar.iglesias@amd.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Connect the 4 TTC timers on the ZynqMP.
3
A simple helper to retrieve the length of the current insn.
4
4
5
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>
5
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Luc Michel <luc@lmichel.fr>
7
Message-id: 20221020030641.2066807-2-richard.henderson@linaro.org
8
Reviewed-by: Francisco Iglesias <frasse.iglesias@gmail.com>
9
Message-id: 20220331222017.2914409-3-edgar.iglesias@gmail.com
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
9
---
12
include/hw/arm/xlnx-zynqmp.h | 4 ++++
10
target/arm/translate.h | 5 +++++
13
hw/arm/xlnx-zynqmp.c | 22 ++++++++++++++++++++++
11
target/arm/translate-vfp.c | 2 +-
14
2 files changed, 26 insertions(+)
12
target/arm/translate.c | 5 ++---
13
3 files changed, 8 insertions(+), 4 deletions(-)
15
14
16
diff --git a/include/hw/arm/xlnx-zynqmp.h b/include/hw/arm/xlnx-zynqmp.h
15
diff --git a/target/arm/translate.h b/target/arm/translate.h
17
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
18
--- a/include/hw/arm/xlnx-zynqmp.h
17
--- a/target/arm/translate.h
19
+++ b/include/hw/arm/xlnx-zynqmp.h
18
+++ b/target/arm/translate.h
20
@@ -XXX,XX +XXX,XX @@
19
@@ -XXX,XX +XXX,XX @@ static inline void disas_set_insn_syndrome(DisasContext *s, uint32_t syn)
21
#include "hw/or-irq.h"
20
s->insn_start = NULL;
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
}
21
}
62
22
63
+static void xlnx_zynqmp_create_ttc(XlnxZynqMPState *s, qemu_irq *gic)
23
+static inline int curr_insn_len(DisasContext *s)
64
+{
24
+{
65
+ SysBusDevice *sbd;
25
+ return s->base.pc_next - s->pc_curr;
66
+ int i, irq;
67
+
68
+ for (i = 0; i < XLNX_ZYNQMP_NUM_TTC; i++) {
69
+ object_initialize_child(OBJECT(s), "ttc[*]", &s->ttc[i],
70
+ TYPE_CADENCE_TTC);
71
+ sbd = SYS_BUS_DEVICE(&s->ttc[i]);
72
+
73
+ sysbus_realize(sbd, &error_fatal);
74
+ sysbus_mmio_map(sbd, 0, TTC0_ADDR + i * 0x10000);
75
+ for (irq = 0; irq < 3; irq++) {
76
+ sysbus_connect_irq(sbd, irq, gic[TTC0_IRQ + i * 3 + irq]);
77
+ }
78
+ }
79
+}
26
+}
80
+
27
+
81
static void xlnx_zynqmp_create_unimp_mmio(XlnxZynqMPState *s)
28
/* is_jmp field values */
82
{
29
#define DISAS_JUMP DISAS_TARGET_0 /* only pc was modified dynamically */
83
static const struct UnimpInfo {
30
/* CPU state was modified dynamically; exit to main loop for interrupts. */
84
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
31
diff --git a/target/arm/translate-vfp.c b/target/arm/translate-vfp.c
85
xlnx_zynqmp_create_efuse(s, gic_spi);
32
index XXXXXXX..XXXXXXX 100644
86
xlnx_zynqmp_create_apu_ctrl(s, gic_spi);
33
--- a/target/arm/translate-vfp.c
87
xlnx_zynqmp_create_crf(s, gic_spi);
34
+++ b/target/arm/translate-vfp.c
88
+ xlnx_zynqmp_create_ttc(s, gic_spi);
35
@@ -XXX,XX +XXX,XX @@ static bool vfp_access_check_a(DisasContext *s, bool ignore_vfp_enabled)
89
xlnx_zynqmp_create_unimp_mmio(s);
36
if (s->sme_trap_nonstreaming) {
90
37
gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
91
for (i = 0; i < XLNX_ZYNQMP_NUM_GDMA_CH; i++) {
38
syn_smetrap(SME_ET_Streaming,
39
- s->base.pc_next - s->pc_curr == 2));
40
+ curr_insn_len(s) == 2));
41
return false;
42
}
43
44
diff --git a/target/arm/translate.c b/target/arm/translate.c
45
index XXXXXXX..XXXXXXX 100644
46
--- a/target/arm/translate.c
47
+++ b/target/arm/translate.c
48
@@ -XXX,XX +XXX,XX @@ static ISSInfo make_issinfo(DisasContext *s, int rd, bool p, bool w)
49
/* ISS not valid if writeback */
50
if (p && !w) {
51
ret = rd;
52
- if (s->base.pc_next - s->pc_curr == 2) {
53
+ if (curr_insn_len(s) == 2) {
54
ret |= ISSIs16Bit;
55
}
56
} else {
57
@@ -XXX,XX +XXX,XX @@ static void arm_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
58
/* nothing more to generate */
59
break;
60
case DISAS_WFI:
61
- gen_helper_wfi(cpu_env,
62
- tcg_constant_i32(dc->base.pc_next - dc->pc_curr));
63
+ gen_helper_wfi(cpu_env, tcg_constant_i32(curr_insn_len(dc)));
64
/*
65
* The helper doesn't necessarily throw an exception, but we
66
* must go back to the main loop to check for interrupts anyway.
92
--
67
--
93
2.25.1
68
2.25.1
69
70
diff view generated by jsdifflib
1
The only time we use the ext_gic_irq[] array in the Exynos4210Irq
1
From: Richard Henderson <richard.henderson@linaro.org>
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
2
3
In preparation for TARGET_TB_PCREL, reduce reliance on absolute values.
4
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20221020030641.2066807-3-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
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
---
9
---
13
include/hw/arm/exynos4210.h | 1 -
10
target/arm/translate-a64.c | 40 ++++++++++++++++++++------------------
14
hw/arm/exynos4210.c | 12 ++++++------
11
target/arm/translate.c | 10 ++++++----
15
2 files changed, 6 insertions(+), 7 deletions(-)
12
2 files changed, 27 insertions(+), 23 deletions(-)
16
13
17
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
14
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
18
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
19
--- a/include/hw/arm/exynos4210.h
16
--- a/target/arm/translate-a64.c
20
+++ b/include/hw/arm/exynos4210.h
17
+++ b/target/arm/translate-a64.c
21
@@ -XXX,XX +XXX,XX @@
18
@@ -XXX,XX +XXX,XX @@ static inline bool use_goto_tb(DisasContext *s, uint64_t dest)
22
typedef struct Exynos4210Irq {
19
return translator_use_goto_tb(&s->base, dest);
23
qemu_irq int_combiner_irq[EXYNOS4210_MAX_INT_COMBINER_IN_IRQ];
20
}
24
qemu_irq ext_combiner_irq[EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ];
21
25
- qemu_irq ext_gic_irq[EXYNOS4210_EXT_GIC_NIRQ];
22
-static inline void gen_goto_tb(DisasContext *s, int n, uint64_t dest)
26
} Exynos4210Irq;
23
+static void gen_goto_tb(DisasContext *s, int n, int64_t diff)
27
24
{
28
struct Exynos4210State {
25
+ uint64_t dest = s->pc_curr + diff;
29
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
26
+
27
if (use_goto_tb(s, dest)) {
28
tcg_gen_goto_tb(n);
29
gen_a64_set_pc_im(dest);
30
@@ -XXX,XX +XXX,XX @@ static inline AArch64DecodeFn *lookup_disas_fn(const AArch64DecodeTable *table,
31
*/
32
static void disas_uncond_b_imm(DisasContext *s, uint32_t insn)
33
{
34
- uint64_t addr = s->pc_curr + sextract32(insn, 0, 26) * 4;
35
+ int64_t diff = sextract32(insn, 0, 26) * 4;
36
37
if (insn & (1U << 31)) {
38
/* BL Branch with link */
39
@@ -XXX,XX +XXX,XX @@ static void disas_uncond_b_imm(DisasContext *s, uint32_t insn)
40
41
/* B Branch / BL Branch with link */
42
reset_btype(s);
43
- gen_goto_tb(s, 0, addr);
44
+ gen_goto_tb(s, 0, diff);
45
}
46
47
/* Compare and branch (immediate)
48
@@ -XXX,XX +XXX,XX @@ static void disas_uncond_b_imm(DisasContext *s, uint32_t insn)
49
static void disas_comp_b_imm(DisasContext *s, uint32_t insn)
50
{
51
unsigned int sf, op, rt;
52
- uint64_t addr;
53
+ int64_t diff;
54
TCGLabel *label_match;
55
TCGv_i64 tcg_cmp;
56
57
sf = extract32(insn, 31, 1);
58
op = extract32(insn, 24, 1); /* 0: CBZ; 1: CBNZ */
59
rt = extract32(insn, 0, 5);
60
- addr = s->pc_curr + sextract32(insn, 5, 19) * 4;
61
+ diff = sextract32(insn, 5, 19) * 4;
62
63
tcg_cmp = read_cpu_reg(s, rt, sf);
64
label_match = gen_new_label();
65
@@ -XXX,XX +XXX,XX @@ static void disas_comp_b_imm(DisasContext *s, uint32_t insn)
66
tcg_gen_brcondi_i64(op ? TCG_COND_NE : TCG_COND_EQ,
67
tcg_cmp, 0, label_match);
68
69
- gen_goto_tb(s, 0, s->base.pc_next);
70
+ gen_goto_tb(s, 0, 4);
71
gen_set_label(label_match);
72
- gen_goto_tb(s, 1, addr);
73
+ gen_goto_tb(s, 1, diff);
74
}
75
76
/* Test and branch (immediate)
77
@@ -XXX,XX +XXX,XX @@ static void disas_comp_b_imm(DisasContext *s, uint32_t insn)
78
static void disas_test_b_imm(DisasContext *s, uint32_t insn)
79
{
80
unsigned int bit_pos, op, rt;
81
- uint64_t addr;
82
+ int64_t diff;
83
TCGLabel *label_match;
84
TCGv_i64 tcg_cmp;
85
86
bit_pos = (extract32(insn, 31, 1) << 5) | extract32(insn, 19, 5);
87
op = extract32(insn, 24, 1); /* 0: TBZ; 1: TBNZ */
88
- addr = s->pc_curr + sextract32(insn, 5, 14) * 4;
89
+ diff = sextract32(insn, 5, 14) * 4;
90
rt = extract32(insn, 0, 5);
91
92
tcg_cmp = tcg_temp_new_i64();
93
@@ -XXX,XX +XXX,XX @@ static void disas_test_b_imm(DisasContext *s, uint32_t insn)
94
tcg_gen_brcondi_i64(op ? TCG_COND_NE : TCG_COND_EQ,
95
tcg_cmp, 0, label_match);
96
tcg_temp_free_i64(tcg_cmp);
97
- gen_goto_tb(s, 0, s->base.pc_next);
98
+ gen_goto_tb(s, 0, 4);
99
gen_set_label(label_match);
100
- gen_goto_tb(s, 1, addr);
101
+ gen_goto_tb(s, 1, diff);
102
}
103
104
/* Conditional branch (immediate)
105
@@ -XXX,XX +XXX,XX @@ static void disas_test_b_imm(DisasContext *s, uint32_t insn)
106
static void disas_cond_b_imm(DisasContext *s, uint32_t insn)
107
{
108
unsigned int cond;
109
- uint64_t addr;
110
+ int64_t diff;
111
112
if ((insn & (1 << 4)) || (insn & (1 << 24))) {
113
unallocated_encoding(s);
114
return;
115
}
116
- addr = s->pc_curr + sextract32(insn, 5, 19) * 4;
117
+ diff = sextract32(insn, 5, 19) * 4;
118
cond = extract32(insn, 0, 4);
119
120
reset_btype(s);
121
@@ -XXX,XX +XXX,XX @@ static void disas_cond_b_imm(DisasContext *s, uint32_t insn)
122
/* genuinely conditional branches */
123
TCGLabel *label_match = gen_new_label();
124
arm_gen_test_cc(cond, label_match);
125
- gen_goto_tb(s, 0, s->base.pc_next);
126
+ gen_goto_tb(s, 0, 4);
127
gen_set_label(label_match);
128
- gen_goto_tb(s, 1, addr);
129
+ gen_goto_tb(s, 1, diff);
130
} else {
131
/* 0xe and 0xf are both "always" conditions */
132
- gen_goto_tb(s, 0, addr);
133
+ gen_goto_tb(s, 0, diff);
134
}
135
}
136
137
@@ -XXX,XX +XXX,XX @@ static void handle_sync(DisasContext *s, uint32_t insn,
138
* any pending interrupts immediately.
139
*/
140
reset_btype(s);
141
- gen_goto_tb(s, 0, s->base.pc_next);
142
+ gen_goto_tb(s, 0, 4);
143
return;
144
145
case 7: /* SB */
146
@@ -XXX,XX +XXX,XX @@ static void handle_sync(DisasContext *s, uint32_t insn,
147
* MB and end the TB instead.
148
*/
149
tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
150
- gen_goto_tb(s, 0, s->base.pc_next);
151
+ gen_goto_tb(s, 0, 4);
152
return;
153
154
default:
155
@@ -XXX,XX +XXX,XX @@ static void aarch64_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
156
switch (dc->base.is_jmp) {
157
case DISAS_NEXT:
158
case DISAS_TOO_MANY:
159
- gen_goto_tb(dc, 1, dc->base.pc_next);
160
+ gen_goto_tb(dc, 1, 4);
161
break;
162
default:
163
case DISAS_UPDATE_EXIT:
164
diff --git a/target/arm/translate.c b/target/arm/translate.c
30
index XXXXXXX..XXXXXXX 100644
165
index XXXXXXX..XXXXXXX 100644
31
--- a/hw/arm/exynos4210.c
166
--- a/target/arm/translate.c
32
+++ b/hw/arm/exynos4210.c
167
+++ b/target/arm/translate.c
33
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init_board_irqs(Exynos4210State *s)
168
@@ -XXX,XX +XXX,XX @@ static void gen_goto_ptr(void)
34
{
169
* cpu_loop_exec. Any live exit_requests will be processed as we
35
uint32_t grp, bit, irq_id, n;
170
* enter the next TB.
36
Exynos4210Irq *is = &s->irqs;
171
*/
37
+ DeviceState *extgicdev = DEVICE(&s->ext_gic);
172
-static void gen_goto_tb(DisasContext *s, int n, target_ulong dest)
38
173
+static void gen_goto_tb(DisasContext *s, int n, int diff)
39
for (n = 0; n < EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ; n++) {
174
{
40
irq_id = 0;
175
+ target_ulong dest = s->pc_curr + diff;
41
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init_board_irqs(Exynos4210State *s)
176
+
42
}
177
if (translator_use_goto_tb(&s->base, dest)) {
43
if (irq_id) {
178
tcg_gen_goto_tb(n);
44
s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
179
gen_set_pc_im(s, dest);
45
- is->ext_gic_irq[irq_id - 32]);
180
@@ -XXX,XX +XXX,XX @@ static inline void gen_jmp_tb(DisasContext *s, uint32_t dest, int tbno)
46
+ qdev_get_gpio_in(extgicdev,
181
* gen_jmp();
47
+ irq_id - 32));
182
* on the second call to gen_jmp().
183
*/
184
- gen_goto_tb(s, tbno, dest);
185
+ gen_goto_tb(s, tbno, dest - s->pc_curr);
186
break;
187
case DISAS_UPDATE_NOCHAIN:
188
case DISAS_UPDATE_EXIT:
189
@@ -XXX,XX +XXX,XX @@ static void arm_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
190
switch (dc->base.is_jmp) {
191
case DISAS_NEXT:
192
case DISAS_TOO_MANY:
193
- gen_goto_tb(dc, 1, dc->base.pc_next);
194
+ gen_goto_tb(dc, 1, curr_insn_len(dc));
195
break;
196
case DISAS_UPDATE_NOCHAIN:
197
gen_set_pc_im(dc, dc->base.pc_next);
198
@@ -XXX,XX +XXX,XX @@ static void arm_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
199
gen_set_pc_im(dc, dc->base.pc_next);
200
gen_singlestep_exception(dc);
48
} else {
201
} else {
49
s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
202
- gen_goto_tb(dc, 1, dc->base.pc_next);
50
is->ext_combiner_irq[n]);
203
+ gen_goto_tb(dc, 1, curr_insn_len(dc));
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
}
204
}
59
}
205
}
60
}
206
}
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
--
207
--
81
2.25.1
208
2.25.1
diff view generated by jsdifflib
1
At this point, the function exynos4210_init_board_irqs() splits input
1
From: Richard Henderson <richard.henderson@linaro.org>
2
IRQ lines to connect them to the input combiner, output combiner and
3
external GIC. The function exynos4210_combiner_get_gpioin() splits
4
some of the combiner input lines further to connect them to multiple
5
different inputs on the combiner.
6
2
7
Because (unlike qemu_irq_split()) the TYPE_SPLIT_IRQ device has a
3
In preparation for TARGET_TB_PCREL, reduce reliance on
8
configurable number of outputs, we can do all this in one place, by
4
absolute values by passing in pc difference.
9
making exynos4210_init_board_irqs() add extra outputs to the splitter
10
device when it must be connected to more than one input on each
11
combiner.
12
5
13
We do this with a new data structure, the combinermap, which is an
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
14
array each of whose elements is a list of the interrupt IDs on the
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
15
combiner which must be tied together. As we loop through each
8
Message-id: 20221020030641.2066807-4-richard.henderson@linaro.org
16
interrupt ID, if we find that it is the first one in one of these
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
lists, we configure the splitter device with eonugh extra outputs and
10
---
18
wire them up to the other interrupt IDs in the list.
11
target/arm/translate-a32.h | 2 +-
12
target/arm/translate.h | 6 ++--
13
target/arm/translate-a64.c | 32 +++++++++---------
14
target/arm/translate-vfp.c | 2 +-
15
target/arm/translate.c | 68 ++++++++++++++++++++------------------
16
5 files changed, 56 insertions(+), 54 deletions(-)
19
17
20
Conveniently, for all the cases where this is necessary, the
18
diff --git a/target/arm/translate-a32.h b/target/arm/translate-a32.h
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>
40
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
41
Message-id: 20220404154658.565020-17-peter.maydell@linaro.org
42
---
43
include/hw/arm/exynos4210.h | 6 +-
44
hw/arm/exynos4210.c | 178 +++++++++++++++++++++++-------------
45
2 files changed, 119 insertions(+), 65 deletions(-)
46
47
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
48
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
49
--- a/include/hw/arm/exynos4210.h
20
--- a/target/arm/translate-a32.h
50
+++ b/include/hw/arm/exynos4210.h
21
+++ b/target/arm/translate-a32.h
51
@@ -XXX,XX +XXX,XX @@
22
@@ -XXX,XX +XXX,XX @@ void write_neon_element64(TCGv_i64 src, int reg, int ele, MemOp memop);
23
TCGv_i32 add_reg_for_lit(DisasContext *s, int reg, int ofs);
24
void gen_set_cpsr(TCGv_i32 var, uint32_t mask);
25
void gen_set_condexec(DisasContext *s);
26
-void gen_set_pc_im(DisasContext *s, target_ulong val);
27
+void gen_update_pc(DisasContext *s, target_long diff);
28
void gen_lookup_tb(DisasContext *s);
29
long vfp_reg_offset(bool dp, unsigned reg);
30
long neon_full_reg_offset(unsigned reg);
31
diff --git a/target/arm/translate.h b/target/arm/translate.h
32
index XXXXXXX..XXXXXXX 100644
33
--- a/target/arm/translate.h
34
+++ b/target/arm/translate.h
35
@@ -XXX,XX +XXX,XX @@ static inline int curr_insn_len(DisasContext *s)
36
* For instructions which want an immediate exit to the main loop, as opposed
37
* to attempting to use lookup_and_goto_ptr. Unlike DISAS_UPDATE_EXIT, this
38
* doesn't write the PC on exiting the translation loop so you need to ensure
39
- * something (gen_a64_set_pc_im or runtime helper) has done so before we reach
40
+ * something (gen_a64_update_pc or runtime helper) has done so before we reach
41
* return from cpu_tb_exec.
42
*/
43
#define DISAS_EXIT DISAS_TARGET_9
44
@@ -XXX,XX +XXX,XX @@ static inline int curr_insn_len(DisasContext *s)
45
46
#ifdef TARGET_AARCH64
47
void a64_translate_init(void);
48
-void gen_a64_set_pc_im(uint64_t val);
49
+void gen_a64_update_pc(DisasContext *s, target_long diff);
50
extern const TranslatorOps aarch64_translator_ops;
51
#else
52
static inline void a64_translate_init(void)
53
{
54
}
55
56
-static inline void gen_a64_set_pc_im(uint64_t val)
57
+static inline void gen_a64_update_pc(DisasContext *s, target_long diff)
58
{
59
}
60
#endif
61
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
62
index XXXXXXX..XXXXXXX 100644
63
--- a/target/arm/translate-a64.c
64
+++ b/target/arm/translate-a64.c
65
@@ -XXX,XX +XXX,XX @@ static void reset_btype(DisasContext *s)
66
}
67
}
68
69
-void gen_a64_set_pc_im(uint64_t val)
70
+void gen_a64_update_pc(DisasContext *s, target_long diff)
71
{
72
- tcg_gen_movi_i64(cpu_pc, val);
73
+ tcg_gen_movi_i64(cpu_pc, s->pc_curr + diff);
74
}
52
75
53
/*
76
/*
54
* We need one splitter for every external combiner input, plus
77
@@ -XXX,XX +XXX,XX @@ static void gen_exception_internal(int excp)
55
- * one for every non-zero entry in combiner_grp_to_gic_id[].
78
56
+ * one for every non-zero entry in combiner_grp_to_gic_id[],
79
static void gen_exception_internal_insn(DisasContext *s, uint64_t pc, int excp)
57
+ * minus one for every external combiner ID in second or later
80
{
58
+ * places in a combinermap[] line.
81
- gen_a64_set_pc_im(pc);
59
* We'll assert in exynos4210_init_board_irqs() if this is wrong.
82
+ gen_a64_update_pc(s, pc - s->pc_curr);
60
*/
83
gen_exception_internal(excp);
61
-#define EXYNOS4210_NUM_SPLITTERS (EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ + 54)
84
s->base.is_jmp = DISAS_NORETURN;
62
+#define EXYNOS4210_NUM_SPLITTERS (EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ + 38)
85
}
63
86
64
typedef struct Exynos4210Irq {
87
static void gen_exception_bkpt_insn(DisasContext *s, uint32_t syndrome)
65
qemu_irq int_combiner_irq[EXYNOS4210_MAX_INT_COMBINER_IN_IRQ];
88
{
66
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
89
- gen_a64_set_pc_im(s->pc_curr);
90
+ gen_a64_update_pc(s, 0);
91
gen_helper_exception_bkpt_insn(cpu_env, tcg_constant_i32(syndrome));
92
s->base.is_jmp = DISAS_NORETURN;
93
}
94
@@ -XXX,XX +XXX,XX @@ static void gen_goto_tb(DisasContext *s, int n, int64_t diff)
95
96
if (use_goto_tb(s, dest)) {
97
tcg_gen_goto_tb(n);
98
- gen_a64_set_pc_im(dest);
99
+ gen_a64_update_pc(s, diff);
100
tcg_gen_exit_tb(s->base.tb, n);
101
s->base.is_jmp = DISAS_NORETURN;
102
} else {
103
- gen_a64_set_pc_im(dest);
104
+ gen_a64_update_pc(s, diff);
105
if (s->ss_active) {
106
gen_step_complete_exception(s);
107
} else {
108
@@ -XXX,XX +XXX,XX @@ static void handle_sys(DisasContext *s, uint32_t insn, bool isread,
109
uint32_t syndrome;
110
111
syndrome = syn_aa64_sysregtrap(op0, op1, op2, crn, crm, rt, isread);
112
- gen_a64_set_pc_im(s->pc_curr);
113
+ gen_a64_update_pc(s, 0);
114
gen_helper_access_check_cp_reg(cpu_env,
115
tcg_constant_ptr(ri),
116
tcg_constant_i32(syndrome),
117
@@ -XXX,XX +XXX,XX @@ static void handle_sys(DisasContext *s, uint32_t insn, bool isread,
118
* The readfn or writefn might raise an exception;
119
* synchronize the CPU state in case it does.
120
*/
121
- gen_a64_set_pc_im(s->pc_curr);
122
+ gen_a64_update_pc(s, 0);
123
}
124
125
/* Handle special cases first */
126
@@ -XXX,XX +XXX,XX @@ static void disas_exc(DisasContext *s, uint32_t insn)
127
/* The pre HVC helper handles cases when HVC gets trapped
128
* as an undefined insn by runtime configuration.
129
*/
130
- gen_a64_set_pc_im(s->pc_curr);
131
+ gen_a64_update_pc(s, 0);
132
gen_helper_pre_hvc(cpu_env);
133
gen_ss_advance(s);
134
gen_exception_insn_el(s, s->base.pc_next, EXCP_HVC,
135
@@ -XXX,XX +XXX,XX @@ static void disas_exc(DisasContext *s, uint32_t insn)
136
unallocated_encoding(s);
137
break;
138
}
139
- gen_a64_set_pc_im(s->pc_curr);
140
+ gen_a64_update_pc(s, 0);
141
gen_helper_pre_smc(cpu_env, tcg_constant_i32(syn_aa64_smc(imm16)));
142
gen_ss_advance(s);
143
gen_exception_insn_el(s, s->base.pc_next, EXCP_SMC,
144
@@ -XXX,XX +XXX,XX @@ static void aarch64_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
145
*/
146
switch (dc->base.is_jmp) {
147
default:
148
- gen_a64_set_pc_im(dc->base.pc_next);
149
+ gen_a64_update_pc(dc, 4);
150
/* fall through */
151
case DISAS_EXIT:
152
case DISAS_JUMP:
153
@@ -XXX,XX +XXX,XX @@ static void aarch64_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
154
break;
155
default:
156
case DISAS_UPDATE_EXIT:
157
- gen_a64_set_pc_im(dc->base.pc_next);
158
+ gen_a64_update_pc(dc, 4);
159
/* fall through */
160
case DISAS_EXIT:
161
tcg_gen_exit_tb(NULL, 0);
162
break;
163
case DISAS_UPDATE_NOCHAIN:
164
- gen_a64_set_pc_im(dc->base.pc_next);
165
+ gen_a64_update_pc(dc, 4);
166
/* fall through */
167
case DISAS_JUMP:
168
tcg_gen_lookup_and_goto_ptr();
169
@@ -XXX,XX +XXX,XX @@ static void aarch64_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
170
case DISAS_SWI:
171
break;
172
case DISAS_WFE:
173
- gen_a64_set_pc_im(dc->base.pc_next);
174
+ gen_a64_update_pc(dc, 4);
175
gen_helper_wfe(cpu_env);
176
break;
177
case DISAS_YIELD:
178
- gen_a64_set_pc_im(dc->base.pc_next);
179
+ gen_a64_update_pc(dc, 4);
180
gen_helper_yield(cpu_env);
181
break;
182
case DISAS_WFI:
183
@@ -XXX,XX +XXX,XX @@ static void aarch64_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
184
* This is a special case because we don't want to just halt
185
* the CPU if trying to debug across a WFI.
186
*/
187
- gen_a64_set_pc_im(dc->base.pc_next);
188
+ gen_a64_update_pc(dc, 4);
189
gen_helper_wfi(cpu_env, tcg_constant_i32(4));
190
/*
191
* The helper doesn't necessarily throw an exception, but we
192
diff --git a/target/arm/translate-vfp.c b/target/arm/translate-vfp.c
67
index XXXXXXX..XXXXXXX 100644
193
index XXXXXXX..XXXXXXX 100644
68
--- a/hw/arm/exynos4210.c
194
--- a/target/arm/translate-vfp.c
69
+++ b/hw/arm/exynos4210.c
195
+++ b/target/arm/translate-vfp.c
70
@@ -XXX,XX +XXX,XX @@ combiner_grp_to_gic_id[64 - EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][8] = {
196
@@ -XXX,XX +XXX,XX @@ static bool trans_VMSR_VMRS(DisasContext *s, arg_VMSR_VMRS *a)
71
#define EXYNOS4210_COMBINER_GET_BIT_NUM(irq) \
197
case ARM_VFP_FPSID:
72
((irq) - 8 * EXYNOS4210_COMBINER_GET_GRP_NUM(irq))
198
if (s->current_el == 1) {
73
199
gen_set_condexec(s);
74
+/*
200
- gen_set_pc_im(s, s->pc_curr);
75
+ * Some interrupt lines go to multiple combiner inputs.
201
+ gen_update_pc(s, 0);
76
+ * This data structure defines those: each array element is
202
gen_helper_check_hcr_el2_trap(cpu_env,
77
+ * a list of combiner inputs which are connected together;
203
tcg_constant_i32(a->rt),
78
+ * the one with the smallest interrupt ID value must be first.
204
tcg_constant_i32(a->reg));
79
+ * As with combiner_grp_to_gic_id[], we rely on (0, 0) not being
205
diff --git a/target/arm/translate.c b/target/arm/translate.c
80
+ * wired to anything so we can use 0 as a terminator.
206
index XXXXXXX..XXXXXXX 100644
81
+ */
207
--- a/target/arm/translate.c
82
+#define IRQNO(G, B) EXYNOS4210_COMBINER_GET_IRQ_NUM(G, B)
208
+++ b/target/arm/translate.c
83
+#define IRQNONE 0
209
@@ -XXX,XX +XXX,XX @@ void gen_set_condexec(DisasContext *s)
210
}
211
}
212
213
-void gen_set_pc_im(DisasContext *s, target_ulong val)
214
+void gen_update_pc(DisasContext *s, target_long diff)
215
{
216
- tcg_gen_movi_i32(cpu_R[15], val);
217
+ tcg_gen_movi_i32(cpu_R[15], s->pc_curr + diff);
218
}
219
220
/* Set PC and Thumb state from var. var is marked as dead. */
221
@@ -XXX,XX +XXX,XX @@ static inline void gen_bxns(DisasContext *s, int rm)
222
223
/* The bxns helper may raise an EXCEPTION_EXIT exception, so in theory
224
* we need to sync state before calling it, but:
225
- * - we don't need to do gen_set_pc_im() because the bxns helper will
226
+ * - we don't need to do gen_update_pc() because the bxns helper will
227
* always set the PC itself
228
* - we don't need to do gen_set_condexec() because BXNS is UNPREDICTABLE
229
* unless it's outside an IT block or the last insn in an IT block,
230
@@ -XXX,XX +XXX,XX @@ static inline void gen_blxns(DisasContext *s, int rm)
231
* We do however need to set the PC, because the blxns helper reads it.
232
* The blxns helper may throw an exception.
233
*/
234
- gen_set_pc_im(s, s->base.pc_next);
235
+ gen_update_pc(s, curr_insn_len(s));
236
gen_helper_v7m_blxns(cpu_env, var);
237
tcg_temp_free_i32(var);
238
s->base.is_jmp = DISAS_EXIT;
239
@@ -XXX,XX +XXX,XX @@ static inline void gen_hvc(DisasContext *s, int imm16)
240
* as an undefined insn by runtime configuration (ie before
241
* the insn really executes).
242
*/
243
- gen_set_pc_im(s, s->pc_curr);
244
+ gen_update_pc(s, 0);
245
gen_helper_pre_hvc(cpu_env);
246
/* Otherwise we will treat this as a real exception which
247
* happens after execution of the insn. (The distinction matters
248
@@ -XXX,XX +XXX,XX @@ static inline void gen_hvc(DisasContext *s, int imm16)
249
* for single stepping.)
250
*/
251
s->svc_imm = imm16;
252
- gen_set_pc_im(s, s->base.pc_next);
253
+ gen_update_pc(s, curr_insn_len(s));
254
s->base.is_jmp = DISAS_HVC;
255
}
256
257
@@ -XXX,XX +XXX,XX @@ static inline void gen_smc(DisasContext *s)
258
/* As with HVC, we may take an exception either before or after
259
* the insn executes.
260
*/
261
- gen_set_pc_im(s, s->pc_curr);
262
+ gen_update_pc(s, 0);
263
gen_helper_pre_smc(cpu_env, tcg_constant_i32(syn_aa32_smc()));
264
- gen_set_pc_im(s, s->base.pc_next);
265
+ gen_update_pc(s, curr_insn_len(s));
266
s->base.is_jmp = DISAS_SMC;
267
}
268
269
static void gen_exception_internal_insn(DisasContext *s, uint32_t pc, int excp)
270
{
271
gen_set_condexec(s);
272
- gen_set_pc_im(s, pc);
273
+ gen_update_pc(s, pc - s->pc_curr);
274
gen_exception_internal(excp);
275
s->base.is_jmp = DISAS_NORETURN;
276
}
277
@@ -XXX,XX +XXX,XX @@ static void gen_exception_insn_el_v(DisasContext *s, uint64_t pc, int excp,
278
uint32_t syn, TCGv_i32 tcg_el)
279
{
280
if (s->aarch64) {
281
- gen_a64_set_pc_im(pc);
282
+ gen_a64_update_pc(s, pc - s->pc_curr);
283
} else {
284
gen_set_condexec(s);
285
- gen_set_pc_im(s, pc);
286
+ gen_update_pc(s, pc - s->pc_curr);
287
}
288
gen_exception_el_v(excp, syn, tcg_el);
289
s->base.is_jmp = DISAS_NORETURN;
290
@@ -XXX,XX +XXX,XX @@ void gen_exception_insn_el(DisasContext *s, uint64_t pc, int excp,
291
void gen_exception_insn(DisasContext *s, uint64_t pc, int excp, uint32_t syn)
292
{
293
if (s->aarch64) {
294
- gen_a64_set_pc_im(pc);
295
+ gen_a64_update_pc(s, pc - s->pc_curr);
296
} else {
297
gen_set_condexec(s);
298
- gen_set_pc_im(s, pc);
299
+ gen_update_pc(s, pc - s->pc_curr);
300
}
301
gen_exception(excp, syn);
302
s->base.is_jmp = DISAS_NORETURN;
303
@@ -XXX,XX +XXX,XX @@ void gen_exception_insn(DisasContext *s, uint64_t pc, int excp, uint32_t syn)
304
static void gen_exception_bkpt_insn(DisasContext *s, uint32_t syn)
305
{
306
gen_set_condexec(s);
307
- gen_set_pc_im(s, s->pc_curr);
308
+ gen_update_pc(s, 0);
309
gen_helper_exception_bkpt_insn(cpu_env, tcg_constant_i32(syn));
310
s->base.is_jmp = DISAS_NORETURN;
311
}
312
@@ -XXX,XX +XXX,XX @@ static void gen_goto_tb(DisasContext *s, int n, int diff)
313
314
if (translator_use_goto_tb(&s->base, dest)) {
315
tcg_gen_goto_tb(n);
316
- gen_set_pc_im(s, dest);
317
+ gen_update_pc(s, diff);
318
tcg_gen_exit_tb(s->base.tb, n);
319
} else {
320
- gen_set_pc_im(s, dest);
321
+ gen_update_pc(s, diff);
322
gen_goto_ptr();
323
}
324
s->base.is_jmp = DISAS_NORETURN;
325
@@ -XXX,XX +XXX,XX @@ static void gen_goto_tb(DisasContext *s, int n, int diff)
326
/* Jump, specifying which TB number to use if we gen_goto_tb() */
327
static inline void gen_jmp_tb(DisasContext *s, uint32_t dest, int tbno)
328
{
329
+ int diff = dest - s->pc_curr;
84
+
330
+
85
+#define COMBINERMAP_SIZE 16
331
if (unlikely(s->ss_active)) {
86
+
332
/* An indirect jump so that we still trigger the debug exception. */
87
+static const int combinermap[COMBINERMAP_SIZE][6] = {
333
- gen_set_pc_im(s, dest);
88
+ /* MDNIE_LCD1 */
334
+ gen_update_pc(s, diff);
89
+ { IRQNO(0, 4), IRQNO(1, 0), IRQNONE },
335
s->base.is_jmp = DISAS_JUMP;
90
+ { IRQNO(0, 5), IRQNO(1, 1), IRQNONE },
336
return;
91
+ { IRQNO(0, 6), IRQNO(1, 2), IRQNONE },
337
}
92
+ { IRQNO(0, 7), IRQNO(1, 3), IRQNONE },
338
@@ -XXX,XX +XXX,XX @@ static inline void gen_jmp_tb(DisasContext *s, uint32_t dest, int tbno)
93
+ /* TMU */
339
* gen_jmp();
94
+ { IRQNO(2, 4), IRQNO(3, 4), IRQNONE },
340
* on the second call to gen_jmp().
95
+ { IRQNO(2, 5), IRQNO(3, 5), IRQNONE },
341
*/
96
+ { IRQNO(2, 6), IRQNO(3, 6), IRQNONE },
342
- gen_goto_tb(s, tbno, dest - s->pc_curr);
97
+ { IRQNO(2, 7), IRQNO(3, 7), IRQNONE },
343
+ gen_goto_tb(s, tbno, diff);
98
+ /* LCD1 */
344
break;
99
+ { IRQNO(11, 4), IRQNO(12, 0), IRQNONE },
345
case DISAS_UPDATE_NOCHAIN:
100
+ { IRQNO(11, 5), IRQNO(12, 1), IRQNONE },
346
case DISAS_UPDATE_EXIT:
101
+ { IRQNO(11, 6), IRQNO(12, 2), IRQNONE },
347
@@ -XXX,XX +XXX,XX @@ static inline void gen_jmp_tb(DisasContext *s, uint32_t dest, int tbno)
102
+ { IRQNO(11, 7), IRQNO(12, 3), IRQNONE },
348
* Avoid using goto_tb so we really do exit back to the main loop
103
+ /* Multi-core timer */
349
* and don't chain to another TB.
104
+ { IRQNO(1, 4), IRQNO(12, 4), IRQNO(35, 4), IRQNO(51, 4), IRQNO(53, 4), IRQNONE },
350
*/
105
+ { IRQNO(1, 5), IRQNO(12, 5), IRQNO(35, 5), IRQNO(51, 5), IRQNO(53, 5), IRQNONE },
351
- gen_set_pc_im(s, dest);
106
+ { IRQNO(1, 6), IRQNO(12, 6), IRQNO(35, 6), IRQNO(51, 6), IRQNO(53, 6), IRQNONE },
352
+ gen_update_pc(s, diff);
107
+ { IRQNO(1, 7), IRQNO(12, 7), IRQNO(35, 7), IRQNO(51, 7), IRQNO(53, 7), IRQNONE },
353
gen_goto_ptr();
108
+};
354
s->base.is_jmp = DISAS_NORETURN;
109
+
355
break;
110
+#undef IRQNO
356
@@ -XXX,XX +XXX,XX @@ static void gen_msr_banked(DisasContext *s, int r, int sysm, int rn)
111
+
357
112
+static const int *combinermap_entry(int irq)
358
/* Sync state because msr_banked() can raise exceptions */
113
+{
359
gen_set_condexec(s);
114
+ /*
360
- gen_set_pc_im(s, s->pc_curr);
115
+ * If the interrupt number passed in is the first entry in some
361
+ gen_update_pc(s, 0);
116
+ * line of the combinermap, return a pointer to that line;
362
tcg_reg = load_reg(s, rn);
117
+ * otherwise return NULL.
363
gen_helper_msr_banked(cpu_env, tcg_reg,
118
+ */
364
tcg_constant_i32(tgtmode),
119
+ int i;
365
@@ -XXX,XX +XXX,XX @@ static void gen_mrs_banked(DisasContext *s, int r, int sysm, int rn)
120
+ for (i = 0; i < COMBINERMAP_SIZE; i++) {
366
121
+ if (combinermap[i][0] == irq) {
367
/* Sync state because mrs_banked() can raise exceptions */
122
+ return combinermap[i];
368
gen_set_condexec(s);
123
+ }
369
- gen_set_pc_im(s, s->pc_curr);
124
+ }
370
+ gen_update_pc(s, 0);
125
+ return NULL;
371
tcg_reg = tcg_temp_new_i32();
126
+}
372
gen_helper_mrs_banked(tcg_reg, cpu_env,
127
+
373
tcg_constant_i32(tgtmode),
128
+static int mapline_size(const int *mapline)
374
@@ -XXX,XX +XXX,XX @@ static void do_coproc_insn(DisasContext *s, int cpnum, int is64,
129
+{
375
}
130
+ /* Return number of entries in this mapline in total */
376
131
+ int i = 0;
377
gen_set_condexec(s);
132
+
378
- gen_set_pc_im(s, s->pc_curr);
133
+ if (!mapline) {
379
+ gen_update_pc(s, 0);
134
+ /* Not in the map? IRQ goes to exactly one combiner input */
380
gen_helper_access_check_cp_reg(cpu_env,
135
+ return 1;
381
tcg_constant_ptr(ri),
136
+ }
382
tcg_constant_i32(syndrome),
137
+ while (*mapline != IRQNONE) {
383
@@ -XXX,XX +XXX,XX @@ static void do_coproc_insn(DisasContext *s, int cpnum, int is64,
138
+ mapline++;
384
* synchronize the CPU state in case it does.
139
+ i++;
385
*/
140
+ }
386
gen_set_condexec(s);
141
+ return i;
387
- gen_set_pc_im(s, s->pc_curr);
142
+}
388
+ gen_update_pc(s, 0);
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
}
389
}
159
390
160
+ if (s->irq_table[n]) {
391
/* Handle special cases first */
161
+ /*
392
@@ -XXX,XX +XXX,XX @@ static void do_coproc_insn(DisasContext *s, int cpnum, int is64,
162
+ * This must be some non-first entry in a combinermap line,
393
unallocated_encoding(s);
163
+ * and we've already filled it in.
394
return;
164
+ */
395
}
165
+ continue;
396
- gen_set_pc_im(s, s->base.pc_next);
166
+ }
397
+ gen_update_pc(s, curr_insn_len(s));
167
+ mapline = combinermap_entry(n);
398
s->base.is_jmp = DISAS_WFI;
168
+ /*
399
return;
169
+ * We need to connect the IRQ to multiple inputs on both combiners
400
default:
170
+ * and possibly also to the external GIC.
401
@@ -XXX,XX +XXX,XX @@ static void gen_srs(DisasContext *s,
171
+ */
402
addr = tcg_temp_new_i32();
172
+ numlines = 2 * mapline_size(mapline);
403
/* get_r13_banked() will raise an exception if called from System mode */
173
+ if (irq_id) {
404
gen_set_condexec(s);
174
+ numlines++;
405
- gen_set_pc_im(s, s->pc_curr);
175
+ }
406
+ gen_update_pc(s, 0);
176
assert(splitcount < EXYNOS4210_NUM_SPLITTERS);
407
gen_helper_get_r13_banked(addr, cpu_env, tcg_constant_i32(mode));
177
splitter = DEVICE(&s->splitter[splitcount]);
408
switch (amode) {
178
- qdev_prop_set_uint16(splitter, "num-lines", irq_id ? 3 : 2);
409
case 0: /* DA */
179
+ qdev_prop_set_uint16(splitter, "num-lines", numlines);
410
@@ -XXX,XX +XXX,XX @@ static bool trans_YIELD(DisasContext *s, arg_YIELD *a)
180
qdev_realize(splitter, NULL, &error_abort);
411
* scheduling of other vCPUs.
181
splitcount++;
412
*/
182
- s->irq_table[n] = qdev_get_gpio_in(splitter, 0);
413
if (!(tb_cflags(s->base.tb) & CF_PARALLEL)) {
183
- qdev_connect_gpio_out(splitter, 0, is->int_combiner_irq[n]);
414
- gen_set_pc_im(s, s->base.pc_next);
184
- qdev_connect_gpio_out(splitter, 1, is->ext_combiner_irq[n]);
415
+ gen_update_pc(s, curr_insn_len(s));
185
+
416
s->base.is_jmp = DISAS_YIELD;
186
+ in = n;
417
}
187
+ splitin = 0;
418
return true;
188
+ for (;;) {
419
@@ -XXX,XX +XXX,XX @@ static bool trans_WFE(DisasContext *s, arg_WFE *a)
189
+ s->irq_table[in] = qdev_get_gpio_in(splitter, 0);
420
* implemented so we can't sleep like WFI does.
190
+ qdev_connect_gpio_out(splitter, splitin, is->int_combiner_irq[in]);
421
*/
191
+ qdev_connect_gpio_out(splitter, splitin + 1, is->ext_combiner_irq[in]);
422
if (!(tb_cflags(s->base.tb) & CF_PARALLEL)) {
192
+ splitin += 2;
423
- gen_set_pc_im(s, s->base.pc_next);
193
+ if (!mapline) {
424
+ gen_update_pc(s, curr_insn_len(s));
194
+ break;
425
s->base.is_jmp = DISAS_WFE;
195
+ }
426
}
196
+ mapline++;
427
return true;
197
+ in = *mapline;
428
@@ -XXX,XX +XXX,XX @@ static bool trans_WFE(DisasContext *s, arg_WFE *a)
198
+ if (in == IRQNONE) {
429
static bool trans_WFI(DisasContext *s, arg_WFI *a)
199
+ break;
430
{
200
+ }
431
/* For WFI, halt the vCPU until an IRQ. */
201
+ }
432
- gen_set_pc_im(s, s->base.pc_next);
202
if (irq_id) {
433
+ gen_update_pc(s, curr_insn_len(s));
203
- qdev_connect_gpio_out(splitter, 2,
434
s->base.is_jmp = DISAS_WFI;
204
+ qdev_connect_gpio_out(splitter, splitin,
435
return true;
205
qdev_get_gpio_in(extgicdev, irq_id - 32));
436
}
206
}
437
@@ -XXX,XX +XXX,XX @@ static bool trans_SVC(DisasContext *s, arg_SVC *a)
207
}
438
(a->imm == semihost_imm)) {
208
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init_board_irqs(Exynos4210State *s)
439
gen_exception_internal_insn(s, s->pc_curr, EXCP_SEMIHOST);
209
irq_id = combiner_grp_to_gic_id[grp -
440
} else {
210
EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][bit];
441
- gen_set_pc_im(s, s->base.pc_next);
211
442
+ gen_update_pc(s, curr_insn_len(s));
212
+ if (s->irq_table[n]) {
443
s->svc_imm = a->imm;
213
+ /*
444
s->base.is_jmp = DISAS_SWI;
214
+ * This must be some non-first entry in a combinermap line,
445
}
215
+ * and we've already filled it in.
446
@@ -XXX,XX +XXX,XX @@ static void arm_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
216
+ */
447
case DISAS_TOO_MANY:
217
+ continue;
448
case DISAS_UPDATE_EXIT:
218
+ }
449
case DISAS_UPDATE_NOCHAIN:
219
+
450
- gen_set_pc_im(dc, dc->base.pc_next);
220
if (irq_id) {
451
+ gen_update_pc(dc, curr_insn_len(dc));
221
assert(splitcount < EXYNOS4210_NUM_SPLITTERS);
452
/* fall through */
222
splitter = DEVICE(&s->splitter[splitcount]);
453
default:
223
@@ -XXX,XX +XXX,XX @@ static void exynos4210_combiner_get_gpioin(Exynos4210Irq *irqs,
454
/* FIXME: Single stepping a WFI insn will not halt the CPU. */
224
DeviceState *dev, int ext)
455
@@ -XXX,XX +XXX,XX @@ static void arm_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
225
{
456
gen_goto_tb(dc, 1, curr_insn_len(dc));
226
int n;
457
break;
227
- int bit;
458
case DISAS_UPDATE_NOCHAIN:
228
int max;
459
- gen_set_pc_im(dc, dc->base.pc_next);
229
qemu_irq *irq;
460
+ gen_update_pc(dc, curr_insn_len(dc));
230
461
/* fall through */
231
@@ -XXX,XX +XXX,XX @@ static void exynos4210_combiner_get_gpioin(Exynos4210Irq *irqs,
462
case DISAS_JUMP:
232
EXYNOS4210_MAX_INT_COMBINER_IN_IRQ;
463
gen_goto_ptr();
233
irq = ext ? irqs->ext_combiner_irq : irqs->int_combiner_irq;
464
break;
234
465
case DISAS_UPDATE_EXIT:
235
- /*
466
- gen_set_pc_im(dc, dc->base.pc_next);
236
- * Some IRQs of Int/External Combiner are going to two Combiners groups,
467
+ gen_update_pc(dc, curr_insn_len(dc));
237
- * so let split them.
468
/* fall through */
238
- */
469
default:
239
for (n = 0; n < max; n++) {
470
/* indicate that the hash table must be used to find the next TB */
240
-
471
@@ -XXX,XX +XXX,XX @@ static void arm_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
241
- bit = EXYNOS4210_COMBINER_GET_BIT_NUM(n);
472
gen_set_label(dc->condlabel);
242
-
473
gen_set_condexec(dc);
243
- switch (n) {
474
if (unlikely(dc->ss_active)) {
244
- /* MDNIE_LCD1 INTG1 */
475
- gen_set_pc_im(dc, dc->base.pc_next);
245
- case EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 0) ...
476
+ gen_update_pc(dc, curr_insn_len(dc));
246
- EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 3):
477
gen_singlestep_exception(dc);
247
- irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
478
} else {
248
- irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(0, bit + 4)]);
479
gen_goto_tb(dc, 1, curr_insn_len(dc));
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
}
296
--
480
--
297
2.25.1
481
2.25.1
482
483
diff view generated by jsdifflib
1
From: "Edgar E. Iglesias" <edgar.iglesias@amd.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Break out header file to allow embedding of the the TTC.
3
In preparation for TARGET_TB_PCREL, reduce reliance on absolute values.
4
4
5
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>
5
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Luc Michel <luc@lmichel.fr>
7
Message-id: 20221020030641.2066807-5-richard.henderson@linaro.org
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>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
9
---
12
include/hw/timer/cadence_ttc.h | 54 ++++++++++++++++++++++++++++++++++
10
target/arm/translate.h | 5 +++--
13
hw/timer/cadence_ttc.c | 32 ++------------------
11
target/arm/translate-a64.c | 28 ++++++++++-------------
14
2 files changed, 56 insertions(+), 30 deletions(-)
12
target/arm/translate-m-nocp.c | 6 ++---
15
create mode 100644 include/hw/timer/cadence_ttc.h
13
target/arm/translate-mve.c | 2 +-
16
14
target/arm/translate-vfp.c | 6 ++---
17
diff --git a/include/hw/timer/cadence_ttc.h b/include/hw/timer/cadence_ttc.h
15
target/arm/translate.c | 42 +++++++++++++++++------------------
18
new file mode 100644
16
6 files changed, 43 insertions(+), 46 deletions(-)
19
index XXXXXXX..XXXXXXX
17
20
--- /dev/null
18
diff --git a/target/arm/translate.h b/target/arm/translate.h
21
+++ b/include/hw/timer/cadence_ttc.h
19
index XXXXXXX..XXXXXXX 100644
22
@@ -XXX,XX +XXX,XX @@
20
--- a/target/arm/translate.h
23
+/*
21
+++ b/target/arm/translate.h
24
+ * Xilinx Zynq cadence TTC model
22
@@ -XXX,XX +XXX,XX @@ void arm_jump_cc(DisasCompare *cmp, TCGLabel *label);
25
+ *
23
void arm_gen_test_cc(int cc, TCGLabel *label);
26
+ * Copyright (c) 2011 Xilinx Inc.
24
MemOp pow2_align(unsigned i);
27
+ * Copyright (c) 2012 Peter A.G. Crosthwaite (peter.crosthwaite@petalogix.com)
25
void unallocated_encoding(DisasContext *s);
28
+ * Copyright (c) 2012 PetaLogix Pty Ltd.
26
-void gen_exception_insn_el(DisasContext *s, uint64_t pc, int excp,
29
+ * Written By Haibing Ma
27
+void gen_exception_insn_el(DisasContext *s, target_long pc_diff, int excp,
30
+ * M. Habib
28
uint32_t syn, uint32_t target_el);
31
+ *
29
-void gen_exception_insn(DisasContext *s, uint64_t pc, int excp, uint32_t syn);
32
+ * This program is free software; you can redistribute it and/or
30
+void gen_exception_insn(DisasContext *s, target_long pc_diff,
33
+ * modify it under the terms of the GNU General Public License
31
+ int excp, uint32_t syn);
34
+ * as published by the Free Software Foundation; either version
32
35
+ * 2 of the License, or (at your option) any later version.
33
/* Return state of Alternate Half-precision flag, caller frees result */
36
+ *
34
static inline TCGv_i32 get_ahp_flag(void)
37
+ * You should have received a copy of the GNU General Public License along
35
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
38
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
36
index XXXXXXX..XXXXXXX 100644
39
+ */
37
--- a/target/arm/translate-a64.c
40
+#ifndef HW_TIMER_CADENCE_TTC_H
38
+++ b/target/arm/translate-a64.c
41
+#define HW_TIMER_CADENCE_TTC_H
39
@@ -XXX,XX +XXX,XX @@ static bool fp_access_check_only(DisasContext *s)
42
+
40
assert(!s->fp_access_checked);
43
+#include "hw/sysbus.h"
41
s->fp_access_checked = true;
44
+#include "qemu/timer.h"
42
45
+
43
- gen_exception_insn_el(s, s->pc_curr, EXCP_UDEF,
46
+typedef struct {
44
+ gen_exception_insn_el(s, 0, EXCP_UDEF,
47
+ QEMUTimer *timer;
45
syn_fp_access_trap(1, 0xe, false, 0),
48
+ int freq;
46
s->fp_excp_el);
49
+
47
return false;
50
+ uint32_t reg_clock;
48
@@ -XXX,XX +XXX,XX @@ static bool fp_access_check(DisasContext *s)
51
+ uint32_t reg_count;
49
return false;
52
+ uint32_t reg_value;
50
}
53
+ uint16_t reg_interval;
51
if (s->sme_trap_nonstreaming && s->is_nonstreaming) {
54
+ uint16_t reg_match[3];
52
- gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
55
+ uint32_t reg_intr;
53
+ gen_exception_insn(s, 0, EXCP_UDEF,
56
+ uint32_t reg_intr_en;
54
syn_smetrap(SME_ET_Streaming, false));
57
+ uint32_t reg_event_ctrl;
55
return false;
58
+ uint32_t reg_event;
56
}
59
+
57
@@ -XXX,XX +XXX,XX @@ bool sve_access_check(DisasContext *s)
60
+ uint64_t cpu_time;
58
goto fail_exit;
61
+ unsigned int cpu_time_valid;
59
}
62
+
60
} else if (s->sve_excp_el) {
63
+ qemu_irq irq;
61
- gen_exception_insn_el(s, s->pc_curr, EXCP_UDEF,
64
+} CadenceTimerState;
62
+ gen_exception_insn_el(s, 0, EXCP_UDEF,
65
+
63
syn_sve_access_trap(), s->sve_excp_el);
66
+#define TYPE_CADENCE_TTC "cadence_ttc"
64
goto fail_exit;
67
+OBJECT_DECLARE_SIMPLE_TYPE(CadenceTTCState, CADENCE_TTC)
65
}
68
+
66
@@ -XXX,XX +XXX,XX @@ bool sve_access_check(DisasContext *s)
69
+struct CadenceTTCState {
67
static bool sme_access_check(DisasContext *s)
70
+ SysBusDevice parent_obj;
68
{
71
+
69
if (s->sme_excp_el) {
72
+ MemoryRegion iomem;
70
- gen_exception_insn_el(s, s->pc_curr, EXCP_UDEF,
73
+ CadenceTimerState timer[3];
71
+ gen_exception_insn_el(s, 0, EXCP_UDEF,
74
+};
72
syn_smetrap(SME_ET_AccessTrap, false),
75
+
73
s->sme_excp_el);
76
+#endif
74
return false;
77
diff --git a/hw/timer/cadence_ttc.c b/hw/timer/cadence_ttc.c
75
@@ -XXX,XX +XXX,XX @@ bool sme_enabled_check_with_svcr(DisasContext *s, unsigned req)
78
index XXXXXXX..XXXXXXX 100644
76
return false;
79
--- a/hw/timer/cadence_ttc.c
77
}
80
+++ b/hw/timer/cadence_ttc.c
78
if (FIELD_EX64(req, SVCR, SM) && !s->pstate_sm) {
81
@@ -XXX,XX +XXX,XX @@
79
- gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
82
#include "qemu/timer.h"
80
+ gen_exception_insn(s, 0, EXCP_UDEF,
83
#include "qom/object.h"
81
syn_smetrap(SME_ET_NotStreaming, false));
84
82
return false;
85
+#include "hw/timer/cadence_ttc.h"
83
}
86
+
84
if (FIELD_EX64(req, SVCR, ZA) && !s->pstate_za) {
87
#ifdef CADENCE_TTC_ERR_DEBUG
85
- gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
88
#define DB_PRINT(...) do { \
86
+ gen_exception_insn(s, 0, EXCP_UDEF,
89
fprintf(stderr, ": %s: ", __func__); \
87
syn_smetrap(SME_ET_InactiveZA, false));
90
@@ -XXX,XX +XXX,XX @@
88
return false;
91
#define CLOCK_CTRL_PS_EN 0x00000001
89
}
92
#define CLOCK_CTRL_PS_V 0x0000001e
90
@@ -XXX,XX +XXX,XX @@ static void gen_sysreg_undef(DisasContext *s, bool isread,
93
91
} else {
94
-typedef struct {
92
syndrome = syn_uncategorized();
95
- QEMUTimer *timer;
93
}
96
- int freq;
94
- gen_exception_insn(s, s->pc_curr, EXCP_UDEF, syndrome);
97
-
95
+ gen_exception_insn(s, 0, EXCP_UDEF, syndrome);
98
- uint32_t reg_clock;
96
}
99
- uint32_t reg_count;
97
100
- uint32_t reg_value;
98
/* MRS - move from system register
101
- uint16_t reg_interval;
99
@@ -XXX,XX +XXX,XX @@ static void disas_exc(DisasContext *s, uint32_t insn)
102
- uint16_t reg_match[3];
100
switch (op2_ll) {
103
- uint32_t reg_intr;
101
case 1: /* SVC */
104
- uint32_t reg_intr_en;
102
gen_ss_advance(s);
105
- uint32_t reg_event_ctrl;
103
- gen_exception_insn(s, s->base.pc_next, EXCP_SWI,
106
- uint32_t reg_event;
104
- syn_aa64_svc(imm16));
107
-
105
+ gen_exception_insn(s, 4, EXCP_SWI, syn_aa64_svc(imm16));
108
- uint64_t cpu_time;
106
break;
109
- unsigned int cpu_time_valid;
107
case 2: /* HVC */
110
-
108
if (s->current_el == 0) {
111
- qemu_irq irq;
109
@@ -XXX,XX +XXX,XX @@ static void disas_exc(DisasContext *s, uint32_t insn)
112
-} CadenceTimerState;
110
gen_a64_update_pc(s, 0);
113
-
111
gen_helper_pre_hvc(cpu_env);
114
-#define TYPE_CADENCE_TTC "cadence_ttc"
112
gen_ss_advance(s);
115
-OBJECT_DECLARE_SIMPLE_TYPE(CadenceTTCState, CADENCE_TTC)
113
- gen_exception_insn_el(s, s->base.pc_next, EXCP_HVC,
116
-
114
- syn_aa64_hvc(imm16), 2);
117
-struct CadenceTTCState {
115
+ gen_exception_insn_el(s, 4, EXCP_HVC, syn_aa64_hvc(imm16), 2);
118
- SysBusDevice parent_obj;
116
break;
119
-
117
case 3: /* SMC */
120
- MemoryRegion iomem;
118
if (s->current_el == 0) {
121
- CadenceTimerState timer[3];
119
@@ -XXX,XX +XXX,XX @@ static void disas_exc(DisasContext *s, uint32_t insn)
122
-};
120
gen_a64_update_pc(s, 0);
123
-
121
gen_helper_pre_smc(cpu_env, tcg_constant_i32(syn_aa64_smc(imm16)));
124
static void cadence_timer_update(CadenceTimerState *s)
122
gen_ss_advance(s);
125
{
123
- gen_exception_insn_el(s, s->base.pc_next, EXCP_SMC,
126
qemu_set_irq(s->irq, !!(s->reg_intr & s->reg_intr_en));
124
- syn_aa64_smc(imm16), 3);
125
+ gen_exception_insn_el(s, 4, EXCP_SMC, syn_aa64_smc(imm16), 3);
126
break;
127
default:
128
unallocated_encoding(s);
129
@@ -XXX,XX +XXX,XX @@ static void aarch64_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
130
* Illegal execution state. This has priority over BTI
131
* exceptions, but comes after instruction abort exceptions.
132
*/
133
- gen_exception_insn(s, s->pc_curr, EXCP_UDEF, syn_illegalstate());
134
+ gen_exception_insn(s, 0, EXCP_UDEF, syn_illegalstate());
135
return;
136
}
137
138
@@ -XXX,XX +XXX,XX @@ static void aarch64_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
139
if (s->btype != 0
140
&& s->guarded_page
141
&& !btype_destination_ok(insn, s->bt, s->btype)) {
142
- gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
143
- syn_btitrap(s->btype));
144
+ gen_exception_insn(s, 0, EXCP_UDEF, syn_btitrap(s->btype));
145
return;
146
}
147
} else {
148
diff --git a/target/arm/translate-m-nocp.c b/target/arm/translate-m-nocp.c
149
index XXXXXXX..XXXXXXX 100644
150
--- a/target/arm/translate-m-nocp.c
151
+++ b/target/arm/translate-m-nocp.c
152
@@ -XXX,XX +XXX,XX @@ static bool trans_VSCCLRM(DisasContext *s, arg_VSCCLRM *a)
153
tcg_gen_brcondi_i32(TCG_COND_EQ, sfpa, 0, s->condlabel);
154
155
if (s->fp_excp_el != 0) {
156
- gen_exception_insn_el(s, s->pc_curr, EXCP_NOCP,
157
+ gen_exception_insn_el(s, 0, EXCP_NOCP,
158
syn_uncategorized(), s->fp_excp_el);
159
return true;
160
}
161
@@ -XXX,XX +XXX,XX @@ static bool trans_NOCP(DisasContext *s, arg_nocp *a)
162
}
163
164
if (a->cp != 10) {
165
- gen_exception_insn(s, s->pc_curr, EXCP_NOCP, syn_uncategorized());
166
+ gen_exception_insn(s, 0, EXCP_NOCP, syn_uncategorized());
167
return true;
168
}
169
170
if (s->fp_excp_el != 0) {
171
- gen_exception_insn_el(s, s->pc_curr, EXCP_NOCP,
172
+ gen_exception_insn_el(s, 0, EXCP_NOCP,
173
syn_uncategorized(), s->fp_excp_el);
174
return true;
175
}
176
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
177
index XXXXXXX..XXXXXXX 100644
178
--- a/target/arm/translate-mve.c
179
+++ b/target/arm/translate-mve.c
180
@@ -XXX,XX +XXX,XX @@ bool mve_eci_check(DisasContext *s)
181
return true;
182
default:
183
/* Reserved value: INVSTATE UsageFault */
184
- gen_exception_insn(s, s->pc_curr, EXCP_INVSTATE, syn_uncategorized());
185
+ gen_exception_insn(s, 0, EXCP_INVSTATE, syn_uncategorized());
186
return false;
187
}
188
}
189
diff --git a/target/arm/translate-vfp.c b/target/arm/translate-vfp.c
190
index XXXXXXX..XXXXXXX 100644
191
--- a/target/arm/translate-vfp.c
192
+++ b/target/arm/translate-vfp.c
193
@@ -XXX,XX +XXX,XX @@ static bool vfp_access_check_a(DisasContext *s, bool ignore_vfp_enabled)
194
int coproc = arm_dc_feature(s, ARM_FEATURE_V8) ? 0 : 0xa;
195
uint32_t syn = syn_fp_access_trap(1, 0xe, false, coproc);
196
197
- gen_exception_insn_el(s, s->pc_curr, EXCP_UDEF, syn, s->fp_excp_el);
198
+ gen_exception_insn_el(s, 0, EXCP_UDEF, syn, s->fp_excp_el);
199
return false;
200
}
201
202
@@ -XXX,XX +XXX,XX @@ static bool vfp_access_check_a(DisasContext *s, bool ignore_vfp_enabled)
203
* appear to be any insns which touch VFP which are allowed.
204
*/
205
if (s->sme_trap_nonstreaming) {
206
- gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
207
+ gen_exception_insn(s, 0, EXCP_UDEF,
208
syn_smetrap(SME_ET_Streaming,
209
curr_insn_len(s) == 2));
210
return false;
211
@@ -XXX,XX +XXX,XX @@ bool vfp_access_check_m(DisasContext *s, bool skip_context_update)
212
* the encoding space handled by the patterns in m-nocp.decode,
213
* and for them we may need to raise NOCP here.
214
*/
215
- gen_exception_insn_el(s, s->pc_curr, EXCP_NOCP,
216
+ gen_exception_insn_el(s, 0, EXCP_NOCP,
217
syn_uncategorized(), s->fp_excp_el);
218
return false;
219
}
220
diff --git a/target/arm/translate.c b/target/arm/translate.c
221
index XXXXXXX..XXXXXXX 100644
222
--- a/target/arm/translate.c
223
+++ b/target/arm/translate.c
224
@@ -XXX,XX +XXX,XX @@ static void gen_exception(int excp, uint32_t syndrome)
225
tcg_constant_i32(syndrome));
226
}
227
228
-static void gen_exception_insn_el_v(DisasContext *s, uint64_t pc, int excp,
229
- uint32_t syn, TCGv_i32 tcg_el)
230
+static void gen_exception_insn_el_v(DisasContext *s, target_long pc_diff,
231
+ int excp, uint32_t syn, TCGv_i32 tcg_el)
232
{
233
if (s->aarch64) {
234
- gen_a64_update_pc(s, pc - s->pc_curr);
235
+ gen_a64_update_pc(s, pc_diff);
236
} else {
237
gen_set_condexec(s);
238
- gen_update_pc(s, pc - s->pc_curr);
239
+ gen_update_pc(s, pc_diff);
240
}
241
gen_exception_el_v(excp, syn, tcg_el);
242
s->base.is_jmp = DISAS_NORETURN;
243
}
244
245
-void gen_exception_insn_el(DisasContext *s, uint64_t pc, int excp,
246
+void gen_exception_insn_el(DisasContext *s, target_long pc_diff, int excp,
247
uint32_t syn, uint32_t target_el)
248
{
249
- gen_exception_insn_el_v(s, pc, excp, syn, tcg_constant_i32(target_el));
250
+ gen_exception_insn_el_v(s, pc_diff, excp, syn,
251
+ tcg_constant_i32(target_el));
252
}
253
254
-void gen_exception_insn(DisasContext *s, uint64_t pc, int excp, uint32_t syn)
255
+void gen_exception_insn(DisasContext *s, target_long pc_diff,
256
+ int excp, uint32_t syn)
257
{
258
if (s->aarch64) {
259
- gen_a64_update_pc(s, pc - s->pc_curr);
260
+ gen_a64_update_pc(s, pc_diff);
261
} else {
262
gen_set_condexec(s);
263
- gen_update_pc(s, pc - s->pc_curr);
264
+ gen_update_pc(s, pc_diff);
265
}
266
gen_exception(excp, syn);
267
s->base.is_jmp = DISAS_NORETURN;
268
@@ -XXX,XX +XXX,XX @@ static void gen_exception_bkpt_insn(DisasContext *s, uint32_t syn)
269
void unallocated_encoding(DisasContext *s)
270
{
271
/* Unallocated and reserved encodings are uncategorized */
272
- gen_exception_insn(s, s->pc_curr, EXCP_UDEF, syn_uncategorized());
273
+ gen_exception_insn(s, 0, EXCP_UDEF, syn_uncategorized());
274
}
275
276
/* Force a TB lookup after an instruction that changes the CPU state. */
277
@@ -XXX,XX +XXX,XX @@ static bool msr_banked_access_decode(DisasContext *s, int r, int sysm, int rn,
278
tcg_el = tcg_constant_i32(3);
279
}
280
281
- gen_exception_insn_el_v(s, s->pc_curr, EXCP_UDEF,
282
+ gen_exception_insn_el_v(s, 0, EXCP_UDEF,
283
syn_uncategorized(), tcg_el);
284
tcg_temp_free_i32(tcg_el);
285
return false;
286
@@ -XXX,XX +XXX,XX @@ static bool msr_banked_access_decode(DisasContext *s, int r, int sysm, int rn,
287
288
undef:
289
/* If we get here then some access check did not pass */
290
- gen_exception_insn(s, s->pc_curr, EXCP_UDEF, syn_uncategorized());
291
+ gen_exception_insn(s, 0, EXCP_UDEF, syn_uncategorized());
292
return false;
293
}
294
295
@@ -XXX,XX +XXX,XX @@ static void gen_srs(DisasContext *s,
296
* For the UNPREDICTABLE cases we choose to UNDEF.
297
*/
298
if (s->current_el == 1 && !s->ns && mode == ARM_CPU_MODE_MON) {
299
- gen_exception_insn_el(s, s->pc_curr, EXCP_UDEF,
300
- syn_uncategorized(), 3);
301
+ gen_exception_insn_el(s, 0, EXCP_UDEF, syn_uncategorized(), 3);
302
return;
303
}
304
305
@@ -XXX,XX +XXX,XX @@ static bool trans_WLS(DisasContext *s, arg_WLS *a)
306
* Do the check-and-raise-exception by hand.
307
*/
308
if (s->fp_excp_el) {
309
- gen_exception_insn_el(s, s->pc_curr, EXCP_NOCP,
310
+ gen_exception_insn_el(s, 0, EXCP_NOCP,
311
syn_uncategorized(), s->fp_excp_el);
312
return true;
313
}
314
@@ -XXX,XX +XXX,XX @@ static bool trans_LE(DisasContext *s, arg_LE *a)
315
tmp = load_cpu_field(v7m.ltpsize);
316
tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 4, skipexc);
317
tcg_temp_free_i32(tmp);
318
- gen_exception_insn(s, s->pc_curr, EXCP_INVSTATE, syn_uncategorized());
319
+ gen_exception_insn(s, 0, EXCP_INVSTATE, syn_uncategorized());
320
gen_set_label(skipexc);
321
}
322
323
@@ -XXX,XX +XXX,XX @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
324
* UsageFault exception.
325
*/
326
if (arm_dc_feature(s, ARM_FEATURE_M)) {
327
- gen_exception_insn(s, s->pc_curr, EXCP_INVSTATE, syn_uncategorized());
328
+ gen_exception_insn(s, 0, EXCP_INVSTATE, syn_uncategorized());
329
return;
330
}
331
332
@@ -XXX,XX +XXX,XX @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
333
* Illegal execution state. This has priority over BTI
334
* exceptions, but comes after instruction abort exceptions.
335
*/
336
- gen_exception_insn(s, s->pc_curr, EXCP_UDEF, syn_illegalstate());
337
+ gen_exception_insn(s, 0, EXCP_UDEF, syn_illegalstate());
338
return;
339
}
340
341
@@ -XXX,XX +XXX,XX @@ static void thumb_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
342
* Illegal execution state. This has priority over BTI
343
* exceptions, but comes after instruction abort exceptions.
344
*/
345
- gen_exception_insn(dc, dc->pc_curr, EXCP_UDEF, syn_illegalstate());
346
+ gen_exception_insn(dc, 0, EXCP_UDEF, syn_illegalstate());
347
return;
348
}
349
350
@@ -XXX,XX +XXX,XX @@ static void thumb_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
351
*/
352
tcg_remove_ops_after(dc->insn_eci_rewind);
353
dc->condjmp = 0;
354
- gen_exception_insn(dc, dc->pc_curr, EXCP_INVSTATE,
355
- syn_uncategorized());
356
+ gen_exception_insn(dc, 0, EXCP_INVSTATE, syn_uncategorized());
357
}
358
359
arm_post_translate_insn(dc);
127
--
360
--
128
2.25.1
361
2.25.1
362
363
diff view generated by jsdifflib
1
From: Zongyuan Li <zongyuan.li@smartx.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Signed-off-by: Zongyuan Li <zongyuan.li@smartx.com>
3
In preparation for TARGET_TB_PCREL, reduce reliance on absolute values.
4
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Since we always pass dc->pc_curr, fold the arithmetic to zero displacement.
5
Message-id: 20220324181557.203805-5-zongyuan.li@smartx.com
5
6
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/811
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20221020030641.2066807-6-richard.henderson@linaro.org
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
target/arm/translate-a64.c | 6 +++---
10
hw/core/irq.c | 15 ---------------
12
target/arm/translate.c | 10 +++++-----
11
2 files changed, 20 deletions(-)
13
2 files changed, 8 insertions(+), 8 deletions(-)
12
14
13
diff --git a/include/hw/irq.h b/include/hw/irq.h
15
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
14
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
15
--- a/include/hw/irq.h
17
--- a/target/arm/translate-a64.c
16
+++ b/include/hw/irq.h
18
+++ b/target/arm/translate-a64.c
17
@@ -XXX,XX +XXX,XX @@ void qemu_free_irq(qemu_irq irq);
19
@@ -XXX,XX +XXX,XX @@ static void gen_exception_internal(int excp)
18
/* Returns a new IRQ with opposite polarity. */
20
gen_helper_exception_internal(cpu_env, tcg_constant_i32(excp));
19
qemu_irq qemu_irq_invert(qemu_irq irq);
21
}
20
22
21
-/* Returns a new IRQ which feeds into both the passed IRQs.
23
-static void gen_exception_internal_insn(DisasContext *s, uint64_t pc, int excp)
22
- * It's probably better to use the TYPE_SPLIT_IRQ device instead.
24
+static void gen_exception_internal_insn(DisasContext *s, int excp)
23
- */
25
{
24
-qemu_irq qemu_irq_split(qemu_irq irq1, qemu_irq irq2);
26
- gen_a64_update_pc(s, pc - s->pc_curr);
25
-
27
+ gen_a64_update_pc(s, 0);
26
/* For internal use in qtest. Similar to qemu_irq_split, but operating
28
gen_exception_internal(excp);
27
on an existing vector of qemu_irq. */
29
s->base.is_jmp = DISAS_NORETURN;
28
void qemu_irq_intercept_in(qemu_irq *gpio_in, qemu_irq_handler handler, int n);
30
}
29
diff --git a/hw/core/irq.c b/hw/core/irq.c
31
@@ -XXX,XX +XXX,XX @@ static void disas_exc(DisasContext *s, uint32_t insn)
32
* Secondly, "HLT 0xf000" is the A64 semihosting syscall instruction.
33
*/
34
if (semihosting_enabled(s->current_el == 0) && imm16 == 0xf000) {
35
- gen_exception_internal_insn(s, s->pc_curr, EXCP_SEMIHOST);
36
+ gen_exception_internal_insn(s, EXCP_SEMIHOST);
37
} else {
38
unallocated_encoding(s);
39
}
40
diff --git a/target/arm/translate.c b/target/arm/translate.c
30
index XXXXXXX..XXXXXXX 100644
41
index XXXXXXX..XXXXXXX 100644
31
--- a/hw/core/irq.c
42
--- a/target/arm/translate.c
32
+++ b/hw/core/irq.c
43
+++ b/target/arm/translate.c
33
@@ -XXX,XX +XXX,XX @@ qemu_irq qemu_irq_invert(qemu_irq irq)
44
@@ -XXX,XX +XXX,XX @@ static inline void gen_smc(DisasContext *s)
34
return qemu_allocate_irq(qemu_notirq, irq, 0);
45
s->base.is_jmp = DISAS_SMC;
35
}
46
}
36
47
37
-static void qemu_splitirq(void *opaque, int line, int level)
48
-static void gen_exception_internal_insn(DisasContext *s, uint32_t pc, int excp)
38
-{
49
+static void gen_exception_internal_insn(DisasContext *s, int excp)
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
{
50
{
54
int i;
51
gen_set_condexec(s);
52
- gen_update_pc(s, pc - s->pc_curr);
53
+ gen_update_pc(s, 0);
54
gen_exception_internal(excp);
55
s->base.is_jmp = DISAS_NORETURN;
56
}
57
@@ -XXX,XX +XXX,XX @@ static inline void gen_hlt(DisasContext *s, int imm)
58
*/
59
if (semihosting_enabled(s->current_el != 0) &&
60
(imm == (s->thumb ? 0x3c : 0xf000))) {
61
- gen_exception_internal_insn(s, s->pc_curr, EXCP_SEMIHOST);
62
+ gen_exception_internal_insn(s, EXCP_SEMIHOST);
63
return;
64
}
65
66
@@ -XXX,XX +XXX,XX @@ static bool trans_BKPT(DisasContext *s, arg_BKPT *a)
67
if (arm_dc_feature(s, ARM_FEATURE_M) &&
68
semihosting_enabled(s->current_el == 0) &&
69
(a->imm == 0xab)) {
70
- gen_exception_internal_insn(s, s->pc_curr, EXCP_SEMIHOST);
71
+ gen_exception_internal_insn(s, EXCP_SEMIHOST);
72
} else {
73
gen_exception_bkpt_insn(s, syn_aa32_bkpt(a->imm, false));
74
}
75
@@ -XXX,XX +XXX,XX @@ static bool trans_SVC(DisasContext *s, arg_SVC *a)
76
if (!arm_dc_feature(s, ARM_FEATURE_M) &&
77
semihosting_enabled(s->current_el == 0) &&
78
(a->imm == semihost_imm)) {
79
- gen_exception_internal_insn(s, s->pc_curr, EXCP_SEMIHOST);
80
+ gen_exception_internal_insn(s, EXCP_SEMIHOST);
81
} else {
82
gen_update_pc(s, curr_insn_len(s));
83
s->svc_imm = a->imm;
55
--
84
--
56
2.25.1
85
2.25.1
86
87
diff view generated by jsdifflib
1
From: "Edgar E. Iglesias" <edgar.iglesias@amd.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Connect the CRL (Clock Reset LPD) to the Versal SoC.
3
In preparation for TARGET_TB_PCREL, reduce reliance on absolute values.
4
4
5
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Frederic Konrad <fkonrad@amd.com>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Francisco Iglesias <francisco.iglesias@amd.com>
7
Message-id: 20221020030641.2066807-7-richard.henderson@linaro.org
8
Message-id: 20220406174303.2022038-5-edgar.iglesias@xilinx.com
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
9
---
11
include/hw/arm/xlnx-versal.h | 4 +++
10
target/arm/translate.c | 37 +++++++++++++++++++++----------------
12
hw/arm/xlnx-versal.c | 54 ++++++++++++++++++++++++++++++++++--
11
1 file changed, 21 insertions(+), 16 deletions(-)
13
2 files changed, 56 insertions(+), 2 deletions(-)
14
12
15
diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
13
diff --git a/target/arm/translate.c b/target/arm/translate.c
16
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
17
--- a/include/hw/arm/xlnx-versal.h
15
--- a/target/arm/translate.c
18
+++ b/include/hw/arm/xlnx-versal.h
16
+++ b/target/arm/translate.c
19
@@ -XXX,XX +XXX,XX @@
17
@@ -XXX,XX +XXX,XX @@ static uint32_t read_pc(DisasContext *s)
20
#include "hw/nvram/xlnx-versal-efuse.h"
18
return s->pc_curr + (s->thumb ? 4 : 8);
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
}
19
}
51
20
52
+static void versal_create_crl(Versal *s, qemu_irq *pic)
21
+/* The pc_curr difference for an architectural jump. */
22
+static target_long jmp_diff(DisasContext *s, target_long diff)
53
+{
23
+{
54
+ SysBusDevice *sbd;
24
+ return diff + (s->thumb ? 4 : 8);
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
+}
25
+}
102
+
26
+
103
/* This takes the board allocated linear DDR memory and creates aliases
27
/* Set a variable to the value of a CPU register. */
104
* for each split DDR range/aperture on the Versal address map.
28
void load_reg_var(DisasContext *s, TCGv_i32 var, int reg)
29
{
30
@@ -XXX,XX +XXX,XX @@ static void gen_goto_ptr(void)
31
* cpu_loop_exec. Any live exit_requests will be processed as we
32
* enter the next TB.
105
*/
33
*/
106
@@ -XXX,XX +XXX,XX @@ static void versal_unimp(Versal *s)
34
-static void gen_goto_tb(DisasContext *s, int n, int diff)
107
35
+static void gen_goto_tb(DisasContext *s, int n, target_long diff)
108
versal_unimp_area(s, "psm", &s->mr_ps,
36
{
109
MM_PSM_START, MM_PSM_END - MM_PSM_START);
37
target_ulong dest = s->pc_curr + diff;
110
- versal_unimp_area(s, "crl", &s->mr_ps,
38
111
- MM_CRL, MM_CRL_SIZE);
39
@@ -XXX,XX +XXX,XX @@ static void gen_goto_tb(DisasContext *s, int n, int diff)
112
versal_unimp_area(s, "crf", &s->mr_ps,
40
}
113
MM_FPD_CRF, MM_FPD_CRF_SIZE);
41
114
versal_unimp_area(s, "apu", &s->mr_ps,
42
/* Jump, specifying which TB number to use if we gen_goto_tb() */
115
@@ -XXX,XX +XXX,XX @@ static void versal_realize(DeviceState *dev, Error **errp)
43
-static inline void gen_jmp_tb(DisasContext *s, uint32_t dest, int tbno)
116
versal_create_efuse(s, pic);
44
+static void gen_jmp_tb(DisasContext *s, target_long diff, int tbno)
117
versal_create_pmc_iou_slcr(s, pic);
45
{
118
versal_create_ospi(s, pic);
46
- int diff = dest - s->pc_curr;
119
+ versal_create_crl(s, pic);
47
-
120
versal_map_ddr(s);
48
if (unlikely(s->ss_active)) {
121
versal_unimp(s);
49
/* An indirect jump so that we still trigger the debug exception. */
50
gen_update_pc(s, diff);
51
@@ -XXX,XX +XXX,XX @@ static inline void gen_jmp_tb(DisasContext *s, uint32_t dest, int tbno)
52
}
53
}
54
55
-static inline void gen_jmp(DisasContext *s, uint32_t dest)
56
+static inline void gen_jmp(DisasContext *s, target_long diff)
57
{
58
- gen_jmp_tb(s, dest, 0);
59
+ gen_jmp_tb(s, diff, 0);
60
}
61
62
static inline void gen_mulxy(TCGv_i32 t0, TCGv_i32 t1, int x, int y)
63
@@ -XXX,XX +XXX,XX @@ static bool trans_CLRM(DisasContext *s, arg_CLRM *a)
64
65
static bool trans_B(DisasContext *s, arg_i *a)
66
{
67
- gen_jmp(s, read_pc(s) + a->imm);
68
+ gen_jmp(s, jmp_diff(s, a->imm));
69
return true;
70
}
71
72
@@ -XXX,XX +XXX,XX @@ static bool trans_B_cond_thumb(DisasContext *s, arg_ci *a)
73
return true;
74
}
75
arm_skip_unless(s, a->cond);
76
- gen_jmp(s, read_pc(s) + a->imm);
77
+ gen_jmp(s, jmp_diff(s, a->imm));
78
return true;
79
}
80
81
static bool trans_BL(DisasContext *s, arg_i *a)
82
{
83
tcg_gen_movi_i32(cpu_R[14], s->base.pc_next | s->thumb);
84
- gen_jmp(s, read_pc(s) + a->imm);
85
+ gen_jmp(s, jmp_diff(s, a->imm));
86
return true;
87
}
88
89
@@ -XXX,XX +XXX,XX @@ static bool trans_BLX_i(DisasContext *s, arg_BLX_i *a)
90
}
91
tcg_gen_movi_i32(cpu_R[14], s->base.pc_next | s->thumb);
92
store_cpu_field_constant(!s->thumb, thumb);
93
- gen_jmp(s, (read_pc(s) & ~3) + a->imm);
94
+ /* This jump is computed from an aligned PC: subtract off the low bits. */
95
+ gen_jmp(s, jmp_diff(s, a->imm - (s->pc_curr & 3)));
96
return true;
97
}
98
99
@@ -XXX,XX +XXX,XX @@ static bool trans_WLS(DisasContext *s, arg_WLS *a)
100
* when we take this upcoming exit from this TB, so gen_jmp_tb() is OK.
101
*/
102
}
103
- gen_jmp_tb(s, s->base.pc_next, 1);
104
+ gen_jmp_tb(s, curr_insn_len(s), 1);
105
106
gen_set_label(nextlabel);
107
- gen_jmp(s, read_pc(s) + a->imm);
108
+ gen_jmp(s, jmp_diff(s, a->imm));
109
return true;
110
}
111
112
@@ -XXX,XX +XXX,XX @@ static bool trans_LE(DisasContext *s, arg_LE *a)
113
114
if (a->f) {
115
/* Loop-forever: just jump back to the loop start */
116
- gen_jmp(s, read_pc(s) - a->imm);
117
+ gen_jmp(s, jmp_diff(s, -a->imm));
118
return true;
119
}
120
121
@@ -XXX,XX +XXX,XX @@ static bool trans_LE(DisasContext *s, arg_LE *a)
122
tcg_temp_free_i32(decr);
123
}
124
/* Jump back to the loop start */
125
- gen_jmp(s, read_pc(s) - a->imm);
126
+ gen_jmp(s, jmp_diff(s, -a->imm));
127
128
gen_set_label(loopend);
129
if (a->tp) {
130
@@ -XXX,XX +XXX,XX @@ static bool trans_LE(DisasContext *s, arg_LE *a)
131
store_cpu_field(tcg_constant_i32(4), v7m.ltpsize);
132
}
133
/* End TB, continuing to following insn */
134
- gen_jmp_tb(s, s->base.pc_next, 1);
135
+ gen_jmp_tb(s, curr_insn_len(s), 1);
136
return true;
137
}
138
139
@@ -XXX,XX +XXX,XX @@ static bool trans_CBZ(DisasContext *s, arg_CBZ *a)
140
tcg_gen_brcondi_i32(a->nz ? TCG_COND_EQ : TCG_COND_NE,
141
tmp, 0, s->condlabel);
142
tcg_temp_free_i32(tmp);
143
- gen_jmp(s, read_pc(s) + a->imm);
144
+ gen_jmp(s, jmp_diff(s, a->imm));
145
return true;
146
}
122
147
123
--
148
--
124
2.25.1
149
2.25.1
diff view generated by jsdifflib
1
From: "Edgar E. Iglesias" <edgar.iglesias@amd.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Add the Cortex-R5Fs of the Versal RPU (Real-time Processing Unit)
3
In preparation for TARGET_TB_PCREL, reduce reliance on absolute values.
4
subsystem.
5
4
6
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Francisco Iglesias <francisco.iglesias@amd.com>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20220406174303.2022038-3-edgar.iglesias@xilinx.com
7
Message-id: 20221020030641.2066807-8-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
9
---
11
include/hw/arm/xlnx-versal.h | 10 ++++++++++
10
target/arm/translate-a64.c | 41 +++++++++++++++++++++++++++-----------
12
hw/arm/xlnx-versal-virt.c | 6 +++---
11
1 file changed, 29 insertions(+), 12 deletions(-)
13
hw/arm/xlnx-versal.c | 36 ++++++++++++++++++++++++++++++++++++
14
3 files changed, 49 insertions(+), 3 deletions(-)
15
12
16
diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
13
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
17
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
18
--- a/include/hw/arm/xlnx-versal.h
15
--- a/target/arm/translate-a64.c
19
+++ b/include/hw/arm/xlnx-versal.h
16
+++ b/target/arm/translate-a64.c
20
@@ -XXX,XX +XXX,XX @@
17
@@ -XXX,XX +XXX,XX @@ static void reset_btype(DisasContext *s)
21
OBJECT_DECLARE_SIMPLE_TYPE(Versal, XLNX_VERSAL)
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
}
61
diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
62
index XXXXXXX..XXXXXXX 100644
63
--- a/hw/arm/xlnx-versal.c
64
+++ b/hw/arm/xlnx-versal.c
65
@@ -XXX,XX +XXX,XX @@
66
#include "hw/sysbus.h"
67
68
#define XLNX_VERSAL_ACPU_TYPE ARM_CPU_TYPE_NAME("cortex-a72")
69
+#define XLNX_VERSAL_RCPU_TYPE ARM_CPU_TYPE_NAME("cortex-r5f")
70
#define GEM_REVISION 0x40070106
71
72
#define VERSAL_NUM_PMC_APB_IRQS 3
73
@@ -XXX,XX +XXX,XX @@ static void versal_create_apu_gic(Versal *s, qemu_irq *pic)
74
}
18
}
75
}
19
}
76
20
77
+static void versal_create_rpu_cpus(Versal *s)
21
+static void gen_pc_plus_diff(DisasContext *s, TCGv_i64 dest, target_long diff)
78
+{
22
+{
79
+ int i;
23
+ tcg_gen_movi_i64(dest, s->pc_curr + diff);
80
+
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
+}
24
+}
105
+
25
+
106
static void versal_create_uarts(Versal *s, qemu_irq *pic)
26
void gen_a64_update_pc(DisasContext *s, target_long diff)
107
{
27
{
108
int i;
28
- tcg_gen_movi_i64(cpu_pc, s->pc_curr + diff);
109
@@ -XXX,XX +XXX,XX @@ static void versal_realize(DeviceState *dev, Error **errp)
29
+ gen_pc_plus_diff(s, cpu_pc, diff);
110
111
versal_create_apu_cpus(s);
112
versal_create_apu_gic(s, pic);
113
+ versal_create_rpu_cpus(s);
114
versal_create_uarts(s, pic);
115
versal_create_usbs(s, pic);
116
versal_create_gems(s, pic);
117
@@ -XXX,XX +XXX,XX @@ static void versal_realize(DeviceState *dev, Error **errp)
118
119
memory_region_add_subregion_overlap(&s->mr_ps, MM_OCM, &s->lpd.mr_ocm, 0);
120
memory_region_add_subregion_overlap(&s->fpd.apu.mr, 0, &s->mr_ps, 0);
121
+ memory_region_add_subregion_overlap(&s->lpd.rpu.mr, 0,
122
+ &s->lpd.rpu.mr_ps_alias, 0);
123
}
30
}
124
31
125
static void versal_init(Object *obj)
32
/*
126
@@ -XXX,XX +XXX,XX @@ static void versal_init(Object *obj)
33
@@ -XXX,XX +XXX,XX @@ static void disas_uncond_b_imm(DisasContext *s, uint32_t insn)
127
Versal *s = XLNX_VERSAL(obj);
34
128
35
if (insn & (1U << 31)) {
129
memory_region_init(&s->fpd.apu.mr, obj, "mr-apu", UINT64_MAX);
36
/* BL Branch with link */
130
+ memory_region_init(&s->lpd.rpu.mr, obj, "mr-rpu", UINT64_MAX);
37
- tcg_gen_movi_i64(cpu_reg(s, 30), s->base.pc_next);
131
memory_region_init(&s->mr_ps, obj, "mr-ps-switch", UINT64_MAX);
38
+ gen_pc_plus_diff(s, cpu_reg(s, 30), curr_insn_len(s));
132
+ memory_region_init_alias(&s->lpd.rpu.mr_ps_alias, OBJECT(s),
39
}
133
+ "mr-rpu-ps-alias", &s->mr_ps, 0, UINT64_MAX);
40
41
/* B Branch / BL Branch with link */
42
@@ -XXX,XX +XXX,XX @@ static void disas_uncond_b_reg(DisasContext *s, uint32_t insn)
43
default:
44
goto do_unallocated;
45
}
46
- gen_a64_set_pc(s, dst);
47
/* BLR also needs to load return address */
48
if (opc == 1) {
49
- tcg_gen_movi_i64(cpu_reg(s, 30), s->base.pc_next);
50
+ TCGv_i64 lr = cpu_reg(s, 30);
51
+ if (dst == lr) {
52
+ TCGv_i64 tmp = new_tmp_a64(s);
53
+ tcg_gen_mov_i64(tmp, dst);
54
+ dst = tmp;
55
+ }
56
+ gen_pc_plus_diff(s, lr, curr_insn_len(s));
57
}
58
+ gen_a64_set_pc(s, dst);
59
break;
60
61
case 8: /* BRAA */
62
@@ -XXX,XX +XXX,XX @@ static void disas_uncond_b_reg(DisasContext *s, uint32_t insn)
63
} else {
64
dst = cpu_reg(s, rn);
65
}
66
- gen_a64_set_pc(s, dst);
67
/* BLRAA also needs to load return address */
68
if (opc == 9) {
69
- tcg_gen_movi_i64(cpu_reg(s, 30), s->base.pc_next);
70
+ TCGv_i64 lr = cpu_reg(s, 30);
71
+ if (dst == lr) {
72
+ TCGv_i64 tmp = new_tmp_a64(s);
73
+ tcg_gen_mov_i64(tmp, dst);
74
+ dst = tmp;
75
+ }
76
+ gen_pc_plus_diff(s, lr, curr_insn_len(s));
77
}
78
+ gen_a64_set_pc(s, dst);
79
break;
80
81
case 4: /* ERET */
82
@@ -XXX,XX +XXX,XX @@ static void disas_ld_lit(DisasContext *s, uint32_t insn)
83
84
tcg_rt = cpu_reg(s, rt);
85
86
- clean_addr = tcg_constant_i64(s->pc_curr + imm);
87
+ clean_addr = new_tmp_a64(s);
88
+ gen_pc_plus_diff(s, clean_addr, imm);
89
if (is_vector) {
90
do_fp_ld(s, rt, clean_addr, size);
91
} else {
92
@@ -XXX,XX +XXX,XX @@ static void disas_ldst(DisasContext *s, uint32_t insn)
93
static void disas_pc_rel_adr(DisasContext *s, uint32_t insn)
94
{
95
unsigned int page, rd;
96
- uint64_t base;
97
- uint64_t offset;
98
+ int64_t offset;
99
100
page = extract32(insn, 31, 1);
101
/* SignExtend(immhi:immlo) -> offset */
102
offset = sextract64(insn, 5, 19);
103
offset = offset << 2 | extract32(insn, 29, 2);
104
rd = extract32(insn, 0, 5);
105
- base = s->pc_curr;
106
107
if (page) {
108
/* ADRP (page based) */
109
- base &= ~0xfff;
110
offset <<= 12;
111
+ /* The page offset is ok for TARGET_TB_PCREL. */
112
+ offset -= s->pc_curr & 0xfff;
113
}
114
115
- tcg_gen_movi_i64(cpu_reg(s, rd), base + offset);
116
+ gen_pc_plus_diff(s, cpu_reg(s, rd), offset);
134
}
117
}
135
118
136
static Property versal_properties[] = {
119
/*
137
--
120
--
138
2.25.1
121
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
1
Now we have removed the only use of TYPE_EXYNOS4210_IRQ_GATE we can
1
From: Richard Henderson <richard.henderson@linaro.org>
2
delete the device entirely.
3
2
3
In preparation for TARGET_TB_PCREL, reduce reliance on absolute values.
4
5
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20221020030641.2066807-9-richard.henderson@linaro.org
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
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
---
9
---
8
hw/intc/exynos4210_gic.c | 107 ---------------------------------------
10
target/arm/translate.c | 38 +++++++++++++++++++++-----------------
9
1 file changed, 107 deletions(-)
11
1 file changed, 21 insertions(+), 17 deletions(-)
10
12
11
diff --git a/hw/intc/exynos4210_gic.c b/hw/intc/exynos4210_gic.c
13
diff --git a/target/arm/translate.c b/target/arm/translate.c
12
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
13
--- a/hw/intc/exynos4210_gic.c
15
--- a/target/arm/translate.c
14
+++ b/hw/intc/exynos4210_gic.c
16
+++ b/target/arm/translate.c
15
@@ -XXX,XX +XXX,XX @@ static void exynos4210_gic_register_types(void)
17
@@ -XXX,XX +XXX,XX @@ static inline int get_a32_user_mem_index(DisasContext *s)
18
}
16
}
19
}
17
20
18
type_init(exynos4210_gic_register_types)
21
-/* The architectural value of PC. */
19
-
22
-static uint32_t read_pc(DisasContext *s)
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
-{
23
-{
56
- Exynos4210IRQGateState *s = (Exynos4210IRQGateState *)opaque;
24
- return s->pc_curr + (s->thumb ? 4 : 8);
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
-}
25
-}
72
-
26
-
73
-static void exynos4210_irq_gate_reset(DeviceState *d)
27
/* The pc_curr difference for an architectural jump. */
74
-{
28
static target_long jmp_diff(DisasContext *s, target_long diff)
75
- Exynos4210IRQGateState *s = EXYNOS4210_IRQ_GATE(d);
29
{
76
-
30
return diff + (s->thumb ? 4 : 8);
77
- memset(s->level, 0, s->n_in * sizeof(*s->level));
31
}
78
-}
32
79
-
33
+static void gen_pc_plus_diff(DisasContext *s, TCGv_i32 var, target_long diff)
80
-/*
34
+{
81
- * IRQ Gate initialization.
35
+ tcg_gen_movi_i32(var, s->pc_curr + diff);
82
- */
36
+}
83
-static void exynos4210_irq_gate_init(Object *obj)
37
+
84
-{
38
/* Set a variable to the value of a CPU register. */
85
- Exynos4210IRQGateState *s = EXYNOS4210_IRQ_GATE(obj);
39
void load_reg_var(DisasContext *s, TCGv_i32 var, int reg)
86
- SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
40
{
87
-
41
if (reg == 15) {
88
- sysbus_init_irq(sbd, &s->out);
42
- tcg_gen_movi_i32(var, read_pc(s));
89
-}
43
+ gen_pc_plus_diff(s, var, jmp_diff(s, 0));
90
-
44
} else {
91
-static void exynos4210_irq_gate_realize(DeviceState *dev, Error **errp)
45
tcg_gen_mov_i32(var, cpu_R[reg]);
92
-{
46
}
93
- Exynos4210IRQGateState *s = EXYNOS4210_IRQ_GATE(dev);
47
@@ -XXX,XX +XXX,XX @@ TCGv_i32 add_reg_for_lit(DisasContext *s, int reg, int ofs)
94
-
48
TCGv_i32 tmp = tcg_temp_new_i32();
95
- /* Allocate general purpose input signals and connect a handler to each of
49
96
- * them */
50
if (reg == 15) {
97
- qdev_init_gpio_in(dev, exynos4210_irq_gate_handler, s->n_in);
51
- tcg_gen_movi_i32(tmp, (read_pc(s) & ~3) + ofs);
98
-
52
+ /*
99
- s->level = g_malloc0(s->n_in * sizeof(*s->level));
53
+ * This address is computed from an aligned PC:
100
-}
54
+ * subtract off the low bits.
101
-
55
+ */
102
-static void exynos4210_irq_gate_class_init(ObjectClass *klass, void *data)
56
+ gen_pc_plus_diff(s, tmp, jmp_diff(s, ofs - (s->pc_curr & 3)));
103
-{
57
} else {
104
- DeviceClass *dc = DEVICE_CLASS(klass);
58
tcg_gen_addi_i32(tmp, cpu_R[reg], ofs);
105
-
59
}
106
- dc->reset = exynos4210_irq_gate_reset;
60
@@ -XXX,XX +XXX,XX @@ void unallocated_encoding(DisasContext *s)
107
- dc->vmsd = &vmstate_exynos4210_irq_gate;
61
/* Force a TB lookup after an instruction that changes the CPU state. */
108
- device_class_set_props(dc, exynos4210_irq_gate_properties);
62
void gen_lookup_tb(DisasContext *s)
109
- dc->realize = exynos4210_irq_gate_realize;
63
{
110
-}
64
- tcg_gen_movi_i32(cpu_R[15], s->base.pc_next);
111
-
65
+ gen_pc_plus_diff(s, cpu_R[15], curr_insn_len(s));
112
-static const TypeInfo exynos4210_irq_gate_info = {
66
s->base.is_jmp = DISAS_EXIT;
113
- .name = TYPE_EXYNOS4210_IRQ_GATE,
67
}
114
- .parent = TYPE_SYS_BUS_DEVICE,
68
115
- .instance_size = sizeof(Exynos4210IRQGateState),
69
@@ -XXX,XX +XXX,XX @@ static bool trans_BLX_r(DisasContext *s, arg_BLX_r *a)
116
- .instance_init = exynos4210_irq_gate_init,
70
return false;
117
- .class_init = exynos4210_irq_gate_class_init,
71
}
118
-};
72
tmp = load_reg(s, a->rm);
119
-
73
- tcg_gen_movi_i32(cpu_R[14], s->base.pc_next | s->thumb);
120
-static void exynos4210_irq_gate_register_types(void)
74
+ gen_pc_plus_diff(s, cpu_R[14], curr_insn_len(s) | s->thumb);
121
-{
75
gen_bx(s, tmp);
122
- type_register_static(&exynos4210_irq_gate_info);
76
return true;
123
-}
77
}
124
-
78
@@ -XXX,XX +XXX,XX @@ static bool trans_B_cond_thumb(DisasContext *s, arg_ci *a)
125
-type_init(exynos4210_irq_gate_register_types)
79
80
static bool trans_BL(DisasContext *s, arg_i *a)
81
{
82
- tcg_gen_movi_i32(cpu_R[14], s->base.pc_next | s->thumb);
83
+ gen_pc_plus_diff(s, cpu_R[14], curr_insn_len(s) | s->thumb);
84
gen_jmp(s, jmp_diff(s, a->imm));
85
return true;
86
}
87
@@ -XXX,XX +XXX,XX @@ static bool trans_BLX_i(DisasContext *s, arg_BLX_i *a)
88
if (s->thumb && (a->imm & 2)) {
89
return false;
90
}
91
- tcg_gen_movi_i32(cpu_R[14], s->base.pc_next | s->thumb);
92
+ gen_pc_plus_diff(s, cpu_R[14], curr_insn_len(s) | s->thumb);
93
store_cpu_field_constant(!s->thumb, thumb);
94
/* This jump is computed from an aligned PC: subtract off the low bits. */
95
gen_jmp(s, jmp_diff(s, a->imm - (s->pc_curr & 3)));
96
@@ -XXX,XX +XXX,XX @@ static bool trans_BLX_i(DisasContext *s, arg_BLX_i *a)
97
static bool trans_BL_BLX_prefix(DisasContext *s, arg_BL_BLX_prefix *a)
98
{
99
assert(!arm_dc_feature(s, ARM_FEATURE_THUMB2));
100
- tcg_gen_movi_i32(cpu_R[14], read_pc(s) + (a->imm << 12));
101
+ gen_pc_plus_diff(s, cpu_R[14], jmp_diff(s, a->imm << 12));
102
return true;
103
}
104
105
@@ -XXX,XX +XXX,XX @@ static bool trans_BL_suffix(DisasContext *s, arg_BL_suffix *a)
106
107
assert(!arm_dc_feature(s, ARM_FEATURE_THUMB2));
108
tcg_gen_addi_i32(tmp, cpu_R[14], (a->imm << 1) | 1);
109
- tcg_gen_movi_i32(cpu_R[14], s->base.pc_next | 1);
110
+ gen_pc_plus_diff(s, cpu_R[14], curr_insn_len(s) | 1);
111
gen_bx(s, tmp);
112
return true;
113
}
114
@@ -XXX,XX +XXX,XX @@ static bool trans_BLX_suffix(DisasContext *s, arg_BLX_suffix *a)
115
tmp = tcg_temp_new_i32();
116
tcg_gen_addi_i32(tmp, cpu_R[14], a->imm << 1);
117
tcg_gen_andi_i32(tmp, tmp, 0xfffffffc);
118
- tcg_gen_movi_i32(cpu_R[14], s->base.pc_next | 1);
119
+ gen_pc_plus_diff(s, cpu_R[14], curr_insn_len(s) | 1);
120
gen_bx(s, tmp);
121
return true;
122
}
123
@@ -XXX,XX +XXX,XX @@ static bool op_tbranch(DisasContext *s, arg_tbranch *a, bool half)
124
tcg_gen_add_i32(addr, addr, tmp);
125
126
gen_aa32_ld_i32(s, tmp, addr, get_mem_index(s), half ? MO_UW : MO_UB);
127
- tcg_temp_free_i32(addr);
128
129
tcg_gen_add_i32(tmp, tmp, tmp);
130
- tcg_gen_addi_i32(tmp, tmp, read_pc(s));
131
+ gen_pc_plus_diff(s, addr, jmp_diff(s, 0));
132
+ tcg_gen_add_i32(tmp, tmp, addr);
133
+ tcg_temp_free_i32(addr);
134
store_reg(s, 15, tmp);
135
return true;
136
}
126
--
137
--
127
2.25.1
138
2.25.1
139
140
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
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
1
The function exynos4210_init_board_irqs() currently lives in
1
From: Richard Henderson <richard.henderson@linaro.org>
2
exynos4210_gic.c, but it isn't really part of the exynos4210.gic
3
device -- it is a function that implements (some of) the wiring up of
4
interrupts between the SoC's GIC and combiner components. This means
5
it fits better in exynos4210.c, which is the SoC-level code. Move it
6
there. Similarly, exynos4210_git_irq() is used almost only in the
7
SoC-level code, so move it too.
8
2
3
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
4
Message-id: 20221020030641.2066807-10-richard.henderson@linaro.org
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20220404154658.565020-8-peter.maydell@linaro.org
12
---
7
---
13
include/hw/arm/exynos4210.h | 4 -
8
target/arm/cpu-param.h | 2 +
14
hw/arm/exynos4210.c | 202 +++++++++++++++++++++++++++++++++++
9
target/arm/translate.h | 50 +++++++++++++++-
15
hw/intc/exynos4210_gic.c | 204 ------------------------------------
10
target/arm/cpu.c | 23 ++++----
16
3 files changed, 202 insertions(+), 208 deletions(-)
11
target/arm/translate-a64.c | 64 +++++++++++++-------
12
target/arm/translate-m-nocp.c | 2 +-
13
target/arm/translate.c | 108 +++++++++++++++++++++++-----------
14
6 files changed, 178 insertions(+), 71 deletions(-)
17
15
18
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
16
diff --git a/target/arm/cpu-param.h b/target/arm/cpu-param.h
19
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
20
--- a/include/hw/arm/exynos4210.h
18
--- a/target/arm/cpu-param.h
21
+++ b/include/hw/arm/exynos4210.h
19
+++ b/target/arm/cpu-param.h
22
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_SIMPLE_TYPE(Exynos4210State, EXYNOS4210_SOC)
20
@@ -XXX,XX +XXX,XX @@
23
void exynos4210_write_secondary(ARMCPU *cpu,
21
# define TARGET_PAGE_BITS_VARY
24
const struct arm_boot_info *info);
22
# define TARGET_PAGE_BITS_MIN 10
25
23
26
-/* Initialize board IRQs.
24
+# define TARGET_TB_PCREL 1
27
- * These IRQs contain splitted Int/External Combiner and External Gic IRQs */
25
+
28
-void exynos4210_init_board_irqs(Exynos4210State *s);
26
/*
29
-
27
* Cache the attrs and shareability fields from the page table entry.
30
/* Get IRQ number from exynos4210 IRQ subsystem stub.
28
*
31
* To identify IRQ source use internal combiner group and bit number
29
diff --git a/target/arm/translate.h b/target/arm/translate.h
32
* grp - group number
33
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
34
index XXXXXXX..XXXXXXX 100644
30
index XXXXXXX..XXXXXXX 100644
35
--- a/hw/arm/exynos4210.c
31
--- a/target/arm/translate.h
36
+++ b/hw/arm/exynos4210.c
32
+++ b/target/arm/translate.h
37
@@ -XXX,XX +XXX,XX @@
33
@@ -XXX,XX +XXX,XX @@
38
#define EXYNOS4210_PL330_BASE1_ADDR 0x12690000
34
39
#define EXYNOS4210_PL330_BASE2_ADDR 0x12850000
35
40
36
/* internal defines */
41
+enum ExtGicId {
42
+ EXT_GIC_ID_MDMA_LCD0 = 66,
43
+ EXT_GIC_ID_PDMA0,
44
+ EXT_GIC_ID_PDMA1,
45
+ EXT_GIC_ID_TIMER0,
46
+ EXT_GIC_ID_TIMER1,
47
+ EXT_GIC_ID_TIMER2,
48
+ EXT_GIC_ID_TIMER3,
49
+ EXT_GIC_ID_TIMER4,
50
+ EXT_GIC_ID_MCT_L0,
51
+ EXT_GIC_ID_WDT,
52
+ EXT_GIC_ID_RTC_ALARM,
53
+ EXT_GIC_ID_RTC_TIC,
54
+ EXT_GIC_ID_GPIO_XB,
55
+ EXT_GIC_ID_GPIO_XA,
56
+ EXT_GIC_ID_MCT_L1,
57
+ EXT_GIC_ID_IEM_APC,
58
+ EXT_GIC_ID_IEM_IEC,
59
+ EXT_GIC_ID_NFC,
60
+ EXT_GIC_ID_UART0,
61
+ EXT_GIC_ID_UART1,
62
+ EXT_GIC_ID_UART2,
63
+ EXT_GIC_ID_UART3,
64
+ EXT_GIC_ID_UART4,
65
+ EXT_GIC_ID_MCT_G0,
66
+ EXT_GIC_ID_I2C0,
67
+ EXT_GIC_ID_I2C1,
68
+ EXT_GIC_ID_I2C2,
69
+ EXT_GIC_ID_I2C3,
70
+ EXT_GIC_ID_I2C4,
71
+ EXT_GIC_ID_I2C5,
72
+ EXT_GIC_ID_I2C6,
73
+ EXT_GIC_ID_I2C7,
74
+ EXT_GIC_ID_SPI0,
75
+ EXT_GIC_ID_SPI1,
76
+ EXT_GIC_ID_SPI2,
77
+ EXT_GIC_ID_MCT_G1,
78
+ EXT_GIC_ID_USB_HOST,
79
+ EXT_GIC_ID_USB_DEVICE,
80
+ EXT_GIC_ID_MODEMIF,
81
+ EXT_GIC_ID_HSMMC0,
82
+ EXT_GIC_ID_HSMMC1,
83
+ EXT_GIC_ID_HSMMC2,
84
+ EXT_GIC_ID_HSMMC3,
85
+ EXT_GIC_ID_SDMMC,
86
+ EXT_GIC_ID_MIPI_CSI_4LANE,
87
+ EXT_GIC_ID_MIPI_DSI_4LANE,
88
+ EXT_GIC_ID_MIPI_CSI_2LANE,
89
+ EXT_GIC_ID_MIPI_DSI_2LANE,
90
+ EXT_GIC_ID_ONENAND_AUDI,
91
+ EXT_GIC_ID_ROTATOR,
92
+ EXT_GIC_ID_FIMC0,
93
+ EXT_GIC_ID_FIMC1,
94
+ EXT_GIC_ID_FIMC2,
95
+ EXT_GIC_ID_FIMC3,
96
+ EXT_GIC_ID_JPEG,
97
+ EXT_GIC_ID_2D,
98
+ EXT_GIC_ID_PCIe,
99
+ EXT_GIC_ID_MIXER,
100
+ EXT_GIC_ID_HDMI,
101
+ EXT_GIC_ID_HDMI_I2C,
102
+ EXT_GIC_ID_MFC,
103
+ EXT_GIC_ID_TVENC,
104
+};
105
+
106
+enum ExtInt {
107
+ EXT_GIC_ID_EXTINT0 = 48,
108
+ EXT_GIC_ID_EXTINT1,
109
+ EXT_GIC_ID_EXTINT2,
110
+ EXT_GIC_ID_EXTINT3,
111
+ EXT_GIC_ID_EXTINT4,
112
+ EXT_GIC_ID_EXTINT5,
113
+ EXT_GIC_ID_EXTINT6,
114
+ EXT_GIC_ID_EXTINT7,
115
+ EXT_GIC_ID_EXTINT8,
116
+ EXT_GIC_ID_EXTINT9,
117
+ EXT_GIC_ID_EXTINT10,
118
+ EXT_GIC_ID_EXTINT11,
119
+ EXT_GIC_ID_EXTINT12,
120
+ EXT_GIC_ID_EXTINT13,
121
+ EXT_GIC_ID_EXTINT14,
122
+ EXT_GIC_ID_EXTINT15
123
+};
124
+
37
+
125
+/*
38
+/*
126
+ * External GIC sources which are not from External Interrupt Combiner or
39
+ * Save pc_save across a branch, so that we may restore the value from
127
+ * External Interrupts are starting from EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ,
40
+ * before the branch at the point the label is emitted.
128
+ * which is INTG16 in Internal Interrupt Combiner.
129
+ */
41
+ */
42
+typedef struct DisasLabel {
43
+ TCGLabel *label;
44
+ target_ulong pc_save;
45
+} DisasLabel;
130
+
46
+
131
+static const uint32_t
47
typedef struct DisasContext {
132
+combiner_grp_to_gic_id[64 - EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][8] = {
48
DisasContextBase base;
133
+ /* int combiner groups 16-19 */
49
const ARMISARegisters *isar;
134
+ { }, { }, { }, { },
50
135
+ /* int combiner group 20 */
51
/* The address of the current instruction being translated. */
136
+ { 0, EXT_GIC_ID_MDMA_LCD0 },
52
target_ulong pc_curr;
137
+ /* int combiner group 21 */
53
+ /*
138
+ { EXT_GIC_ID_PDMA0, EXT_GIC_ID_PDMA1 },
54
+ * For TARGET_TB_PCREL, the full value of cpu_pc is not known
139
+ /* int combiner group 22 */
55
+ * (although the page offset is known). For convenience, the
140
+ { EXT_GIC_ID_TIMER0, EXT_GIC_ID_TIMER1, EXT_GIC_ID_TIMER2,
56
+ * translation loop uses the full virtual address that triggered
141
+ EXT_GIC_ID_TIMER3, EXT_GIC_ID_TIMER4 },
57
+ * the translation, from base.pc_start through pc_curr.
142
+ /* int combiner group 23 */
58
+ * For efficiency, we do not update cpu_pc for every instruction.
143
+ { EXT_GIC_ID_RTC_ALARM, EXT_GIC_ID_RTC_TIC },
59
+ * Instead, pc_save has the value of pc_curr at the time of the
144
+ /* int combiner group 24 */
60
+ * last update to cpu_pc, which allows us to compute the addend
145
+ { EXT_GIC_ID_GPIO_XB, EXT_GIC_ID_GPIO_XA },
61
+ * needed to bring cpu_pc current: pc_curr - pc_save.
146
+ /* int combiner group 25 */
62
+ * If cpu_pc now contains the destination of an indirect branch,
147
+ { EXT_GIC_ID_IEM_APC, EXT_GIC_ID_IEM_IEC },
63
+ * pc_save contains -1 to indicate that relative updates are no
148
+ /* int combiner group 26 */
64
+ * longer possible.
149
+ { EXT_GIC_ID_UART0, EXT_GIC_ID_UART1, EXT_GIC_ID_UART2, EXT_GIC_ID_UART3,
65
+ */
150
+ EXT_GIC_ID_UART4 },
66
+ target_ulong pc_save;
151
+ /* int combiner group 27 */
67
target_ulong page_start;
152
+ { EXT_GIC_ID_I2C0, EXT_GIC_ID_I2C1, EXT_GIC_ID_I2C2, EXT_GIC_ID_I2C3,
68
uint32_t insn;
153
+ EXT_GIC_ID_I2C4, EXT_GIC_ID_I2C5, EXT_GIC_ID_I2C6,
69
/* Nonzero if this instruction has been conditionally skipped. */
154
+ EXT_GIC_ID_I2C7 },
70
int condjmp;
155
+ /* int combiner group 28 */
71
/* The label that will be jumped to when the instruction is skipped. */
156
+ { EXT_GIC_ID_SPI0, EXT_GIC_ID_SPI1, EXT_GIC_ID_SPI2 , EXT_GIC_ID_USB_HOST},
72
- TCGLabel *condlabel;
157
+ /* int combiner group 29 */
73
+ DisasLabel condlabel;
158
+ { EXT_GIC_ID_HSMMC0, EXT_GIC_ID_HSMMC1, EXT_GIC_ID_HSMMC2,
74
/* Thumb-2 conditional execution bits. */
159
+ EXT_GIC_ID_HSMMC3, EXT_GIC_ID_SDMMC },
75
int condexec_mask;
160
+ /* int combiner group 30 */
76
int condexec_cond;
161
+ { EXT_GIC_ID_MIPI_CSI_4LANE, EXT_GIC_ID_MIPI_CSI_2LANE },
77
@@ -XXX,XX +XXX,XX @@ typedef struct DisasContext {
162
+ /* int combiner group 31 */
78
* after decode (ie after any UNDEF checks)
163
+ { EXT_GIC_ID_MIPI_DSI_4LANE, EXT_GIC_ID_MIPI_DSI_2LANE },
79
*/
164
+ /* int combiner group 32 */
80
bool eci_handled;
165
+ { EXT_GIC_ID_FIMC0, EXT_GIC_ID_FIMC1 },
81
- /* TCG op to rewind to if this turns out to be an invalid ECI state */
166
+ /* int combiner group 33 */
82
- TCGOp *insn_eci_rewind;
167
+ { EXT_GIC_ID_FIMC2, EXT_GIC_ID_FIMC3 },
83
int sctlr_b;
168
+ /* int combiner group 34 */
84
MemOp be_data;
169
+ { EXT_GIC_ID_ONENAND_AUDI, EXT_GIC_ID_NFC },
85
#if !defined(CONFIG_USER_ONLY)
170
+ /* int combiner group 35 */
86
@@ -XXX,XX +XXX,XX @@ static inline MemOp finalize_memop(DisasContext *s, MemOp opc)
171
+ { 0, 0, 0, EXT_GIC_ID_MCT_L1, EXT_GIC_ID_MCT_G0, EXT_GIC_ID_MCT_G1 },
87
*/
172
+ /* int combiner group 36 */
88
uint64_t asimd_imm_const(uint32_t imm, int cmode, int op);
173
+ { EXT_GIC_ID_MIXER },
89
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
+/*
90
+/*
190
+ * Initialize board IRQs.
91
+ * gen_disas_label:
191
+ * These IRQs contain splitted Int/External Combiner and External Gic IRQs.
92
+ * Create a label and cache a copy of pc_save.
192
+ */
93
+ */
193
+static void exynos4210_init_board_irqs(Exynos4210State *s)
94
+static inline DisasLabel gen_disas_label(DisasContext *s)
194
+{
95
+{
195
+ uint32_t grp, bit, irq_id, n;
96
+ return (DisasLabel){
196
+ Exynos4210Irq *is = &s->irqs;
97
+ .label = gen_new_label(),
197
+
98
+ .pc_save = s->pc_save,
198
+ for (n = 0; n < EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ; n++) {
99
+ };
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
+ }
205
+ if (n == EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 5) ||
206
+ n == EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 5)) {
207
+ /* MCT_G1 is passed to External and GIC */
208
+ irq_id = EXT_GIC_ID_MCT_G1;
209
+ }
210
+ if (irq_id) {
211
+ s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
212
+ is->ext_gic_irq[irq_id - 32]);
213
+ } else {
214
+ s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
215
+ is->ext_combiner_irq[n]);
216
+ }
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
+ }
230
+}
100
+}
231
+
101
+
232
+/*
102
+/*
233
+ * Get IRQ number from exynos4210 IRQ subsystem stub.
103
+ * set_disas_label:
234
+ * To identify IRQ source use internal combiner group and bit number
104
+ * Emit a label and restore the cached copy of pc_save.
235
+ * grp - group number
236
+ * bit - bit number inside group
237
+ */
105
+ */
238
+uint32_t exynos4210_get_irq(uint32_t grp, uint32_t bit)
106
+static inline void set_disas_label(DisasContext *s, DisasLabel l)
239
+{
107
+{
240
+ return EXYNOS4210_COMBINER_GET_IRQ_NUM(grp, bit);
108
+ gen_set_label(l.label);
109
+ s->pc_save = l.pc_save;
241
+}
110
+}
242
+
111
+
243
static uint8_t chipid_and_omr[] = { 0x11, 0x02, 0x21, 0x43,
112
/*
244
0x09, 0x00, 0x00, 0x00 };
113
* Helpers for implementing sets of trans_* functions.
245
114
* Defer the implementation of NAME to FUNC, with optional extra arguments.
246
diff --git a/hw/intc/exynos4210_gic.c b/hw/intc/exynos4210_gic.c
115
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
247
index XXXXXXX..XXXXXXX 100644
116
index XXXXXXX..XXXXXXX 100644
248
--- a/hw/intc/exynos4210_gic.c
117
--- a/target/arm/cpu.c
249
+++ b/hw/intc/exynos4210_gic.c
118
+++ b/target/arm/cpu.c
250
@@ -XXX,XX +XXX,XX @@
119
@@ -XXX,XX +XXX,XX @@ static vaddr arm_cpu_get_pc(CPUState *cs)
251
#include "hw/arm/exynos4210.h"
120
void arm_cpu_synchronize_from_tb(CPUState *cs,
252
#include "qom/object.h"
121
const TranslationBlock *tb)
253
122
{
254
-enum ExtGicId {
123
- ARMCPU *cpu = ARM_CPU(cs);
255
- EXT_GIC_ID_MDMA_LCD0 = 66,
124
- CPUARMState *env = &cpu->env;
256
- EXT_GIC_ID_PDMA0,
257
- EXT_GIC_ID_PDMA1,
258
- EXT_GIC_ID_TIMER0,
259
- EXT_GIC_ID_TIMER1,
260
- EXT_GIC_ID_TIMER2,
261
- EXT_GIC_ID_TIMER3,
262
- EXT_GIC_ID_TIMER4,
263
- EXT_GIC_ID_MCT_L0,
264
- EXT_GIC_ID_WDT,
265
- EXT_GIC_ID_RTC_ALARM,
266
- EXT_GIC_ID_RTC_TIC,
267
- EXT_GIC_ID_GPIO_XB,
268
- EXT_GIC_ID_GPIO_XA,
269
- EXT_GIC_ID_MCT_L1,
270
- EXT_GIC_ID_IEM_APC,
271
- EXT_GIC_ID_IEM_IEC,
272
- EXT_GIC_ID_NFC,
273
- EXT_GIC_ID_UART0,
274
- EXT_GIC_ID_UART1,
275
- EXT_GIC_ID_UART2,
276
- EXT_GIC_ID_UART3,
277
- EXT_GIC_ID_UART4,
278
- EXT_GIC_ID_MCT_G0,
279
- EXT_GIC_ID_I2C0,
280
- EXT_GIC_ID_I2C1,
281
- EXT_GIC_ID_I2C2,
282
- EXT_GIC_ID_I2C3,
283
- EXT_GIC_ID_I2C4,
284
- EXT_GIC_ID_I2C5,
285
- EXT_GIC_ID_I2C6,
286
- EXT_GIC_ID_I2C7,
287
- EXT_GIC_ID_SPI0,
288
- EXT_GIC_ID_SPI1,
289
- EXT_GIC_ID_SPI2,
290
- EXT_GIC_ID_MCT_G1,
291
- EXT_GIC_ID_USB_HOST,
292
- EXT_GIC_ID_USB_DEVICE,
293
- EXT_GIC_ID_MODEMIF,
294
- EXT_GIC_ID_HSMMC0,
295
- EXT_GIC_ID_HSMMC1,
296
- EXT_GIC_ID_HSMMC2,
297
- EXT_GIC_ID_HSMMC3,
298
- EXT_GIC_ID_SDMMC,
299
- EXT_GIC_ID_MIPI_CSI_4LANE,
300
- EXT_GIC_ID_MIPI_DSI_4LANE,
301
- EXT_GIC_ID_MIPI_CSI_2LANE,
302
- EXT_GIC_ID_MIPI_DSI_2LANE,
303
- EXT_GIC_ID_ONENAND_AUDI,
304
- EXT_GIC_ID_ROTATOR,
305
- EXT_GIC_ID_FIMC0,
306
- EXT_GIC_ID_FIMC1,
307
- EXT_GIC_ID_FIMC2,
308
- EXT_GIC_ID_FIMC3,
309
- EXT_GIC_ID_JPEG,
310
- EXT_GIC_ID_2D,
311
- EXT_GIC_ID_PCIe,
312
- EXT_GIC_ID_MIXER,
313
- EXT_GIC_ID_HDMI,
314
- EXT_GIC_ID_HDMI_I2C,
315
- EXT_GIC_ID_MFC,
316
- EXT_GIC_ID_TVENC,
317
-};
318
-
125
-
319
-enum ExtInt {
126
- /*
320
- EXT_GIC_ID_EXTINT0 = 48,
127
- * It's OK to look at env for the current mode here, because it's
321
- EXT_GIC_ID_EXTINT1,
128
- * never possible for an AArch64 TB to chain to an AArch32 TB.
322
- EXT_GIC_ID_EXTINT2,
129
- */
323
- EXT_GIC_ID_EXTINT3,
130
- if (is_a64(env)) {
324
- EXT_GIC_ID_EXTINT4,
131
- env->pc = tb_pc(tb);
325
- EXT_GIC_ID_EXTINT5,
132
- } else {
326
- EXT_GIC_ID_EXTINT6,
133
- env->regs[15] = tb_pc(tb);
327
- EXT_GIC_ID_EXTINT7,
134
+ /* The program counter is always up to date with TARGET_TB_PCREL. */
328
- EXT_GIC_ID_EXTINT8,
135
+ if (!TARGET_TB_PCREL) {
329
- EXT_GIC_ID_EXTINT9,
136
+ CPUARMState *env = cs->env_ptr;
330
- EXT_GIC_ID_EXTINT10,
137
+ /*
331
- EXT_GIC_ID_EXTINT11,
138
+ * It's OK to look at env for the current mode here, because it's
332
- EXT_GIC_ID_EXTINT12,
139
+ * never possible for an AArch64 TB to chain to an AArch32 TB.
333
- EXT_GIC_ID_EXTINT13,
140
+ */
334
- EXT_GIC_ID_EXTINT14,
141
+ if (is_a64(env)) {
335
- EXT_GIC_ID_EXTINT15
142
+ env->pc = tb_pc(tb);
336
-};
143
+ } else {
144
+ env->regs[15] = tb_pc(tb);
145
+ }
146
}
147
}
148
#endif /* CONFIG_TCG */
149
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
150
index XXXXXXX..XXXXXXX 100644
151
--- a/target/arm/translate-a64.c
152
+++ b/target/arm/translate-a64.c
153
@@ -XXX,XX +XXX,XX @@ static void reset_btype(DisasContext *s)
154
155
static void gen_pc_plus_diff(DisasContext *s, TCGv_i64 dest, target_long diff)
156
{
157
- tcg_gen_movi_i64(dest, s->pc_curr + diff);
158
+ assert(s->pc_save != -1);
159
+ if (TARGET_TB_PCREL) {
160
+ tcg_gen_addi_i64(dest, cpu_pc, (s->pc_curr - s->pc_save) + diff);
161
+ } else {
162
+ tcg_gen_movi_i64(dest, s->pc_curr + diff);
163
+ }
164
}
165
166
void gen_a64_update_pc(DisasContext *s, target_long diff)
167
{
168
gen_pc_plus_diff(s, cpu_pc, diff);
169
+ s->pc_save = s->pc_curr + diff;
170
}
171
172
/*
173
@@ -XXX,XX +XXX,XX @@ static void gen_a64_set_pc(DisasContext *s, TCGv_i64 src)
174
* then loading an address into the PC will clear out any tag.
175
*/
176
gen_top_byte_ignore(s, cpu_pc, src, s->tbii);
177
+ s->pc_save = -1;
178
}
179
180
/*
181
@@ -XXX,XX +XXX,XX @@ static inline bool use_goto_tb(DisasContext *s, uint64_t dest)
182
183
static void gen_goto_tb(DisasContext *s, int n, int64_t diff)
184
{
185
- uint64_t dest = s->pc_curr + diff;
337
-
186
-
338
-/*
187
- if (use_goto_tb(s, dest)) {
339
- * External GIC sources which are not from External Interrupt Combiner or
188
- tcg_gen_goto_tb(n);
340
- * External Interrupts are starting from EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ,
189
- gen_a64_update_pc(s, diff);
341
- * which is INTG16 in Internal Interrupt Combiner.
190
+ if (use_goto_tb(s, s->pc_curr + diff)) {
342
- */
191
+ /*
192
+ * For pcrel, the pc must always be up-to-date on entry to
193
+ * the linked TB, so that it can use simple additions for all
194
+ * further adjustments. For !pcrel, the linked TB is compiled
195
+ * to know its full virtual address, so we can delay the
196
+ * update to pc to the unlinked path. A long chain of links
197
+ * can thus avoid many updates to the PC.
198
+ */
199
+ if (TARGET_TB_PCREL) {
200
+ gen_a64_update_pc(s, diff);
201
+ tcg_gen_goto_tb(n);
202
+ } else {
203
+ tcg_gen_goto_tb(n);
204
+ gen_a64_update_pc(s, diff);
205
+ }
206
tcg_gen_exit_tb(s->base.tb, n);
207
s->base.is_jmp = DISAS_NORETURN;
208
} else {
209
@@ -XXX,XX +XXX,XX @@ static void disas_comp_b_imm(DisasContext *s, uint32_t insn)
210
{
211
unsigned int sf, op, rt;
212
int64_t diff;
213
- TCGLabel *label_match;
214
+ DisasLabel match;
215
TCGv_i64 tcg_cmp;
216
217
sf = extract32(insn, 31, 1);
218
@@ -XXX,XX +XXX,XX @@ static void disas_comp_b_imm(DisasContext *s, uint32_t insn)
219
diff = sextract32(insn, 5, 19) * 4;
220
221
tcg_cmp = read_cpu_reg(s, rt, sf);
222
- label_match = gen_new_label();
343
-
223
-
344
-static const uint32_t
224
reset_btype(s);
345
-combiner_grp_to_gic_id[64 - EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][8] = {
225
- tcg_gen_brcondi_i64(op ? TCG_COND_NE : TCG_COND_EQ,
346
- /* int combiner groups 16-19 */
226
- tcg_cmp, 0, label_match);
347
- { }, { }, { }, { },
227
348
- /* int combiner group 20 */
228
+ match = gen_disas_label(s);
349
- { 0, EXT_GIC_ID_MDMA_LCD0 },
229
+ tcg_gen_brcondi_i64(op ? TCG_COND_NE : TCG_COND_EQ,
350
- /* int combiner group 21 */
230
+ tcg_cmp, 0, match.label);
351
- { EXT_GIC_ID_PDMA0, EXT_GIC_ID_PDMA1 },
231
gen_goto_tb(s, 0, 4);
352
- /* int combiner group 22 */
232
- gen_set_label(label_match);
353
- { EXT_GIC_ID_TIMER0, EXT_GIC_ID_TIMER1, EXT_GIC_ID_TIMER2,
233
+ set_disas_label(s, match);
354
- EXT_GIC_ID_TIMER3, EXT_GIC_ID_TIMER4 },
234
gen_goto_tb(s, 1, diff);
355
- /* int combiner group 23 */
235
}
356
- { EXT_GIC_ID_RTC_ALARM, EXT_GIC_ID_RTC_TIC },
236
357
- /* int combiner group 24 */
237
@@ -XXX,XX +XXX,XX @@ static void disas_test_b_imm(DisasContext *s, uint32_t insn)
358
- { EXT_GIC_ID_GPIO_XB, EXT_GIC_ID_GPIO_XA },
238
{
359
- /* int combiner group 25 */
239
unsigned int bit_pos, op, rt;
360
- { EXT_GIC_ID_IEM_APC, EXT_GIC_ID_IEM_IEC },
240
int64_t diff;
361
- /* int combiner group 26 */
241
- TCGLabel *label_match;
362
- { EXT_GIC_ID_UART0, EXT_GIC_ID_UART1, EXT_GIC_ID_UART2, EXT_GIC_ID_UART3,
242
+ DisasLabel match;
363
- EXT_GIC_ID_UART4 },
243
TCGv_i64 tcg_cmp;
364
- /* int combiner group 27 */
244
365
- { EXT_GIC_ID_I2C0, EXT_GIC_ID_I2C1, EXT_GIC_ID_I2C2, EXT_GIC_ID_I2C3,
245
bit_pos = (extract32(insn, 31, 1) << 5) | extract32(insn, 19, 5);
366
- EXT_GIC_ID_I2C4, EXT_GIC_ID_I2C5, EXT_GIC_ID_I2C6,
246
@@ -XXX,XX +XXX,XX @@ static void disas_test_b_imm(DisasContext *s, uint32_t insn)
367
- EXT_GIC_ID_I2C7 },
247
368
- /* int combiner group 28 */
248
tcg_cmp = tcg_temp_new_i64();
369
- { EXT_GIC_ID_SPI0, EXT_GIC_ID_SPI1, EXT_GIC_ID_SPI2 , EXT_GIC_ID_USB_HOST},
249
tcg_gen_andi_i64(tcg_cmp, cpu_reg(s, rt), (1ULL << bit_pos));
370
- /* int combiner group 29 */
250
- label_match = gen_new_label();
371
- { EXT_GIC_ID_HSMMC0, EXT_GIC_ID_HSMMC1, EXT_GIC_ID_HSMMC2,
251
372
- EXT_GIC_ID_HSMMC3, EXT_GIC_ID_SDMMC },
252
reset_btype(s);
373
- /* int combiner group 30 */
253
+
374
- { EXT_GIC_ID_MIPI_CSI_4LANE, EXT_GIC_ID_MIPI_CSI_2LANE },
254
+ match = gen_disas_label(s);
375
- /* int combiner group 31 */
255
tcg_gen_brcondi_i64(op ? TCG_COND_NE : TCG_COND_EQ,
376
- { EXT_GIC_ID_MIPI_DSI_4LANE, EXT_GIC_ID_MIPI_DSI_2LANE },
256
- tcg_cmp, 0, label_match);
377
- /* int combiner group 32 */
257
+ tcg_cmp, 0, match.label);
378
- { EXT_GIC_ID_FIMC0, EXT_GIC_ID_FIMC1 },
258
tcg_temp_free_i64(tcg_cmp);
379
- /* int combiner group 33 */
259
gen_goto_tb(s, 0, 4);
380
- { EXT_GIC_ID_FIMC2, EXT_GIC_ID_FIMC3 },
260
- gen_set_label(label_match);
381
- /* int combiner group 34 */
261
+ set_disas_label(s, match);
382
- { EXT_GIC_ID_ONENAND_AUDI, EXT_GIC_ID_NFC },
262
gen_goto_tb(s, 1, diff);
383
- /* int combiner group 35 */
263
}
384
- { 0, 0, 0, EXT_GIC_ID_MCT_L1, EXT_GIC_ID_MCT_G0, EXT_GIC_ID_MCT_G1 },
264
385
- /* int combiner group 36 */
265
@@ -XXX,XX +XXX,XX @@ static void disas_cond_b_imm(DisasContext *s, uint32_t insn)
386
- { EXT_GIC_ID_MIXER },
266
reset_btype(s);
387
- /* int combiner group 37 */
267
if (cond < 0x0e) {
388
- { EXT_GIC_ID_EXTINT4, EXT_GIC_ID_EXTINT5, EXT_GIC_ID_EXTINT6,
268
/* genuinely conditional branches */
389
- EXT_GIC_ID_EXTINT7 },
269
- TCGLabel *label_match = gen_new_label();
390
- /* groups 38-50 */
270
- arm_gen_test_cc(cond, label_match);
391
- { }, { }, { }, { }, { }, { }, { }, { }, { }, { }, { }, { }, { },
271
+ DisasLabel match = gen_disas_label(s);
392
- /* int combiner group 51 */
272
+ arm_gen_test_cc(cond, match.label);
393
- { EXT_GIC_ID_MCT_L0, 0, 0, 0, EXT_GIC_ID_MCT_G0, EXT_GIC_ID_MCT_G1 },
273
gen_goto_tb(s, 0, 4);
394
- /* group 52 */
274
- gen_set_label(label_match);
395
- { },
275
+ set_disas_label(s, match);
396
- /* int combiner group 53 */
276
gen_goto_tb(s, 1, diff);
397
- { EXT_GIC_ID_WDT, 0, 0, 0, EXT_GIC_ID_MCT_G0, EXT_GIC_ID_MCT_G1 },
277
} else {
398
- /* groups 54-63 */
278
/* 0xe and 0xf are both "always" conditions */
399
- { }, { }, { }, { }, { }, { }, { }, { }, { }, { }
279
@@ -XXX,XX +XXX,XX @@ static void aarch64_tr_init_disas_context(DisasContextBase *dcbase,
400
-};
280
281
dc->isar = &arm_cpu->isar;
282
dc->condjmp = 0;
401
-
283
-
402
#define EXYNOS4210_GIC_NIRQ 160
284
+ dc->pc_save = dc->base.pc_first;
403
285
dc->aarch64 = true;
404
#define EXYNOS4210_EXT_GIC_CPU_REGION_SIZE 0x10000
286
dc->thumb = false;
405
@@ -XXX,XX +XXX,XX @@ combiner_grp_to_gic_id[64 - EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][8] = {
287
dc->sctlr_b = 0;
406
#define EXYNOS4210_GIC_CPU_REGION_SIZE 0x100
288
@@ -XXX,XX +XXX,XX @@ static void aarch64_tr_tb_start(DisasContextBase *db, CPUState *cpu)
407
#define EXYNOS4210_GIC_DIST_REGION_SIZE 0x1000
289
static void aarch64_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
408
290
{
409
-/*
291
DisasContext *dc = container_of(dcbase, DisasContext, base);
410
- * Initialize board IRQs.
292
+ target_ulong pc_arg = dc->base.pc_next;
411
- * These IRQs contain splitted Int/External Combiner and External Gic IRQs.
293
412
- */
294
- tcg_gen_insn_start(dc->base.pc_next, 0, 0);
413
-void exynos4210_init_board_irqs(Exynos4210State *s)
295
+ if (TARGET_TB_PCREL) {
414
-{
296
+ pc_arg &= ~TARGET_PAGE_MASK;
415
- uint32_t grp, bit, irq_id, n;
297
+ }
416
- Exynos4210Irq *is = &s->irqs;
298
+ tcg_gen_insn_start(pc_arg, 0, 0);
299
dc->insn_start = tcg_last_op();
300
}
301
302
diff --git a/target/arm/translate-m-nocp.c b/target/arm/translate-m-nocp.c
303
index XXXXXXX..XXXXXXX 100644
304
--- a/target/arm/translate-m-nocp.c
305
+++ b/target/arm/translate-m-nocp.c
306
@@ -XXX,XX +XXX,XX @@ static bool trans_VSCCLRM(DisasContext *s, arg_VSCCLRM *a)
307
tcg_gen_andi_i32(sfpa, sfpa, R_V7M_CONTROL_SFPA_MASK);
308
tcg_gen_or_i32(sfpa, sfpa, aspen);
309
arm_gen_condlabel(s);
310
- tcg_gen_brcondi_i32(TCG_COND_EQ, sfpa, 0, s->condlabel);
311
+ tcg_gen_brcondi_i32(TCG_COND_EQ, sfpa, 0, s->condlabel.label);
312
313
if (s->fp_excp_el != 0) {
314
gen_exception_insn_el(s, 0, EXCP_NOCP,
315
diff --git a/target/arm/translate.c b/target/arm/translate.c
316
index XXXXXXX..XXXXXXX 100644
317
--- a/target/arm/translate.c
318
+++ b/target/arm/translate.c
319
@@ -XXX,XX +XXX,XX @@ uint64_t asimd_imm_const(uint32_t imm, int cmode, int op)
320
void arm_gen_condlabel(DisasContext *s)
321
{
322
if (!s->condjmp) {
323
- s->condlabel = gen_new_label();
324
+ s->condlabel = gen_disas_label(s);
325
s->condjmp = 1;
326
}
327
}
328
@@ -XXX,XX +XXX,XX @@ static target_long jmp_diff(DisasContext *s, target_long diff)
329
330
static void gen_pc_plus_diff(DisasContext *s, TCGv_i32 var, target_long diff)
331
{
332
- tcg_gen_movi_i32(var, s->pc_curr + diff);
333
+ assert(s->pc_save != -1);
334
+ if (TARGET_TB_PCREL) {
335
+ tcg_gen_addi_i32(var, cpu_R[15], (s->pc_curr - s->pc_save) + diff);
336
+ } else {
337
+ tcg_gen_movi_i32(var, s->pc_curr + diff);
338
+ }
339
}
340
341
/* Set a variable to the value of a CPU register. */
342
@@ -XXX,XX +XXX,XX @@ void store_reg(DisasContext *s, int reg, TCGv_i32 var)
343
*/
344
tcg_gen_andi_i32(var, var, s->thumb ? ~1 : ~3);
345
s->base.is_jmp = DISAS_JUMP;
346
+ s->pc_save = -1;
347
} else if (reg == 13 && arm_dc_feature(s, ARM_FEATURE_M)) {
348
/* For M-profile SP bits [1:0] are always zero */
349
tcg_gen_andi_i32(var, var, ~3);
350
@@ -XXX,XX +XXX,XX @@ void gen_set_condexec(DisasContext *s)
351
352
void gen_update_pc(DisasContext *s, target_long diff)
353
{
354
- tcg_gen_movi_i32(cpu_R[15], s->pc_curr + diff);
355
+ gen_pc_plus_diff(s, cpu_R[15], diff);
356
+ s->pc_save = s->pc_curr + diff;
357
}
358
359
/* Set PC and Thumb state from var. var is marked as dead. */
360
@@ -XXX,XX +XXX,XX @@ static inline void gen_bx(DisasContext *s, TCGv_i32 var)
361
tcg_gen_andi_i32(cpu_R[15], var, ~1);
362
tcg_gen_andi_i32(var, var, 1);
363
store_cpu_field(var, thumb);
364
+ s->pc_save = -1;
365
}
366
367
/*
368
@@ -XXX,XX +XXX,XX @@ static inline void gen_bx_excret(DisasContext *s, TCGv_i32 var)
369
static inline void gen_bx_excret_final_code(DisasContext *s)
370
{
371
/* Generate the code to finish possible exception return and end the TB */
372
- TCGLabel *excret_label = gen_new_label();
373
+ DisasLabel excret_label = gen_disas_label(s);
374
uint32_t min_magic;
375
376
if (arm_dc_feature(s, ARM_FEATURE_M_SECURITY)) {
377
@@ -XXX,XX +XXX,XX @@ static inline void gen_bx_excret_final_code(DisasContext *s)
378
}
379
380
/* Is the new PC value in the magic range indicating exception return? */
381
- tcg_gen_brcondi_i32(TCG_COND_GEU, cpu_R[15], min_magic, excret_label);
382
+ tcg_gen_brcondi_i32(TCG_COND_GEU, cpu_R[15], min_magic, excret_label.label);
383
/* No: end the TB as we would for a DISAS_JMP */
384
if (s->ss_active) {
385
gen_singlestep_exception(s);
386
} else {
387
tcg_gen_exit_tb(NULL, 0);
388
}
389
- gen_set_label(excret_label);
390
+ set_disas_label(s, excret_label);
391
/* Yes: this is an exception return.
392
* At this point in runtime env->regs[15] and env->thumb will hold
393
* the exception-return magic number, which do_v7m_exception_exit()
394
@@ -XXX,XX +XXX,XX @@ static void gen_goto_ptr(void)
395
*/
396
static void gen_goto_tb(DisasContext *s, int n, target_long diff)
397
{
398
- target_ulong dest = s->pc_curr + diff;
417
-
399
-
418
- for (n = 0; n < EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ; n++) {
400
- if (translator_use_goto_tb(&s->base, dest)) {
419
- irq_id = 0;
401
- tcg_gen_goto_tb(n);
420
- if (n == EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 4) ||
402
- gen_update_pc(s, diff);
421
- n == EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 4)) {
403
+ if (translator_use_goto_tb(&s->base, s->pc_curr + diff)) {
422
- /* MCT_G0 is passed to External GIC */
404
+ /*
423
- irq_id = EXT_GIC_ID_MCT_G0;
405
+ * For pcrel, the pc must always be up-to-date on entry to
424
- }
406
+ * the linked TB, so that it can use simple additions for all
425
- if (n == EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 5) ||
407
+ * further adjustments. For !pcrel, the linked TB is compiled
426
- n == EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 5)) {
408
+ * to know its full virtual address, so we can delay the
427
- /* MCT_G1 is passed to External and GIC */
409
+ * update to pc to the unlinked path. A long chain of links
428
- irq_id = EXT_GIC_ID_MCT_G1;
410
+ * can thus avoid many updates to the PC.
429
- }
411
+ */
430
- if (irq_id) {
412
+ if (TARGET_TB_PCREL) {
431
- s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
413
+ gen_update_pc(s, diff);
432
- is->ext_gic_irq[irq_id - 32]);
414
+ tcg_gen_goto_tb(n);
433
- } else {
415
+ } else {
434
- s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
416
+ tcg_gen_goto_tb(n);
435
- is->ext_combiner_irq[n]);
417
+ gen_update_pc(s, diff);
436
- }
418
+ }
437
- }
419
tcg_gen_exit_tb(s->base.tb, n);
438
- for (; n < EXYNOS4210_MAX_INT_COMBINER_IN_IRQ; n++) {
420
} else {
439
- /* these IDs are passed to Internal Combiner and External GIC */
421
gen_update_pc(s, diff);
440
- grp = EXYNOS4210_COMBINER_GET_GRP_NUM(n);
422
@@ -XXX,XX +XXX,XX @@ static void gen_srs(DisasContext *s,
441
- bit = EXYNOS4210_COMBINER_GET_BIT_NUM(n);
423
static void arm_skip_unless(DisasContext *s, uint32_t cond)
442
- irq_id = combiner_grp_to_gic_id[grp -
424
{
443
- EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][bit];
425
arm_gen_condlabel(s);
426
- arm_gen_test_cc(cond ^ 1, s->condlabel);
427
+ arm_gen_test_cc(cond ^ 1, s->condlabel.label);
428
}
429
430
431
@@ -XXX,XX +XXX,XX @@ static bool trans_WLS(DisasContext *s, arg_WLS *a)
432
{
433
/* M-profile low-overhead while-loop start */
434
TCGv_i32 tmp;
435
- TCGLabel *nextlabel;
436
+ DisasLabel nextlabel;
437
438
if (!dc_isar_feature(aa32_lob, s)) {
439
return false;
440
@@ -XXX,XX +XXX,XX @@ static bool trans_WLS(DisasContext *s, arg_WLS *a)
441
}
442
}
443
444
- nextlabel = gen_new_label();
445
- tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_R[a->rn], 0, nextlabel);
446
+ nextlabel = gen_disas_label(s);
447
+ tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_R[a->rn], 0, nextlabel.label);
448
tmp = load_reg(s, a->rn);
449
store_reg(s, 14, tmp);
450
if (a->size != 4) {
451
@@ -XXX,XX +XXX,XX @@ static bool trans_WLS(DisasContext *s, arg_WLS *a)
452
}
453
gen_jmp_tb(s, curr_insn_len(s), 1);
454
455
- gen_set_label(nextlabel);
456
+ set_disas_label(s, nextlabel);
457
gen_jmp(s, jmp_diff(s, a->imm));
458
return true;
459
}
460
@@ -XXX,XX +XXX,XX @@ static bool trans_LE(DisasContext *s, arg_LE *a)
461
* any faster.
462
*/
463
TCGv_i32 tmp;
464
- TCGLabel *loopend;
465
+ DisasLabel loopend;
466
bool fpu_active;
467
468
if (!dc_isar_feature(aa32_lob, s)) {
469
@@ -XXX,XX +XXX,XX @@ static bool trans_LE(DisasContext *s, arg_LE *a)
470
471
if (!a->tp && dc_isar_feature(aa32_mve, s) && fpu_active) {
472
/* Need to do a runtime check for LTPSIZE != 4 */
473
- TCGLabel *skipexc = gen_new_label();
474
+ DisasLabel skipexc = gen_disas_label(s);
475
tmp = load_cpu_field(v7m.ltpsize);
476
- tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 4, skipexc);
477
+ tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 4, skipexc.label);
478
tcg_temp_free_i32(tmp);
479
gen_exception_insn(s, 0, EXCP_INVSTATE, syn_uncategorized());
480
- gen_set_label(skipexc);
481
+ set_disas_label(s, skipexc);
482
}
483
484
if (a->f) {
485
@@ -XXX,XX +XXX,XX @@ static bool trans_LE(DisasContext *s, arg_LE *a)
486
* loop decrement value is 1. For LETP we need to calculate the decrement
487
* value from LTPSIZE.
488
*/
489
- loopend = gen_new_label();
490
+ loopend = gen_disas_label(s);
491
if (!a->tp) {
492
- tcg_gen_brcondi_i32(TCG_COND_LEU, cpu_R[14], 1, loopend);
493
+ tcg_gen_brcondi_i32(TCG_COND_LEU, cpu_R[14], 1, loopend.label);
494
tcg_gen_addi_i32(cpu_R[14], cpu_R[14], -1);
495
} else {
496
/*
497
@@ -XXX,XX +XXX,XX @@ static bool trans_LE(DisasContext *s, arg_LE *a)
498
tcg_gen_shl_i32(decr, tcg_constant_i32(1), decr);
499
tcg_temp_free_i32(ltpsize);
500
501
- tcg_gen_brcond_i32(TCG_COND_LEU, cpu_R[14], decr, loopend);
502
+ tcg_gen_brcond_i32(TCG_COND_LEU, cpu_R[14], decr, loopend.label);
503
504
tcg_gen_sub_i32(cpu_R[14], cpu_R[14], decr);
505
tcg_temp_free_i32(decr);
506
@@ -XXX,XX +XXX,XX @@ static bool trans_LE(DisasContext *s, arg_LE *a)
507
/* Jump back to the loop start */
508
gen_jmp(s, jmp_diff(s, -a->imm));
509
510
- gen_set_label(loopend);
511
+ set_disas_label(s, loopend);
512
if (a->tp) {
513
/* Exits from tail-pred loops must reset LTPSIZE to 4 */
514
store_cpu_field(tcg_constant_i32(4), v7m.ltpsize);
515
@@ -XXX,XX +XXX,XX @@ static bool trans_CBZ(DisasContext *s, arg_CBZ *a)
516
517
arm_gen_condlabel(s);
518
tcg_gen_brcondi_i32(a->nz ? TCG_COND_EQ : TCG_COND_NE,
519
- tmp, 0, s->condlabel);
520
+ tmp, 0, s->condlabel.label);
521
tcg_temp_free_i32(tmp);
522
gen_jmp(s, jmp_diff(s, a->imm));
523
return true;
524
@@ -XXX,XX +XXX,XX @@ static void arm_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
525
526
dc->isar = &cpu->isar;
527
dc->condjmp = 0;
444
-
528
-
445
- if (irq_id) {
529
+ dc->pc_save = dc->base.pc_first;
446
- s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
530
dc->aarch64 = false;
447
- is->ext_gic_irq[irq_id - 32]);
531
dc->thumb = EX_TBFLAG_AM32(tb_flags, THUMB);
448
- }
532
dc->be_data = EX_TBFLAG_ANY(tb_flags, BE_DATA) ? MO_BE : MO_LE;
449
- }
533
@@ -XXX,XX +XXX,XX @@ static void arm_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
450
-}
534
*/
451
-
535
dc->eci = dc->condexec_mask = dc->condexec_cond = 0;
452
-/*
536
dc->eci_handled = false;
453
- * Get IRQ number from exynos4210 IRQ subsystem stub.
537
- dc->insn_eci_rewind = NULL;
454
- * To identify IRQ source use internal combiner group and bit number
538
if (condexec & 0xf) {
455
- * grp - group number
539
dc->condexec_mask = (condexec & 0xf) << 1;
456
- * bit - bit number inside group
540
dc->condexec_cond = condexec >> 4;
457
- */
541
@@ -XXX,XX +XXX,XX @@ static void arm_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
458
-uint32_t exynos4210_get_irq(uint32_t grp, uint32_t bit)
542
* fields here.
459
-{
543
*/
460
- return EXYNOS4210_COMBINER_GET_IRQ_NUM(grp, bit);
544
uint32_t condexec_bits;
461
-}
545
+ target_ulong pc_arg = dc->base.pc_next;
462
-
546
463
-/********* GIC part *********/
547
+ if (TARGET_TB_PCREL) {
464
-
548
+ pc_arg &= ~TARGET_PAGE_MASK;
465
#define TYPE_EXYNOS4210_GIC "exynos4210.gic"
549
+ }
466
OBJECT_DECLARE_SIMPLE_TYPE(Exynos4210GicState, EXYNOS4210_GIC)
550
if (dc->eci) {
467
551
condexec_bits = dc->eci << 4;
552
} else {
553
condexec_bits = (dc->condexec_cond << 4) | (dc->condexec_mask >> 1);
554
}
555
- tcg_gen_insn_start(dc->base.pc_next, condexec_bits, 0);
556
+ tcg_gen_insn_start(pc_arg, condexec_bits, 0);
557
dc->insn_start = tcg_last_op();
558
}
559
560
@@ -XXX,XX +XXX,XX @@ static bool arm_check_ss_active(DisasContext *dc)
561
562
static void arm_post_translate_insn(DisasContext *dc)
563
{
564
- if (dc->condjmp && !dc->base.is_jmp) {
565
- gen_set_label(dc->condlabel);
566
+ if (dc->condjmp && dc->base.is_jmp == DISAS_NEXT) {
567
+ if (dc->pc_save != dc->condlabel.pc_save) {
568
+ gen_update_pc(dc, dc->condlabel.pc_save - dc->pc_save);
569
+ }
570
+ gen_set_label(dc->condlabel.label);
571
dc->condjmp = 0;
572
}
573
translator_loop_temp_check(&dc->base);
574
@@ -XXX,XX +XXX,XX @@ static void thumb_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
575
uint32_t pc = dc->base.pc_next;
576
uint32_t insn;
577
bool is_16bit;
578
+ /* TCG op to rewind to if this turns out to be an invalid ECI state */
579
+ TCGOp *insn_eci_rewind = NULL;
580
+ target_ulong insn_eci_pc_save = -1;
581
582
/* Misaligned thumb PC is architecturally impossible. */
583
assert((dc->base.pc_next & 1) == 0);
584
@@ -XXX,XX +XXX,XX @@ static void thumb_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
585
* insn" case. We will rewind to the marker (ie throwing away
586
* all the generated code) and instead emit "take exception".
587
*/
588
- dc->insn_eci_rewind = tcg_last_op();
589
+ insn_eci_rewind = tcg_last_op();
590
+ insn_eci_pc_save = dc->pc_save;
591
}
592
593
if (dc->condexec_mask && !thumb_insn_is_unconditional(dc, insn)) {
594
@@ -XXX,XX +XXX,XX @@ static void thumb_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
595
* Insn wasn't valid for ECI/ICI at all: undo what we
596
* just generated and instead emit an exception
597
*/
598
- tcg_remove_ops_after(dc->insn_eci_rewind);
599
+ tcg_remove_ops_after(insn_eci_rewind);
600
+ dc->pc_save = insn_eci_pc_save;
601
dc->condjmp = 0;
602
gen_exception_insn(dc, 0, EXCP_INVSTATE, syn_uncategorized());
603
}
604
@@ -XXX,XX +XXX,XX @@ static void arm_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
605
606
if (dc->condjmp) {
607
/* "Condition failed" instruction codepath for the branch/trap insn */
608
- gen_set_label(dc->condlabel);
609
+ set_disas_label(dc, dc->condlabel);
610
gen_set_condexec(dc);
611
if (unlikely(dc->ss_active)) {
612
gen_update_pc(dc, curr_insn_len(dc));
613
@@ -XXX,XX +XXX,XX @@ void restore_state_to_opc(CPUARMState *env, TranslationBlock *tb,
614
target_ulong *data)
615
{
616
if (is_a64(env)) {
617
- env->pc = data[0];
618
+ if (TARGET_TB_PCREL) {
619
+ env->pc = (env->pc & TARGET_PAGE_MASK) | data[0];
620
+ } else {
621
+ env->pc = data[0];
622
+ }
623
env->condexec_bits = 0;
624
env->exception.syndrome = data[2] << ARM_INSN_START_WORD2_SHIFT;
625
} else {
626
- env->regs[15] = data[0];
627
+ if (TARGET_TB_PCREL) {
628
+ env->regs[15] = (env->regs[15] & TARGET_PAGE_MASK) | data[0];
629
+ } else {
630
+ env->regs[15] = data[0];
631
+ }
632
env->condexec_bits = data[1];
633
env->exception.syndrome = data[2] << ARM_INSN_START_WORD2_SHIFT;
634
}
468
--
635
--
469
2.25.1
636
2.25.1
diff view generated by jsdifflib
Deleted patch
1
Delete a couple of #defines which are never used.
2
1
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20220404154658.565020-12-peter.maydell@linaro.org
6
---
7
include/hw/arm/exynos4210.h | 4 ----
8
1 file changed, 4 deletions(-)
9
10
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
11
index XXXXXXX..XXXXXXX 100644
12
--- a/include/hw/arm/exynos4210.h
13
+++ b/include/hw/arm/exynos4210.h
14
@@ -XXX,XX +XXX,XX @@
15
#define EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ \
16
(EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ * 8)
17
18
-/* IRQs number for external and internal GIC */
19
-#define EXYNOS4210_EXT_GIC_NIRQ (160-32)
20
-#define EXYNOS4210_INT_GIC_NIRQ 64
21
-
22
#define EXYNOS4210_I2C_NUMBER 9
23
24
#define EXYNOS4210_NUM_DMA 3
25
--
26
2.25.1
diff view generated by jsdifflib
Deleted patch
1
In exynos4210_init_board_irqs(), the loop that handles IRQ lines that
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
1
9
I don't have a reliable datasheet for this SoC, but since we do wire
10
up one interrupt line in this category (the HDMI I2C device on
11
interrupt 16,1), this seems like it must be a bug in the existing
12
QEMU code. Fill in the irq_table[] entries where we're not splitting
13
the IRQ to both the internal combiner and the external GIC with the
14
IRQ line of the internal combiner. (That is, these IRQ lines go to
15
just one device, not multiple.)
16
17
This bug didn't have any visible guest effects because the only
18
implemented device that was affected was the HDMI I2C controller,
19
and we never connect any I2C devices to that bus.
20
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
22
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
23
Message-id: 20220404154658.565020-14-peter.maydell@linaro.org
24
---
25
hw/arm/exynos4210.c | 2 ++
26
1 file changed, 2 insertions(+)
27
28
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
29
index XXXXXXX..XXXXXXX 100644
30
--- a/hw/arm/exynos4210.c
31
+++ b/hw/arm/exynos4210.c
32
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init_board_irqs(Exynos4210State *s)
33
qdev_connect_gpio_out(splitter, 0, is->int_combiner_irq[n]);
34
qdev_connect_gpio_out(splitter, 1,
35
qdev_get_gpio_in(extgicdev, irq_id - 32));
36
+ } else {
37
+ s->irq_table[n] = is->int_combiner_irq[n];
38
}
39
}
40
/*
41
--
42
2.25.1
diff view generated by jsdifflib
Deleted patch
1
Currently for the interrupts MCT_G0 and MCT_G1 which are
2
the only ones in the input range of the external combiner
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
1
11
Wire these interrupts up to both combiners, like the rest.
12
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
Message-id: 20220404154658.565020-15-peter.maydell@linaro.org
16
---
17
hw/arm/exynos4210.c | 7 +++----
18
1 file changed, 3 insertions(+), 4 deletions(-)
19
20
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
21
index XXXXXXX..XXXXXXX 100644
22
--- a/hw/arm/exynos4210.c
23
+++ b/hw/arm/exynos4210.c
24
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init_board_irqs(Exynos4210State *s)
25
26
assert(splitcount < EXYNOS4210_NUM_SPLITTERS);
27
splitter = DEVICE(&s->splitter[splitcount]);
28
- qdev_prop_set_uint16(splitter, "num-lines", 2);
29
+ qdev_prop_set_uint16(splitter, "num-lines", irq_id ? 3 : 2);
30
qdev_realize(splitter, NULL, &error_abort);
31
splitcount++;
32
s->irq_table[n] = qdev_get_gpio_in(splitter, 0);
33
qdev_connect_gpio_out(splitter, 0, is->int_combiner_irq[n]);
34
+ qdev_connect_gpio_out(splitter, 1, is->ext_combiner_irq[n]);
35
if (irq_id) {
36
- qdev_connect_gpio_out(splitter, 1,
37
+ qdev_connect_gpio_out(splitter, 2,
38
qdev_get_gpio_in(extgicdev, irq_id - 32));
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
--
45
2.25.1
diff view generated by jsdifflib
Deleted patch
1
The combiner_grp_to_gic_id[] array includes the EXT_GIC_ID_MCT_G0
2
and EXT_GIC_ID_MCT_G1 multiple times. This means that we will
3
connect multiple IRQs up to the same external GIC input, which
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
1
8
Overall we do this for interrupt IDs
9
(1, 4), (12, 4), (35, 4), (51, 4), (53, 4) for EXT_GIC_ID_MCT_G0
10
and
11
(1, 5), (12, 5), (35, 5), (51, 5), (53, 5) for EXT_GIC_ID_MCT_G1
12
13
These correspond to the cases for the multi-core timer that we are
14
wiring up to multiple inputs on the combiner in
15
exynos4210_combiner_get_gpioin(). That code already deals with all
16
these interrupt IDs being the same input source, so we don't need to
17
connect the external GIC interrupt for any of them except the first
18
(1, 4) and (1, 5). Remove the array entries and conditionals which
19
were incorrectly causing us to wire up extra lines.
20
21
This bug didn't cause any visible effects, because we only connect
22
up a device to the "primary" ID values (1, 4) and (1, 5), so the
23
extra lines would never be set to a level.
24
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
35
--- a/include/hw/arm/exynos4210.h
36
+++ b/include/hw/arm/exynos4210.h
37
@@ -XXX,XX +XXX,XX @@
38
* one for every non-zero entry in combiner_grp_to_gic_id[].
39
* We'll assert in exynos4210_init_board_irqs() if this is wrong.
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
}
83
- if (n == EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 5) ||
84
- n == EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 5)) {
85
+ if (n == EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 5)) {
86
/* MCT_G1 is passed to External and GIC */
87
irq_id = EXT_GIC_ID_MCT_G1;
88
}
89
--
90
2.25.1
diff view generated by jsdifflib
1
Switch the creation of the combiner devices to the new-style
1
Currently the microdrive code uses device_legacy_reset() to reset
2
"embedded in state struct" approach, so we can easily refer
2
itself, and has its reset method call reset on the IDE bus as the
3
to the object elsewhere during realize.
3
last thing it does. Switch to using device_cold_reset().
4
5
The only concrete microdrive device is the TYPE_DSCM1XXXX; it is not
6
command-line pluggable, so it is used only by the old pxa2xx Arm
7
boards 'akita', 'borzoi', 'spitz', 'terrier' and 'tosa'.
8
9
You might think that this would result in the IDE bus being
10
reset automatically, but it does not, because the IDEBus type
11
does not set the BusClass::reset method. Instead the controller
12
must explicitly call ide_bus_reset(). We therefore leave that
13
call in md_reset().
14
15
Note also that because the PCMCIA card device is a direct subclass of
16
TYPE_DEVICE and we don't model the PCMCIA controller-to-card
17
interface as a qbus, PCMCIA cards are not on any qbus and so they
18
don't get reset when the system is reset. The reset only happens via
19
the dscm1xxxx_attach() and dscm1xxxx_detach() functions during
20
machine creation.
21
22
Because our aim here is merely to try to get rid of calls to the
23
device_legacy_reset() function, we leave these other dubious
24
reset-related issues alone. (They all stem from this code being
25
absolutely ancient.)
4
26
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
27
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
28
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
7
Message-id: 20220404154658.565020-18-peter.maydell@linaro.org
29
Message-id: 20221013174042.1602926-1-peter.maydell@linaro.org
8
---
30
---
9
include/hw/arm/exynos4210.h | 3 ++
31
hw/ide/microdrive.c | 8 ++++----
10
include/hw/intc/exynos4210_combiner.h | 57 +++++++++++++++++++++++++++
32
1 file changed, 4 insertions(+), 4 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
33
16
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
34
diff --git a/hw/ide/microdrive.c b/hw/ide/microdrive.c
17
index XXXXXXX..XXXXXXX 100644
35
index XXXXXXX..XXXXXXX 100644
18
--- a/include/hw/arm/exynos4210.h
36
--- a/hw/ide/microdrive.c
19
+++ b/include/hw/arm/exynos4210.h
37
+++ b/hw/ide/microdrive.c
20
@@ -XXX,XX +XXX,XX @@
38
@@ -XXX,XX +XXX,XX @@ static void md_attr_write(PCMCIACardState *card, uint32_t at, uint8_t value)
21
#include "hw/sysbus.h"
39
case 0x00:    /* Configuration Option Register */
22
#include "hw/cpu/a9mpcore.h"
40
s->opt = value & 0xcf;
23
#include "hw/intc/exynos4210_gic.h"
41
if (value & OPT_SRESET) {
24
+#include "hw/intc/exynos4210_combiner.h"
42
- device_legacy_reset(DEVICE(s));
25
#include "hw/core/split-irq.h"
43
+ device_cold_reset(DEVICE(s));
26
#include "target/arm/cpu-qom.h"
44
}
27
#include "qom/object.h"
45
md_interrupt_update(s);
28
@@ -XXX,XX +XXX,XX @@ struct Exynos4210State {
46
break;
29
qemu_or_irq cpu_irq_orgate[EXYNOS4210_NCPUS];
47
@@ -XXX,XX +XXX,XX @@ static void md_common_write(PCMCIACardState *card, uint32_t at, uint16_t value)
30
A9MPPrivState a9mpcore;
48
case 0xe:    /* Device Control */
31
Exynos4210GicState ext_gic;
49
s->ctrl = value;
32
+ Exynos4210CombinerState int_combiner;
50
if (value & CTRL_SRST) {
33
+ Exynos4210CombinerState ext_combiner;
51
- device_legacy_reset(DEVICE(s));
34
SplitIRQ splitter[EXYNOS4210_NUM_SPLITTERS];
52
+ device_cold_reset(DEVICE(s));
35
};
53
}
36
54
md_interrupt_update(s);
37
diff --git a/include/hw/intc/exynos4210_combiner.h b/include/hw/intc/exynos4210_combiner.h
55
break;
38
new file mode 100644
56
@@ -XXX,XX +XXX,XX @@ static int dscm1xxxx_attach(PCMCIACardState *card)
39
index XXXXXXX..XXXXXXX
57
md->attr_base = pcc->cis[0x74] | (pcc->cis[0x76] << 8);
40
--- /dev/null
58
md->io_base = 0x0;
41
+++ b/include/hw/intc/exynos4210_combiner.h
59
42
@@ -XXX,XX +XXX,XX @@
60
- device_legacy_reset(DEVICE(md));
43
+/*
61
+ device_cold_reset(DEVICE(md));
44
+ * Samsung exynos4210 Interrupt Combiner
62
md_interrupt_update(md);
45
+ *
63
46
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd.
64
return 0;
47
+ * All rights reserved.
65
@@ -XXX,XX +XXX,XX @@ static int dscm1xxxx_detach(PCMCIACardState *card)
48
+ *
66
{
49
+ * Evgeny Voevodin <e.voevodin@samsung.com>
67
MicroDriveState *md = MICRODRIVE(card);
50
+ *
68
51
+ * This program is free software; you can redistribute it and/or modify it
69
- device_legacy_reset(DEVICE(md));
52
+ * under the terms of the GNU General Public License as published by the
70
+ device_cold_reset(DEVICE(md));
53
+ * Free Software Foundation; either version 2 of the License, or (at your
71
return 0;
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
}
106
107
/* Internal Interrupt Combiner */
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
}
72
}
146
73
147
static void exynos4210_class_init(ObjectClass *klass, void *data)
148
diff --git a/hw/intc/exynos4210_combiner.c b/hw/intc/exynos4210_combiner.c
149
index XXXXXXX..XXXXXXX 100644
150
--- a/hw/intc/exynos4210_combiner.c
151
+++ b/hw/intc/exynos4210_combiner.c
152
@@ -XXX,XX +XXX,XX @@
153
#include "hw/sysbus.h"
154
#include "migration/vmstate.h"
155
#include "qemu/module.h"
156
-
157
+#include "hw/intc/exynos4210_combiner.h"
158
#include "hw/arm/exynos4210.h"
159
#include "hw/hw.h"
160
#include "hw/irq.h"
161
@@ -XXX,XX +XXX,XX @@
162
#define DPRINTF(fmt, ...) do {} while (0)
163
#endif
164
165
-#define IIC_NGRP 64 /* Internal Interrupt Combiner
166
- Groups number */
167
-#define IIC_NIRQ (IIC_NGRP * 8)/* Internal Interrupt Combiner
168
- Interrupts number */
169
#define IIC_REGION_SIZE 0x108 /* Size of memory mapped region */
170
-#define IIC_REGSET_SIZE 0x41
171
-
172
-/*
173
- * State for each output signal of internal combiner
174
- */
175
-typedef struct CombinerGroupState {
176
- uint8_t src_mask; /* 1 - source enabled, 0 - disabled */
177
- uint8_t src_pending; /* Pending source interrupts before masking */
178
-} CombinerGroupState;
179
-
180
-#define TYPE_EXYNOS4210_COMBINER "exynos4210.combiner"
181
-OBJECT_DECLARE_SIMPLE_TYPE(Exynos4210CombinerState, EXYNOS4210_COMBINER)
182
-
183
-struct Exynos4210CombinerState {
184
- SysBusDevice parent_obj;
185
-
186
- MemoryRegion iomem;
187
-
188
- struct CombinerGroupState group[IIC_NGRP];
189
- uint32_t reg_set[IIC_REGSET_SIZE];
190
- uint32_t icipsr[2];
191
- uint32_t external; /* 1 means that this combiner is external */
192
-
193
- qemu_irq output_irq[IIC_NGRP];
194
-};
195
196
static const VMStateDescription vmstate_exynos4210_combiner_group_state = {
197
.name = "exynos4210.combiner.groupstate",
198
--
74
--
199
2.25.1
75
2.25.1
76
77
diff view generated by jsdifflib