1
The following changes since commit 4c41341af76cfc85b5a6c0f87de4838672ab9f89:
1
First arm pullreq for 7.1. The bulk of this is the qemu_split_irq
2
removal.
2
3
3
Merge remote-tracking branch 'remotes/aperard/tags/pull-xen-20201020' into staging (2020-10-20 11:20:36 +0100)
4
I have enough stuff in my to-review queue that I expect to do another
5
pullreq early next week, but 31 patches is enough to not hang on to.
6
7
thanks
8
-- PMM
9
10
The following changes since commit 9c125d17e9402c232c46610802e5931b3639d77b:
11
12
Merge tag 'pull-tcg-20220420' of https://gitlab.com/rth7680/qemu into staging (2022-04-20 16:43:11 -0700)
4
13
5
are available in the Git repository at:
14
are available in the Git repository at:
6
15
7
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20201020
16
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20220421
8
17
9
for you to fetch changes up to 6358890cb939192f6169fdf7664d903bf9b1d338:
18
for you to fetch changes up to 5b415dd61bdbf61fb4be0e9f1a7172b8bce682c6:
10
19
11
tests/tcg/aarch64: Add bti smoke tests (2020-10-20 16:12:02 +0100)
20
hw/arm: Use bit fields for NPCM7XX PWRON STRAPs (2022-04-21 11:37:05 +0100)
12
21
13
----------------------------------------------------------------
22
----------------------------------------------------------------
14
target-arm queue:
23
target-arm queue:
15
* Fix AArch32 SMLAD incorrect setting of Q bit
24
* hw/arm/virt: Check for attempt to use TrustZone with KVM or HVF
16
* AArch32 VCVT fixed-point to float is always round-to-nearest
25
* versal: Add the Cortex-R5s in the Real-Time Processing Unit (RPU) subsystem
17
* strongarm: Fix 'time to transmit a char' unit comment
26
* versal: model enough of the Clock/Reset Low-power domain (CRL) to allow control of the Cortex-R5s
18
* Restrict APEI tables generation to the 'virt' machine
27
* xlnx-zynqmp: Connect 4 TTC timers
19
* bcm2835: minor code cleanups
28
* exynos4210: Refactor GIC/combiner code to stop using qemu_split_irq
20
* correctly flush TLBs when TBI is enabled
29
* realview: replace 'qemu_split_irq' with 'TYPE_SPLIT_IRQ'
21
* tests/qtest: Add npcm7xx timer test
30
* stellaris: replace 'qemu_split_irq' with 'TYPE_SPLIT_IRQ'
22
* loads-stores.rst: add footnote that clarifies GETPC usage
31
* hw/core/irq: remove unused 'qemu_irq_split' function
23
* Fix reported EL for mte_check_fail
32
* npcm7xx: use symbolic constants for PWRON STRAP bit fields
24
* Ignore HCR_EL2.ATA when {E2H,TGE} != 11
33
* virt: document impact of gic-version on max CPUs
25
* microbit_i2c: Fix coredump when dump-vmstate
26
* nseries: Fix loading kernel image on n8x0 machines
27
* Implement v8.1M low-overhead-loops
28
* linux-user: Support AArch64 BTI
29
34
30
----------------------------------------------------------------
35
----------------------------------------------------------------
31
Emanuele Giuseppe Esposito (1):
36
Edgar E. Iglesias (6):
32
loads-stores.rst: add footnote that clarifies GETPC usage
37
timer: cadence_ttc: Break out header file to allow embedding
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
33
43
34
Havard Skinnemoen (1):
44
Hao Wu (2):
35
tests/qtest: Add npcm7xx timer test
45
hw/misc: Add PWRON STRAP bit fields in GCR module
46
hw/arm: Use bit fields for NPCM7XX PWRON STRAPs
36
47
37
Peng Liang (1):
48
Heinrich Schuchardt (1):
38
microbit_i2c: Fix coredump when dump-vmstate
49
hw/arm/virt: impact of gic-version on max CPUs
39
50
40
Peter Maydell (12):
51
Peter Maydell (19):
41
target/arm: Fix SMLAD incorrect setting of Q bit
52
hw/arm/virt: Check for attempt to use TrustZone with KVM or HVF
42
target/arm: AArch32 VCVT fixed-point to float is always round-to-nearest
53
hw/arm/exynos4210: Use TYPE_OR_IRQ instead of custom OR-gate device
43
decodetree: Fix codegen for non-overlapping group inside overlapping group
54
hw/intc/exynos4210_gic: Remove unused TYPE_EXYNOS4210_IRQ_GATE
44
target/arm: Implement v8.1M NOCP handling
55
hw/arm/exynos4210: Put a9mpcore device into state struct
45
target/arm: Implement v8.1M conditional-select insns
56
hw/arm/exynos4210: Drop int_gic_irq[] from Exynos4210Irq struct
46
target/arm: Make the t32 insn[25:23]=111 group non-overlapping
57
hw/arm/exynos4210: Coalesce board_irqs and irq_table
47
target/arm: Don't allow BLX imm for M-profile
58
hw/arm/exynos4210: Fix code style nit in combiner_grp_to_gic_id[]
48
target/arm: Implement v8.1M branch-future insns (as NOPs)
59
hw/arm/exynos4210: Move exynos4210_init_board_irqs() into exynos4210.c
49
target/arm: Implement v8.1M low-overhead-loop instructions
60
hw/arm/exynos4210: Put external GIC into state struct
50
target/arm: Fix has_vfp/has_neon ID reg squashing for M-profile
61
hw/arm/exynos4210: Drop ext_gic_irq[] from Exynos4210Irq struct
51
target/arm: Allow M-profile CPUs with FP16 to set FPSCR.FP16
62
hw/arm/exynos4210: Move exynos4210_combiner_get_gpioin() into exynos4210.c
52
target/arm: Implement FPSCR.LTPSIZE for M-profile LOB extension
63
hw/arm/exynos4210: Delete unused macro definitions
64
hw/arm/exynos4210: Use TYPE_SPLIT_IRQ in exynos4210_init_board_irqs()
65
hw/arm/exynos4210: Fill in irq_table[] for internal-combiner-only IRQ lines
66
hw/arm/exynos4210: Connect MCT_G0 and MCT_G1 to both combiners
67
hw/arm/exynos4210: Don't connect multiple lines to external GIC inputs
68
hw/arm/exynos4210: Fold combiner splits into exynos4210_init_board_irqs()
69
hw/arm/exynos4210: Put combiners into state struct
70
hw/arm/exynos4210: Drop Exynos4210Irq struct
53
71
54
Philippe Mathieu-Daudé (10):
72
Zongyuan Li (3):
55
hw/arm/strongarm: Fix 'time to transmit a char' unit comment
73
hw/arm/realview: replace 'qemu_split_irq' with 'TYPE_SPLIT_IRQ'
56
hw/arm: Restrict APEI tables generation to the 'virt' machine
74
hw/arm/stellaris: replace 'qemu_split_irq' with 'TYPE_SPLIT_IRQ'
57
hw/timer/bcm2835: Introduce BCM2835_SYSTIMER_COUNT definition
75
hw/core/irq: remove unused 'qemu_irq_split' function
58
hw/timer/bcm2835: Rename variable holding CTRL_STATUS register
59
hw/timer/bcm2835: Support the timer COMPARE registers
60
hw/arm/bcm2835_peripherals: Correctly wire the SYS_timer IRQs
61
hw/intc/bcm2835_ic: Trace GPU/CPU IRQ handlers
62
hw/intc/bcm2836_control: Use IRQ definitions instead of magic numbers
63
hw/arm/nseries: Fix loading kernel image on n8x0 machines
64
linux-user/elfload: Avoid leaking interp_name using GLib memory API
65
76
66
Richard Henderson (16):
77
docs/system/arm/virt.rst | 4 +-
67
accel/tcg: Add tlb_flush_page_bits_by_mmuidx*
78
include/hw/arm/exynos4210.h | 50 ++--
68
target/arm: Use tlb_flush_page_bits_by_mmuidx*
79
include/hw/arm/xlnx-versal.h | 16 ++
69
target/arm: Remove redundant mmu_idx lookup
80
include/hw/arm/xlnx-zynqmp.h | 4 +
70
target/arm: Fix reported EL for mte_check_fail
81
include/hw/intc/exynos4210_combiner.h | 57 +++++
71
target/arm: Ignore HCR_EL2.ATA when {E2H,TGE} != 11
82
include/hw/intc/exynos4210_gic.h | 43 ++++
72
linux-user/aarch64: Reset btype for signals
83
include/hw/irq.h | 5 -
73
linux-user: Set PAGE_TARGET_1 for TARGET_PROT_BTI
84
include/hw/misc/npcm7xx_gcr.h | 30 +++
74
include/elf: Add defines related to GNU property notes for AArch64
85
include/hw/misc/xlnx-versal-crl.h | 235 +++++++++++++++++++
75
linux-user/elfload: Fix coding style in load_elf_image
86
include/hw/timer/cadence_ttc.h | 54 +++++
76
linux-user/elfload: Adjust iteration over phdr
87
hw/arm/exynos4210.c | 430 ++++++++++++++++++++++++++++++----
77
linux-user/elfload: Move PT_INTERP detection to first loop
88
hw/arm/npcm7xx_boards.c | 24 +-
78
linux-user/elfload: Use Error for load_elf_image
89
hw/arm/realview.c | 33 ++-
79
linux-user/elfload: Use Error for load_elf_interp
90
hw/arm/stellaris.c | 15 +-
80
linux-user/elfload: Parse NT_GNU_PROPERTY_TYPE_0 notes
91
hw/arm/virt.c | 7 +
81
linux-user/elfload: Parse GNU_PROPERTY_AARCH64_FEATURE_1_AND
92
hw/arm/xlnx-versal-virt.c | 6 +-
82
tests/tcg/aarch64: Add bti smoke tests
93
hw/arm/xlnx-versal.c | 99 +++++++-
83
94
hw/arm/xlnx-zynqmp.c | 22 ++
84
docs/devel/loads-stores.rst | 8 +-
95
hw/core/irq.c | 15 --
85
default-configs/devices/arm-softmmu.mak | 1 -
96
hw/intc/exynos4210_combiner.c | 108 +--------
86
include/elf.h | 22 ++
97
hw/intc/exynos4210_gic.c | 344 +--------------------------
87
include/exec/cpu-all.h | 2 +
98
hw/misc/xlnx-versal-crl.c | 421 +++++++++++++++++++++++++++++++++
88
include/exec/exec-all.h | 36 ++
99
hw/timer/cadence_ttc.c | 32 +--
89
include/hw/timer/bcm2835_systmr.h | 17 +-
100
MAINTAINERS | 2 +-
90
linux-user/qemu.h | 4 +
101
hw/misc/meson.build | 1 +
91
linux-user/syscall_defs.h | 4 +
102
25 files changed, 1457 insertions(+), 600 deletions(-)
92
target/arm/cpu.h | 13 +
103
create mode 100644 include/hw/intc/exynos4210_combiner.h
93
target/arm/helper.h | 13 +
104
create mode 100644 include/hw/intc/exynos4210_gic.h
94
target/arm/internals.h | 9 +-
105
create mode 100644 include/hw/misc/xlnx-versal-crl.h
95
target/arm/m-nocp.decode | 10 +-
106
create mode 100644 include/hw/timer/cadence_ttc.h
96
target/arm/t32.decode | 50 ++-
107
create mode 100644 hw/misc/xlnx-versal-crl.c
97
accel/tcg/cputlb.c | 275 +++++++++++++++-
98
hw/arm/bcm2835_peripherals.c | 13 +-
99
hw/arm/nseries.c | 1 +
100
hw/arm/strongarm.c | 2 +-
101
hw/i2c/microbit_i2c.c | 1 +
102
hw/intc/bcm2835_ic.c | 4 +-
103
hw/intc/bcm2836_control.c | 8 +-
104
hw/timer/bcm2835_systmr.c | 57 ++--
105
linux-user/aarch64/signal.c | 10 +-
106
linux-user/elfload.c | 326 ++++++++++++++----
107
linux-user/mmap.c | 16 +
108
target/arm/cpu.c | 38 ++-
109
target/arm/helper.c | 55 +++-
110
target/arm/mte_helper.c | 13 +-
111
target/arm/translate-a64.c | 6 +-
112
target/arm/translate.c | 239 +++++++++++++-
113
target/arm/vfp_helper.c | 76 +++--
114
tests/qtest/npcm7xx_timer-test.c | 562 ++++++++++++++++++++++++++++++++
115
tests/tcg/aarch64/bti-1.c | 62 ++++
116
tests/tcg/aarch64/bti-2.c | 108 ++++++
117
tests/tcg/aarch64/bti-crt.inc.c | 51 +++
118
hw/arm/Kconfig | 1 +
119
hw/intc/trace-events | 4 +
120
hw/timer/trace-events | 6 +-
121
scripts/decodetree.py | 2 +-
122
target/arm/translate-vfp.c.inc | 41 ++-
123
tests/qtest/meson.build | 1 +
124
tests/tcg/aarch64/Makefile.target | 10 +
125
tests/tcg/configure.sh | 4 +
126
42 files changed, 1973 insertions(+), 208 deletions(-)
127
create mode 100644 tests/qtest/npcm7xx_timer-test.c
128
create mode 100644 tests/tcg/aarch64/bti-1.c
129
create mode 100644 tests/tcg/aarch64/bti-2.c
130
create mode 100644 tests/tcg/aarch64/bti-crt.inc.c
131
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
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:
2
6
3
Fix an unlikely memory leak in load_elf_image().
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
4
11
5
Fixes: bf858897b7 ("linux-user: Re-use load_elf_image for the main binary.")
12
Check for this combination of options and report an error, in the
6
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
13
same way we already do for attempts to give a KVM or HVF guest the
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
14
Virtualization or MTE extensions. Now we will report:
8
Message-id: 20201016184207.786698-5-richard.henderson@linaro.org
15
9
Message-Id: <20201003174944.1972444-1-f4bug@amsat.org>
16
qemu-system-aarch64: mach-virt: KVM does not support providing Security extensions (TrustZone) to the guest CPU
10
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
17
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
18
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/961
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
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
13
---
22
---
14
linux-user/elfload.c | 8 ++++----
23
hw/arm/virt.c | 7 +++++++
15
1 file changed, 4 insertions(+), 4 deletions(-)
24
1 file changed, 7 insertions(+)
16
25
17
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
26
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
18
index XXXXXXX..XXXXXXX 100644
27
index XXXXXXX..XXXXXXX 100644
19
--- a/linux-user/elfload.c
28
--- a/hw/arm/virt.c
20
+++ b/linux-user/elfload.c
29
+++ b/hw/arm/virt.c
21
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
30
@@ -XXX,XX +XXX,XX @@ static void machvirt_init(MachineState *machine)
22
info->brk = vaddr_em;
31
exit(1);
23
}
24
} else if (eppnt->p_type == PT_INTERP && pinterp_name) {
25
- char *interp_name;
26
+ g_autofree char *interp_name = NULL;
27
28
if (*pinterp_name) {
29
errmsg = "Multiple PT_INTERP entries";
30
goto exit_errmsg;
31
}
32
- interp_name = malloc(eppnt->p_filesz);
33
+ interp_name = g_malloc(eppnt->p_filesz);
34
if (!interp_name) {
35
goto exit_perror;
36
}
37
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
38
errmsg = "Invalid PT_INTERP entry";
39
goto exit_errmsg;
40
}
41
- *pinterp_name = interp_name;
42
+ *pinterp_name = g_steal_pointer(&interp_name);
43
#ifdef TARGET_MIPS
44
} else if (eppnt->p_type == PT_MIPS_ABIFLAGS) {
45
Mips_elf_abiflags_v0 abiflags;
46
@@ -XXX,XX +XXX,XX @@ int load_elf_binary(struct linux_binprm *bprm, struct image_info *info)
47
if (elf_interpreter) {
48
info->load_bias = interp_info.load_bias;
49
info->entry = interp_info.entry;
50
- free(elf_interpreter);
51
+ g_free(elf_interpreter);
52
}
32
}
53
33
54
#ifdef USE_ELF_CORE_DUMP
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",
55
--
44
--
56
2.20.1
45
2.25.1
57
58
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: "Edgar E. Iglesias" <edgar.iglesias@amd.com>
2
2
3
Use the new generic support for NT_GNU_PROPERTY_TYPE_0.
3
Break out header file to allow embedding of the the TTC.
4
4
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>
6
Message-id: 20201016184207.786698-12-richard.henderson@linaro.org
6
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Luc Michel <luc@lmichel.fr>
8
Reviewed-by: Francisco Iglesias <frasse.iglesias@gmail.com>
9
Message-id: 20220331222017.2914409-2-edgar.iglesias@gmail.com
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
11
---
10
linux-user/elfload.c | 48 ++++++++++++++++++++++++++++++++++++++++++--
12
include/hw/timer/cadence_ttc.h | 54 ++++++++++++++++++++++++++++++++++
11
1 file changed, 46 insertions(+), 2 deletions(-)
13
hw/timer/cadence_ttc.c | 32 ++------------------
14
2 files changed, 56 insertions(+), 30 deletions(-)
15
create mode 100644 include/hw/timer/cadence_ttc.h
12
16
13
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
17
diff --git a/include/hw/timer/cadence_ttc.h b/include/hw/timer/cadence_ttc.h
18
new file mode 100644
19
index XXXXXXX..XXXXXXX
20
--- /dev/null
21
+++ b/include/hw/timer/cadence_ttc.h
22
@@ -XXX,XX +XXX,XX @@
23
+/*
24
+ * Xilinx Zynq cadence TTC model
25
+ *
26
+ * Copyright (c) 2011 Xilinx Inc.
27
+ * Copyright (c) 2012 Peter A.G. Crosthwaite (peter.crosthwaite@petalogix.com)
28
+ * Copyright (c) 2012 PetaLogix Pty Ltd.
29
+ * Written By Haibing Ma
30
+ * M. Habib
31
+ *
32
+ * This program is free software; you can redistribute it and/or
33
+ * modify it under the terms of the GNU General Public License
34
+ * as published by the Free Software Foundation; either version
35
+ * 2 of the License, or (at your option) any later version.
36
+ *
37
+ * You should have received a copy of the GNU General Public License along
38
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
39
+ */
40
+#ifndef HW_TIMER_CADENCE_TTC_H
41
+#define HW_TIMER_CADENCE_TTC_H
42
+
43
+#include "hw/sysbus.h"
44
+#include "qemu/timer.h"
45
+
46
+typedef struct {
47
+ QEMUTimer *timer;
48
+ int freq;
49
+
50
+ uint32_t reg_clock;
51
+ uint32_t reg_count;
52
+ uint32_t reg_value;
53
+ uint16_t reg_interval;
54
+ uint16_t reg_match[3];
55
+ uint32_t reg_intr;
56
+ uint32_t reg_intr_en;
57
+ uint32_t reg_event_ctrl;
58
+ uint32_t reg_event;
59
+
60
+ uint64_t cpu_time;
61
+ unsigned int cpu_time_valid;
62
+
63
+ qemu_irq irq;
64
+} CadenceTimerState;
65
+
66
+#define TYPE_CADENCE_TTC "cadence_ttc"
67
+OBJECT_DECLARE_SIMPLE_TYPE(CadenceTTCState, CADENCE_TTC)
68
+
69
+struct CadenceTTCState {
70
+ SysBusDevice parent_obj;
71
+
72
+ MemoryRegion iomem;
73
+ CadenceTimerState timer[3];
74
+};
75
+
76
+#endif
77
diff --git a/hw/timer/cadence_ttc.c b/hw/timer/cadence_ttc.c
14
index XXXXXXX..XXXXXXX 100644
78
index XXXXXXX..XXXXXXX 100644
15
--- a/linux-user/elfload.c
79
--- a/hw/timer/cadence_ttc.c
16
+++ b/linux-user/elfload.c
80
+++ b/hw/timer/cadence_ttc.c
17
@@ -XXX,XX +XXX,XX @@ static void elf_core_copy_regs(target_elf_gregset_t *regs,
81
@@ -XXX,XX +XXX,XX @@
18
82
#include "qemu/timer.h"
19
#include "elf.h"
83
#include "qom/object.h"
20
84
21
+/* We must delay the following stanzas until after "elf.h". */
85
+#include "hw/timer/cadence_ttc.h"
22
+#if defined(TARGET_AARCH64)
23
+
86
+
24
+static bool arch_parse_elf_property(uint32_t pr_type, uint32_t pr_datasz,
87
#ifdef CADENCE_TTC_ERR_DEBUG
25
+ const uint32_t *data,
88
#define DB_PRINT(...) do { \
26
+ struct image_info *info,
89
fprintf(stderr, ": %s: ", __func__); \
27
+ Error **errp)
90
@@ -XXX,XX +XXX,XX @@
28
+{
91
#define CLOCK_CTRL_PS_EN 0x00000001
29
+ if (pr_type == GNU_PROPERTY_AARCH64_FEATURE_1_AND) {
92
#define CLOCK_CTRL_PS_V 0x0000001e
30
+ if (pr_datasz != sizeof(uint32_t)) {
93
31
+ error_setg(errp, "Ill-formed GNU_PROPERTY_AARCH64_FEATURE_1_AND");
94
-typedef struct {
32
+ return false;
95
- QEMUTimer *timer;
33
+ }
96
- int freq;
34
+ /* We will extract GNU_PROPERTY_AARCH64_FEATURE_1_BTI later. */
97
-
35
+ info->note_flags = *data;
98
- uint32_t reg_clock;
36
+ }
99
- uint32_t reg_count;
37
+ return true;
100
- uint32_t reg_value;
38
+}
101
- uint16_t reg_interval;
39
+#define ARCH_USE_GNU_PROPERTY 1
102
- uint16_t reg_match[3];
40
+
103
- uint32_t reg_intr;
41
+#else
104
- uint32_t reg_intr_en;
42
+
105
- uint32_t reg_event_ctrl;
43
static bool arch_parse_elf_property(uint32_t pr_type, uint32_t pr_datasz,
106
- uint32_t reg_event;
44
const uint32_t *data,
107
-
45
struct image_info *info,
108
- uint64_t cpu_time;
46
@@ -XXX,XX +XXX,XX @@ static bool arch_parse_elf_property(uint32_t pr_type, uint32_t pr_datasz,
109
- unsigned int cpu_time_valid;
47
}
110
-
48
#define ARCH_USE_GNU_PROPERTY 0
111
- qemu_irq irq;
49
112
-} CadenceTimerState;
50
+#endif
113
-
51
+
114
-#define TYPE_CADENCE_TTC "cadence_ttc"
52
struct exec
115
-OBJECT_DECLARE_SIMPLE_TYPE(CadenceTTCState, CADENCE_TTC)
116
-
117
-struct CadenceTTCState {
118
- SysBusDevice parent_obj;
119
-
120
- MemoryRegion iomem;
121
- CadenceTimerState timer[3];
122
-};
123
-
124
static void cadence_timer_update(CadenceTimerState *s)
53
{
125
{
54
unsigned int a_info; /* Use macros N_MAGIC, etc for access */
126
qemu_set_irq(s->irq, !!(s->reg_intr & s->reg_intr_en));
55
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
56
struct elfhdr *ehdr = (struct elfhdr *)bprm_buf;
57
struct elf_phdr *phdr;
58
abi_ulong load_addr, load_bias, loaddr, hiaddr, error;
59
- int i, retval;
60
+ int i, retval, prot_exec;
61
Error *err = NULL;
62
63
/* First of all, some simple consistency checks */
64
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
65
info->brk = 0;
66
info->elf_flags = ehdr->e_flags;
67
68
+ prot_exec = PROT_EXEC;
69
+#ifdef TARGET_AARCH64
70
+ /*
71
+ * If the BTI feature is present, this indicates that the executable
72
+ * pages of the startup binary should be mapped with PROT_BTI, so that
73
+ * branch targets are enforced.
74
+ *
75
+ * The startup binary is either the interpreter or the static executable.
76
+ * The interpreter is responsible for all pages of a dynamic executable.
77
+ *
78
+ * Elf notes are backward compatible to older cpus.
79
+ * Do not enable BTI unless it is supported.
80
+ */
81
+ if ((info->note_flags & GNU_PROPERTY_AARCH64_FEATURE_1_BTI)
82
+ && (pinterp_name == NULL || *pinterp_name == 0)
83
+ && cpu_isar_feature(aa64_bti, ARM_CPU(thread_cpu))) {
84
+ prot_exec |= TARGET_PROT_BTI;
85
+ }
86
+#endif
87
+
88
for (i = 0; i < ehdr->e_phnum; i++) {
89
struct elf_phdr *eppnt = phdr + i;
90
if (eppnt->p_type == PT_LOAD) {
91
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
92
elf_prot |= PROT_WRITE;
93
}
94
if (eppnt->p_flags & PF_X) {
95
- elf_prot |= PROT_EXEC;
96
+ elf_prot |= prot_exec;
97
}
98
99
vaddr = load_bias + eppnt->p_vaddr;
100
--
127
--
101
2.20.1
128
2.25.1
102
103
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: "Edgar E. Iglesias" <edgar.iglesias@amd.com>
2
2
3
These are all of the defines required to parse
3
Connect the 4 TTC timers on the ZynqMP.
4
GNU_PROPERTY_AARCH64_FEATURE_1_AND, copied from binutils.
5
Other missing defines related to other GNU program headers
6
and notes are elided for now.
7
4
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
10
Message-id: 20201016184207.786698-4-richard.henderson@linaro.org
7
Reviewed-by: Luc Michel <luc@lmichel.fr>
8
Reviewed-by: Francisco Iglesias <frasse.iglesias@gmail.com>
9
Message-id: 20220331222017.2914409-3-edgar.iglesias@gmail.com
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
11
---
13
include/elf.h | 22 ++++++++++++++++++++++
12
include/hw/arm/xlnx-zynqmp.h | 4 ++++
14
1 file changed, 22 insertions(+)
13
hw/arm/xlnx-zynqmp.c | 22 ++++++++++++++++++++++
14
2 files changed, 26 insertions(+)
15
15
16
diff --git a/include/elf.h b/include/elf.h
16
diff --git a/include/hw/arm/xlnx-zynqmp.h b/include/hw/arm/xlnx-zynqmp.h
17
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
18
--- a/include/elf.h
18
--- a/include/hw/arm/xlnx-zynqmp.h
19
+++ b/include/elf.h
19
+++ b/include/hw/arm/xlnx-zynqmp.h
20
@@ -XXX,XX +XXX,XX @@ typedef int64_t Elf64_Sxword;
20
@@ -XXX,XX +XXX,XX @@
21
#define PT_NOTE 4
21
#include "hw/or-irq.h"
22
#define PT_SHLIB 5
22
#include "hw/misc/xlnx-zynqmp-apu-ctrl.h"
23
#define PT_PHDR 6
23
#include "hw/misc/xlnx-zynqmp-crf.h"
24
+#define PT_LOOS 0x60000000
24
+#include "hw/timer/cadence_ttc.h"
25
+#define PT_HIOS 0x6fffffff
25
26
#define PT_LOPROC 0x70000000
26
#define TYPE_XLNX_ZYNQMP "xlnx-zynqmp"
27
#define PT_HIPROC 0x7fffffff
27
OBJECT_DECLARE_SIMPLE_TYPE(XlnxZynqMPState, XLNX_ZYNQMP)
28
28
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_SIMPLE_TYPE(XlnxZynqMPState, XLNX_ZYNQMP)
29
+#define PT_GNU_PROPERTY (PT_LOOS + 0x474e553)
29
#define XLNX_ZYNQMP_MAX_RAM_SIZE (XLNX_ZYNQMP_MAX_LOW_RAM_SIZE + \
30
+
30
XLNX_ZYNQMP_MAX_HIGH_RAM_SIZE)
31
#define PT_MIPS_REGINFO 0x70000000
31
32
#define PT_MIPS_RTPROC 0x70000001
32
+#define XLNX_ZYNQMP_NUM_TTC 4
33
#define PT_MIPS_OPTIONS 0x70000002
34
@@ -XXX,XX +XXX,XX @@ typedef struct elf64_shdr {
35
#define NT_ARM_SYSTEM_CALL 0x404 /* ARM system call number */
36
#define NT_ARM_SVE 0x405 /* ARM Scalable Vector Extension regs */
37
38
+/* Defined note types for GNU systems. */
39
+
40
+#define NT_GNU_PROPERTY_TYPE_0 5 /* Program property */
41
+
42
+/* Values used in GNU .note.gnu.property notes (NT_GNU_PROPERTY_TYPE_0). */
43
+
44
+#define GNU_PROPERTY_STACK_SIZE 1
45
+#define GNU_PROPERTY_NO_COPY_ON_PROTECTED 2
46
+
47
+#define GNU_PROPERTY_LOPROC 0xc0000000
48
+#define GNU_PROPERTY_HIPROC 0xdfffffff
49
+#define GNU_PROPERTY_LOUSER 0xe0000000
50
+#define GNU_PROPERTY_HIUSER 0xffffffff
51
+
52
+#define GNU_PROPERTY_AARCH64_FEATURE_1_AND 0xc0000000
53
+#define GNU_PROPERTY_AARCH64_FEATURE_1_BTI (1u << 0)
54
+#define GNU_PROPERTY_AARCH64_FEATURE_1_PAC (1u << 1)
55
+
33
+
56
/*
34
/*
57
* Physical entry point into the kernel.
35
* Unimplemented mmio regions needed to boot some images.
58
*
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
}
62
63
+static void xlnx_zynqmp_create_ttc(XlnxZynqMPState *s, qemu_irq *gic)
64
+{
65
+ SysBusDevice *sbd;
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
+}
80
+
81
static void xlnx_zynqmp_create_unimp_mmio(XlnxZynqMPState *s)
82
{
83
static const struct UnimpInfo {
84
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
85
xlnx_zynqmp_create_efuse(s, gic_spi);
86
xlnx_zynqmp_create_apu_ctrl(s, gic_spi);
87
xlnx_zynqmp_create_crf(s, gic_spi);
88
+ xlnx_zynqmp_create_ttc(s, gic_spi);
89
xlnx_zynqmp_create_unimp_mmio(s);
90
91
for (i = 0; i < XLNX_ZYNQMP_NUM_GDMA_CH; i++) {
59
--
92
--
60
2.20.1
93
2.25.1
61
62
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
From: "Edgar E. Iglesias" <edgar.iglesias@amd.com>
2
2
3
This peripheral has 1 free-running timer and 4 compare registers.
3
Create an APU CPU Cluster. This is in preparation to add the RPU.
4
4
5
Only the free-running timer is implemented. Add support the
5
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>
6
COMPARE registers (each register is wired to an IRQ).
6
Reviewed-by: Francisco Iglesias <francisco.iglesias@amd.com>
7
7
Message-id: 20220406174303.2022038-2-edgar.iglesias@xilinx.com
8
Reference: "BCM2835 ARM Peripherals" datasheet [*]
9
chapter 12 "System Timer":
10
11
The System Timer peripheral provides four 32-bit timer channels
12
and a single 64-bit free running counter. Each channel has an
13
output compare register, which is compared against the 32 least
14
significant bits of the free running counter values. When the
15
two values match, the system timer peripheral generates a signal
16
to indicate a match for the appropriate channel. The match signal
17
is then fed into the interrupt controller.
18
19
This peripheral is used since Linux 3.7, commit ee4af5696720
20
("ARM: bcm2835: add system timer").
21
22
[*] https://www.raspberrypi.org/app/uploads/2012/02/BCM2835-ARM-Peripherals.pdf
23
24
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
25
Reviewed-by: Luc Michel <luc@lmichel.fr>
26
Message-id: 20201010203709.3116542-4-f4bug@amsat.org
27
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
28
---
9
---
29
include/hw/timer/bcm2835_systmr.h | 11 +++++--
10
include/hw/arm/xlnx-versal.h | 2 ++
30
hw/timer/bcm2835_systmr.c | 48 ++++++++++++++++++++-----------
11
hw/arm/xlnx-versal.c | 9 ++++++++-
31
hw/timer/trace-events | 6 ++--
12
2 files changed, 10 insertions(+), 1 deletion(-)
32
3 files changed, 44 insertions(+), 21 deletions(-)
33
13
34
diff --git a/include/hw/timer/bcm2835_systmr.h b/include/hw/timer/bcm2835_systmr.h
14
diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
35
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
36
--- a/include/hw/timer/bcm2835_systmr.h
16
--- a/include/hw/arm/xlnx-versal.h
37
+++ b/include/hw/timer/bcm2835_systmr.h
17
+++ b/include/hw/arm/xlnx-versal.h
38
@@ -XXX,XX +XXX,XX @@
18
@@ -XXX,XX +XXX,XX @@
39
19
40
#include "hw/sysbus.h"
20
#include "hw/sysbus.h"
41
#include "hw/irq.h"
21
#include "hw/arm/boot.h"
42
+#include "qemu/timer.h"
22
+#include "hw/cpu/cluster.h"
43
#include "qom/object.h"
23
#include "hw/or-irq.h"
44
24
#include "hw/sd/sdhci.h"
45
#define TYPE_BCM2835_SYSTIMER "bcm2835-sys-timer"
25
#include "hw/intc/arm_gicv3.h"
46
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_SIMPLE_TYPE(BCM2835SystemTimerState, BCM2835_SYSTIMER)
26
@@ -XXX,XX +XXX,XX @@ struct Versal {
47
27
struct {
48
#define BCM2835_SYSTIMER_COUNT 4
28
struct {
49
29
MemoryRegion mr;
50
+typedef struct {
30
+ CPUClusterState cluster;
51
+ unsigned id;
31
ARMCPU cpu[XLNX_VERSAL_NR_ACPUS];
52
+ QEMUTimer timer;
32
GICv3State gic;
53
+ qemu_irq irq;
33
} apu;
54
+ BCM2835SystemTimerState *state;
34
diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
55
+} BCM2835SystemTimerCompare;
35
index XXXXXXX..XXXXXXX 100644
36
--- a/hw/arm/xlnx-versal.c
37
+++ b/hw/arm/xlnx-versal.c
38
@@ -XXX,XX +XXX,XX @@ static void versal_create_apu_cpus(Versal *s)
39
{
40
int i;
41
42
+ object_initialize_child(OBJECT(s), "apu-cluster", &s->fpd.apu.cluster,
43
+ TYPE_CPU_CLUSTER);
44
+ qdev_prop_set_uint32(DEVICE(&s->fpd.apu.cluster), "cluster-id", 0);
56
+
45
+
57
struct BCM2835SystemTimerState {
46
for (i = 0; i < ARRAY_SIZE(s->fpd.apu.cpu); i++) {
58
/*< private >*/
47
Object *obj;
59
SysBusDevice parent_obj;
48
60
49
- object_initialize_child(OBJECT(s), "apu-cpu[*]", &s->fpd.apu.cpu[i],
61
/*< public >*/
50
+ object_initialize_child(OBJECT(&s->fpd.apu.cluster),
62
MemoryRegion iomem;
51
+ "apu-cpu[*]", &s->fpd.apu.cpu[i],
63
- qemu_irq irq;
52
XLNX_VERSAL_ACPU_TYPE);
64
-
53
obj = OBJECT(&s->fpd.apu.cpu[i]);
65
struct {
54
if (i) {
66
uint32_t ctrl_status;
55
@@ -XXX,XX +XXX,XX @@ static void versal_create_apu_cpus(Versal *s)
67
uint32_t compare[BCM2835_SYSTIMER_COUNT];
56
&error_abort);
68
} reg;
57
qdev_realize(DEVICE(obj), NULL, &error_fatal);
69
+ BCM2835SystemTimerCompare tmr[BCM2835_SYSTIMER_COUNT];
58
}
70
};
59
+
71
60
+ qdev_realize(DEVICE(&s->fpd.apu.cluster), NULL, &error_fatal);
72
#endif
73
diff --git a/hw/timer/bcm2835_systmr.c b/hw/timer/bcm2835_systmr.c
74
index XXXXXXX..XXXXXXX 100644
75
--- a/hw/timer/bcm2835_systmr.c
76
+++ b/hw/timer/bcm2835_systmr.c
77
@@ -XXX,XX +XXX,XX @@ REG32(COMPARE1, 0x10)
78
REG32(COMPARE2, 0x14)
79
REG32(COMPARE3, 0x18)
80
81
-static void bcm2835_systmr_update_irq(BCM2835SystemTimerState *s)
82
+static void bcm2835_systmr_timer_expire(void *opaque)
83
{
84
- bool enable = !!s->reg.ctrl_status;
85
+ BCM2835SystemTimerCompare *tmr = opaque;
86
87
- trace_bcm2835_systmr_irq(enable);
88
- qemu_set_irq(s->irq, enable);
89
-}
90
-
91
-static void bcm2835_systmr_update_compare(BCM2835SystemTimerState *s,
92
- unsigned timer_index)
93
-{
94
- /* TODO fow now, since neither Linux nor U-boot use these timers. */
95
- qemu_log_mask(LOG_UNIMP, "COMPARE register %u not implemented\n",
96
- timer_index);
97
+ trace_bcm2835_systmr_timer_expired(tmr->id);
98
+ tmr->state->reg.ctrl_status |= 1 << tmr->id;
99
+ qemu_set_irq(tmr->irq, 1);
100
}
61
}
101
62
102
static uint64_t bcm2835_systmr_read(void *opaque, hwaddr offset,
63
static void versal_create_apu_gic(Versal *s, qemu_irq *pic)
103
@@ -XXX,XX +XXX,XX @@ static uint64_t bcm2835_systmr_read(void *opaque, hwaddr offset,
104
}
105
106
static void bcm2835_systmr_write(void *opaque, hwaddr offset,
107
- uint64_t value, unsigned size)
108
+ uint64_t value64, unsigned size)
109
{
110
BCM2835SystemTimerState *s = BCM2835_SYSTIMER(opaque);
111
+ int index;
112
+ uint32_t value = value64;
113
+ uint32_t triggers_delay_us;
114
+ uint64_t now;
115
116
trace_bcm2835_systmr_write(offset, value);
117
switch (offset) {
118
case A_CTRL_STATUS:
119
s->reg.ctrl_status &= ~value; /* Ack */
120
- bcm2835_systmr_update_irq(s);
121
+ for (index = 0; index < ARRAY_SIZE(s->tmr); index++) {
122
+ if (extract32(value, index, 1)) {
123
+ trace_bcm2835_systmr_irq_ack(index);
124
+ qemu_set_irq(s->tmr[index].irq, 0);
125
+ }
126
+ }
127
break;
128
case A_COMPARE0 ... A_COMPARE3:
129
- s->reg.compare[(offset - A_COMPARE0) >> 2] = value;
130
- bcm2835_systmr_update_compare(s, (offset - A_COMPARE0) >> 2);
131
+ index = (offset - A_COMPARE0) >> 2;
132
+ s->reg.compare[index] = value;
133
+ now = qemu_clock_get_us(QEMU_CLOCK_VIRTUAL);
134
+ /* Compare lower 32-bits of the free-running counter. */
135
+ triggers_delay_us = value - now;
136
+ trace_bcm2835_systmr_run(index, triggers_delay_us);
137
+ timer_mod(&s->tmr[index].timer, now + triggers_delay_us);
138
break;
139
case A_COUNTER_LOW:
140
case A_COUNTER_HIGH:
141
@@ -XXX,XX +XXX,XX @@ static void bcm2835_systmr_realize(DeviceState *dev, Error **errp)
142
memory_region_init_io(&s->iomem, OBJECT(dev), &bcm2835_systmr_ops,
143
s, "bcm2835-sys-timer", 0x20);
144
sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->iomem);
145
- sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->irq);
146
+
147
+ for (size_t i = 0; i < ARRAY_SIZE(s->tmr); i++) {
148
+ s->tmr[i].id = i;
149
+ s->tmr[i].state = s;
150
+ sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->tmr[i].irq);
151
+ timer_init_us(&s->tmr[i].timer, QEMU_CLOCK_VIRTUAL,
152
+ bcm2835_systmr_timer_expire, &s->tmr[i]);
153
+ }
154
}
155
156
static const VMStateDescription bcm2835_systmr_vmstate = {
157
diff --git a/hw/timer/trace-events b/hw/timer/trace-events
158
index XXXXXXX..XXXXXXX 100644
159
--- a/hw/timer/trace-events
160
+++ b/hw/timer/trace-events
161
@@ -XXX,XX +XXX,XX @@ nrf51_timer_write(uint8_t timer_id, uint64_t addr, uint32_t value, unsigned size
162
nrf51_timer_set_count(uint8_t timer_id, uint8_t counter_id, uint32_t value) "timer %u counter %u count 0x%" PRIx32
163
164
# bcm2835_systmr.c
165
-bcm2835_systmr_irq(bool enable) "timer irq state %u"
166
+bcm2835_systmr_timer_expired(unsigned id) "timer #%u expired"
167
+bcm2835_systmr_irq_ack(unsigned id) "timer #%u acked"
168
bcm2835_systmr_read(uint64_t offset, uint64_t data) "timer read: offset 0x%" PRIx64 " data 0x%" PRIx64
169
-bcm2835_systmr_write(uint64_t offset, uint64_t data) "timer write: offset 0x%" PRIx64 " data 0x%" PRIx64
170
+bcm2835_systmr_write(uint64_t offset, uint32_t data) "timer write: offset 0x%" PRIx64 " data 0x%" PRIx32
171
+bcm2835_systmr_run(unsigned id, uint64_t delay_us) "timer #%u expiring in %"PRIu64" us"
172
173
# avr_timer16.c
174
avr_timer16_read(uint8_t addr, uint8_t value) "timer16 read addr:%u value:%u"
175
--
64
--
176
2.20.1
65
2.25.1
177
178
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: "Edgar E. Iglesias" <edgar.iglesias@amd.com>
2
2
3
When TBI is enabled in a given regime, 56 bits of the address
3
Add the Cortex-R5Fs of the Versal RPU (Real-time Processing Unit)
4
are significant and we need to clear out any other matching
4
subsystem.
5
virtual addresses with differing tags.
6
5
7
The other uses of tlb_flush_page (without mmuidx) in this file
6
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>
8
are only used by aarch32 mode.
7
Reviewed-by: Francisco Iglesias <francisco.iglesias@amd.com>
9
8
Message-id: 20220406174303.2022038-3-edgar.iglesias@xilinx.com
10
Fixes: 38d931687fa1
11
Reported-by: Jordan Frank <jordanfrank@fb.com>
12
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
14
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
15
Message-id: 20201016210754.818257-3-richard.henderson@linaro.org
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
---
10
---
18
target/arm/helper.c | 46 ++++++++++++++++++++++++++++++++++++++-------
11
include/hw/arm/xlnx-versal.h | 10 ++++++++++
19
1 file changed, 39 insertions(+), 7 deletions(-)
12
hw/arm/xlnx-versal-virt.c | 6 +++---
13
hw/arm/xlnx-versal.c | 36 ++++++++++++++++++++++++++++++++++++
14
3 files changed, 49 insertions(+), 3 deletions(-)
20
15
21
diff --git a/target/arm/helper.c b/target/arm/helper.c
16
diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
22
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
23
--- a/target/arm/helper.c
18
--- a/include/hw/arm/xlnx-versal.h
24
+++ b/target/arm/helper.c
19
+++ b/include/hw/arm/xlnx-versal.h
25
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, target_ulong address,
20
@@ -XXX,XX +XXX,XX @@
26
#endif
21
OBJECT_DECLARE_SIMPLE_TYPE(Versal, XLNX_VERSAL)
27
22
28
static void switch_mode(CPUARMState *env, int mode);
23
#define XLNX_VERSAL_NR_ACPUS 2
29
+static int aa64_va_parameter_tbi(uint64_t tcr, ARMMMUIdx mmu_idx);
24
+#define XLNX_VERSAL_NR_RCPUS 2
30
25
#define XLNX_VERSAL_NR_UARTS 2
31
static int vfp_gdb_get_reg(CPUARMState *env, GByteArray *buf, int reg)
26
#define XLNX_VERSAL_NR_GEMS 2
32
{
27
#define XLNX_VERSAL_NR_ADMAS 8
33
@@ -XXX,XX +XXX,XX @@ static int vae1_tlbmask(CPUARMState *env)
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)
34
}
74
}
35
}
75
}
36
76
37
+/* Return 56 if TBI is enabled, 64 otherwise. */
77
+static void versal_create_rpu_cpus(Versal *s)
38
+static int tlbbits_for_regime(CPUARMState *env, ARMMMUIdx mmu_idx,
39
+ uint64_t addr)
40
+{
78
+{
41
+ uint64_t tcr = regime_tcr(env, mmu_idx)->raw_tcr;
79
+ int i;
42
+ int tbi = aa64_va_parameter_tbi(tcr, mmu_idx);
43
+ int select = extract64(addr, 55, 1);
44
+
80
+
45
+ return (tbi >> select) & 1 ? 56 : 64;
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);
46
+}
104
+}
47
+
105
+
48
+static int vae1_tlbbits(CPUARMState *env, uint64_t addr)
106
static void versal_create_uarts(Versal *s, qemu_irq *pic)
49
+{
50
+ ARMMMUIdx mmu_idx;
51
+
52
+ /* Only the regime of the mmu_idx below is significant. */
53
+ if (arm_is_secure_below_el3(env)) {
54
+ mmu_idx = ARMMMUIdx_SE10_0;
55
+ } else if ((env->cp15.hcr_el2 & (HCR_E2H | HCR_TGE))
56
+ == (HCR_E2H | HCR_TGE)) {
57
+ mmu_idx = ARMMMUIdx_E20_0;
58
+ } else {
59
+ mmu_idx = ARMMMUIdx_E10_0;
60
+ }
61
+ return tlbbits_for_regime(env, mmu_idx, addr);
62
+}
63
+
64
static void tlbi_aa64_vmalle1is_write(CPUARMState *env, const ARMCPRegInfo *ri,
65
uint64_t value)
66
{
107
{
67
@@ -XXX,XX +XXX,XX @@ static void tlbi_aa64_vae1is_write(CPUARMState *env, const ARMCPRegInfo *ri,
108
int i;
68
CPUState *cs = env_cpu(env);
109
@@ -XXX,XX +XXX,XX @@ static void versal_realize(DeviceState *dev, Error **errp)
69
int mask = vae1_tlbmask(env);
110
70
uint64_t pageaddr = sextract64(value << 12, 0, 56);
111
versal_create_apu_cpus(s);
71
+ int bits = vae1_tlbbits(env, pageaddr);
112
versal_create_apu_gic(s, pic);
72
113
+ versal_create_rpu_cpus(s);
73
- tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr, mask);
114
versal_create_uarts(s, pic);
74
+ tlb_flush_page_bits_by_mmuidx_all_cpus_synced(cs, pageaddr, mask, bits);
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);
75
}
123
}
76
124
77
static void tlbi_aa64_vae1_write(CPUARMState *env, const ARMCPRegInfo *ri,
125
static void versal_init(Object *obj)
78
@@ -XXX,XX +XXX,XX @@ static void tlbi_aa64_vae1_write(CPUARMState *env, const ARMCPRegInfo *ri,
126
@@ -XXX,XX +XXX,XX @@ static void versal_init(Object *obj)
79
CPUState *cs = env_cpu(env);
127
Versal *s = XLNX_VERSAL(obj);
80
int mask = vae1_tlbmask(env);
128
81
uint64_t pageaddr = sextract64(value << 12, 0, 56);
129
memory_region_init(&s->fpd.apu.mr, obj, "mr-apu", UINT64_MAX);
82
+ int bits = vae1_tlbbits(env, pageaddr);
130
+ memory_region_init(&s->lpd.rpu.mr, obj, "mr-rpu", UINT64_MAX);
83
131
memory_region_init(&s->mr_ps, obj, "mr-ps-switch", UINT64_MAX);
84
if (tlb_force_broadcast(env)) {
132
+ memory_region_init_alias(&s->lpd.rpu.mr_ps_alias, OBJECT(s),
85
- tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr, mask);
133
+ "mr-rpu-ps-alias", &s->mr_ps, 0, UINT64_MAX);
86
+ tlb_flush_page_bits_by_mmuidx_all_cpus_synced(cs, pageaddr, mask, bits);
87
} else {
88
- tlb_flush_page_by_mmuidx(cs, pageaddr, mask);
89
+ tlb_flush_page_bits_by_mmuidx(cs, pageaddr, mask, bits);
90
}
91
}
134
}
92
135
93
@@ -XXX,XX +XXX,XX @@ static void tlbi_aa64_vae2is_write(CPUARMState *env, const ARMCPRegInfo *ri,
136
static Property versal_properties[] = {
94
{
95
CPUState *cs = env_cpu(env);
96
uint64_t pageaddr = sextract64(value << 12, 0, 56);
97
+ int bits = tlbbits_for_regime(env, ARMMMUIdx_E2, pageaddr);
98
99
- tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr,
100
- ARMMMUIdxBit_E2);
101
+ tlb_flush_page_bits_by_mmuidx_all_cpus_synced(cs, pageaddr,
102
+ ARMMMUIdxBit_E2, bits);
103
}
104
105
static void tlbi_aa64_vae3is_write(CPUARMState *env, const ARMCPRegInfo *ri,
106
@@ -XXX,XX +XXX,XX @@ static void tlbi_aa64_vae3is_write(CPUARMState *env, const ARMCPRegInfo *ri,
107
{
108
CPUState *cs = env_cpu(env);
109
uint64_t pageaddr = sextract64(value << 12, 0, 56);
110
+ int bits = tlbbits_for_regime(env, ARMMMUIdx_SE3, pageaddr);
111
112
- tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr,
113
- ARMMMUIdxBit_SE3);
114
+ tlb_flush_page_bits_by_mmuidx_all_cpus_synced(cs, pageaddr,
115
+ ARMMMUIdxBit_SE3, bits);
116
}
117
118
static CPAccessResult aa64_zva_access(CPUARMState *env, const ARMCPRegInfo *ri,
119
--
137
--
120
2.20.1
138
2.25.1
121
122
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: "Edgar E. Iglesias" <edgar.iglesias@amd.com>
2
2
3
The note test requires gcc 10 for -mbranch-protection=standard.
3
Add a model of the Xilinx Versal CRL.
4
The mmap test uses PROT_BTI and does not require special compiler support.
5
4
6
Acked-by: Alex Bennée <alex.bennee@linaro.org>
5
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Frederic Konrad <fkonrad@amd.com>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Francisco Iglesias <francisco.iglesias@amd.com>
9
Message-id: 20201016184207.786698-13-richard.henderson@linaro.org
8
Message-id: 20220406174303.2022038-4-edgar.iglesias@xilinx.com
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
10
---
12
tests/tcg/aarch64/bti-1.c | 62 +++++++++++++++++
11
include/hw/misc/xlnx-versal-crl.h | 235 +++++++++++++++++
13
tests/tcg/aarch64/bti-2.c | 108 ++++++++++++++++++++++++++++++
12
hw/misc/xlnx-versal-crl.c | 421 ++++++++++++++++++++++++++++++
14
tests/tcg/aarch64/bti-crt.inc.c | 51 ++++++++++++++
13
hw/misc/meson.build | 1 +
15
tests/tcg/aarch64/Makefile.target | 10 +++
14
3 files changed, 657 insertions(+)
16
tests/tcg/configure.sh | 4 ++
15
create mode 100644 include/hw/misc/xlnx-versal-crl.h
17
5 files changed, 235 insertions(+)
16
create mode 100644 hw/misc/xlnx-versal-crl.c
18
create mode 100644 tests/tcg/aarch64/bti-1.c
19
create mode 100644 tests/tcg/aarch64/bti-2.c
20
create mode 100644 tests/tcg/aarch64/bti-crt.inc.c
21
17
22
diff --git a/tests/tcg/aarch64/bti-1.c b/tests/tcg/aarch64/bti-1.c
18
diff --git a/include/hw/misc/xlnx-versal-crl.h b/include/hw/misc/xlnx-versal-crl.h
23
new file mode 100644
19
new file mode 100644
24
index XXXXXXX..XXXXXXX
20
index XXXXXXX..XXXXXXX
25
--- /dev/null
21
--- /dev/null
26
+++ b/tests/tcg/aarch64/bti-1.c
22
+++ b/include/hw/misc/xlnx-versal-crl.h
27
@@ -XXX,XX +XXX,XX @@
23
@@ -XXX,XX +XXX,XX @@
28
+/*
24
+/*
29
+ * Branch target identification, basic notskip cases.
25
+ * QEMU model of the Clock-Reset-LPD (CRL).
26
+ *
27
+ * Copyright (c) 2022 Xilinx Inc.
28
+ * SPDX-License-Identifier: GPL-2.0-or-later
29
+ *
30
+ * Written by Edgar E. Iglesias <edgar.iglesias@xilinx.com>
30
+ */
31
+ */
31
+
32
+#ifndef HW_MISC_XLNX_VERSAL_CRL_H
32
+#include "bti-crt.inc.c"
33
+#define HW_MISC_XLNX_VERSAL_CRL_H
33
+
34
+
34
+static void skip2_sigill(int sig, siginfo_t *info, ucontext_t *uc)
35
+#include "hw/sysbus.h"
35
+{
36
+#include "hw/register.h"
36
+ uc->uc_mcontext.pc += 8;
37
+#include "target/arm/cpu.h"
37
+ uc->uc_mcontext.pstate = 1;
38
+
38
+}
39
+#define TYPE_XLNX_VERSAL_CRL "xlnx,versal-crl"
39
+
40
+OBJECT_DECLARE_SIMPLE_TYPE(XlnxVersalCRL, XLNX_VERSAL_CRL)
40
+#define NOP "nop"
41
+
41
+#define BTI_N "hint #32"
42
+REG32(ERR_CTRL, 0x0)
42
+#define BTI_C "hint #34"
43
+ FIELD(ERR_CTRL, SLVERR_ENABLE, 0, 1)
43
+#define BTI_J "hint #36"
44
+REG32(IR_STATUS, 0x4)
44
+#define BTI_JC "hint #38"
45
+ FIELD(IR_STATUS, ADDR_DECODE_ERR, 0, 1)
45
+
46
+REG32(IR_MASK, 0x8)
46
+#define BTYPE_1(DEST) \
47
+ FIELD(IR_MASK, ADDR_DECODE_ERR, 0, 1)
47
+ asm("mov %0,#1; adr x16, 1f; br x16; 1: " DEST "; mov %0,#0" \
48
+REG32(IR_ENABLE, 0xc)
48
+ : "=r"(skipped) : : "x16")
49
+ FIELD(IR_ENABLE, ADDR_DECODE_ERR, 0, 1)
49
+
50
+REG32(IR_DISABLE, 0x10)
50
+#define BTYPE_2(DEST) \
51
+ FIELD(IR_DISABLE, ADDR_DECODE_ERR, 0, 1)
51
+ asm("mov %0,#1; adr x16, 1f; blr x16; 1: " DEST "; mov %0,#0" \
52
+REG32(WPROT, 0x1c)
52
+ : "=r"(skipped) : : "x16", "x30")
53
+ FIELD(WPROT, ACTIVE, 0, 1)
53
+
54
+REG32(PLL_CLK_OTHER_DMN, 0x20)
54
+#define BTYPE_3(DEST) \
55
+ FIELD(PLL_CLK_OTHER_DMN, APLL_BYPASS, 0, 1)
55
+ asm("mov %0,#1; adr x15, 1f; br x15; 1: " DEST "; mov %0,#0" \
56
+REG32(RPLL_CTRL, 0x40)
56
+ : "=r"(skipped) : : "x15")
57
+ FIELD(RPLL_CTRL, POST_SRC, 24, 3)
57
+
58
+ FIELD(RPLL_CTRL, PRE_SRC, 20, 3)
58
+#define TEST(WHICH, DEST, EXPECT) \
59
+ FIELD(RPLL_CTRL, CLKOUTDIV, 16, 2)
59
+ do { WHICH(DEST); fail += skipped ^ EXPECT; } while (0)
60
+ FIELD(RPLL_CTRL, FBDIV, 8, 8)
60
+
61
+ FIELD(RPLL_CTRL, BYPASS, 3, 1)
61
+
62
+ FIELD(RPLL_CTRL, RESET, 0, 1)
62
+int main()
63
+REG32(RPLL_CFG, 0x44)
63
+{
64
+ FIELD(RPLL_CFG, LOCK_DLY, 25, 7)
64
+ int fail = 0;
65
+ FIELD(RPLL_CFG, LOCK_CNT, 13, 10)
65
+ int skipped;
66
+ FIELD(RPLL_CFG, LFHF, 10, 2)
66
+
67
+ FIELD(RPLL_CFG, CP, 5, 4)
67
+ /* Signal-like with SA_SIGINFO. */
68
+ FIELD(RPLL_CFG, RES, 0, 4)
68
+ signal_info(SIGILL, skip2_sigill);
69
+REG32(RPLL_FRAC_CFG, 0x48)
69
+
70
+ FIELD(RPLL_FRAC_CFG, ENABLED, 31, 1)
70
+ TEST(BTYPE_1, NOP, 1);
71
+ FIELD(RPLL_FRAC_CFG, SEED, 22, 3)
71
+ TEST(BTYPE_1, BTI_N, 1);
72
+ FIELD(RPLL_FRAC_CFG, ALGRTHM, 19, 1)
72
+ TEST(BTYPE_1, BTI_C, 0);
73
+ FIELD(RPLL_FRAC_CFG, ORDER, 18, 1)
73
+ TEST(BTYPE_1, BTI_J, 0);
74
+ FIELD(RPLL_FRAC_CFG, DATA, 0, 16)
74
+ TEST(BTYPE_1, BTI_JC, 0);
75
+REG32(PLL_STATUS, 0x50)
75
+
76
+ FIELD(PLL_STATUS, RPLL_STABLE, 2, 1)
76
+ TEST(BTYPE_2, NOP, 1);
77
+ FIELD(PLL_STATUS, RPLL_LOCK, 0, 1)
77
+ TEST(BTYPE_2, BTI_N, 1);
78
+REG32(RPLL_TO_XPD_CTRL, 0x100)
78
+ TEST(BTYPE_2, BTI_C, 0);
79
+ FIELD(RPLL_TO_XPD_CTRL, CLKACT, 25, 1)
79
+ TEST(BTYPE_2, BTI_J, 1);
80
+ FIELD(RPLL_TO_XPD_CTRL, DIVISOR0, 8, 10)
80
+ TEST(BTYPE_2, BTI_JC, 0);
81
+REG32(LPD_TOP_SWITCH_CTRL, 0x104)
81
+
82
+ FIELD(LPD_TOP_SWITCH_CTRL, CLKACT_ADMA, 26, 1)
82
+ TEST(BTYPE_3, NOP, 1);
83
+ FIELD(LPD_TOP_SWITCH_CTRL, CLKACT, 25, 1)
83
+ TEST(BTYPE_3, BTI_N, 1);
84
+ FIELD(LPD_TOP_SWITCH_CTRL, DIVISOR0, 8, 10)
84
+ TEST(BTYPE_3, BTI_C, 1);
85
+ FIELD(LPD_TOP_SWITCH_CTRL, SRCSEL, 0, 3)
85
+ TEST(BTYPE_3, BTI_J, 0);
86
+REG32(LPD_LSBUS_CTRL, 0x108)
86
+ TEST(BTYPE_3, BTI_JC, 0);
87
+ FIELD(LPD_LSBUS_CTRL, CLKACT, 25, 1)
87
+
88
+ FIELD(LPD_LSBUS_CTRL, DIVISOR0, 8, 10)
88
+ return fail;
89
+ FIELD(LPD_LSBUS_CTRL, SRCSEL, 0, 3)
89
+}
90
+REG32(CPU_R5_CTRL, 0x10c)
90
diff --git a/tests/tcg/aarch64/bti-2.c b/tests/tcg/aarch64/bti-2.c
91
+ FIELD(CPU_R5_CTRL, CLKACT_OCM2, 28, 1)
92
+ FIELD(CPU_R5_CTRL, CLKACT_OCM, 27, 1)
93
+ FIELD(CPU_R5_CTRL, CLKACT_CORE, 26, 1)
94
+ FIELD(CPU_R5_CTRL, CLKACT, 25, 1)
95
+ FIELD(CPU_R5_CTRL, DIVISOR0, 8, 10)
96
+ FIELD(CPU_R5_CTRL, SRCSEL, 0, 3)
97
+REG32(IOU_SWITCH_CTRL, 0x114)
98
+ FIELD(IOU_SWITCH_CTRL, CLKACT, 25, 1)
99
+ FIELD(IOU_SWITCH_CTRL, DIVISOR0, 8, 10)
100
+ FIELD(IOU_SWITCH_CTRL, SRCSEL, 0, 3)
101
+REG32(GEM0_REF_CTRL, 0x118)
102
+ FIELD(GEM0_REF_CTRL, CLKACT_RX, 27, 1)
103
+ FIELD(GEM0_REF_CTRL, CLKACT_TX, 26, 1)
104
+ FIELD(GEM0_REF_CTRL, CLKACT, 25, 1)
105
+ FIELD(GEM0_REF_CTRL, DIVISOR0, 8, 10)
106
+ FIELD(GEM0_REF_CTRL, SRCSEL, 0, 3)
107
+REG32(GEM1_REF_CTRL, 0x11c)
108
+ FIELD(GEM1_REF_CTRL, CLKACT_RX, 27, 1)
109
+ FIELD(GEM1_REF_CTRL, CLKACT_TX, 26, 1)
110
+ FIELD(GEM1_REF_CTRL, CLKACT, 25, 1)
111
+ FIELD(GEM1_REF_CTRL, DIVISOR0, 8, 10)
112
+ FIELD(GEM1_REF_CTRL, SRCSEL, 0, 3)
113
+REG32(GEM_TSU_REF_CTRL, 0x120)
114
+ FIELD(GEM_TSU_REF_CTRL, CLKACT, 25, 1)
115
+ FIELD(GEM_TSU_REF_CTRL, DIVISOR0, 8, 10)
116
+ FIELD(GEM_TSU_REF_CTRL, SRCSEL, 0, 3)
117
+REG32(USB0_BUS_REF_CTRL, 0x124)
118
+ FIELD(USB0_BUS_REF_CTRL, CLKACT, 25, 1)
119
+ FIELD(USB0_BUS_REF_CTRL, DIVISOR0, 8, 10)
120
+ FIELD(USB0_BUS_REF_CTRL, SRCSEL, 0, 3)
121
+REG32(UART0_REF_CTRL, 0x128)
122
+ FIELD(UART0_REF_CTRL, CLKACT, 25, 1)
123
+ FIELD(UART0_REF_CTRL, DIVISOR0, 8, 10)
124
+ FIELD(UART0_REF_CTRL, SRCSEL, 0, 3)
125
+REG32(UART1_REF_CTRL, 0x12c)
126
+ FIELD(UART1_REF_CTRL, CLKACT, 25, 1)
127
+ FIELD(UART1_REF_CTRL, DIVISOR0, 8, 10)
128
+ FIELD(UART1_REF_CTRL, SRCSEL, 0, 3)
129
+REG32(SPI0_REF_CTRL, 0x130)
130
+ FIELD(SPI0_REF_CTRL, CLKACT, 25, 1)
131
+ FIELD(SPI0_REF_CTRL, DIVISOR0, 8, 10)
132
+ FIELD(SPI0_REF_CTRL, SRCSEL, 0, 3)
133
+REG32(SPI1_REF_CTRL, 0x134)
134
+ FIELD(SPI1_REF_CTRL, CLKACT, 25, 1)
135
+ FIELD(SPI1_REF_CTRL, DIVISOR0, 8, 10)
136
+ FIELD(SPI1_REF_CTRL, SRCSEL, 0, 3)
137
+REG32(CAN0_REF_CTRL, 0x138)
138
+ FIELD(CAN0_REF_CTRL, CLKACT, 25, 1)
139
+ FIELD(CAN0_REF_CTRL, DIVISOR0, 8, 10)
140
+ FIELD(CAN0_REF_CTRL, SRCSEL, 0, 3)
141
+REG32(CAN1_REF_CTRL, 0x13c)
142
+ FIELD(CAN1_REF_CTRL, CLKACT, 25, 1)
143
+ FIELD(CAN1_REF_CTRL, DIVISOR0, 8, 10)
144
+ FIELD(CAN1_REF_CTRL, SRCSEL, 0, 3)
145
+REG32(I2C0_REF_CTRL, 0x140)
146
+ FIELD(I2C0_REF_CTRL, CLKACT, 25, 1)
147
+ FIELD(I2C0_REF_CTRL, DIVISOR0, 8, 10)
148
+ FIELD(I2C0_REF_CTRL, SRCSEL, 0, 3)
149
+REG32(I2C1_REF_CTRL, 0x144)
150
+ FIELD(I2C1_REF_CTRL, CLKACT, 25, 1)
151
+ FIELD(I2C1_REF_CTRL, DIVISOR0, 8, 10)
152
+ FIELD(I2C1_REF_CTRL, SRCSEL, 0, 3)
153
+REG32(DBG_LPD_CTRL, 0x148)
154
+ FIELD(DBG_LPD_CTRL, CLKACT, 25, 1)
155
+ FIELD(DBG_LPD_CTRL, DIVISOR0, 8, 10)
156
+ FIELD(DBG_LPD_CTRL, SRCSEL, 0, 3)
157
+REG32(TIMESTAMP_REF_CTRL, 0x14c)
158
+ FIELD(TIMESTAMP_REF_CTRL, CLKACT, 25, 1)
159
+ FIELD(TIMESTAMP_REF_CTRL, DIVISOR0, 8, 10)
160
+ FIELD(TIMESTAMP_REF_CTRL, SRCSEL, 0, 3)
161
+REG32(CRL_SAFETY_CHK, 0x150)
162
+REG32(PSM_REF_CTRL, 0x154)
163
+ FIELD(PSM_REF_CTRL, DIVISOR0, 8, 10)
164
+ FIELD(PSM_REF_CTRL, SRCSEL, 0, 3)
165
+REG32(DBG_TSTMP_CTRL, 0x158)
166
+ FIELD(DBG_TSTMP_CTRL, CLKACT, 25, 1)
167
+ FIELD(DBG_TSTMP_CTRL, DIVISOR0, 8, 10)
168
+ FIELD(DBG_TSTMP_CTRL, SRCSEL, 0, 3)
169
+REG32(CPM_TOPSW_REF_CTRL, 0x15c)
170
+ FIELD(CPM_TOPSW_REF_CTRL, CLKACT, 25, 1)
171
+ FIELD(CPM_TOPSW_REF_CTRL, DIVISOR0, 8, 10)
172
+ FIELD(CPM_TOPSW_REF_CTRL, SRCSEL, 0, 3)
173
+REG32(USB3_DUAL_REF_CTRL, 0x160)
174
+ FIELD(USB3_DUAL_REF_CTRL, CLKACT, 25, 1)
175
+ FIELD(USB3_DUAL_REF_CTRL, DIVISOR0, 8, 10)
176
+ FIELD(USB3_DUAL_REF_CTRL, SRCSEL, 0, 3)
177
+REG32(RST_CPU_R5, 0x300)
178
+ FIELD(RST_CPU_R5, RESET_PGE, 4, 1)
179
+ FIELD(RST_CPU_R5, RESET_AMBA, 2, 1)
180
+ FIELD(RST_CPU_R5, RESET_CPU1, 1, 1)
181
+ FIELD(RST_CPU_R5, RESET_CPU0, 0, 1)
182
+REG32(RST_ADMA, 0x304)
183
+ FIELD(RST_ADMA, RESET, 0, 1)
184
+REG32(RST_GEM0, 0x308)
185
+ FIELD(RST_GEM0, RESET, 0, 1)
186
+REG32(RST_GEM1, 0x30c)
187
+ FIELD(RST_GEM1, RESET, 0, 1)
188
+REG32(RST_SPARE, 0x310)
189
+ FIELD(RST_SPARE, RESET, 0, 1)
190
+REG32(RST_USB0, 0x314)
191
+ FIELD(RST_USB0, RESET, 0, 1)
192
+REG32(RST_UART0, 0x318)
193
+ FIELD(RST_UART0, RESET, 0, 1)
194
+REG32(RST_UART1, 0x31c)
195
+ FIELD(RST_UART1, RESET, 0, 1)
196
+REG32(RST_SPI0, 0x320)
197
+ FIELD(RST_SPI0, RESET, 0, 1)
198
+REG32(RST_SPI1, 0x324)
199
+ FIELD(RST_SPI1, RESET, 0, 1)
200
+REG32(RST_CAN0, 0x328)
201
+ FIELD(RST_CAN0, RESET, 0, 1)
202
+REG32(RST_CAN1, 0x32c)
203
+ FIELD(RST_CAN1, RESET, 0, 1)
204
+REG32(RST_I2C0, 0x330)
205
+ FIELD(RST_I2C0, RESET, 0, 1)
206
+REG32(RST_I2C1, 0x334)
207
+ FIELD(RST_I2C1, RESET, 0, 1)
208
+REG32(RST_DBG_LPD, 0x338)
209
+ FIELD(RST_DBG_LPD, RPU_DBG1_RESET, 5, 1)
210
+ FIELD(RST_DBG_LPD, RPU_DBG0_RESET, 4, 1)
211
+ FIELD(RST_DBG_LPD, RESET_HSDP, 1, 1)
212
+ FIELD(RST_DBG_LPD, RESET, 0, 1)
213
+REG32(RST_GPIO, 0x33c)
214
+ FIELD(RST_GPIO, RESET, 0, 1)
215
+REG32(RST_TTC, 0x344)
216
+ FIELD(RST_TTC, TTC3_RESET, 3, 1)
217
+ FIELD(RST_TTC, TTC2_RESET, 2, 1)
218
+ FIELD(RST_TTC, TTC1_RESET, 1, 1)
219
+ FIELD(RST_TTC, TTC0_RESET, 0, 1)
220
+REG32(RST_TIMESTAMP, 0x348)
221
+ FIELD(RST_TIMESTAMP, RESET, 0, 1)
222
+REG32(RST_SWDT, 0x34c)
223
+ FIELD(RST_SWDT, RESET, 0, 1)
224
+REG32(RST_OCM, 0x350)
225
+ FIELD(RST_OCM, RESET, 0, 1)
226
+REG32(RST_IPI, 0x354)
227
+ FIELD(RST_IPI, RESET, 0, 1)
228
+REG32(RST_SYSMON, 0x358)
229
+ FIELD(RST_SYSMON, SEQ_RST, 1, 1)
230
+ FIELD(RST_SYSMON, CFG_RST, 0, 1)
231
+REG32(RST_FPD, 0x360)
232
+ FIELD(RST_FPD, SRST, 1, 1)
233
+ FIELD(RST_FPD, POR, 0, 1)
234
+REG32(PSM_RST_MODE, 0x370)
235
+ FIELD(PSM_RST_MODE, WAKEUP, 2, 1)
236
+ FIELD(PSM_RST_MODE, RST_MODE, 0, 2)
237
+
238
+#define CRL_R_MAX (R_PSM_RST_MODE + 1)
239
+
240
+#define RPU_MAX_CPU 2
241
+
242
+struct XlnxVersalCRL {
243
+ SysBusDevice parent_obj;
244
+ qemu_irq irq;
245
+
246
+ struct {
247
+ ARMCPU *cpu_r5[RPU_MAX_CPU];
248
+ DeviceState *adma[8];
249
+ DeviceState *uart[2];
250
+ DeviceState *gem[2];
251
+ DeviceState *usb;
252
+ } cfg;
253
+
254
+ RegisterInfoArray *reg_array;
255
+ uint32_t regs[CRL_R_MAX];
256
+ RegisterInfo regs_info[CRL_R_MAX];
257
+};
258
+#endif
259
diff --git a/hw/misc/xlnx-versal-crl.c b/hw/misc/xlnx-versal-crl.c
91
new file mode 100644
260
new file mode 100644
92
index XXXXXXX..XXXXXXX
261
index XXXXXXX..XXXXXXX
93
--- /dev/null
262
--- /dev/null
94
+++ b/tests/tcg/aarch64/bti-2.c
263
+++ b/hw/misc/xlnx-versal-crl.c
95
@@ -XXX,XX +XXX,XX @@
264
@@ -XXX,XX +XXX,XX @@
96
+/*
265
+/*
97
+ * Branch target identification, basic notskip cases.
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>
98
+ */
272
+ */
99
+
273
+
100
+#include <stdio.h>
274
+#include "qemu/osdep.h"
101
+#include <signal.h>
275
+#include "qapi/error.h"
102
+#include <string.h>
276
+#include "qemu/log.h"
103
+#include <unistd.h>
277
+#include "qemu/bitops.h"
104
+#include <sys/mman.h>
278
+#include "migration/vmstate.h"
105
+
279
+#include "hw/qdev-properties.h"
106
+#ifndef PROT_BTI
280
+#include "hw/sysbus.h"
107
+#define PROT_BTI 0x10
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
108
+#endif
290
+#endif
109
+
291
+
110
+static void skip2_sigill(int sig, siginfo_t *info, void *vuc)
292
+static void crl_update_irq(XlnxVersalCRL *s)
111
+{
293
+{
112
+ ucontext_t *uc = vuc;
294
+ bool pending = s->regs[R_IR_STATUS] & ~s->regs[R_IR_MASK];
113
+ uc->uc_mcontext.pc += 8;
295
+ qemu_set_irq(s->irq, pending);
114
+ uc->uc_mcontext.pstate = 1;
296
+}
115
+}
297
+
116
+
298
+static void crl_status_postw(RegisterInfo *reg, uint64_t val64)
117
+#define NOP "nop"
299
+{
118
+#define BTI_N "hint #32"
300
+ XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque);
119
+#define BTI_C "hint #34"
301
+ crl_update_irq(s);
120
+#define BTI_J "hint #36"
302
+}
121
+#define BTI_JC "hint #38"
303
+
122
+
304
+static uint64_t crl_enable_prew(RegisterInfo *reg, uint64_t val64)
123
+#define BTYPE_1(DEST) \
305
+{
124
+ "mov x1, #1\n\t" \
306
+ XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque);
125
+ "adr x16, 1f\n\t" \
307
+ uint32_t val = val64;
126
+ "br x16\n" \
308
+
127
+"1: " DEST "\n\t" \
309
+ s->regs[R_IR_MASK] &= ~val;
128
+ "mov x1, #0"
310
+ crl_update_irq(s);
129
+
311
+ return 0;
130
+#define BTYPE_2(DEST) \
312
+}
131
+ "mov x1, #1\n\t" \
313
+
132
+ "adr x16, 1f\n\t" \
314
+static uint64_t crl_disable_prew(RegisterInfo *reg, uint64_t val64)
133
+ "blr x16\n" \
315
+{
134
+"1: " DEST "\n\t" \
316
+ XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque);
135
+ "mov x1, #0"
317
+ uint32_t val = val64;
136
+
318
+
137
+#define BTYPE_3(DEST) \
319
+ s->regs[R_IR_MASK] |= val;
138
+ "mov x1, #1\n\t" \
320
+ crl_update_irq(s);
139
+ "adr x15, 1f\n\t" \
321
+ return 0;
140
+ "br x15\n" \
322
+}
141
+"1: " DEST "\n\t" \
323
+
142
+ "mov x1, #0"
324
+static void crl_reset_dev(XlnxVersalCRL *s, DeviceState *dev,
143
+
325
+ bool rst_old, bool rst_new)
144
+#define TEST(WHICH, DEST, EXPECT) \
326
+{
145
+ WHICH(DEST) "\n" \
327
+ device_cold_reset(dev);
146
+ ".if " #EXPECT "\n\t" \
328
+}
147
+ "eor x1, x1," #EXPECT "\n" \
329
+
148
+ ".endif\n\t" \
330
+static void crl_reset_cpu(XlnxVersalCRL *s, ARMCPU *armcpu,
149
+ "add x0, x0, x1\n\t"
331
+ bool rst_old, bool rst_new)
150
+
332
+{
151
+extern char test_begin[], test_end[];
333
+ if (rst_new) {
152
+
334
+ arm_set_cpu_off(armcpu->mp_affinity);
153
+asm("\n"
335
+ } else {
154
+"test_begin:\n\t"
336
+ arm_set_cpu_on_and_reset(armcpu->mp_affinity);
155
+ BTI_C "\n\t"
337
+ }
156
+ "mov x2, x30\n\t"
338
+}
157
+ "mov x0, #0\n\t"
339
+
158
+
340
+#define REGFIELD_RESET(type, s, reg, f, new_val, dev) { \
159
+ TEST(BTYPE_1, NOP, 1)
341
+ bool old_f = ARRAY_FIELD_EX32((s)->regs, reg, f); \
160
+ TEST(BTYPE_1, BTI_N, 1)
342
+ bool new_f = FIELD_EX32(new_val, reg, f); \
161
+ TEST(BTYPE_1, BTI_C, 0)
343
+ \
162
+ TEST(BTYPE_1, BTI_J, 0)
344
+ /* Detect edges. */ \
163
+ TEST(BTYPE_1, BTI_JC, 0)
345
+ if (dev && old_f != new_f) { \
164
+
346
+ crl_reset_ ## type(s, dev, old_f, new_f); \
165
+ TEST(BTYPE_2, NOP, 1)
347
+ } \
166
+ TEST(BTYPE_2, BTI_N, 1)
348
+}
167
+ TEST(BTYPE_2, BTI_C, 0)
349
+
168
+ TEST(BTYPE_2, BTI_J, 1)
350
+static uint64_t crl_rst_r5_prew(RegisterInfo *reg, uint64_t val64)
169
+ TEST(BTYPE_2, BTI_JC, 0)
351
+{
170
+
352
+ XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque);
171
+ TEST(BTYPE_3, NOP, 1)
353
+
172
+ TEST(BTYPE_3, BTI_N, 1)
354
+ REGFIELD_RESET(cpu, s, RST_CPU_R5, RESET_CPU0, val64, s->cfg.cpu_r5[0]);
173
+ TEST(BTYPE_3, BTI_C, 1)
355
+ REGFIELD_RESET(cpu, s, RST_CPU_R5, RESET_CPU1, val64, s->cfg.cpu_r5[1]);
174
+ TEST(BTYPE_3, BTI_J, 0)
356
+ return val64;
175
+ TEST(BTYPE_3, BTI_JC, 0)
357
+}
176
+
358
+
177
+ "ret x2\n"
359
+static uint64_t crl_rst_adma_prew(RegisterInfo *reg, uint64_t val64)
178
+"test_end:"
360
+{
179
+);
361
+ XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque);
180
+
362
+ int i;
181
+int main()
363
+
182
+{
364
+ /* A single register fans out to all ADMA reset inputs. */
183
+ struct sigaction sa;
365
+ for (i = 0; i < ARRAY_SIZE(s->cfg.adma); i++) {
184
+
366
+ REGFIELD_RESET(dev, s, RST_ADMA, RESET, val64, s->cfg.adma[i]);
185
+ void *p = mmap(0, getpagesize(),
367
+ }
186
+ PROT_EXEC | PROT_READ | PROT_WRITE | PROT_BTI,
368
+ return val64;
187
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
369
+}
188
+ if (p == MAP_FAILED) {
370
+
189
+ perror("mmap");
371
+static uint64_t crl_rst_uart0_prew(RegisterInfo *reg, uint64_t val64)
190
+ return 1;
372
+{
191
+ }
373
+ XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque);
192
+
374
+
193
+ memset(&sa, 0, sizeof(sa));
375
+ REGFIELD_RESET(dev, s, RST_UART0, RESET, val64, s->cfg.uart[0]);
194
+ sa.sa_sigaction = skip2_sigill;
376
+ return val64;
195
+ sa.sa_flags = SA_SIGINFO;
377
+}
196
+ if (sigaction(SIGILL, &sa, NULL) < 0) {
378
+
197
+ perror("sigaction");
379
+static uint64_t crl_rst_uart1_prew(RegisterInfo *reg, uint64_t val64)
198
+ return 1;
380
+{
199
+ }
381
+ XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque);
200
+
382
+
201
+ memcpy(p, test_begin, test_end - test_begin);
383
+ REGFIELD_RESET(dev, s, RST_UART1, RESET, val64, s->cfg.uart[1]);
202
+ return ((int (*)(void))p)();
384
+ return val64;
203
+}
385
+}
204
diff --git a/tests/tcg/aarch64/bti-crt.inc.c b/tests/tcg/aarch64/bti-crt.inc.c
386
+
205
new file mode 100644
387
+static uint64_t crl_rst_gem0_prew(RegisterInfo *reg, uint64_t val64)
206
index XXXXXXX..XXXXXXX
388
+{
207
--- /dev/null
389
+ XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque);
208
+++ b/tests/tcg/aarch64/bti-crt.inc.c
390
+
209
@@ -XXX,XX +XXX,XX @@
391
+ REGFIELD_RESET(dev, s, RST_GEM0, RESET, val64, s->cfg.gem[0]);
210
+/*
392
+ return val64;
211
+ * Minimal user-environment for testing BTI.
393
+}
212
+ *
394
+
213
+ * Normal libc is not (yet) built with BTI support enabled,
395
+static uint64_t crl_rst_gem1_prew(RegisterInfo *reg, uint64_t val64)
214
+ * and so could generate a BTI TRAP before ever reaching main.
396
+{
215
+ */
397
+ XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque);
216
+
398
+
217
+#include <stdlib.h>
399
+ REGFIELD_RESET(dev, s, RST_GEM1, RESET, val64, s->cfg.gem[1]);
218
+#include <signal.h>
400
+ return val64;
219
+#include <ucontext.h>
401
+}
220
+#include <asm/unistd.h>
402
+
221
+
403
+static uint64_t crl_rst_usb_prew(RegisterInfo *reg, uint64_t val64)
222
+int main(void);
404
+{
223
+
405
+ XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque);
224
+void _start(void)
406
+
225
+{
407
+ REGFIELD_RESET(dev, s, RST_USB0, RESET, val64, s->cfg.usb);
226
+ exit(main());
408
+ return val64;
227
+}
409
+}
228
+
410
+
229
+void exit(int ret)
411
+static const RegisterAccessInfo crl_regs_info[] = {
230
+{
412
+ { .name = "ERR_CTRL", .addr = A_ERR_CTRL,
231
+ register int x0 __asm__("x0") = ret;
413
+ },{ .name = "IR_STATUS", .addr = A_IR_STATUS,
232
+ register int x8 __asm__("x8") = __NR_exit;
414
+ .w1c = 0x1,
233
+
415
+ .post_write = crl_status_postw,
234
+ asm volatile("svc #0" : : "r"(x0), "r"(x8));
416
+ },{ .name = "IR_MASK", .addr = A_IR_MASK,
235
+ __builtin_unreachable();
417
+ .reset = 0x1,
236
+}
418
+ .ro = 0x1,
237
+
419
+ },{ .name = "IR_ENABLE", .addr = A_IR_ENABLE,
238
+/*
420
+ .pre_write = crl_enable_prew,
239
+ * Irritatingly, the user API struct sigaction does not match the
421
+ },{ .name = "IR_DISABLE", .addr = A_IR_DISABLE,
240
+ * kernel API struct sigaction. So for simplicity, isolate the
422
+ .pre_write = crl_disable_prew,
241
+ * kernel ABI here, and make this act like signal.
423
+ },{ .name = "WPROT", .addr = A_WPROT,
242
+ */
424
+ },{ .name = "PLL_CLK_OTHER_DMN", .addr = A_PLL_CLK_OTHER_DMN,
243
+void signal_info(int sig, void (*fn)(int, siginfo_t *, ucontext_t *))
425
+ .reset = 0x1,
244
+{
426
+ .rsvd = 0xe,
245
+ struct kernel_sigaction {
427
+ },{ .name = "RPLL_CTRL", .addr = A_RPLL_CTRL,
246
+ void (*handler)(int, siginfo_t *, ucontext_t *);
428
+ .reset = 0x24809,
247
+ unsigned long flags;
429
+ .rsvd = 0xf88c00f6,
248
+ unsigned long restorer;
430
+ },{ .name = "RPLL_CFG", .addr = A_RPLL_CFG,
249
+ unsigned long mask;
431
+ .reset = 0x2000000,
250
+ } sa = { fn, SA_SIGINFO, 0, 0 };
432
+ .rsvd = 0x1801210,
251
+
433
+ },{ .name = "RPLL_FRAC_CFG", .addr = A_RPLL_FRAC_CFG,
252
+ register int x0 __asm__("x0") = sig;
434
+ .rsvd = 0x7e330000,
253
+ register void *x1 __asm__("x1") = &sa;
435
+ },{ .name = "PLL_STATUS", .addr = A_PLL_STATUS,
254
+ register void *x2 __asm__("x2") = 0;
436
+ .reset = R_PLL_STATUS_RPLL_STABLE_MASK |
255
+ register int x3 __asm__("x3") = sizeof(unsigned long);
437
+ R_PLL_STATUS_RPLL_LOCK_MASK,
256
+ register int x8 __asm__("x8") = __NR_rt_sigaction;
438
+ .rsvd = 0xfa,
257
+
439
+ .ro = 0x5,
258
+ asm volatile("svc #0"
440
+ },{ .name = "RPLL_TO_XPD_CTRL", .addr = A_RPLL_TO_XPD_CTRL,
259
+ : : "r"(x0), "r"(x1), "r"(x2), "r"(x3), "r"(x8) : "memory");
441
+ .reset = 0x2000100,
260
+}
442
+ .rsvd = 0xfdfc00ff,
261
diff --git a/tests/tcg/aarch64/Makefile.target b/tests/tcg/aarch64/Makefile.target
443
+ },{ .name = "LPD_TOP_SWITCH_CTRL", .addr = A_LPD_TOP_SWITCH_CTRL,
444
+ .reset = 0x6000300,
445
+ .rsvd = 0xf9fc00f8,
446
+ },{ .name = "LPD_LSBUS_CTRL", .addr = A_LPD_LSBUS_CTRL,
447
+ .reset = 0x2000800,
448
+ .rsvd = 0xfdfc00f8,
449
+ },{ .name = "CPU_R5_CTRL", .addr = A_CPU_R5_CTRL,
450
+ .reset = 0xe000300,
451
+ .rsvd = 0xe1fc00f8,
452
+ },{ .name = "IOU_SWITCH_CTRL", .addr = A_IOU_SWITCH_CTRL,
453
+ .reset = 0x2000500,
454
+ .rsvd = 0xfdfc00f8,
455
+ },{ .name = "GEM0_REF_CTRL", .addr = A_GEM0_REF_CTRL,
456
+ .reset = 0xe000a00,
457
+ .rsvd = 0xf1fc00f8,
458
+ },{ .name = "GEM1_REF_CTRL", .addr = A_GEM1_REF_CTRL,
459
+ .reset = 0xe000a00,
460
+ .rsvd = 0xf1fc00f8,
461
+ },{ .name = "GEM_TSU_REF_CTRL", .addr = A_GEM_TSU_REF_CTRL,
462
+ .reset = 0x300,
463
+ .rsvd = 0xfdfc00f8,
464
+ },{ .name = "USB0_BUS_REF_CTRL", .addr = A_USB0_BUS_REF_CTRL,
465
+ .reset = 0x2001900,
466
+ .rsvd = 0xfdfc00f8,
467
+ },{ .name = "UART0_REF_CTRL", .addr = A_UART0_REF_CTRL,
468
+ .reset = 0xc00,
469
+ .rsvd = 0xfdfc00f8,
470
+ },{ .name = "UART1_REF_CTRL", .addr = A_UART1_REF_CTRL,
471
+ .reset = 0xc00,
472
+ .rsvd = 0xfdfc00f8,
473
+ },{ .name = "SPI0_REF_CTRL", .addr = A_SPI0_REF_CTRL,
474
+ .reset = 0x600,
475
+ .rsvd = 0xfdfc00f8,
476
+ },{ .name = "SPI1_REF_CTRL", .addr = A_SPI1_REF_CTRL,
477
+ .reset = 0x600,
478
+ .rsvd = 0xfdfc00f8,
479
+ },{ .name = "CAN0_REF_CTRL", .addr = A_CAN0_REF_CTRL,
480
+ .reset = 0xc00,
481
+ .rsvd = 0xfdfc00f8,
482
+ },{ .name = "CAN1_REF_CTRL", .addr = A_CAN1_REF_CTRL,
483
+ .reset = 0xc00,
484
+ .rsvd = 0xfdfc00f8,
485
+ },{ .name = "I2C0_REF_CTRL", .addr = A_I2C0_REF_CTRL,
486
+ .reset = 0xc00,
487
+ .rsvd = 0xfdfc00f8,
488
+ },{ .name = "I2C1_REF_CTRL", .addr = A_I2C1_REF_CTRL,
489
+ .reset = 0xc00,
490
+ .rsvd = 0xfdfc00f8,
491
+ },{ .name = "DBG_LPD_CTRL", .addr = A_DBG_LPD_CTRL,
492
+ .reset = 0x300,
493
+ .rsvd = 0xfdfc00f8,
494
+ },{ .name = "TIMESTAMP_REF_CTRL", .addr = A_TIMESTAMP_REF_CTRL,
495
+ .reset = 0x2000c00,
496
+ .rsvd = 0xfdfc00f8,
497
+ },{ .name = "CRL_SAFETY_CHK", .addr = A_CRL_SAFETY_CHK,
498
+ },{ .name = "PSM_REF_CTRL", .addr = A_PSM_REF_CTRL,
499
+ .reset = 0xf04,
500
+ .rsvd = 0xfffc00f8,
501
+ },{ .name = "DBG_TSTMP_CTRL", .addr = A_DBG_TSTMP_CTRL,
502
+ .reset = 0x300,
503
+ .rsvd = 0xfdfc00f8,
504
+ },{ .name = "CPM_TOPSW_REF_CTRL", .addr = A_CPM_TOPSW_REF_CTRL,
505
+ .reset = 0x300,
506
+ .rsvd = 0xfdfc00f8,
507
+ },{ .name = "USB3_DUAL_REF_CTRL", .addr = A_USB3_DUAL_REF_CTRL,
508
+ .reset = 0x3c00,
509
+ .rsvd = 0xfdfc00f8,
510
+ },{ .name = "RST_CPU_R5", .addr = A_RST_CPU_R5,
511
+ .reset = 0x17,
512
+ .rsvd = 0x8,
513
+ .pre_write = crl_rst_r5_prew,
514
+ },{ .name = "RST_ADMA", .addr = A_RST_ADMA,
515
+ .reset = 0x1,
516
+ .pre_write = crl_rst_adma_prew,
517
+ },{ .name = "RST_GEM0", .addr = A_RST_GEM0,
518
+ .reset = 0x1,
519
+ .pre_write = crl_rst_gem0_prew,
520
+ },{ .name = "RST_GEM1", .addr = A_RST_GEM1,
521
+ .reset = 0x1,
522
+ .pre_write = crl_rst_gem1_prew,
523
+ },{ .name = "RST_SPARE", .addr = A_RST_SPARE,
524
+ .reset = 0x1,
525
+ },{ .name = "RST_USB0", .addr = A_RST_USB0,
526
+ .reset = 0x1,
527
+ .pre_write = crl_rst_usb_prew,
528
+ },{ .name = "RST_UART0", .addr = A_RST_UART0,
529
+ .reset = 0x1,
530
+ .pre_write = crl_rst_uart0_prew,
531
+ },{ .name = "RST_UART1", .addr = A_RST_UART1,
532
+ .reset = 0x1,
533
+ .pre_write = crl_rst_uart1_prew,
534
+ },{ .name = "RST_SPI0", .addr = A_RST_SPI0,
535
+ .reset = 0x1,
536
+ },{ .name = "RST_SPI1", .addr = A_RST_SPI1,
537
+ .reset = 0x1,
538
+ },{ .name = "RST_CAN0", .addr = A_RST_CAN0,
539
+ .reset = 0x1,
540
+ },{ .name = "RST_CAN1", .addr = A_RST_CAN1,
541
+ .reset = 0x1,
542
+ },{ .name = "RST_I2C0", .addr = A_RST_I2C0,
543
+ .reset = 0x1,
544
+ },{ .name = "RST_I2C1", .addr = A_RST_I2C1,
545
+ .reset = 0x1,
546
+ },{ .name = "RST_DBG_LPD", .addr = A_RST_DBG_LPD,
547
+ .reset = 0x33,
548
+ .rsvd = 0xcc,
549
+ },{ .name = "RST_GPIO", .addr = A_RST_GPIO,
550
+ .reset = 0x1,
551
+ },{ .name = "RST_TTC", .addr = A_RST_TTC,
552
+ .reset = 0xf,
553
+ },{ .name = "RST_TIMESTAMP", .addr = A_RST_TIMESTAMP,
554
+ .reset = 0x1,
555
+ },{ .name = "RST_SWDT", .addr = A_RST_SWDT,
556
+ .reset = 0x1,
557
+ },{ .name = "RST_OCM", .addr = A_RST_OCM,
558
+ },{ .name = "RST_IPI", .addr = A_RST_IPI,
559
+ },{ .name = "RST_FPD", .addr = A_RST_FPD,
560
+ .reset = 0x3,
561
+ },{ .name = "PSM_RST_MODE", .addr = A_PSM_RST_MODE,
562
+ .reset = 0x1,
563
+ .rsvd = 0xf8,
564
+ }
565
+};
566
+
567
+static void crl_reset_enter(Object *obj, ResetType type)
568
+{
569
+ XlnxVersalCRL *s = XLNX_VERSAL_CRL(obj);
570
+ unsigned int i;
571
+
572
+ for (i = 0; i < ARRAY_SIZE(s->regs_info); ++i) {
573
+ register_reset(&s->regs_info[i]);
574
+ }
575
+}
576
+
577
+static void crl_reset_hold(Object *obj)
578
+{
579
+ XlnxVersalCRL *s = XLNX_VERSAL_CRL(obj);
580
+
581
+ crl_update_irq(s);
582
+}
583
+
584
+static const MemoryRegionOps crl_ops = {
585
+ .read = register_read_memory,
586
+ .write = register_write_memory,
587
+ .endianness = DEVICE_LITTLE_ENDIAN,
588
+ .valid = {
589
+ .min_access_size = 4,
590
+ .max_access_size = 4,
591
+ },
592
+};
593
+
594
+static void crl_init(Object *obj)
595
+{
596
+ XlnxVersalCRL *s = XLNX_VERSAL_CRL(obj);
597
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
598
+ int i;
599
+
600
+ s->reg_array =
601
+ register_init_block32(DEVICE(obj), crl_regs_info,
602
+ ARRAY_SIZE(crl_regs_info),
603
+ s->regs_info, s->regs,
604
+ &crl_ops,
605
+ XLNX_VERSAL_CRL_ERR_DEBUG,
606
+ CRL_R_MAX * 4);
607
+ sysbus_init_mmio(sbd, &s->reg_array->mem);
608
+ sysbus_init_irq(sbd, &s->irq);
609
+
610
+ for (i = 0; i < ARRAY_SIZE(s->cfg.cpu_r5); ++i) {
611
+ object_property_add_link(obj, "cpu_r5[*]", TYPE_ARM_CPU,
612
+ (Object **)&s->cfg.cpu_r5[i],
613
+ qdev_prop_allow_set_link_before_realize,
614
+ OBJ_PROP_LINK_STRONG);
615
+ }
616
+
617
+ for (i = 0; i < ARRAY_SIZE(s->cfg.adma); ++i) {
618
+ object_property_add_link(obj, "adma[*]", TYPE_DEVICE,
619
+ (Object **)&s->cfg.adma[i],
620
+ qdev_prop_allow_set_link_before_realize,
621
+ OBJ_PROP_LINK_STRONG);
622
+ }
623
+
624
+ for (i = 0; i < ARRAY_SIZE(s->cfg.uart); ++i) {
625
+ object_property_add_link(obj, "uart[*]", TYPE_DEVICE,
626
+ (Object **)&s->cfg.uart[i],
627
+ qdev_prop_allow_set_link_before_realize,
628
+ OBJ_PROP_LINK_STRONG);
629
+ }
630
+
631
+ for (i = 0; i < ARRAY_SIZE(s->cfg.gem); ++i) {
632
+ object_property_add_link(obj, "gem[*]", TYPE_DEVICE,
633
+ (Object **)&s->cfg.gem[i],
634
+ qdev_prop_allow_set_link_before_realize,
635
+ OBJ_PROP_LINK_STRONG);
636
+ }
637
+
638
+ object_property_add_link(obj, "usb", TYPE_DEVICE,
639
+ (Object **)&s->cfg.gem[i],
640
+ qdev_prop_allow_set_link_before_realize,
641
+ OBJ_PROP_LINK_STRONG);
642
+}
643
+
644
+static void crl_finalize(Object *obj)
645
+{
646
+ XlnxVersalCRL *s = XLNX_VERSAL_CRL(obj);
647
+ register_finalize_block(s->reg_array);
648
+}
649
+
650
+static const VMStateDescription vmstate_crl = {
651
+ .name = TYPE_XLNX_VERSAL_CRL,
652
+ .version_id = 1,
653
+ .minimum_version_id = 1,
654
+ .fields = (VMStateField[]) {
655
+ VMSTATE_UINT32_ARRAY(regs, XlnxVersalCRL, CRL_R_MAX),
656
+ VMSTATE_END_OF_LIST(),
657
+ }
658
+};
659
+
660
+static void crl_class_init(ObjectClass *klass, void *data)
661
+{
662
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
663
+ DeviceClass *dc = DEVICE_CLASS(klass);
664
+
665
+ dc->vmsd = &vmstate_crl;
666
+
667
+ rc->phases.enter = crl_reset_enter;
668
+ rc->phases.hold = crl_reset_hold;
669
+}
670
+
671
+static const TypeInfo crl_info = {
672
+ .name = TYPE_XLNX_VERSAL_CRL,
673
+ .parent = TYPE_SYS_BUS_DEVICE,
674
+ .instance_size = sizeof(XlnxVersalCRL),
675
+ .class_init = crl_class_init,
676
+ .instance_init = crl_init,
677
+ .instance_finalize = crl_finalize,
678
+};
679
+
680
+static void crl_register_types(void)
681
+{
682
+ type_register_static(&crl_info);
683
+}
684
+
685
+type_init(crl_register_types)
686
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
262
index XXXXXXX..XXXXXXX 100644
687
index XXXXXXX..XXXXXXX 100644
263
--- a/tests/tcg/aarch64/Makefile.target
688
--- a/hw/misc/meson.build
264
+++ b/tests/tcg/aarch64/Makefile.target
689
+++ b/hw/misc/meson.build
265
@@ -XXX,XX +XXX,XX @@ run-pauth-%: QEMU_OPTS += -cpu max
690
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_SLAVIO', if_true: files('slavio_misc.c'))
266
run-plugin-pauth-%: QEMU_OPTS += -cpu max
691
softmmu_ss.add(when: 'CONFIG_ZYNQ', if_true: files('zynq_slcr.c'))
267
endif
692
specific_ss.add(when: 'CONFIG_XLNX_ZYNQMP_ARM', if_true: files('xlnx-zynqmp-crf.c'))
268
693
specific_ss.add(when: 'CONFIG_XLNX_ZYNQMP_ARM', if_true: files('xlnx-zynqmp-apu-ctrl.c'))
269
+# BTI Tests
694
+specific_ss.add(when: 'CONFIG_XLNX_VERSAL', if_true: files('xlnx-versal-crl.c'))
270
+# bti-1 tests the elf notes, so we require special compiler support.
695
softmmu_ss.add(when: 'CONFIG_XLNX_VERSAL', if_true: files(
271
+ifneq ($(DOCKER_IMAGE)$(CROSS_CC_HAS_ARMV8_BTI),)
696
'xlnx-versal-xramc.c',
272
+AARCH64_TESTS += bti-1
697
'xlnx-versal-pmc-iou-slcr.c',
273
+bti-1: CFLAGS += -mbranch-protection=standard
274
+bti-1: LDFLAGS += -nostdlib
275
+endif
276
+# bti-2 tests PROT_BTI, so no special compiler support required.
277
+AARCH64_TESTS += bti-2
278
+
279
# Semihosting smoke test for linux-user
280
AARCH64_TESTS += semihosting
281
run-semihosting: semihosting
282
diff --git a/tests/tcg/configure.sh b/tests/tcg/configure.sh
283
index XXXXXXX..XXXXXXX 100755
284
--- a/tests/tcg/configure.sh
285
+++ b/tests/tcg/configure.sh
286
@@ -XXX,XX +XXX,XX @@ for target in $target_list; do
287
-march=armv8.3-a -o $TMPE $TMPC; then
288
echo "CROSS_CC_HAS_ARMV8_3=y" >> $config_target_mak
289
fi
290
+ if do_compiler "$target_compiler" $target_compiler_cflags \
291
+ -mbranch-protection=standard -o $TMPE $TMPC; then
292
+ echo "CROSS_CC_HAS_ARMV8_BTI=y" >> $config_target_mak
293
+ fi
294
;;
295
esac
296
297
--
698
--
298
2.20.1
699
2.25.1
299
300
diff view generated by jsdifflib
1
v8.1M brings four new insns to M-profile:
1
From: "Edgar E. Iglesias" <edgar.iglesias@amd.com>
2
* CSEL : Rd = cond ? Rn : Rm
3
* CSINC : Rd = cond ? Rn : Rm+1
4
* CSINV : Rd = cond ? Rn : ~Rm
5
* CSNEG : Rd = cond ? Rn : -Rm
6
2
7
Implement these.
3
Connect the CRL (Clock Reset LPD) to the Versal SoC.
8
4
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>
6
Reviewed-by: Frederic Konrad <fkonrad@amd.com>
7
Reviewed-by: Francisco Iglesias <francisco.iglesias@amd.com>
8
Message-id: 20220406174303.2022038-5-edgar.iglesias@xilinx.com
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Message-id: 20201019151301.2046-4-peter.maydell@linaro.org
12
---
10
---
13
target/arm/t32.decode | 3 +++
11
include/hw/arm/xlnx-versal.h | 4 +++
14
target/arm/translate.c | 60 ++++++++++++++++++++++++++++++++++++++++++
12
hw/arm/xlnx-versal.c | 54 ++++++++++++++++++++++++++++++++++--
15
2 files changed, 63 insertions(+)
13
2 files changed, 56 insertions(+), 2 deletions(-)
16
14
17
diff --git a/target/arm/t32.decode b/target/arm/t32.decode
15
diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
18
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/t32.decode
17
--- a/include/hw/arm/xlnx-versal.h
20
+++ b/target/arm/t32.decode
18
+++ b/include/hw/arm/xlnx-versal.h
21
@@ -XXX,XX +XXX,XX @@ SBC_rrri 1110101 1011 . .... 0 ... .... .... .... @s_rrr_shi
19
@@ -XXX,XX +XXX,XX @@
20
#include "hw/nvram/xlnx-versal-efuse.h"
21
#include "hw/ssi/xlnx-versal-ospi.h"
22
#include "hw/dma/xlnx_csu_dma.h"
23
+#include "hw/misc/xlnx-versal-crl.h"
24
#include "hw/misc/xlnx-versal-pmc-iou-slcr.h"
25
26
#define TYPE_XLNX_VERSAL "xlnx-versal"
27
@@ -XXX,XX +XXX,XX @@ struct Versal {
28
qemu_or_irq irq_orgate;
29
XlnxXramCtrl ctrl[XLNX_VERSAL_NR_XRAM];
30
} xram;
31
+
32
+ XlnxVersalCRL crl;
33
} lpd;
34
35
/* The Platform Management Controller subsystem. */
36
@@ -XXX,XX +XXX,XX @@ struct Versal {
37
#define VERSAL_TIMER_NS_EL1_IRQ 14
38
#define VERSAL_TIMER_NS_EL2_IRQ 10
39
40
+#define VERSAL_CRL_IRQ 10
41
#define VERSAL_UART0_IRQ_0 18
42
#define VERSAL_UART1_IRQ_0 19
43
#define VERSAL_USB0_IRQ_0 22
44
diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
45
index XXXXXXX..XXXXXXX 100644
46
--- a/hw/arm/xlnx-versal.c
47
+++ b/hw/arm/xlnx-versal.c
48
@@ -XXX,XX +XXX,XX @@ static void versal_create_ospi(Versal *s, qemu_irq *pic)
49
qdev_connect_gpio_out(orgate, 0, pic[VERSAL_OSPI_IRQ]);
22
}
50
}
23
RSB_rrri 1110101 1110 . .... 0 ... .... .... .... @s_rrr_shi
51
24
52
+static void versal_create_crl(Versal *s, qemu_irq *pic)
25
+# v8.1M CSEL and friends
53
+{
26
+CSEL 1110101 0010 1 rn:4 10 op:2 rd:4 fcond:4 rm:4
54
+ SysBusDevice *sbd;
55
+ int i;
27
+
56
+
28
# Data-processing (register-shifted register)
57
+ object_initialize_child(OBJECT(s), "crl", &s->lpd.crl,
29
58
+ TYPE_XLNX_VERSAL_CRL);
30
MOV_rxrr 1111 1010 0 shty:2 s:1 rm:4 1111 rd:4 0000 rs:4 \
59
+ sbd = SYS_BUS_DEVICE(&s->lpd.crl);
31
diff --git a/target/arm/translate.c b/target/arm/translate.c
32
index XXXXXXX..XXXXXXX 100644
33
--- a/target/arm/translate.c
34
+++ b/target/arm/translate.c
35
@@ -XXX,XX +XXX,XX @@ static bool trans_IT(DisasContext *s, arg_IT *a)
36
return true;
37
}
38
39
+/* v8.1M CSEL/CSINC/CSNEG/CSINV */
40
+static bool trans_CSEL(DisasContext *s, arg_CSEL *a)
41
+{
42
+ TCGv_i32 rn, rm, zero;
43
+ DisasCompare c;
44
+
60
+
45
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
61
+ for (i = 0; i < ARRAY_SIZE(s->lpd.rpu.cpu); i++) {
46
+ return false;
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);
47
+ }
67
+ }
48
+
68
+
49
+ if (a->rm == 13) {
69
+ for (i = 0; i < ARRAY_SIZE(s->lpd.iou.gem); i++) {
50
+ /* SEE "Related encodings" (MVE shifts) */
70
+ g_autofree gchar *name = g_strdup_printf("gem[%d]", i);
51
+ return false;
71
+
72
+ object_property_set_link(OBJECT(&s->lpd.crl),
73
+ name, OBJECT(&s->lpd.iou.gem[i]),
74
+ &error_abort);
52
+ }
75
+ }
53
+
76
+
54
+ if (a->rd == 13 || a->rd == 15 || a->rn == 13 || a->fcond >= 14) {
77
+ for (i = 0; i < ARRAY_SIZE(s->lpd.iou.adma); i++) {
55
+ /* CONSTRAINED UNPREDICTABLE: we choose to UNDEF */
78
+ g_autofree gchar *name = g_strdup_printf("adma[%d]", i);
56
+ return false;
79
+
80
+ object_property_set_link(OBJECT(&s->lpd.crl),
81
+ name, OBJECT(&s->lpd.iou.adma[i]),
82
+ &error_abort);
57
+ }
83
+ }
58
+
84
+
59
+ /* In this insn input reg fields of 0b1111 mean "zero", not "PC" */
85
+ for (i = 0; i < ARRAY_SIZE(s->lpd.iou.uart); i++) {
60
+ if (a->rn == 15) {
86
+ g_autofree gchar *name = g_strdup_printf("uart[%d]", i);
61
+ rn = tcg_const_i32(0);
87
+
62
+ } else {
88
+ object_property_set_link(OBJECT(&s->lpd.crl),
63
+ rn = load_reg(s, a->rn);
89
+ name, OBJECT(&s->lpd.iou.uart[i]),
64
+ }
90
+ &error_abort);
65
+ if (a->rm == 15) {
66
+ rm = tcg_const_i32(0);
67
+ } else {
68
+ rm = load_reg(s, a->rm);
69
+ }
91
+ }
70
+
92
+
71
+ switch (a->op) {
93
+ object_property_set_link(OBJECT(&s->lpd.crl),
72
+ case 0: /* CSEL */
94
+ "usb", OBJECT(&s->lpd.iou.usb),
73
+ break;
95
+ &error_abort);
74
+ case 1: /* CSINC */
75
+ tcg_gen_addi_i32(rm, rm, 1);
76
+ break;
77
+ case 2: /* CSINV */
78
+ tcg_gen_not_i32(rm, rm);
79
+ break;
80
+ case 3: /* CSNEG */
81
+ tcg_gen_neg_i32(rm, rm);
82
+ break;
83
+ default:
84
+ g_assert_not_reached();
85
+ }
86
+
96
+
87
+ arm_test_cc(&c, a->fcond);
97
+ sysbus_realize(sbd, &error_fatal);
88
+ zero = tcg_const_i32(0);
98
+ memory_region_add_subregion(&s->mr_ps, MM_CRL,
89
+ tcg_gen_movcond_i32(c.cond, rn, c.value, zero, rn, rm);
99
+ sysbus_mmio_get_region(sbd, 0));
90
+ arm_free_cc(&c);
100
+ sysbus_connect_irq(sbd, 0, pic[VERSAL_CRL_IRQ]);
91
+ tcg_temp_free_i32(zero);
92
+
93
+ store_reg(s, a->rd, rn);
94
+ tcg_temp_free_i32(rm);
95
+
96
+ return true;
97
+}
101
+}
98
+
102
+
99
/*
103
/* This takes the board allocated linear DDR memory and creates aliases
100
* Legacy decoder.
104
* for each split DDR range/aperture on the Versal address map.
101
*/
105
*/
106
@@ -XXX,XX +XXX,XX @@ static void versal_unimp(Versal *s)
107
108
versal_unimp_area(s, "psm", &s->mr_ps,
109
MM_PSM_START, MM_PSM_END - MM_PSM_START);
110
- versal_unimp_area(s, "crl", &s->mr_ps,
111
- MM_CRL, MM_CRL_SIZE);
112
versal_unimp_area(s, "crf", &s->mr_ps,
113
MM_FPD_CRF, MM_FPD_CRF_SIZE);
114
versal_unimp_area(s, "apu", &s->mr_ps,
115
@@ -XXX,XX +XXX,XX @@ static void versal_realize(DeviceState *dev, Error **errp)
116
versal_create_efuse(s, pic);
117
versal_create_pmc_iou_slcr(s, pic);
118
versal_create_ospi(s, pic);
119
+ versal_create_crl(s, pic);
120
versal_map_ddr(s);
121
versal_unimp(s);
122
102
--
123
--
103
2.20.1
124
2.25.1
104
105
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
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.
2
5
3
This is slightly clearer than just using strerror, though
6
(This is a migration compatibility break, but that is OK for this
4
the different forms produced by error_setg_file_open and
7
machine type.)
5
error_setg_errno isn't entirely convenient.
6
8
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Message-id: 20201016184207.786698-10-richard.henderson@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20220404154658.565020-2-peter.maydell@linaro.org
11
---
12
---
12
linux-user/elfload.c | 15 ++++++++-------
13
include/hw/arm/exynos4210.h | 1 +
13
1 file changed, 8 insertions(+), 7 deletions(-)
14
hw/arm/exynos4210.c | 31 ++++++++++++++++---------------
15
2 files changed, 17 insertions(+), 15 deletions(-)
14
16
15
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
17
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
16
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
17
--- a/linux-user/elfload.c
19
--- a/include/hw/arm/exynos4210.h
18
+++ b/linux-user/elfload.c
20
+++ b/include/hw/arm/exynos4210.h
19
@@ -XXX,XX +XXX,XX @@ static void load_elf_interp(const char *filename, struct image_info *info,
21
@@ -XXX,XX +XXX,XX @@ struct Exynos4210State {
20
char bprm_buf[BPRM_BUF_SIZE])
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)
21
{
34
{
22
int fd, retval;
35
Exynos4210State *s = EXYNOS4210_SOC(socdev);
23
+ Error *err = NULL;
36
MemoryRegion *system_mem = get_system_memory();
24
37
- qemu_irq gate_irq[EXYNOS4210_NCPUS][EXYNOS4210_IRQ_GATE_NINPUTS];
25
fd = open(path(filename), O_RDONLY);
38
SysBusDevice *busdev;
26
if (fd < 0) {
39
DeviceState *dev, *uart[4], *pl330[3];
27
- goto exit_perror;
40
int i, n;
28
+ error_setg_file_open(&err, errno, filename);
41
@@ -XXX,XX +XXX,XX @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
29
+ error_report_err(err);
42
30
+ exit(-1);
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));
31
}
64
}
32
65
33
retval = read(fd, bprm_buf, BPRM_BUF_SIZE);
66
/* Private memory region and Internal GIC */
34
if (retval < 0) {
67
@@ -XXX,XX +XXX,XX @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
35
- goto exit_perror;
68
sysbus_realize_and_unref(busdev, &error_fatal);
36
+ error_setg_errno(&err, errno, "Error reading file header");
69
sysbus_mmio_map(busdev, 0, EXYNOS4210_SMP_PRIVATE_BASE_ADDR);
37
+ error_reportf_err(err, "%s: ", filename);
70
for (n = 0; n < EXYNOS4210_NCPUS; n++) {
38
+ exit(-1);
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);
39
}
90
}
40
+
91
+
41
if (retval < BPRM_BUF_SIZE) {
92
+ for (i = 0; i < ARRAY_SIZE(s->cpu_irq_orgate); i++) {
42
memset(bprm_buf + retval, 0, BPRM_BUF_SIZE - retval);
93
+ g_autofree char *name = g_strdup_printf("cpu-irq-orgate%d", i);
43
}
94
+ object_initialize_child(obj, name, &s->cpu_irq_orgate[i], TYPE_OR_IRQ);
44
95
+ }
45
load_elf_image(filename, fd, info, NULL, bprm_buf);
46
- return;
47
-
48
- exit_perror:
49
- fprintf(stderr, "%s: %s\n", filename, strerror(errno));
50
- exit(-1);
51
}
96
}
52
97
53
static int symfind(const void *s0, const void *s1)
98
static void exynos4210_class_init(ObjectClass *klass, void *data)
54
--
99
--
55
2.20.1
100
2.25.1
56
57
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
Now we have removed the only use of TYPE_EXYNOS4210_IRQ_GATE we can
2
delete the device entirely.
2
3
3
The IRQ values are defined few lines earlier, use them instead of
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
the magic numbers.
5
Reviewed-by: Francisco Iglesias <frasse.iglesias@gmail.com>
6
Message-id: 20220404154658.565020-3-peter.maydell@linaro.org
7
---
8
hw/intc/exynos4210_gic.c | 107 ---------------------------------------
9
1 file changed, 107 deletions(-)
5
10
6
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
11
diff --git a/hw/intc/exynos4210_gic.c b/hw/intc/exynos4210_gic.c
7
Message-id: 20201017180731.1165871-3-f4bug@amsat.org
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
hw/intc/bcm2836_control.c | 8 ++++----
12
1 file changed, 4 insertions(+), 4 deletions(-)
13
14
diff --git a/hw/intc/bcm2836_control.c b/hw/intc/bcm2836_control.c
15
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/intc/bcm2836_control.c
13
--- a/hw/intc/exynos4210_gic.c
17
+++ b/hw/intc/bcm2836_control.c
14
+++ b/hw/intc/exynos4210_gic.c
18
@@ -XXX,XX +XXX,XX @@ static void bcm2836_control_set_local_irq(void *opaque, int core, int local_irq,
15
@@ -XXX,XX +XXX,XX @@ static void exynos4210_gic_register_types(void)
19
20
static void bcm2836_control_set_local_irq0(void *opaque, int core, int level)
21
{
22
- bcm2836_control_set_local_irq(opaque, core, 0, level);
23
+ bcm2836_control_set_local_irq(opaque, core, IRQ_CNTPSIRQ, level);
24
}
16
}
25
17
26
static void bcm2836_control_set_local_irq1(void *opaque, int core, int level)
18
type_init(exynos4210_gic_register_types)
27
{
19
-
28
- bcm2836_control_set_local_irq(opaque, core, 1, level);
20
-/* IRQ OR Gate struct.
29
+ bcm2836_control_set_local_irq(opaque, core, IRQ_CNTPNSIRQ, level);
21
- *
30
}
22
- * This device models an OR gate. There are n_in input qdev gpio lines and one
31
23
- * output sysbus IRQ line. The output IRQ level is formed as OR between all
32
static void bcm2836_control_set_local_irq2(void *opaque, int core, int level)
24
- * gpio inputs.
33
{
25
- */
34
- bcm2836_control_set_local_irq(opaque, core, 2, level);
26
-
35
+ bcm2836_control_set_local_irq(opaque, core, IRQ_CNTHPIRQ, level);
27
-#define TYPE_EXYNOS4210_IRQ_GATE "exynos4210.irq_gate"
36
}
28
-OBJECT_DECLARE_SIMPLE_TYPE(Exynos4210IRQGateState, EXYNOS4210_IRQ_GATE)
37
29
-
38
static void bcm2836_control_set_local_irq3(void *opaque, int core, int level)
30
-struct Exynos4210IRQGateState {
39
{
31
- SysBusDevice parent_obj;
40
- bcm2836_control_set_local_irq(opaque, core, 3, level);
32
-
41
+ bcm2836_control_set_local_irq(opaque, core, IRQ_CNTVIRQ, level);
33
- uint32_t n_in; /* inputs amount */
42
}
34
- uint32_t *level; /* input levels */
43
35
- qemu_irq out; /* output IRQ */
44
static void bcm2836_control_set_gpu_irq(void *opaque, int irq, int level)
36
-};
37
-
38
-static Property exynos4210_irq_gate_properties[] = {
39
- DEFINE_PROP_UINT32("n_in", Exynos4210IRQGateState, n_in, 1),
40
- DEFINE_PROP_END_OF_LIST(),
41
-};
42
-
43
-static const VMStateDescription vmstate_exynos4210_irq_gate = {
44
- .name = "exynos4210.irq_gate",
45
- .version_id = 2,
46
- .minimum_version_id = 2,
47
- .fields = (VMStateField[]) {
48
- VMSTATE_VBUFFER_UINT32(level, Exynos4210IRQGateState, 1, NULL, n_in),
49
- VMSTATE_END_OF_LIST()
50
- }
51
-};
52
-
53
-/* Process a change in IRQ input. */
54
-static void exynos4210_irq_gate_handler(void *opaque, int irq, int level)
55
-{
56
- Exynos4210IRQGateState *s = (Exynos4210IRQGateState *)opaque;
57
- uint32_t i;
58
-
59
- assert(irq < s->n_in);
60
-
61
- s->level[irq] = level;
62
-
63
- for (i = 0; i < s->n_in; i++) {
64
- if (s->level[i] >= 1) {
65
- qemu_irq_raise(s->out);
66
- return;
67
- }
68
- }
69
-
70
- qemu_irq_lower(s->out);
71
-}
72
-
73
-static void exynos4210_irq_gate_reset(DeviceState *d)
74
-{
75
- Exynos4210IRQGateState *s = EXYNOS4210_IRQ_GATE(d);
76
-
77
- memset(s->level, 0, s->n_in * sizeof(*s->level));
78
-}
79
-
80
-/*
81
- * IRQ Gate initialization.
82
- */
83
-static void exynos4210_irq_gate_init(Object *obj)
84
-{
85
- Exynos4210IRQGateState *s = EXYNOS4210_IRQ_GATE(obj);
86
- SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
87
-
88
- sysbus_init_irq(sbd, &s->out);
89
-}
90
-
91
-static void exynos4210_irq_gate_realize(DeviceState *dev, Error **errp)
92
-{
93
- Exynos4210IRQGateState *s = EXYNOS4210_IRQ_GATE(dev);
94
-
95
- /* Allocate general purpose input signals and connect a handler to each of
96
- * them */
97
- qdev_init_gpio_in(dev, exynos4210_irq_gate_handler, s->n_in);
98
-
99
- s->level = g_malloc0(s->n_in * sizeof(*s->level));
100
-}
101
-
102
-static void exynos4210_irq_gate_class_init(ObjectClass *klass, void *data)
103
-{
104
- DeviceClass *dc = DEVICE_CLASS(klass);
105
-
106
- dc->reset = exynos4210_irq_gate_reset;
107
- dc->vmsd = &vmstate_exynos4210_irq_gate;
108
- device_class_set_props(dc, exynos4210_irq_gate_properties);
109
- dc->realize = exynos4210_irq_gate_realize;
110
-}
111
-
112
-static const TypeInfo exynos4210_irq_gate_info = {
113
- .name = TYPE_EXYNOS4210_IRQ_GATE,
114
- .parent = TYPE_SYS_BUS_DEVICE,
115
- .instance_size = sizeof(Exynos4210IRQGateState),
116
- .instance_init = exynos4210_irq_gate_init,
117
- .class_init = exynos4210_irq_gate_class_init,
118
-};
119
-
120
-static void exynos4210_irq_gate_register_types(void)
121
-{
122
- type_register_static(&exynos4210_irq_gate_info);
123
-}
124
-
125
-type_init(exynos4210_irq_gate_register_types)
45
--
126
--
46
2.20.1
127
2.25.1
47
48
diff view generated by jsdifflib
1
M-profile CPUs with half-precision floating point support should
1
The exynos4210 SoC mostly creates its child devices as if it were
2
be able to write to FPSCR.FZ16, but an M-profile specific masking
2
board code. This includes the a9mpcore object. Switch that to a
3
of the value at the top of vfp_set_fpscr() currently prevents that.
3
new-style "embedded in the state struct" creation, because in the
4
This is not yet an active bug because we have no M-profile
4
next commit we're going to want to refer to the object again further
5
FP16 CPUs, but needs to be fixed before we can add any.
5
down in the exynos4210_realize() function.
6
7
The bits that the masking is effectively preventing from being
8
set are the A-profile only short-vector Len and Stride fields,
9
plus the Neon QC bit. Rearrange the order of the function so
10
that those fields are handled earlier and only under a suitable
11
guard; this allows us to drop the M-profile specific masking,
12
making FZ16 writeable.
13
14
This change also makes the QC bit correctly RAZ/WI for older
15
no-Neon A-profile cores.
16
17
This refactoring also paves the way for the low-overhead-branch
18
LTPSIZE field, which uses some of the bits that are used for
19
A-profile Stride and Len.
20
6
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
22
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
23
Message-id: 20201019151301.2046-10-peter.maydell@linaro.org
9
Message-id: 20220404154658.565020-4-peter.maydell@linaro.org
24
---
10
---
25
target/arm/vfp_helper.c | 47 ++++++++++++++++++++++++-----------------
11
include/hw/arm/exynos4210.h | 2 ++
26
1 file changed, 28 insertions(+), 19 deletions(-)
12
hw/arm/exynos4210.c | 11 ++++++-----
13
2 files changed, 8 insertions(+), 5 deletions(-)
27
14
28
diff --git a/target/arm/vfp_helper.c b/target/arm/vfp_helper.c
15
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
29
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
30
--- a/target/arm/vfp_helper.c
17
--- a/include/hw/arm/exynos4210.h
31
+++ b/target/arm/vfp_helper.c
18
+++ b/include/hw/arm/exynos4210.h
32
@@ -XXX,XX +XXX,XX @@ void HELPER(vfp_set_fpscr)(CPUARMState *env, uint32_t val)
19
@@ -XXX,XX +XXX,XX @@
33
val &= ~FPCR_FZ16;
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)
34
}
40
}
35
41
36
- if (arm_feature(env, ARM_FEATURE_M)) {
42
/* Private memory region and Internal GIC */
37
+ vfp_set_fpscr_to_host(env, val);
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
}
38
+
65
+
39
+ if (!arm_feature(env, ARM_FEATURE_M)) {
66
+ object_initialize_child(obj, "a9mpcore", &s->a9mpcore, TYPE_A9MPCORE_PRIV);
40
/*
41
- * M profile FPSCR is RES0 for the QC, STRIDE, FZ16, LEN bits
42
- * and also for the trapped-exception-handling bits IxE.
43
+ * Short-vector length and stride; on M-profile these bits
44
+ * are used for different purposes.
45
+ * We can't make this conditional be "if MVFR0.FPShVec != 0",
46
+ * because in v7A no-short-vector-support cores still had to
47
+ * allow Stride/Len to be written with the only effect that
48
+ * some insns are required to UNDEF if the guest sets them.
49
+ *
50
+ * TODO: if M-profile MVE implemented, set LTPSIZE.
51
*/
52
- val &= 0xf7c0009f;
53
+ env->vfp.vec_len = extract32(val, 16, 3);
54
+ env->vfp.vec_stride = extract32(val, 20, 2);
55
}
56
57
- vfp_set_fpscr_to_host(env, val);
58
+ if (arm_feature(env, ARM_FEATURE_NEON)) {
59
+ /*
60
+ * The bit we set within fpscr_q is arbitrary; the register as a
61
+ * whole being zero/non-zero is what counts.
62
+ * TODO: M-profile MVE also has a QC bit.
63
+ */
64
+ env->vfp.qc[0] = val & FPCR_QC;
65
+ env->vfp.qc[1] = 0;
66
+ env->vfp.qc[2] = 0;
67
+ env->vfp.qc[3] = 0;
68
+ }
69
70
/*
71
* We don't implement trapped exception handling, so the
72
* trap enable bits, IDE|IXE|UFE|OFE|DZE|IOE are all RAZ/WI (not RES0!)
73
*
74
- * If we exclude the exception flags, IOC|DZC|OFC|UFC|IXC|IDC
75
- * (which are stored in fp_status), and the other RES0 bits
76
- * in between, then we clear all of the low 16 bits.
77
+ * The exception flags IOC|DZC|OFC|UFC|IXC|IDC are stored in
78
+ * fp_status; QC, Len and Stride are stored separately earlier.
79
+ * Clear out all of those and the RES0 bits: only NZCV, AHP, DN,
80
+ * FZ, RMode and FZ16 are kept in vfp.xregs[FPSCR].
81
*/
82
env->vfp.xregs[ARM_VFP_FPSCR] = val & 0xf7c80000;
83
- env->vfp.vec_len = (val >> 16) & 7;
84
- env->vfp.vec_stride = (val >> 20) & 3;
85
-
86
- /*
87
- * The bit we set within fpscr_q is arbitrary; the register as a
88
- * whole being zero/non-zero is what counts.
89
- */
90
- env->vfp.qc[0] = val & FPCR_QC;
91
- env->vfp.qc[1] = 0;
92
- env->vfp.qc[2] = 0;
93
- env->vfp.qc[3] = 0;
94
}
67
}
95
68
96
void vfp_set_fpscr(CPUARMState *env, uint32_t val)
69
static void exynos4210_class_init(ObjectClass *klass, void *data)
97
--
70
--
98
2.20.1
71
2.25.1
99
100
diff view generated by jsdifflib
1
If the M-profile low-overhead-branch extension is implemented, FPSCR
1
The only time we use the int_gic_irq[] array in the Exynos4210Irq
2
bits [18:16] are a new field LTPSIZE. If MVE is not implemented
2
struct is in the exynos4210_realize() function: we initialize it with
3
(currently always true for us) then this field always reads as 4 and
3
the GPIO inputs of the a9mpcore device, and then a bit later on we
4
ignores writes.
4
connect those to the outputs of the internal combiner. Now that the
5
5
a9mpcore object is easily accessible as s->a9mpcore we can make the
6
These bits used to be the vector-length field for the old
6
connection directly from one device to the other without going via
7
short-vector extension, so we need to take care that they are not
7
this array.
8
misinterpreted as setting vec_len. We do this with a rearrangement
9
of the vfp_set_fpscr() code that deals with vec_len, vec_stride
10
and also the QC bit; this obviates the need for the M-profile
11
only masking step that we used to have at the start of the function.
12
13
We provide a new field in CPUState for LTPSIZE, even though this
14
will always be 4, in preparation for MVE, so we don't have to
15
come back later and split it out of the vfp.xregs[FPSCR] value.
16
(This state struct field will be saved and restored as part of
17
the FPSCR value via the vmstate_fpscr in machine.c.)
18
8
19
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
20
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
21
Message-id: 20201019151301.2046-11-peter.maydell@linaro.org
11
Message-id: 20220404154658.565020-5-peter.maydell@linaro.org
22
---
12
---
23
target/arm/cpu.h | 1 +
13
include/hw/arm/exynos4210.h | 1 -
24
target/arm/cpu.c | 9 +++++++++
14
hw/arm/exynos4210.c | 6 ++----
25
target/arm/vfp_helper.c | 6 ++++++
15
2 files changed, 2 insertions(+), 5 deletions(-)
26
3 files changed, 16 insertions(+)
27
16
28
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
17
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
29
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
30
--- a/target/arm/cpu.h
19
--- a/include/hw/arm/exynos4210.h
31
+++ b/target/arm/cpu.h
20
+++ b/include/hw/arm/exynos4210.h
32
@@ -XXX,XX +XXX,XX @@ typedef struct CPUARMState {
21
@@ -XXX,XX +XXX,XX @@
33
uint32_t fpdscr[M_REG_NUM_BANKS];
22
typedef struct Exynos4210Irq {
34
uint32_t cpacr[M_REG_NUM_BANKS];
23
qemu_irq int_combiner_irq[EXYNOS4210_MAX_INT_COMBINER_IN_IRQ];
35
uint32_t nsacr;
24
qemu_irq ext_combiner_irq[EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ];
36
+ int ltpsize;
25
- qemu_irq int_gic_irq[EXYNOS4210_INT_GIC_NIRQ];
37
} v7m;
26
qemu_irq ext_gic_irq[EXYNOS4210_EXT_GIC_NIRQ];
38
27
qemu_irq board_irqs[EXYNOS4210_MAX_INT_COMBINER_IN_IRQ];
39
/* Information associated with an exception about to be taken:
28
} Exynos4210Irq;
40
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
29
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
41
index XXXXXXX..XXXXXXX 100644
30
index XXXXXXX..XXXXXXX 100644
42
--- a/target/arm/cpu.c
31
--- a/hw/arm/exynos4210.c
43
+++ b/target/arm/cpu.c
32
+++ b/hw/arm/exynos4210.c
44
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_reset(DeviceState *dev)
33
@@ -XXX,XX +XXX,XX @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
45
uint8_t *rom;
34
sysbus_connect_irq(busdev, n,
46
uint32_t vecbase;
35
qdev_get_gpio_in(DEVICE(&s->cpu_irq_orgate[n]), 0));
47
36
}
48
+ if (cpu_isar_feature(aa32_lob, cpu)) {
37
- for (n = 0; n < EXYNOS4210_INT_GIC_NIRQ; n++) {
49
+ /*
38
- s->irqs.int_gic_irq[n] = qdev_get_gpio_in(DEVICE(&s->a9mpcore), n);
50
+ * LTPSIZE is constant 4 if MVE not implemented, and resets
39
- }
51
+ * to an UNKNOWN value if MVE is implemented. We choose to
40
52
+ * always reset to 4.
41
/* Cache controller */
53
+ */
42
sysbus_create_simple("l2x0", EXYNOS4210_L2X0_BASE_ADDR, NULL);
54
+ env->v7m.ltpsize = 4;
43
@@ -XXX,XX +XXX,XX @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
55
+ }
44
busdev = SYS_BUS_DEVICE(dev);
56
+
45
sysbus_realize_and_unref(busdev, &error_fatal);
57
if (arm_feature(env, ARM_FEATURE_M_SECURITY)) {
46
for (n = 0; n < EXYNOS4210_MAX_INT_COMBINER_OUT_IRQ; n++) {
58
env->v7m.secure = true;
47
- sysbus_connect_irq(busdev, n, s->irqs.int_gic_irq[n]);
59
} else {
48
+ sysbus_connect_irq(busdev, n,
60
diff --git a/target/arm/vfp_helper.c b/target/arm/vfp_helper.c
49
+ qdev_get_gpio_in(DEVICE(&s->a9mpcore), n));
61
index XXXXXXX..XXXXXXX 100644
50
}
62
--- a/target/arm/vfp_helper.c
51
exynos4210_combiner_get_gpioin(&s->irqs, dev, 0);
63
+++ b/target/arm/vfp_helper.c
52
sysbus_mmio_map(busdev, 0, EXYNOS4210_INT_COMBINER_BASE_ADDR);
64
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(vfp_get_fpscr)(CPUARMState *env)
65
| (env->vfp.vec_len << 16)
66
| (env->vfp.vec_stride << 20);
67
68
+ /*
69
+ * M-profile LTPSIZE overlaps A-profile Stride; whichever of the
70
+ * two is not applicable to this CPU will always be zero.
71
+ */
72
+ fpscr |= env->v7m.ltpsize << 16;
73
+
74
fpscr |= vfp_get_fpscr_from_host(env);
75
76
i = env->vfp.qc[0] | env->vfp.qc[1] | env->vfp.qc[2] | env->vfp.qc[3];
77
--
53
--
78
2.20.1
54
2.25.1
79
80
diff view generated by jsdifflib
1
In arm_cpu_realizefn(), if the CPU has VFP or Neon disabled then we
1
The exynos4210 code currently has two very similar arrays of IRQs:
2
squash the ID register fields so that we don't advertise it to the
3
guest. This code was written for A-profile and needs some tweaks to
4
work correctly on M-profile:
5
2
6
* A-profile only fields should not be zeroed on M-profile:
3
* board_irqs is a field of the Exynos4210Irq struct which is filled
7
- MVFR0.FPSHVEC,FPTRAP
4
in by exynos4210_init_board_irqs() with the appropriate qemu_irqs
8
- MVFR1.SIMDLS,SIMDINT,SIMDSP,SIMDHP
5
for each IRQ the board/SoC can assert
9
- MVFR2.SIMDMISC
6
* irq_table is a set of qemu_irqs pointed to from the
10
* M-profile only fields should be zeroed on M-profile:
7
Exynos4210State struct. It's allocated in exynos4210_init_irq,
11
- MVFR1.FP16
8
and the only behaviour these irqs have is that they pass on the
9
level to the equivalent board_irqs[] irq
12
10
13
In particular, because MVFR1.SIMDHP on A-profile is the same field as
11
The extra indirection through irq_table is unnecessary, so coalesce
14
MVFR1.FP16 on M-profile this code was incorrectly disabling FP16
12
these into a single irq_table[] array as a direct field in
15
support on an M-profile CPU (where has_neon is always false). This
13
Exynos4210State which exynos4210_init_board_irqs() fills in.
16
isn't a visible bug yet because we don't have any M-profile CPUs with
17
FP16 support, but the change is necessary before we introduce any.
18
14
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
16
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
20
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
Message-id: 20220404154658.565020-6-peter.maydell@linaro.org
21
Message-id: 20201019151301.2046-9-peter.maydell@linaro.org
22
---
18
---
23
target/arm/cpu.c | 29 ++++++++++++++++++-----------
19
include/hw/arm/exynos4210.h | 8 ++------
24
1 file changed, 18 insertions(+), 11 deletions(-)
20
hw/arm/exynos4210.c | 6 +-----
21
hw/intc/exynos4210_gic.c | 32 ++++++++------------------------
22
3 files changed, 11 insertions(+), 35 deletions(-)
25
23
26
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
24
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
27
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
28
--- a/target/arm/cpu.c
26
--- a/include/hw/arm/exynos4210.h
29
+++ b/target/arm/cpu.c
27
+++ b/include/hw/arm/exynos4210.h
30
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
28
@@ -XXX,XX +XXX,XX @@ typedef struct Exynos4210Irq {
31
u = cpu->isar.mvfr0;
29
qemu_irq int_combiner_irq[EXYNOS4210_MAX_INT_COMBINER_IN_IRQ];
32
u = FIELD_DP32(u, MVFR0, FPSP, 0);
30
qemu_irq ext_combiner_irq[EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ];
33
u = FIELD_DP32(u, MVFR0, FPDP, 0);
31
qemu_irq ext_gic_irq[EXYNOS4210_EXT_GIC_NIRQ];
34
- u = FIELD_DP32(u, MVFR0, FPTRAP, 0);
32
- qemu_irq board_irqs[EXYNOS4210_MAX_INT_COMBINER_IN_IRQ];
35
u = FIELD_DP32(u, MVFR0, FPDIVIDE, 0);
33
} Exynos4210Irq;
36
u = FIELD_DP32(u, MVFR0, FPSQRT, 0);
34
37
- u = FIELD_DP32(u, MVFR0, FPSHVEC, 0);
35
struct Exynos4210State {
38
u = FIELD_DP32(u, MVFR0, FPROUND, 0);
36
@@ -XXX,XX +XXX,XX @@ struct Exynos4210State {
39
+ if (!arm_feature(env, ARM_FEATURE_M)) {
37
/*< public >*/
40
+ u = FIELD_DP32(u, MVFR0, FPTRAP, 0);
38
ARMCPU *cpu[EXYNOS4210_NCPUS];
41
+ u = FIELD_DP32(u, MVFR0, FPSHVEC, 0);
39
Exynos4210Irq irqs;
42
+ }
40
- qemu_irq *irq_table;
43
cpu->isar.mvfr0 = u;
41
+ qemu_irq irq_table[EXYNOS4210_MAX_INT_COMBINER_IN_IRQ];
44
42
45
u = cpu->isar.mvfr1;
43
MemoryRegion chipid_mem;
46
u = FIELD_DP32(u, MVFR1, FPFTZ, 0);
44
MemoryRegion iram_mem;
47
u = FIELD_DP32(u, MVFR1, FPDNAN, 0);
45
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_SIMPLE_TYPE(Exynos4210State, EXYNOS4210_SOC)
48
u = FIELD_DP32(u, MVFR1, FPHP, 0);
46
void exynos4210_write_secondary(ARMCPU *cpu,
49
+ if (arm_feature(env, ARM_FEATURE_M)) {
47
const struct arm_boot_info *info);
50
+ u = FIELD_DP32(u, MVFR1, FP16, 0);
48
51
+ }
49
-/* Initialize exynos4210 IRQ subsystem stub */
52
cpu->isar.mvfr1 = u;
50
-qemu_irq *exynos4210_init_irq(Exynos4210Irq *env);
53
51
-
54
u = cpu->isar.mvfr2;
52
/* Initialize board IRQs.
55
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
53
* These IRQs contain splitted Int/External Combiner and External Gic IRQs */
56
u = FIELD_DP32(u, ID_ISAR6, FHM, 0);
54
-void exynos4210_init_board_irqs(Exynos4210Irq *s);
57
cpu->isar.id_isar6 = u;
55
+void exynos4210_init_board_irqs(Exynos4210State *s);
58
56
59
- u = cpu->isar.mvfr1;
57
/* Get IRQ number from exynos4210 IRQ subsystem stub.
60
- u = FIELD_DP32(u, MVFR1, SIMDLS, 0);
58
* To identify IRQ source use internal combiner group and bit number
61
- u = FIELD_DP32(u, MVFR1, SIMDINT, 0);
59
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
62
- u = FIELD_DP32(u, MVFR1, SIMDSP, 0);
60
index XXXXXXX..XXXXXXX 100644
63
- u = FIELD_DP32(u, MVFR1, SIMDHP, 0);
61
--- a/hw/arm/exynos4210.c
64
- cpu->isar.mvfr1 = u;
62
+++ b/hw/arm/exynos4210.c
65
+ if (!arm_feature(env, ARM_FEATURE_M)) {
63
@@ -XXX,XX +XXX,XX @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
66
+ u = cpu->isar.mvfr1;
64
qdev_realize(DEVICE(cpuobj), NULL, &error_fatal);
67
+ u = FIELD_DP32(u, MVFR1, SIMDLS, 0);
68
+ u = FIELD_DP32(u, MVFR1, SIMDINT, 0);
69
+ u = FIELD_DP32(u, MVFR1, SIMDSP, 0);
70
+ u = FIELD_DP32(u, MVFR1, SIMDHP, 0);
71
+ cpu->isar.mvfr1 = u;
72
73
- u = cpu->isar.mvfr2;
74
- u = FIELD_DP32(u, MVFR2, SIMDMISC, 0);
75
- cpu->isar.mvfr2 = u;
76
+ u = cpu->isar.mvfr2;
77
+ u = FIELD_DP32(u, MVFR2, SIMDMISC, 0);
78
+ cpu->isar.mvfr2 = u;
79
+ }
80
}
65
}
81
66
82
if (!cpu->has_neon && !cpu->has_vfp) {
67
- /*** IRQs ***/
68
-
69
- s->irq_table = exynos4210_init_irq(&s->irqs);
70
-
71
/* IRQ Gate */
72
for (i = 0; i < EXYNOS4210_NCPUS; i++) {
73
DeviceState *orgate = DEVICE(&s->cpu_irq_orgate[i]);
74
@@ -XXX,XX +XXX,XX @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
75
sysbus_mmio_map(busdev, 0, EXYNOS4210_EXT_COMBINER_BASE_ADDR);
76
77
/* Initialize board IRQs. */
78
- exynos4210_init_board_irqs(&s->irqs);
79
+ exynos4210_init_board_irqs(s);
80
81
/*** Memory ***/
82
83
diff --git a/hw/intc/exynos4210_gic.c b/hw/intc/exynos4210_gic.c
84
index XXXXXXX..XXXXXXX 100644
85
--- a/hw/intc/exynos4210_gic.c
86
+++ b/hw/intc/exynos4210_gic.c
87
@@ -XXX,XX +XXX,XX @@ combiner_grp_to_gic_id[64-EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][8] = {
88
#define EXYNOS4210_GIC_CPU_REGION_SIZE 0x100
89
#define EXYNOS4210_GIC_DIST_REGION_SIZE 0x1000
90
91
-static void exynos4210_irq_handler(void *opaque, int irq, int level)
92
-{
93
- Exynos4210Irq *s = (Exynos4210Irq *)opaque;
94
-
95
- /* Bypass */
96
- qemu_set_irq(s->board_irqs[irq], level);
97
-}
98
-
99
-/*
100
- * Initialize exynos4210 IRQ subsystem stub.
101
- */
102
-qemu_irq *exynos4210_init_irq(Exynos4210Irq *s)
103
-{
104
- return qemu_allocate_irqs(exynos4210_irq_handler, s,
105
- EXYNOS4210_MAX_INT_COMBINER_IN_IRQ);
106
-}
107
-
108
/*
109
* Initialize board IRQs.
110
* These IRQs contain splitted Int/External Combiner and External Gic IRQs.
111
*/
112
-void exynos4210_init_board_irqs(Exynos4210Irq *s)
113
+void exynos4210_init_board_irqs(Exynos4210State *s)
114
{
115
uint32_t grp, bit, irq_id, n;
116
+ Exynos4210Irq *is = &s->irqs;
117
118
for (n = 0; n < EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ; n++) {
119
irq_id = 0;
120
@@ -XXX,XX +XXX,XX @@ void exynos4210_init_board_irqs(Exynos4210Irq *s)
121
irq_id = EXT_GIC_ID_MCT_G1;
122
}
123
if (irq_id) {
124
- s->board_irqs[n] = qemu_irq_split(s->int_combiner_irq[n],
125
- s->ext_gic_irq[irq_id-32]);
126
+ s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
127
+ is->ext_gic_irq[irq_id - 32]);
128
} else {
129
- s->board_irqs[n] = qemu_irq_split(s->int_combiner_irq[n],
130
- s->ext_combiner_irq[n]);
131
+ s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
132
+ is->ext_combiner_irq[n]);
133
}
134
}
135
for (; n < EXYNOS4210_MAX_INT_COMBINER_IN_IRQ; n++) {
136
@@ -XXX,XX +XXX,XX @@ void exynos4210_init_board_irqs(Exynos4210Irq *s)
137
EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][bit];
138
139
if (irq_id) {
140
- s->board_irqs[n] = qemu_irq_split(s->int_combiner_irq[n],
141
- s->ext_gic_irq[irq_id-32]);
142
+ s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
143
+ is->ext_gic_irq[irq_id - 32]);
144
}
145
}
146
}
83
--
147
--
84
2.20.1
148
2.25.1
85
86
diff view generated by jsdifflib
1
For nested groups like:
1
Fix a missing set of spaces around '-' in the definition of
2
combiner_grp_to_gic_id[]. We're about to move this code, so
3
fix the style issue first to keep checkpatch happy with the
4
code-motion patch.
2
5
3
{
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
[
5
pattern 1
6
pattern 2
7
]
8
pattern 3
9
}
10
11
the intended behaviour is that patterns 1 and 2 must not
12
overlap with each other; if the insn matches neither then
13
we fall through to pattern 3 as the next thing in the
14
outer overlapping group.
15
16
Currently we generate incorrect code for this situation,
17
because in the code path for a failed match inside the
18
inner non-overlapping group we generate a "return" statement,
19
which causes decode to stop entirely rather than continuing
20
to the next thing in the outer group.
21
22
Generate a "break" instead, so that decode flow behaves
23
as required for this nested group case.
24
25
Suggested-by: Richard Henderson <richard.henderson@linaro.org>
26
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
27
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Message-id: 20220404154658.565020-7-peter.maydell@linaro.org
28
Message-id: 20201019151301.2046-2-peter.maydell@linaro.org
29
---
9
---
30
scripts/decodetree.py | 2 +-
10
hw/intc/exynos4210_gic.c | 2 +-
31
1 file changed, 1 insertion(+), 1 deletion(-)
11
1 file changed, 1 insertion(+), 1 deletion(-)
32
12
33
diff --git a/scripts/decodetree.py b/scripts/decodetree.py
13
diff --git a/hw/intc/exynos4210_gic.c b/hw/intc/exynos4210_gic.c
34
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
35
--- a/scripts/decodetree.py
15
--- a/hw/intc/exynos4210_gic.c
36
+++ b/scripts/decodetree.py
16
+++ b/hw/intc/exynos4210_gic.c
37
@@ -XXX,XX +XXX,XX @@ class Tree:
17
@@ -XXX,XX +XXX,XX @@ enum ExtInt {
38
output(ind, ' /* ',
18
*/
39
str_match_bits(innerbits, innermask), ' */\n')
19
40
s.output_code(i + 4, extracted, innerbits, innermask)
20
static const uint32_t
41
- output(ind, ' return false;\n')
21
-combiner_grp_to_gic_id[64-EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][8] = {
42
+ output(ind, ' break;\n')
22
+combiner_grp_to_gic_id[64 - EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][8] = {
43
output(ind, '}\n')
23
/* int combiner groups 16-19 */
44
# end Tree
24
{ }, { }, { }, { },
45
25
/* int combiner group 20 */
46
--
26
--
47
2.20.1
27
2.25.1
48
49
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
The function exynos4210_init_board_irqs() currently lives in
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.
2
8
3
This is generic support, with the code disabled for all targets.
9
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
---
13
include/hw/arm/exynos4210.h | 4 -
14
hw/arm/exynos4210.c | 202 +++++++++++++++++++++++++++++++++++
15
hw/intc/exynos4210_gic.c | 204 ------------------------------------
16
3 files changed, 202 insertions(+), 208 deletions(-)
4
17
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
18
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
6
Message-id: 20201016184207.786698-11-richard.henderson@linaro.org
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
linux-user/qemu.h | 4 ++
11
linux-user/elfload.c | 157 +++++++++++++++++++++++++++++++++++++++++++
12
2 files changed, 161 insertions(+)
13
14
diff --git a/linux-user/qemu.h b/linux-user/qemu.h
15
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
16
--- a/linux-user/qemu.h
20
--- a/include/hw/arm/exynos4210.h
17
+++ b/linux-user/qemu.h
21
+++ b/include/hw/arm/exynos4210.h
18
@@ -XXX,XX +XXX,XX @@ struct image_info {
22
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_SIMPLE_TYPE(Exynos4210State, EXYNOS4210_SOC)
19
abi_ulong interpreter_loadmap_addr;
23
void exynos4210_write_secondary(ARMCPU *cpu,
20
abi_ulong interpreter_pt_dynamic_addr;
24
const struct arm_boot_info *info);
21
struct image_info *other_info;
25
22
+
26
-/* Initialize board IRQs.
23
+ /* For target-specific processing of NT_GNU_PROPERTY_TYPE_0. */
27
- * These IRQs contain splitted Int/External Combiner and External Gic IRQs */
24
+ uint32_t note_flags;
28
-void exynos4210_init_board_irqs(Exynos4210State *s);
25
+
29
-
26
#ifdef TARGET_MIPS
30
/* Get IRQ number from exynos4210 IRQ subsystem stub.
27
int fp_abi;
31
* To identify IRQ source use internal combiner group and bit number
28
int interp_fp_abi;
32
* grp - group number
29
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
33
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
30
index XXXXXXX..XXXXXXX 100644
34
index XXXXXXX..XXXXXXX 100644
31
--- a/linux-user/elfload.c
35
--- a/hw/arm/exynos4210.c
32
+++ b/linux-user/elfload.c
36
+++ b/hw/arm/exynos4210.c
33
@@ -XXX,XX +XXX,XX @@ static void elf_core_copy_regs(target_elf_gregset_t *regs,
37
@@ -XXX,XX +XXX,XX @@
34
38
#define EXYNOS4210_PL330_BASE1_ADDR 0x12690000
35
#include "elf.h"
39
#define EXYNOS4210_PL330_BASE2_ADDR 0x12850000
36
40
37
+static bool arch_parse_elf_property(uint32_t pr_type, uint32_t pr_datasz,
41
+enum ExtGicId {
38
+ const uint32_t *data,
42
+ EXT_GIC_ID_MDMA_LCD0 = 66,
39
+ struct image_info *info,
43
+ EXT_GIC_ID_PDMA0,
40
+ Error **errp)
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
+
125
+/*
126
+ * External GIC sources which are not from External Interrupt Combiner or
127
+ * External Interrupts are starting from EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ,
128
+ * which is INTG16 in Internal Interrupt Combiner.
129
+ */
130
+
131
+static const uint32_t
132
+combiner_grp_to_gic_id[64 - EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][8] = {
133
+ /* int combiner groups 16-19 */
134
+ { }, { }, { }, { },
135
+ /* int combiner group 20 */
136
+ { 0, EXT_GIC_ID_MDMA_LCD0 },
137
+ /* int combiner group 21 */
138
+ { EXT_GIC_ID_PDMA0, EXT_GIC_ID_PDMA1 },
139
+ /* int combiner group 22 */
140
+ { EXT_GIC_ID_TIMER0, EXT_GIC_ID_TIMER1, EXT_GIC_ID_TIMER2,
141
+ EXT_GIC_ID_TIMER3, EXT_GIC_ID_TIMER4 },
142
+ /* int combiner group 23 */
143
+ { EXT_GIC_ID_RTC_ALARM, EXT_GIC_ID_RTC_TIC },
144
+ /* int combiner group 24 */
145
+ { EXT_GIC_ID_GPIO_XB, EXT_GIC_ID_GPIO_XA },
146
+ /* int combiner group 25 */
147
+ { EXT_GIC_ID_IEM_APC, EXT_GIC_ID_IEM_IEC },
148
+ /* int combiner group 26 */
149
+ { EXT_GIC_ID_UART0, EXT_GIC_ID_UART1, EXT_GIC_ID_UART2, EXT_GIC_ID_UART3,
150
+ EXT_GIC_ID_UART4 },
151
+ /* int combiner group 27 */
152
+ { EXT_GIC_ID_I2C0, EXT_GIC_ID_I2C1, EXT_GIC_ID_I2C2, EXT_GIC_ID_I2C3,
153
+ EXT_GIC_ID_I2C4, EXT_GIC_ID_I2C5, EXT_GIC_ID_I2C6,
154
+ EXT_GIC_ID_I2C7 },
155
+ /* int combiner group 28 */
156
+ { EXT_GIC_ID_SPI0, EXT_GIC_ID_SPI1, EXT_GIC_ID_SPI2 , EXT_GIC_ID_USB_HOST},
157
+ /* int combiner group 29 */
158
+ { EXT_GIC_ID_HSMMC0, EXT_GIC_ID_HSMMC1, EXT_GIC_ID_HSMMC2,
159
+ EXT_GIC_ID_HSMMC3, EXT_GIC_ID_SDMMC },
160
+ /* int combiner group 30 */
161
+ { EXT_GIC_ID_MIPI_CSI_4LANE, EXT_GIC_ID_MIPI_CSI_2LANE },
162
+ /* int combiner group 31 */
163
+ { EXT_GIC_ID_MIPI_DSI_4LANE, EXT_GIC_ID_MIPI_DSI_2LANE },
164
+ /* int combiner group 32 */
165
+ { EXT_GIC_ID_FIMC0, EXT_GIC_ID_FIMC1 },
166
+ /* int combiner group 33 */
167
+ { EXT_GIC_ID_FIMC2, EXT_GIC_ID_FIMC3 },
168
+ /* int combiner group 34 */
169
+ { EXT_GIC_ID_ONENAND_AUDI, EXT_GIC_ID_NFC },
170
+ /* int combiner group 35 */
171
+ { 0, 0, 0, EXT_GIC_ID_MCT_L1, EXT_GIC_ID_MCT_G0, EXT_GIC_ID_MCT_G1 },
172
+ /* int combiner group 36 */
173
+ { EXT_GIC_ID_MIXER },
174
+ /* int combiner group 37 */
175
+ { EXT_GIC_ID_EXTINT4, EXT_GIC_ID_EXTINT5, EXT_GIC_ID_EXTINT6,
176
+ EXT_GIC_ID_EXTINT7 },
177
+ /* groups 38-50 */
178
+ { }, { }, { }, { }, { }, { }, { }, { }, { }, { }, { }, { }, { },
179
+ /* int combiner group 51 */
180
+ { EXT_GIC_ID_MCT_L0, 0, 0, 0, EXT_GIC_ID_MCT_G0, EXT_GIC_ID_MCT_G1 },
181
+ /* group 52 */
182
+ { },
183
+ /* int combiner group 53 */
184
+ { EXT_GIC_ID_WDT, 0, 0, 0, EXT_GIC_ID_MCT_G0, EXT_GIC_ID_MCT_G1 },
185
+ /* groups 54-63 */
186
+ { }, { }, { }, { }, { }, { }, { }, { }, { }, { }
187
+};
188
+
189
+/*
190
+ * Initialize board IRQs.
191
+ * These IRQs contain splitted Int/External Combiner and External Gic IRQs.
192
+ */
193
+static void exynos4210_init_board_irqs(Exynos4210State *s)
41
+{
194
+{
42
+ g_assert_not_reached();
195
+ uint32_t grp, bit, irq_id, n;
43
+}
196
+ Exynos4210Irq *is = &s->irqs;
44
+#define ARCH_USE_GNU_PROPERTY 0
197
+
45
+
198
+ for (n = 0; n < EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ; n++) {
46
struct exec
199
+ irq_id = 0;
47
{
200
+ if (n == EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 4) ||
48
unsigned int a_info; /* Use macros N_MAGIC, etc for access */
201
+ n == EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 4)) {
49
@@ -XXX,XX +XXX,XX @@ void probe_guest_base(const char *image_name, abi_ulong guest_loaddr,
202
+ /* MCT_G0 is passed to External GIC */
50
"@ 0x%" PRIx64 "\n", (uint64_t)guest_base);
203
+ irq_id = EXT_GIC_ID_MCT_G0;
51
}
204
+ }
52
205
+ if (n == EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 5) ||
53
+enum {
206
+ n == EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 5)) {
54
+ /* The string "GNU\0" as a magic number. */
207
+ /* MCT_G1 is passed to External and GIC */
55
+ GNU0_MAGIC = const_le32('G' | 'N' << 8 | 'U' << 16),
208
+ irq_id = EXT_GIC_ID_MCT_G1;
56
+ NOTE_DATA_SZ = 1 * KiB,
209
+ }
57
+ NOTE_NAME_SZ = 4,
210
+ if (irq_id) {
58
+ ELF_GNU_PROPERTY_ALIGN = ELF_CLASS == ELFCLASS32 ? 4 : 8,
211
+ s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
59
+};
212
+ is->ext_gic_irq[irq_id - 32]);
60
+
61
+/*
62
+ * Process a single gnu_property entry.
63
+ * Return false for error.
64
+ */
65
+static bool parse_elf_property(const uint32_t *data, int *off, int datasz,
66
+ struct image_info *info, bool have_prev_type,
67
+ uint32_t *prev_type, Error **errp)
68
+{
69
+ uint32_t pr_type, pr_datasz, step;
70
+
71
+ if (*off > datasz || !QEMU_IS_ALIGNED(*off, ELF_GNU_PROPERTY_ALIGN)) {
72
+ goto error_data;
73
+ }
74
+ datasz -= *off;
75
+ data += *off / sizeof(uint32_t);
76
+
77
+ if (datasz < 2 * sizeof(uint32_t)) {
78
+ goto error_data;
79
+ }
80
+ pr_type = data[0];
81
+ pr_datasz = data[1];
82
+ data += 2;
83
+ datasz -= 2 * sizeof(uint32_t);
84
+ step = ROUND_UP(pr_datasz, ELF_GNU_PROPERTY_ALIGN);
85
+ if (step > datasz) {
86
+ goto error_data;
87
+ }
88
+
89
+ /* Properties are supposed to be unique and sorted on pr_type. */
90
+ if (have_prev_type && pr_type <= *prev_type) {
91
+ if (pr_type == *prev_type) {
92
+ error_setg(errp, "Duplicate property in PT_GNU_PROPERTY");
93
+ } else {
213
+ } else {
94
+ error_setg(errp, "Unsorted property in PT_GNU_PROPERTY");
214
+ s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
95
+ }
215
+ is->ext_combiner_irq[n]);
96
+ return false;
97
+ }
98
+ *prev_type = pr_type;
99
+
100
+ if (!arch_parse_elf_property(pr_type, pr_datasz, data, info, errp)) {
101
+ return false;
102
+ }
103
+
104
+ *off += 2 * sizeof(uint32_t) + step;
105
+ return true;
106
+
107
+ error_data:
108
+ error_setg(errp, "Ill-formed property in PT_GNU_PROPERTY");
109
+ return false;
110
+}
111
+
112
+/* Process NT_GNU_PROPERTY_TYPE_0. */
113
+static bool parse_elf_properties(int image_fd,
114
+ struct image_info *info,
115
+ const struct elf_phdr *phdr,
116
+ char bprm_buf[BPRM_BUF_SIZE],
117
+ Error **errp)
118
+{
119
+ union {
120
+ struct elf_note nhdr;
121
+ uint32_t data[NOTE_DATA_SZ / sizeof(uint32_t)];
122
+ } note;
123
+
124
+ int n, off, datasz;
125
+ bool have_prev_type;
126
+ uint32_t prev_type;
127
+
128
+ /* Unless the arch requires properties, ignore them. */
129
+ if (!ARCH_USE_GNU_PROPERTY) {
130
+ return true;
131
+ }
132
+
133
+ /* If the properties are crazy large, that's too bad. */
134
+ n = phdr->p_filesz;
135
+ if (n > sizeof(note)) {
136
+ error_setg(errp, "PT_GNU_PROPERTY too large");
137
+ return false;
138
+ }
139
+ if (n < sizeof(note.nhdr)) {
140
+ error_setg(errp, "PT_GNU_PROPERTY too small");
141
+ return false;
142
+ }
143
+
144
+ if (phdr->p_offset + n <= BPRM_BUF_SIZE) {
145
+ memcpy(&note, bprm_buf + phdr->p_offset, n);
146
+ } else {
147
+ ssize_t len = pread(image_fd, &note, n, phdr->p_offset);
148
+ if (len != n) {
149
+ error_setg_errno(errp, errno, "Error reading file header");
150
+ return false;
151
+ }
216
+ }
152
+ }
217
+ }
153
+
218
+ for (; n < EXYNOS4210_MAX_INT_COMBINER_IN_IRQ; n++) {
154
+ /*
219
+ /* these IDs are passed to Internal Combiner and External GIC */
155
+ * The contents of a valid PT_GNU_PROPERTY is a sequence
220
+ grp = EXYNOS4210_COMBINER_GET_GRP_NUM(n);
156
+ * of uint32_t -- swap them all now.
221
+ bit = EXYNOS4210_COMBINER_GET_BIT_NUM(n);
157
+ */
222
+ irq_id = combiner_grp_to_gic_id[grp -
158
+#ifdef BSWAP_NEEDED
223
+ EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][bit];
159
+ for (int i = 0; i < n / 4; i++) {
224
+
160
+ bswap32s(note.data + i);
225
+ if (irq_id) {
161
+ }
226
+ s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
162
+#endif
227
+ is->ext_gic_irq[irq_id - 32]);
163
+
164
+ /*
165
+ * Note that nhdr is 3 words, and that the "name" described by namesz
166
+ * immediately follows nhdr and is thus at the 4th word. Further, all
167
+ * of the inputs to the kernel's round_up are multiples of 4.
168
+ */
169
+ if (note.nhdr.n_type != NT_GNU_PROPERTY_TYPE_0 ||
170
+ note.nhdr.n_namesz != NOTE_NAME_SZ ||
171
+ note.data[3] != GNU0_MAGIC) {
172
+ error_setg(errp, "Invalid note in PT_GNU_PROPERTY");
173
+ return false;
174
+ }
175
+ off = sizeof(note.nhdr) + NOTE_NAME_SZ;
176
+
177
+ datasz = note.nhdr.n_descsz + off;
178
+ if (datasz > n) {
179
+ error_setg(errp, "Invalid note size in PT_GNU_PROPERTY");
180
+ return false;
181
+ }
182
+
183
+ have_prev_type = false;
184
+ prev_type = 0;
185
+ while (1) {
186
+ if (off == datasz) {
187
+ return true; /* end, exit ok */
188
+ }
228
+ }
189
+ if (!parse_elf_property(note.data, &off, datasz, info,
190
+ have_prev_type, &prev_type, errp)) {
191
+ return false;
192
+ }
193
+ have_prev_type = true;
194
+ }
229
+ }
195
+}
230
+}
196
+
231
+
197
/* Load an ELF image into the address space.
232
+/*
198
233
+ * Get IRQ number from exynos4210 IRQ subsystem stub.
199
IMAGE_NAME is the filename of the image, to use in error messages.
234
+ * To identify IRQ source use internal combiner group and bit number
200
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
235
+ * grp - group number
201
goto exit_errmsg;
236
+ * bit - bit number inside group
202
}
237
+ */
203
*pinterp_name = g_steal_pointer(&interp_name);
238
+uint32_t exynos4210_get_irq(uint32_t grp, uint32_t bit)
204
+ } else if (eppnt->p_type == PT_GNU_PROPERTY) {
239
+{
205
+ if (!parse_elf_properties(image_fd, info, eppnt, bprm_buf, &err)) {
240
+ return EXYNOS4210_COMBINER_GET_IRQ_NUM(grp, bit);
206
+ goto exit_errmsg;
241
+}
207
+ }
242
+
208
}
243
static uint8_t chipid_and_omr[] = { 0x11, 0x02, 0x21, 0x43,
209
}
244
0x09, 0x00, 0x00, 0x00 };
245
246
diff --git a/hw/intc/exynos4210_gic.c b/hw/intc/exynos4210_gic.c
247
index XXXXXXX..XXXXXXX 100644
248
--- a/hw/intc/exynos4210_gic.c
249
+++ b/hw/intc/exynos4210_gic.c
250
@@ -XXX,XX +XXX,XX @@
251
#include "hw/arm/exynos4210.h"
252
#include "qom/object.h"
253
254
-enum ExtGicId {
255
- EXT_GIC_ID_MDMA_LCD0 = 66,
256
- EXT_GIC_ID_PDMA0,
257
- EXT_GIC_ID_PDMA1,
258
- EXT_GIC_ID_TIMER0,
259
- EXT_GIC_ID_TIMER1,
260
- EXT_GIC_ID_TIMER2,
261
- EXT_GIC_ID_TIMER3,
262
- EXT_GIC_ID_TIMER4,
263
- EXT_GIC_ID_MCT_L0,
264
- EXT_GIC_ID_WDT,
265
- EXT_GIC_ID_RTC_ALARM,
266
- EXT_GIC_ID_RTC_TIC,
267
- EXT_GIC_ID_GPIO_XB,
268
- EXT_GIC_ID_GPIO_XA,
269
- EXT_GIC_ID_MCT_L1,
270
- EXT_GIC_ID_IEM_APC,
271
- EXT_GIC_ID_IEM_IEC,
272
- EXT_GIC_ID_NFC,
273
- EXT_GIC_ID_UART0,
274
- EXT_GIC_ID_UART1,
275
- EXT_GIC_ID_UART2,
276
- EXT_GIC_ID_UART3,
277
- EXT_GIC_ID_UART4,
278
- EXT_GIC_ID_MCT_G0,
279
- EXT_GIC_ID_I2C0,
280
- EXT_GIC_ID_I2C1,
281
- EXT_GIC_ID_I2C2,
282
- EXT_GIC_ID_I2C3,
283
- EXT_GIC_ID_I2C4,
284
- EXT_GIC_ID_I2C5,
285
- EXT_GIC_ID_I2C6,
286
- EXT_GIC_ID_I2C7,
287
- EXT_GIC_ID_SPI0,
288
- EXT_GIC_ID_SPI1,
289
- EXT_GIC_ID_SPI2,
290
- EXT_GIC_ID_MCT_G1,
291
- EXT_GIC_ID_USB_HOST,
292
- EXT_GIC_ID_USB_DEVICE,
293
- EXT_GIC_ID_MODEMIF,
294
- EXT_GIC_ID_HSMMC0,
295
- EXT_GIC_ID_HSMMC1,
296
- EXT_GIC_ID_HSMMC2,
297
- EXT_GIC_ID_HSMMC3,
298
- EXT_GIC_ID_SDMMC,
299
- EXT_GIC_ID_MIPI_CSI_4LANE,
300
- EXT_GIC_ID_MIPI_DSI_4LANE,
301
- EXT_GIC_ID_MIPI_CSI_2LANE,
302
- EXT_GIC_ID_MIPI_DSI_2LANE,
303
- EXT_GIC_ID_ONENAND_AUDI,
304
- EXT_GIC_ID_ROTATOR,
305
- EXT_GIC_ID_FIMC0,
306
- EXT_GIC_ID_FIMC1,
307
- EXT_GIC_ID_FIMC2,
308
- EXT_GIC_ID_FIMC3,
309
- EXT_GIC_ID_JPEG,
310
- EXT_GIC_ID_2D,
311
- EXT_GIC_ID_PCIe,
312
- EXT_GIC_ID_MIXER,
313
- EXT_GIC_ID_HDMI,
314
- EXT_GIC_ID_HDMI_I2C,
315
- EXT_GIC_ID_MFC,
316
- EXT_GIC_ID_TVENC,
317
-};
318
-
319
-enum ExtInt {
320
- EXT_GIC_ID_EXTINT0 = 48,
321
- EXT_GIC_ID_EXTINT1,
322
- EXT_GIC_ID_EXTINT2,
323
- EXT_GIC_ID_EXTINT3,
324
- EXT_GIC_ID_EXTINT4,
325
- EXT_GIC_ID_EXTINT5,
326
- EXT_GIC_ID_EXTINT6,
327
- EXT_GIC_ID_EXTINT7,
328
- EXT_GIC_ID_EXTINT8,
329
- EXT_GIC_ID_EXTINT9,
330
- EXT_GIC_ID_EXTINT10,
331
- EXT_GIC_ID_EXTINT11,
332
- EXT_GIC_ID_EXTINT12,
333
- EXT_GIC_ID_EXTINT13,
334
- EXT_GIC_ID_EXTINT14,
335
- EXT_GIC_ID_EXTINT15
336
-};
337
-
338
-/*
339
- * External GIC sources which are not from External Interrupt Combiner or
340
- * External Interrupts are starting from EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ,
341
- * which is INTG16 in Internal Interrupt Combiner.
342
- */
343
-
344
-static const uint32_t
345
-combiner_grp_to_gic_id[64 - EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][8] = {
346
- /* int combiner groups 16-19 */
347
- { }, { }, { }, { },
348
- /* int combiner group 20 */
349
- { 0, EXT_GIC_ID_MDMA_LCD0 },
350
- /* int combiner group 21 */
351
- { EXT_GIC_ID_PDMA0, EXT_GIC_ID_PDMA1 },
352
- /* int combiner group 22 */
353
- { EXT_GIC_ID_TIMER0, EXT_GIC_ID_TIMER1, EXT_GIC_ID_TIMER2,
354
- EXT_GIC_ID_TIMER3, EXT_GIC_ID_TIMER4 },
355
- /* int combiner group 23 */
356
- { EXT_GIC_ID_RTC_ALARM, EXT_GIC_ID_RTC_TIC },
357
- /* int combiner group 24 */
358
- { EXT_GIC_ID_GPIO_XB, EXT_GIC_ID_GPIO_XA },
359
- /* int combiner group 25 */
360
- { EXT_GIC_ID_IEM_APC, EXT_GIC_ID_IEM_IEC },
361
- /* int combiner group 26 */
362
- { EXT_GIC_ID_UART0, EXT_GIC_ID_UART1, EXT_GIC_ID_UART2, EXT_GIC_ID_UART3,
363
- EXT_GIC_ID_UART4 },
364
- /* int combiner group 27 */
365
- { EXT_GIC_ID_I2C0, EXT_GIC_ID_I2C1, EXT_GIC_ID_I2C2, EXT_GIC_ID_I2C3,
366
- EXT_GIC_ID_I2C4, EXT_GIC_ID_I2C5, EXT_GIC_ID_I2C6,
367
- EXT_GIC_ID_I2C7 },
368
- /* int combiner group 28 */
369
- { EXT_GIC_ID_SPI0, EXT_GIC_ID_SPI1, EXT_GIC_ID_SPI2 , EXT_GIC_ID_USB_HOST},
370
- /* int combiner group 29 */
371
- { EXT_GIC_ID_HSMMC0, EXT_GIC_ID_HSMMC1, EXT_GIC_ID_HSMMC2,
372
- EXT_GIC_ID_HSMMC3, EXT_GIC_ID_SDMMC },
373
- /* int combiner group 30 */
374
- { EXT_GIC_ID_MIPI_CSI_4LANE, EXT_GIC_ID_MIPI_CSI_2LANE },
375
- /* int combiner group 31 */
376
- { EXT_GIC_ID_MIPI_DSI_4LANE, EXT_GIC_ID_MIPI_DSI_2LANE },
377
- /* int combiner group 32 */
378
- { EXT_GIC_ID_FIMC0, EXT_GIC_ID_FIMC1 },
379
- /* int combiner group 33 */
380
- { EXT_GIC_ID_FIMC2, EXT_GIC_ID_FIMC3 },
381
- /* int combiner group 34 */
382
- { EXT_GIC_ID_ONENAND_AUDI, EXT_GIC_ID_NFC },
383
- /* int combiner group 35 */
384
- { 0, 0, 0, EXT_GIC_ID_MCT_L1, EXT_GIC_ID_MCT_G0, EXT_GIC_ID_MCT_G1 },
385
- /* int combiner group 36 */
386
- { EXT_GIC_ID_MIXER },
387
- /* int combiner group 37 */
388
- { EXT_GIC_ID_EXTINT4, EXT_GIC_ID_EXTINT5, EXT_GIC_ID_EXTINT6,
389
- EXT_GIC_ID_EXTINT7 },
390
- /* groups 38-50 */
391
- { }, { }, { }, { }, { }, { }, { }, { }, { }, { }, { }, { }, { },
392
- /* int combiner group 51 */
393
- { EXT_GIC_ID_MCT_L0, 0, 0, 0, EXT_GIC_ID_MCT_G0, EXT_GIC_ID_MCT_G1 },
394
- /* group 52 */
395
- { },
396
- /* int combiner group 53 */
397
- { EXT_GIC_ID_WDT, 0, 0, 0, EXT_GIC_ID_MCT_G0, EXT_GIC_ID_MCT_G1 },
398
- /* groups 54-63 */
399
- { }, { }, { }, { }, { }, { }, { }, { }, { }, { }
400
-};
401
-
402
#define EXYNOS4210_GIC_NIRQ 160
403
404
#define EXYNOS4210_EXT_GIC_CPU_REGION_SIZE 0x10000
405
@@ -XXX,XX +XXX,XX @@ combiner_grp_to_gic_id[64 - EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][8] = {
406
#define EXYNOS4210_GIC_CPU_REGION_SIZE 0x100
407
#define EXYNOS4210_GIC_DIST_REGION_SIZE 0x1000
408
409
-/*
410
- * Initialize board IRQs.
411
- * These IRQs contain splitted Int/External Combiner and External Gic IRQs.
412
- */
413
-void exynos4210_init_board_irqs(Exynos4210State *s)
414
-{
415
- uint32_t grp, bit, irq_id, n;
416
- Exynos4210Irq *is = &s->irqs;
417
-
418
- for (n = 0; n < EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ; n++) {
419
- irq_id = 0;
420
- if (n == EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 4) ||
421
- n == EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 4)) {
422
- /* MCT_G0 is passed to External GIC */
423
- irq_id = EXT_GIC_ID_MCT_G0;
424
- }
425
- if (n == EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 5) ||
426
- n == EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 5)) {
427
- /* MCT_G1 is passed to External and GIC */
428
- irq_id = EXT_GIC_ID_MCT_G1;
429
- }
430
- if (irq_id) {
431
- s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
432
- is->ext_gic_irq[irq_id - 32]);
433
- } else {
434
- s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
435
- is->ext_combiner_irq[n]);
436
- }
437
- }
438
- for (; n < EXYNOS4210_MAX_INT_COMBINER_IN_IRQ; n++) {
439
- /* these IDs are passed to Internal Combiner and External GIC */
440
- grp = EXYNOS4210_COMBINER_GET_GRP_NUM(n);
441
- bit = EXYNOS4210_COMBINER_GET_BIT_NUM(n);
442
- irq_id = combiner_grp_to_gic_id[grp -
443
- EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][bit];
444
-
445
- if (irq_id) {
446
- s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
447
- is->ext_gic_irq[irq_id - 32]);
448
- }
449
- }
450
-}
451
-
452
-/*
453
- * Get IRQ number from exynos4210 IRQ subsystem stub.
454
- * To identify IRQ source use internal combiner group and bit number
455
- * grp - group number
456
- * bit - bit number inside group
457
- */
458
-uint32_t exynos4210_get_irq(uint32_t grp, uint32_t bit)
459
-{
460
- return EXYNOS4210_COMBINER_GET_IRQ_NUM(grp, bit);
461
-}
462
-
463
-/********* GIC part *********/
464
-
465
#define TYPE_EXYNOS4210_GIC "exynos4210.gic"
466
OBJECT_DECLARE_SIMPLE_TYPE(Exynos4210GicState, EXYNOS4210_GIC)
210
467
211
--
468
--
212
2.20.1
469
2.25.1
213
214
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
Switch the creation of the external GIC to the new-style "embedded in
2
state struct" approach, so we can easily refer to the object
3
elsewhere during realize.
2
4
3
This is a bit clearer than open-coding some of this
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
with a bare c string.
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20220404154658.565020-9-peter.maydell@linaro.org
8
---
9
include/hw/arm/exynos4210.h | 2 ++
10
include/hw/intc/exynos4210_gic.h | 43 ++++++++++++++++++++++++++++++++
11
hw/arm/exynos4210.c | 10 ++++----
12
hw/intc/exynos4210_gic.c | 17 ++-----------
13
MAINTAINERS | 2 +-
14
5 files changed, 53 insertions(+), 21 deletions(-)
15
create mode 100644 include/hw/intc/exynos4210_gic.h
5
16
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
17
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Message-id: 20201016184207.786698-9-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
linux-user/elfload.c | 37 ++++++++++++++++++++-----------------
12
1 file changed, 20 insertions(+), 17 deletions(-)
13
14
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
15
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
16
--- a/linux-user/elfload.c
19
--- a/include/hw/arm/exynos4210.h
17
+++ b/linux-user/elfload.c
20
+++ b/include/hw/arm/exynos4210.h
18
@@ -XXX,XX +XXX,XX @@
21
@@ -XXX,XX +XXX,XX @@
19
#include "qemu/guest-random.h"
22
#include "hw/or-irq.h"
20
#include "qemu/units.h"
23
#include "hw/sysbus.h"
21
#include "qemu/selfmap.h"
24
#include "hw/cpu/a9mpcore.h"
22
+#include "qapi/error.h"
25
+#include "hw/intc/exynos4210_gic.h"
23
26
#include "target/arm/cpu-qom.h"
24
#ifdef _ARCH_PPC64
27
#include "qom/object.h"
25
#undef ARCH_DLINFO
28
26
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
29
@@ -XXX,XX +XXX,XX @@ struct Exynos4210State {
27
struct elf_phdr *phdr;
30
qemu_or_irq pl330_irq_orgate[EXYNOS4210_NUM_DMA];
28
abi_ulong load_addr, load_bias, loaddr, hiaddr, error;
31
qemu_or_irq cpu_irq_orgate[EXYNOS4210_NCPUS];
29
int i, retval;
32
A9MPPrivState a9mpcore;
30
- const char *errmsg;
33
+ Exynos4210GicState ext_gic;
31
+ Error *err = NULL;
34
};
32
35
33
/* First of all, some simple consistency checks */
36
#define TYPE_EXYNOS4210_SOC "exynos4210"
34
- errmsg = "Invalid ELF image for this architecture";
37
diff --git a/include/hw/intc/exynos4210_gic.h b/include/hw/intc/exynos4210_gic.h
35
if (!elf_check_ident(ehdr)) {
38
new file mode 100644
36
+ error_setg(&err, "Invalid ELF image for this architecture");
39
index XXXXXXX..XXXXXXX
37
goto exit_errmsg;
40
--- /dev/null
41
+++ b/include/hw/intc/exynos4210_gic.h
42
@@ -XXX,XX +XXX,XX @@
43
+/*
44
+ * Samsung exynos4210 GIC implementation. Based on hw/arm_gic.c
45
+ *
46
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd.
47
+ * All rights reserved.
48
+ *
49
+ * Evgeny Voevodin <e.voevodin@samsung.com>
50
+ *
51
+ * This program is free software; you can redistribute it and/or modify it
52
+ * under the terms of the GNU General Public License as published by the
53
+ * Free Software Foundation; either version 2 of the License, or (at your
54
+ * option) any later version.
55
+ *
56
+ * This program is distributed in the hope that it will be useful,
57
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
58
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
59
+ * See the GNU General Public License for more details.
60
+ *
61
+ * You should have received a copy of the GNU General Public License along
62
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
63
+ */
64
+#ifndef HW_INTC_EXYNOS4210_GIC_H
65
+#define HW_INTC_EXYNOS4210_GIC_H
66
+
67
+#include "hw/sysbus.h"
68
+
69
+#define TYPE_EXYNOS4210_GIC "exynos4210.gic"
70
+OBJECT_DECLARE_SIMPLE_TYPE(Exynos4210GicState, EXYNOS4210_GIC)
71
+
72
+#define EXYNOS4210_GIC_NCPUS 2
73
+
74
+struct Exynos4210GicState {
75
+ SysBusDevice parent_obj;
76
+
77
+ MemoryRegion cpu_container;
78
+ MemoryRegion dist_container;
79
+ MemoryRegion cpu_alias[EXYNOS4210_GIC_NCPUS];
80
+ MemoryRegion dist_alias[EXYNOS4210_GIC_NCPUS];
81
+ uint32_t num_cpu;
82
+ DeviceState *gic;
83
+};
84
+
85
+#endif
86
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
87
index XXXXXXX..XXXXXXX 100644
88
--- a/hw/arm/exynos4210.c
89
+++ b/hw/arm/exynos4210.c
90
@@ -XXX,XX +XXX,XX @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
91
sysbus_create_simple("l2x0", EXYNOS4210_L2X0_BASE_ADDR, NULL);
92
93
/* External GIC */
94
- dev = qdev_new("exynos4210.gic");
95
- qdev_prop_set_uint32(dev, "num-cpu", EXYNOS4210_NCPUS);
96
- busdev = SYS_BUS_DEVICE(dev);
97
- sysbus_realize_and_unref(busdev, &error_fatal);
98
+ qdev_prop_set_uint32(DEVICE(&s->ext_gic), "num-cpu", EXYNOS4210_NCPUS);
99
+ busdev = SYS_BUS_DEVICE(&s->ext_gic);
100
+ sysbus_realize(busdev, &error_fatal);
101
/* Map CPU interface */
102
sysbus_mmio_map(busdev, 0, EXYNOS4210_EXT_GIC_CPU_BASE_ADDR);
103
/* Map Distributer interface */
104
@@ -XXX,XX +XXX,XX @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
105
qdev_get_gpio_in(DEVICE(&s->cpu_irq_orgate[n]), 1));
38
}
106
}
39
bswap_ehdr(ehdr);
107
for (n = 0; n < EXYNOS4210_EXT_GIC_NIRQ; n++) {
40
if (!elf_check_ehdr(ehdr)) {
108
- s->irqs.ext_gic_irq[n] = qdev_get_gpio_in(dev, n);
41
+ error_setg(&err, "Invalid ELF image for this architecture");
109
+ s->irqs.ext_gic_irq[n] = qdev_get_gpio_in(DEVICE(&s->ext_gic), n);
42
goto exit_errmsg;
43
}
110
}
44
111
45
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
112
/* Internal Interrupt Combiner */
46
g_autofree char *interp_name = NULL;
113
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init(Object *obj)
47
48
if (*pinterp_name) {
49
- errmsg = "Multiple PT_INTERP entries";
50
+ error_setg(&err, "Multiple PT_INTERP entries");
51
goto exit_errmsg;
52
}
53
+
54
interp_name = g_malloc(eppnt->p_filesz);
55
- if (!interp_name) {
56
- goto exit_perror;
57
- }
58
59
if (eppnt->p_offset + eppnt->p_filesz <= BPRM_BUF_SIZE) {
60
memcpy(interp_name, bprm_buf + eppnt->p_offset,
61
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
62
retval = pread(image_fd, interp_name, eppnt->p_filesz,
63
eppnt->p_offset);
64
if (retval != eppnt->p_filesz) {
65
- goto exit_perror;
66
+ goto exit_read;
67
}
68
}
69
if (interp_name[eppnt->p_filesz - 1] != 0) {
70
- errmsg = "Invalid PT_INTERP entry";
71
+ error_setg(&err, "Invalid PT_INTERP entry");
72
goto exit_errmsg;
73
}
74
*pinterp_name = g_steal_pointer(&interp_name);
75
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
76
(ehdr->e_type == ET_EXEC ? MAP_FIXED : 0),
77
-1, 0);
78
if (load_addr == -1) {
79
- goto exit_perror;
80
+ goto exit_mmap;
81
}
114
}
82
load_bias = load_addr - loaddr;
115
83
116
object_initialize_child(obj, "a9mpcore", &s->a9mpcore, TYPE_A9MPCORE_PRIV);
84
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
117
+ object_initialize_child(obj, "ext-gic", &s->ext_gic, TYPE_EXYNOS4210_GIC);
85
image_fd, eppnt->p_offset - vaddr_po);
86
87
if (error == -1) {
88
- goto exit_perror;
89
+ goto exit_mmap;
90
}
91
}
92
93
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
94
} else if (eppnt->p_type == PT_MIPS_ABIFLAGS) {
95
Mips_elf_abiflags_v0 abiflags;
96
if (eppnt->p_filesz < sizeof(Mips_elf_abiflags_v0)) {
97
- errmsg = "Invalid PT_MIPS_ABIFLAGS entry";
98
+ error_setg(&err, "Invalid PT_MIPS_ABIFLAGS entry");
99
goto exit_errmsg;
100
}
101
if (eppnt->p_offset + eppnt->p_filesz <= BPRM_BUF_SIZE) {
102
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
103
retval = pread(image_fd, &abiflags, sizeof(Mips_elf_abiflags_v0),
104
eppnt->p_offset);
105
if (retval != sizeof(Mips_elf_abiflags_v0)) {
106
- goto exit_perror;
107
+ goto exit_read;
108
}
109
}
110
bswap_mips_abiflags(&abiflags);
111
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
112
113
exit_read:
114
if (retval >= 0) {
115
- errmsg = "Incomplete read of file header";
116
- goto exit_errmsg;
117
+ error_setg(&err, "Incomplete read of file header");
118
+ } else {
119
+ error_setg_errno(&err, errno, "Error reading file header");
120
}
121
- exit_perror:
122
- errmsg = strerror(errno);
123
+ goto exit_errmsg;
124
+ exit_mmap:
125
+ error_setg_errno(&err, errno, "Error mapping file");
126
+ goto exit_errmsg;
127
exit_errmsg:
128
- fprintf(stderr, "%s: %s\n", image_name, errmsg);
129
+ error_reportf_err(err, "%s: ", image_name);
130
exit(-1);
131
}
118
}
132
119
120
static void exynos4210_class_init(ObjectClass *klass, void *data)
121
diff --git a/hw/intc/exynos4210_gic.c b/hw/intc/exynos4210_gic.c
122
index XXXXXXX..XXXXXXX 100644
123
--- a/hw/intc/exynos4210_gic.c
124
+++ b/hw/intc/exynos4210_gic.c
125
@@ -XXX,XX +XXX,XX @@
126
#include "qemu/module.h"
127
#include "hw/irq.h"
128
#include "hw/qdev-properties.h"
129
+#include "hw/intc/exynos4210_gic.h"
130
#include "hw/arm/exynos4210.h"
131
#include "qom/object.h"
132
133
@@ -XXX,XX +XXX,XX @@
134
#define EXYNOS4210_GIC_CPU_REGION_SIZE 0x100
135
#define EXYNOS4210_GIC_DIST_REGION_SIZE 0x1000
136
137
-#define TYPE_EXYNOS4210_GIC "exynos4210.gic"
138
-OBJECT_DECLARE_SIMPLE_TYPE(Exynos4210GicState, EXYNOS4210_GIC)
139
-
140
-struct Exynos4210GicState {
141
- SysBusDevice parent_obj;
142
-
143
- MemoryRegion cpu_container;
144
- MemoryRegion dist_container;
145
- MemoryRegion cpu_alias[EXYNOS4210_NCPUS];
146
- MemoryRegion dist_alias[EXYNOS4210_NCPUS];
147
- uint32_t num_cpu;
148
- DeviceState *gic;
149
-};
150
-
151
static void exynos4210_gic_set_irq(void *opaque, int irq, int level)
152
{
153
Exynos4210GicState *s = (Exynos4210GicState *)opaque;
154
@@ -XXX,XX +XXX,XX @@ static void exynos4210_gic_realize(DeviceState *dev, Error **errp)
155
* enough room for the cpu numbers. gcc 9.2.1 on 32-bit x86
156
* doesn't figure this out, otherwise and gives spurious warnings.
157
*/
158
- assert(n <= EXYNOS4210_NCPUS);
159
+ assert(n <= EXYNOS4210_GIC_NCPUS);
160
for (i = 0; i < n; i++) {
161
/* Map CPU interface per SMP Core */
162
sprintf(cpu_alias_name, "%s%x", cpu_prefix, i);
163
diff --git a/MAINTAINERS b/MAINTAINERS
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>
133
--
176
--
134
2.20.1
177
2.25.1
135
136
diff view generated by jsdifflib
1
v8.1M's "low-overhead-loop" extension has three instructions
1
The only time we use the ext_gic_irq[] array in the Exynos4210Irq
2
for looping:
2
struct is during realize of the SoC -- we initialize it with the
3
* DLS (start of a do-loop)
3
input IRQs of the external GIC device, and then connect those to
4
* WLS (start of a while-loop)
4
outputs of other devices further on in realize (including in the
5
* LE (end of a loop)
5
exynos4210_init_board_irqs() function). Now that the ext_gic object
6
6
is easily accessible as s->ext_gic we can make the connections
7
The loop-start instructions are both simple operations to start a
7
directly from one device to the other without going via this array.
8
loop whose iteration count (if any) is in LR. The loop-end
9
instruction handles "decrement iteration count and jump back to loop
10
start"; it also caches the information about the branch back to the
11
start of the loop to improve performance of the branch on subsequent
12
iterations.
13
14
As with the branch-future instructions, the architecture permits an
15
implementation to discard the LO_BRANCH_INFO cache at any time, and
16
QEMU takes the IMPDEF option to never set it in the first place
17
(equivalent to discarding it immediately), because for us a "real"
18
implementation would be unnecessary complexity.
19
20
(This implementation only provides the simple looping constructs; the
21
vector extension MVE (Helium) adds some extra variants to handle
22
looping across vectors. We'll add those later when we implement
23
MVE.)
24
8
25
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
26
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
27
Message-id: 20201019151301.2046-8-peter.maydell@linaro.org
11
Message-id: 20220404154658.565020-10-peter.maydell@linaro.org
28
---
12
---
29
target/arm/t32.decode | 8 ++++
13
include/hw/arm/exynos4210.h | 1 -
30
target/arm/translate.c | 93 +++++++++++++++++++++++++++++++++++++++++-
14
hw/arm/exynos4210.c | 12 ++++++------
31
2 files changed, 99 insertions(+), 2 deletions(-)
15
2 files changed, 6 insertions(+), 7 deletions(-)
32
16
33
diff --git a/target/arm/t32.decode b/target/arm/t32.decode
17
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
34
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
35
--- a/target/arm/t32.decode
19
--- a/include/hw/arm/exynos4210.h
36
+++ b/target/arm/t32.decode
20
+++ b/include/hw/arm/exynos4210.h
37
@@ -XXX,XX +XXX,XX @@ BL 1111 0. .......... 11.1 ............ @branch24
21
@@ -XXX,XX +XXX,XX @@
38
BF 1111 0 boff:4 10 ----- 1110 - ---------- 1 # BF
22
typedef struct Exynos4210Irq {
39
BF 1111 0 boff:4 11 ----- 1110 0 0000000000 1 # BFX, BFLX
23
qemu_irq int_combiner_irq[EXYNOS4210_MAX_INT_COMBINER_IN_IRQ];
40
]
24
qemu_irq ext_combiner_irq[EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ];
41
+ [
25
- qemu_irq ext_gic_irq[EXYNOS4210_EXT_GIC_NIRQ];
42
+ # LE and WLS immediate
26
} Exynos4210Irq;
43
+ %lob_imm 1:10 11:1 !function=times_2
27
44
+
28
struct Exynos4210State {
45
+ DLS 1111 0 0000 100 rn:4 1110 0000 0000 0001
29
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
46
+ WLS 1111 0 0000 100 rn:4 1100 . .......... 1 imm=%lob_imm
47
+ LE 1111 0 0000 0 f:1 0 1111 1100 . .......... 1 imm=%lob_imm
48
+ ]
49
}
50
diff --git a/target/arm/translate.c b/target/arm/translate.c
51
index XXXXXXX..XXXXXXX 100644
30
index XXXXXXX..XXXXXXX 100644
52
--- a/target/arm/translate.c
31
--- a/hw/arm/exynos4210.c
53
+++ b/target/arm/translate.c
32
+++ b/hw/arm/exynos4210.c
54
@@ -XXX,XX +XXX,XX @@ static void gen_goto_tb(DisasContext *s, int n, target_ulong dest)
33
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init_board_irqs(Exynos4210State *s)
55
s->base.is_jmp = DISAS_NORETURN;
56
}
57
58
-static inline void gen_jmp (DisasContext *s, uint32_t dest)
59
+/* Jump, specifying which TB number to use if we gen_goto_tb() */
60
+static inline void gen_jmp_tb(DisasContext *s, uint32_t dest, int tbno)
61
{
34
{
62
if (unlikely(is_singlestepping(s))) {
35
uint32_t grp, bit, irq_id, n;
63
/* An indirect jump so that we still trigger the debug exception. */
36
Exynos4210Irq *is = &s->irqs;
64
gen_set_pc_im(s, dest);
37
+ DeviceState *extgicdev = DEVICE(&s->ext_gic);
65
s->base.is_jmp = DISAS_JUMP;
38
66
} else {
39
for (n = 0; n < EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ; n++) {
67
- gen_goto_tb(s, 0, dest);
40
irq_id = 0;
68
+ gen_goto_tb(s, tbno, dest);
41
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init_board_irqs(Exynos4210State *s)
42
}
43
if (irq_id) {
44
s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
45
- is->ext_gic_irq[irq_id - 32]);
46
+ qdev_get_gpio_in(extgicdev,
47
+ irq_id - 32));
48
} else {
49
s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
50
is->ext_combiner_irq[n]);
51
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init_board_irqs(Exynos4210State *s)
52
53
if (irq_id) {
54
s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
55
- is->ext_gic_irq[irq_id - 32]);
56
+ qdev_get_gpio_in(extgicdev,
57
+ irq_id - 32));
58
}
69
}
59
}
70
}
60
}
71
61
@@ -XXX,XX +XXX,XX @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
72
+static inline void gen_jmp(DisasContext *s, uint32_t dest)
62
sysbus_connect_irq(busdev, n,
73
+{
63
qdev_get_gpio_in(DEVICE(&s->cpu_irq_orgate[n]), 1));
74
+ gen_jmp_tb(s, dest, 0);
64
}
75
+}
65
- for (n = 0; n < EXYNOS4210_EXT_GIC_NIRQ; n++) {
76
+
66
- s->irqs.ext_gic_irq[n] = qdev_get_gpio_in(DEVICE(&s->ext_gic), n);
77
static inline void gen_mulxy(TCGv_i32 t0, TCGv_i32 t1, int x, int y)
67
- }
78
{
68
79
if (x)
69
/* Internal Interrupt Combiner */
80
@@ -XXX,XX +XXX,XX @@ static bool trans_BF(DisasContext *s, arg_BF *a)
70
dev = qdev_new("exynos4210.combiner");
81
return true;
71
@@ -XXX,XX +XXX,XX @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
82
}
72
busdev = SYS_BUS_DEVICE(dev);
83
73
sysbus_realize_and_unref(busdev, &error_fatal);
84
+static bool trans_DLS(DisasContext *s, arg_DLS *a)
74
for (n = 0; n < EXYNOS4210_MAX_INT_COMBINER_OUT_IRQ; n++) {
85
+{
75
- sysbus_connect_irq(busdev, n, s->irqs.ext_gic_irq[n]);
86
+ /* M-profile low-overhead loop start */
76
+ sysbus_connect_irq(busdev, n, qdev_get_gpio_in(DEVICE(&s->ext_gic), n));
87
+ TCGv_i32 tmp;
77
}
88
+
78
exynos4210_combiner_get_gpioin(&s->irqs, dev, 1);
89
+ if (!dc_isar_feature(aa32_lob, s)) {
79
sysbus_mmio_map(busdev, 0, EXYNOS4210_EXT_COMBINER_BASE_ADDR);
90
+ return false;
91
+ }
92
+ if (a->rn == 13 || a->rn == 15) {
93
+ /* CONSTRAINED UNPREDICTABLE: we choose to UNDEF */
94
+ return false;
95
+ }
96
+
97
+ /* Not a while loop, no tail predication: just set LR to the count */
98
+ tmp = load_reg(s, a->rn);
99
+ store_reg(s, 14, tmp);
100
+ return true;
101
+}
102
+
103
+static bool trans_WLS(DisasContext *s, arg_WLS *a)
104
+{
105
+ /* M-profile low-overhead while-loop start */
106
+ TCGv_i32 tmp;
107
+ TCGLabel *nextlabel;
108
+
109
+ if (!dc_isar_feature(aa32_lob, s)) {
110
+ return false;
111
+ }
112
+ if (a->rn == 13 || a->rn == 15) {
113
+ /* CONSTRAINED UNPREDICTABLE: we choose to UNDEF */
114
+ return false;
115
+ }
116
+ if (s->condexec_mask) {
117
+ /*
118
+ * WLS in an IT block is CONSTRAINED UNPREDICTABLE;
119
+ * we choose to UNDEF, because otherwise our use of
120
+ * gen_goto_tb(1) would clash with the use of TB exit 1
121
+ * in the dc->condjmp condition-failed codepath in
122
+ * arm_tr_tb_stop() and we'd get an assertion.
123
+ */
124
+ return false;
125
+ }
126
+ nextlabel = gen_new_label();
127
+ tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_R[a->rn], 0, nextlabel);
128
+ tmp = load_reg(s, a->rn);
129
+ store_reg(s, 14, tmp);
130
+ gen_jmp_tb(s, s->base.pc_next, 1);
131
+
132
+ gen_set_label(nextlabel);
133
+ gen_jmp(s, read_pc(s) + a->imm);
134
+ return true;
135
+}
136
+
137
+static bool trans_LE(DisasContext *s, arg_LE *a)
138
+{
139
+ /*
140
+ * M-profile low-overhead loop end. The architecture permits an
141
+ * implementation to discard the LO_BRANCH_INFO cache at any time,
142
+ * and we take the IMPDEF option to never set it in the first place
143
+ * (equivalent to always discarding it immediately), because for QEMU
144
+ * a "real" implementation would be complicated and wouldn't execute
145
+ * any faster.
146
+ */
147
+ TCGv_i32 tmp;
148
+
149
+ if (!dc_isar_feature(aa32_lob, s)) {
150
+ return false;
151
+ }
152
+
153
+ if (!a->f) {
154
+ /* Not loop-forever. If LR <= 1 this is the last loop: do nothing. */
155
+ arm_gen_condlabel(s);
156
+ tcg_gen_brcondi_i32(TCG_COND_LEU, cpu_R[14], 1, s->condlabel);
157
+ /* Decrement LR */
158
+ tmp = load_reg(s, 14);
159
+ tcg_gen_addi_i32(tmp, tmp, -1);
160
+ store_reg(s, 14, tmp);
161
+ }
162
+ /* Jump back to the loop start */
163
+ gen_jmp(s, read_pc(s) - a->imm);
164
+ return true;
165
+}
166
+
167
static bool op_tbranch(DisasContext *s, arg_tbranch *a, bool half)
168
{
169
TCGv_i32 addr, tmp;
170
--
80
--
171
2.20.1
81
2.25.1
172
173
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
The function exynos4210_combiner_get_gpioin() currently lives in
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.
2
8
3
Use the BCM2835_SYSTIMER_COUNT definition instead of the
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
magic '4' value.
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20220404154658.565020-11-peter.maydell@linaro.org
12
---
13
include/hw/arm/exynos4210.h | 11 -----
14
hw/arm/exynos4210.c | 82 +++++++++++++++++++++++++++++++++++
15
hw/intc/exynos4210_combiner.c | 77 --------------------------------
16
3 files changed, 82 insertions(+), 88 deletions(-)
5
17
6
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
18
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Message-id: 20201010203709.3116542-2-f4bug@amsat.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
include/hw/timer/bcm2835_systmr.h | 4 +++-
13
hw/timer/bcm2835_systmr.c | 3 ++-
14
2 files changed, 5 insertions(+), 2 deletions(-)
15
16
diff --git a/include/hw/timer/bcm2835_systmr.h b/include/hw/timer/bcm2835_systmr.h
17
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
18
--- a/include/hw/timer/bcm2835_systmr.h
20
--- a/include/hw/arm/exynos4210.h
19
+++ b/include/hw/timer/bcm2835_systmr.h
21
+++ b/include/hw/arm/exynos4210.h
20
@@ -XXX,XX +XXX,XX @@
22
@@ -XXX,XX +XXX,XX @@
21
#define TYPE_BCM2835_SYSTIMER "bcm2835-sys-timer"
23
#define EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ \
22
OBJECT_DECLARE_SIMPLE_TYPE(BCM2835SystemTimerState, BCM2835_SYSTIMER)
24
(EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ * 8)
23
25
24
+#define BCM2835_SYSTIMER_COUNT 4
26
-#define EXYNOS4210_COMBINER_GET_IRQ_NUM(grp, bit) ((grp)*8 + (bit))
25
+
27
-#define EXYNOS4210_COMBINER_GET_GRP_NUM(irq) ((irq) / 8)
26
struct BCM2835SystemTimerState {
28
-#define EXYNOS4210_COMBINER_GET_BIT_NUM(irq) \
27
/*< private >*/
29
- ((irq) - 8 * EXYNOS4210_COMBINER_GET_GRP_NUM(irq))
28
SysBusDevice parent_obj;
30
-
29
@@ -XXX,XX +XXX,XX @@ struct BCM2835SystemTimerState {
31
/* IRQs number for external and internal GIC */
30
32
#define EXYNOS4210_EXT_GIC_NIRQ (160-32)
31
struct {
33
#define EXYNOS4210_INT_GIC_NIRQ 64
32
uint32_t status;
34
@@ -XXX,XX +XXX,XX @@ void exynos4210_write_secondary(ARMCPU *cpu,
33
- uint32_t compare[4];
35
* bit - bit number inside group */
34
+ uint32_t compare[BCM2835_SYSTIMER_COUNT];
36
uint32_t exynos4210_get_irq(uint32_t grp, uint32_t bit);
35
} reg;
37
38
-/*
39
- * Get Combiner input GPIO into irqs structure
40
- */
41
-void exynos4210_combiner_get_gpioin(Exynos4210Irq *irqs, DeviceState *dev,
42
- int ext);
43
-
44
/*
45
* exynos4210 UART
46
*/
47
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
48
index XXXXXXX..XXXXXXX 100644
49
--- a/hw/arm/exynos4210.c
50
+++ b/hw/arm/exynos4210.c
51
@@ -XXX,XX +XXX,XX @@ combiner_grp_to_gic_id[64 - EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][8] = {
52
{ }, { }, { }, { }, { }, { }, { }, { }, { }, { }
36
};
53
};
37
54
38
diff --git a/hw/timer/bcm2835_systmr.c b/hw/timer/bcm2835_systmr.c
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
}
66
67
+/*
68
+ * Get Combiner input GPIO into irqs structure
69
+ */
70
+static void exynos4210_combiner_get_gpioin(Exynos4210Irq *irqs,
71
+ DeviceState *dev, int ext)
72
+{
73
+ int n;
74
+ int bit;
75
+ int max;
76
+ qemu_irq *irq;
77
+
78
+ max = ext ? EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ :
79
+ EXYNOS4210_MAX_INT_COMBINER_IN_IRQ;
80
+ irq = ext ? irqs->ext_combiner_irq : irqs->int_combiner_irq;
81
+
82
+ /*
83
+ * Some IRQs of Int/External Combiner are going to two Combiners groups,
84
+ * so let split them.
85
+ */
86
+ for (n = 0; n < max; n++) {
87
+
88
+ bit = EXYNOS4210_COMBINER_GET_BIT_NUM(n);
89
+
90
+ switch (n) {
91
+ /* MDNIE_LCD1 INTG1 */
92
+ case EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 0) ...
93
+ EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 3):
94
+ irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
95
+ irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(0, bit + 4)]);
96
+ continue;
97
+
98
+ /* TMU INTG3 */
99
+ case EXYNOS4210_COMBINER_GET_IRQ_NUM(3, 4):
100
+ irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
101
+ irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(2, bit)]);
102
+ continue;
103
+
104
+ /* LCD1 INTG12 */
105
+ case EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 0) ...
106
+ EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 3):
107
+ irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
108
+ irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(11, bit + 4)]);
109
+ continue;
110
+
111
+ /* Multi-Core Timer INTG12 */
112
+ case EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 4) ...
113
+ EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 8):
114
+ irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
115
+ irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(1, bit + 4)]);
116
+ continue;
117
+
118
+ /* Multi-Core Timer INTG35 */
119
+ case EXYNOS4210_COMBINER_GET_IRQ_NUM(35, 4) ...
120
+ EXYNOS4210_COMBINER_GET_IRQ_NUM(35, 8):
121
+ irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
122
+ irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(1, bit + 4)]);
123
+ continue;
124
+
125
+ /* Multi-Core Timer INTG51 */
126
+ case EXYNOS4210_COMBINER_GET_IRQ_NUM(51, 4) ...
127
+ EXYNOS4210_COMBINER_GET_IRQ_NUM(51, 8):
128
+ irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
129
+ irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(1, bit + 4)]);
130
+ continue;
131
+
132
+ /* Multi-Core Timer INTG53 */
133
+ case EXYNOS4210_COMBINER_GET_IRQ_NUM(53, 4) ...
134
+ EXYNOS4210_COMBINER_GET_IRQ_NUM(53, 8):
135
+ irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
136
+ irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(1, bit + 4)]);
137
+ continue;
138
+ }
139
+
140
+ irq[n] = qdev_get_gpio_in(dev, n);
141
+ }
142
+}
143
+
144
static uint8_t chipid_and_omr[] = { 0x11, 0x02, 0x21, 0x43,
145
0x09, 0x00, 0x00, 0x00 };
146
147
diff --git a/hw/intc/exynos4210_combiner.c b/hw/intc/exynos4210_combiner.c
39
index XXXXXXX..XXXXXXX 100644
148
index XXXXXXX..XXXXXXX 100644
40
--- a/hw/timer/bcm2835_systmr.c
149
--- a/hw/intc/exynos4210_combiner.c
41
+++ b/hw/timer/bcm2835_systmr.c
150
+++ b/hw/intc/exynos4210_combiner.c
42
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription bcm2835_systmr_vmstate = {
151
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_exynos4210_combiner = {
43
.minimum_version_id = 1,
44
.fields = (VMStateField[]) {
45
VMSTATE_UINT32(reg.status, BCM2835SystemTimerState),
46
- VMSTATE_UINT32_ARRAY(reg.compare, BCM2835SystemTimerState, 4),
47
+ VMSTATE_UINT32_ARRAY(reg.compare, BCM2835SystemTimerState,
48
+ BCM2835_SYSTIMER_COUNT),
49
VMSTATE_END_OF_LIST()
50
}
152
}
51
};
153
};
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
{
52
--
235
--
53
2.20.1
236
2.25.1
54
55
diff view generated by jsdifflib
1
From v8.1M, disabled-coprocessor handling changes slightly:
1
Delete a couple of #defines which are never used.
2
* coprocessors 8, 9, 14 and 15 are also governed by the
3
cp10 enable bit, like cp11
4
* an extra range of instruction patterns is considered
5
to be inside the coprocessor space
6
7
We previously marked these up with TODO comments; implement the
8
correct behaviour.
9
10
Unfortunately there is no ID register field which indicates this
11
behaviour. We could in theory test an unrelated ID register which
12
indicates guaranteed-to-be-in-v8.1M behaviour like ID_ISAR0.CmpBranch
13
>= 3 (low-overhead-loops), but it seems better to simply define a new
14
ARM_FEATURE_V8_1M feature flag and use it for this and other
15
new-in-v8.1M behaviour that isn't identifiable from the ID registers.
16
2
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
19
Message-id: 20201019151301.2046-3-peter.maydell@linaro.org
5
Message-id: 20220404154658.565020-12-peter.maydell@linaro.org
20
---
6
---
21
target/arm/cpu.h | 1 +
7
include/hw/arm/exynos4210.h | 4 ----
22
target/arm/m-nocp.decode | 10 ++++++----
8
1 file changed, 4 deletions(-)
23
target/arm/translate-vfp.c.inc | 17 +++++++++++++++--
24
3 files changed, 22 insertions(+), 6 deletions(-)
25
9
26
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
10
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
27
index XXXXXXX..XXXXXXX 100644
11
index XXXXXXX..XXXXXXX 100644
28
--- a/target/arm/cpu.h
12
--- a/include/hw/arm/exynos4210.h
29
+++ b/target/arm/cpu.h
13
+++ b/include/hw/arm/exynos4210.h
30
@@ -XXX,XX +XXX,XX @@ enum arm_features {
31
ARM_FEATURE_VBAR, /* has cp15 VBAR */
32
ARM_FEATURE_M_SECURITY, /* M profile Security Extension */
33
ARM_FEATURE_M_MAIN, /* M profile Main Extension */
34
+ ARM_FEATURE_V8_1M, /* M profile extras only in v8.1M and later */
35
};
36
37
static inline int arm_feature(CPUARMState *env, int feature)
38
diff --git a/target/arm/m-nocp.decode b/target/arm/m-nocp.decode
39
index XXXXXXX..XXXXXXX 100644
40
--- a/target/arm/m-nocp.decode
41
+++ b/target/arm/m-nocp.decode
42
@@ -XXX,XX +XXX,XX @@
14
@@ -XXX,XX +XXX,XX @@
43
# If the coprocessor is not present or disabled then we will generate
15
#define EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ \
44
# the NOCP exception; otherwise we let the insn through to the main decode.
16
(EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ * 8)
45
17
46
+&nocp cp
18
-/* IRQs number for external and internal GIC */
47
+
19
-#define EXYNOS4210_EXT_GIC_NIRQ (160-32)
48
{
20
-#define EXYNOS4210_INT_GIC_NIRQ 64
49
# Special cases which do not take an early NOCP: VLLDM and VLSTM
21
-
50
VLLDM_VLSTM 1110 1100 001 l:1 rn:4 0000 1010 0000 0000
22
#define EXYNOS4210_I2C_NUMBER 9
51
# TODO: VSCCLRM (new in v8.1M) is similar:
23
52
#VSCCLRM 1110 1100 1-01 1111 ---- 1011 ---- ---0
24
#define EXYNOS4210_NUM_DMA 3
53
54
- NOCP 111- 1110 ---- ---- ---- cp:4 ---- ----
55
- NOCP 111- 110- ---- ---- ---- cp:4 ---- ----
56
- # TODO: From v8.1M onwards we will also want this range to NOCP
57
- #NOCP_8_1 111- 1111 ---- ---- ---- ---- ---- ---- cp=10
58
+ NOCP 111- 1110 ---- ---- ---- cp:4 ---- ---- &nocp
59
+ NOCP 111- 110- ---- ---- ---- cp:4 ---- ---- &nocp
60
+ # From v8.1M onwards this range will also NOCP:
61
+ NOCP_8_1 111- 1111 ---- ---- ---- ---- ---- ---- &nocp cp=10
62
}
63
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
64
index XXXXXXX..XXXXXXX 100644
65
--- a/target/arm/translate-vfp.c.inc
66
+++ b/target/arm/translate-vfp.c.inc
67
@@ -XXX,XX +XXX,XX @@ static bool trans_VLLDM_VLSTM(DisasContext *s, arg_VLLDM_VLSTM *a)
68
return true;
69
}
70
71
-static bool trans_NOCP(DisasContext *s, arg_NOCP *a)
72
+static bool trans_NOCP(DisasContext *s, arg_nocp *a)
73
{
74
/*
75
* Handle M-profile early check for disabled coprocessor:
76
@@ -XXX,XX +XXX,XX @@ static bool trans_NOCP(DisasContext *s, arg_NOCP *a)
77
if (a->cp == 11) {
78
a->cp = 10;
79
}
80
- /* TODO: in v8.1M cp 8, 9, 14, 15 also are governed by the cp10 enable */
81
+ if (arm_dc_feature(s, ARM_FEATURE_V8_1M) &&
82
+ (a->cp == 8 || a->cp == 9 || a->cp == 14 || a->cp == 15)) {
83
+ /* in v8.1M cp 8, 9, 14, 15 also are governed by the cp10 enable */
84
+ a->cp = 10;
85
+ }
86
87
if (a->cp != 10) {
88
gen_exception_insn(s, s->pc_curr, EXCP_NOCP,
89
@@ -XXX,XX +XXX,XX @@ static bool trans_NOCP(DisasContext *s, arg_NOCP *a)
90
return false;
91
}
92
93
+static bool trans_NOCP_8_1(DisasContext *s, arg_nocp *a)
94
+{
95
+ /* This range needs a coprocessor check for v8.1M and later only */
96
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
97
+ return false;
98
+ }
99
+ return trans_NOCP(s, a);
100
+}
101
+
102
static bool trans_VINS(DisasContext *s, arg_VINS *a)
103
{
104
TCGv_i32 rd, rm;
105
--
25
--
106
2.20.1
26
2.25.1
107
108
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
In exynos4210_init_board_irqs(), use the TYPE_SPLIT_IRQ device
2
instead of qemu_irq_split().
2
3
3
On ARM, the Top Byte Ignore feature means that only 56 bits of
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
the address are significant in the virtual address. We are
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
required to give the entire 64-bit address to FAR_ELx on fault,
6
Message-id: 20220404154658.565020-13-peter.maydell@linaro.org
6
which means that we do not "clean" the top byte early in TCG.
7
---
8
include/hw/arm/exynos4210.h | 9 ++++++++
9
hw/arm/exynos4210.c | 41 +++++++++++++++++++++++++++++--------
10
2 files changed, 42 insertions(+), 8 deletions(-)
7
11
8
This new interface allows us to flush all 256 possible aliases
12
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
9
for a given page, currently missed by tlb_flush_page*.
10
11
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
12
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
13
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
Message-id: 20201016210754.818257-2-richard.henderson@linaro.org
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
---
17
include/exec/exec-all.h | 36 ++++++
18
accel/tcg/cputlb.c | 275 ++++++++++++++++++++++++++++++++++++++--
19
2 files changed, 302 insertions(+), 9 deletions(-)
20
21
diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
22
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
23
--- a/include/exec/exec-all.h
14
--- a/include/hw/arm/exynos4210.h
24
+++ b/include/exec/exec-all.h
15
+++ b/include/hw/arm/exynos4210.h
25
@@ -XXX,XX +XXX,XX @@ void tlb_flush_by_mmuidx_all_cpus(CPUState *cpu, uint16_t idxmap);
16
@@ -XXX,XX +XXX,XX @@
26
* depend on when the guests translation ends the TB.
17
#include "hw/sysbus.h"
27
*/
18
#include "hw/cpu/a9mpcore.h"
28
void tlb_flush_by_mmuidx_all_cpus_synced(CPUState *cpu, uint16_t idxmap);
19
#include "hw/intc/exynos4210_gic.h"
20
+#include "hw/core/split-irq.h"
21
#include "target/arm/cpu-qom.h"
22
#include "qom/object.h"
23
24
@@ -XXX,XX +XXX,XX @@
25
26
#define EXYNOS4210_NUM_DMA 3
27
28
+/*
29
+ * We need one splitter for every external combiner input, plus
30
+ * one for every non-zero entry in combiner_grp_to_gic_id[].
31
+ * We'll assert in exynos4210_init_board_irqs() if this is wrong.
32
+ */
33
+#define EXYNOS4210_NUM_SPLITTERS (EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ + 60)
29
+
34
+
30
+/**
35
typedef struct Exynos4210Irq {
31
+ * tlb_flush_page_bits_by_mmuidx
36
qemu_irq int_combiner_irq[EXYNOS4210_MAX_INT_COMBINER_IN_IRQ];
32
+ * @cpu: CPU whose TLB should be flushed
37
qemu_irq ext_combiner_irq[EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ];
33
+ * @addr: virtual address of page to be flushed
38
@@ -XXX,XX +XXX,XX @@ struct Exynos4210State {
34
+ * @idxmap: bitmap of mmu indexes to flush
39
qemu_or_irq cpu_irq_orgate[EXYNOS4210_NCPUS];
35
+ * @bits: number of significant bits in address
40
A9MPPrivState a9mpcore;
36
+ *
41
Exynos4210GicState ext_gic;
37
+ * Similar to tlb_flush_page_mask, but with a bitmap of indexes.
42
+ SplitIRQ splitter[EXYNOS4210_NUM_SPLITTERS];
38
+ */
43
};
39
+void tlb_flush_page_bits_by_mmuidx(CPUState *cpu, target_ulong addr,
44
40
+ uint16_t idxmap, unsigned bits);
45
#define TYPE_EXYNOS4210_SOC "exynos4210"
46
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
47
index XXXXXXX..XXXXXXX 100644
48
--- a/hw/arm/exynos4210.c
49
+++ b/hw/arm/exynos4210.c
50
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init_board_irqs(Exynos4210State *s)
51
uint32_t grp, bit, irq_id, n;
52
Exynos4210Irq *is = &s->irqs;
53
DeviceState *extgicdev = DEVICE(&s->ext_gic);
54
+ int splitcount = 0;
55
+ DeviceState *splitter;
56
57
for (n = 0; n < EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ; n++) {
58
irq_id = 0;
59
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init_board_irqs(Exynos4210State *s)
60
/* MCT_G1 is passed to External and GIC */
61
irq_id = EXT_GIC_ID_MCT_G1;
62
}
41
+
63
+
42
+/* Similarly, with broadcast and syncing. */
64
+ assert(splitcount < EXYNOS4210_NUM_SPLITTERS);
43
+void tlb_flush_page_bits_by_mmuidx_all_cpus(CPUState *cpu, target_ulong addr,
65
+ splitter = DEVICE(&s->splitter[splitcount]);
44
+ uint16_t idxmap, unsigned bits);
66
+ qdev_prop_set_uint16(splitter, "num-lines", 2);
45
+void tlb_flush_page_bits_by_mmuidx_all_cpus_synced
67
+ qdev_realize(splitter, NULL, &error_abort);
46
+ (CPUState *cpu, target_ulong addr, uint16_t idxmap, unsigned bits);
68
+ splitcount++;
47
+
69
+ s->irq_table[n] = qdev_get_gpio_in(splitter, 0);
48
/**
70
+ qdev_connect_gpio_out(splitter, 0, is->int_combiner_irq[n]);
49
* tlb_set_page_with_attrs:
71
if (irq_id) {
50
* @cpu: CPU to add this TLB entry for
72
- s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
51
@@ -XXX,XX +XXX,XX @@ static inline void tlb_flush_by_mmuidx_all_cpus_synced(CPUState *cpu,
73
- qdev_get_gpio_in(extgicdev,
52
uint16_t idxmap)
74
- irq_id - 32));
53
{
75
+ qdev_connect_gpio_out(splitter, 1,
54
}
76
+ qdev_get_gpio_in(extgicdev, irq_id - 32));
55
+static inline void tlb_flush_page_bits_by_mmuidx(CPUState *cpu,
77
} else {
56
+ target_ulong addr,
78
- s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
57
+ uint16_t idxmap,
79
- is->ext_combiner_irq[n]);
58
+ unsigned bits)
80
+ qdev_connect_gpio_out(splitter, 1, is->ext_combiner_irq[n]);
59
+{
60
+}
61
+static inline void tlb_flush_page_bits_by_mmuidx_all_cpus(CPUState *cpu,
62
+ target_ulong addr,
63
+ uint16_t idxmap,
64
+ unsigned bits)
65
+{
66
+}
67
+static inline void
68
+tlb_flush_page_bits_by_mmuidx_all_cpus_synced(CPUState *cpu, target_ulong addr,
69
+ uint16_t idxmap, unsigned bits)
70
+{
71
+}
72
#endif
73
/**
74
* probe_access:
75
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
76
index XXXXXXX..XXXXXXX 100644
77
--- a/accel/tcg/cputlb.c
78
+++ b/accel/tcg/cputlb.c
79
@@ -XXX,XX +XXX,XX @@ void tlb_flush_all_cpus_synced(CPUState *src_cpu)
80
tlb_flush_by_mmuidx_all_cpus_synced(src_cpu, ALL_MMUIDX_BITS);
81
}
82
83
+static bool tlb_hit_page_mask_anyprot(CPUTLBEntry *tlb_entry,
84
+ target_ulong page, target_ulong mask)
85
+{
86
+ page &= mask;
87
+ mask &= TARGET_PAGE_MASK | TLB_INVALID_MASK;
88
+
89
+ return (page == (tlb_entry->addr_read & mask) ||
90
+ page == (tlb_addr_write(tlb_entry) & mask) ||
91
+ page == (tlb_entry->addr_code & mask));
92
+}
93
+
94
static inline bool tlb_hit_page_anyprot(CPUTLBEntry *tlb_entry,
95
target_ulong page)
96
{
97
- return tlb_hit_page(tlb_entry->addr_read, page) ||
98
- tlb_hit_page(tlb_addr_write(tlb_entry), page) ||
99
- tlb_hit_page(tlb_entry->addr_code, page);
100
+ return tlb_hit_page_mask_anyprot(tlb_entry, page, -1);
101
}
102
103
/**
104
@@ -XXX,XX +XXX,XX @@ static inline bool tlb_entry_is_empty(const CPUTLBEntry *te)
105
}
106
107
/* Called with tlb_c.lock held */
108
-static inline bool tlb_flush_entry_locked(CPUTLBEntry *tlb_entry,
109
- target_ulong page)
110
+static bool tlb_flush_entry_mask_locked(CPUTLBEntry *tlb_entry,
111
+ target_ulong page,
112
+ target_ulong mask)
113
{
114
- if (tlb_hit_page_anyprot(tlb_entry, page)) {
115
+ if (tlb_hit_page_mask_anyprot(tlb_entry, page, mask)) {
116
memset(tlb_entry, -1, sizeof(*tlb_entry));
117
return true;
118
}
119
return false;
120
}
121
122
+static inline bool tlb_flush_entry_locked(CPUTLBEntry *tlb_entry,
123
+ target_ulong page)
124
+{
125
+ return tlb_flush_entry_mask_locked(tlb_entry, page, -1);
126
+}
127
+
128
/* Called with tlb_c.lock held */
129
-static inline void tlb_flush_vtlb_page_locked(CPUArchState *env, int mmu_idx,
130
- target_ulong page)
131
+static void tlb_flush_vtlb_page_mask_locked(CPUArchState *env, int mmu_idx,
132
+ target_ulong page,
133
+ target_ulong mask)
134
{
135
CPUTLBDesc *d = &env_tlb(env)->d[mmu_idx];
136
int k;
137
138
assert_cpu_is_self(env_cpu(env));
139
for (k = 0; k < CPU_VTLB_SIZE; k++) {
140
- if (tlb_flush_entry_locked(&d->vtable[k], page)) {
141
+ if (tlb_flush_entry_mask_locked(&d->vtable[k], page, mask)) {
142
tlb_n_used_entries_dec(env, mmu_idx);
143
}
81
}
144
}
82
}
83
for (; n < EXYNOS4210_MAX_INT_COMBINER_IN_IRQ; n++) {
84
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init_board_irqs(Exynos4210State *s)
85
EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][bit];
86
87
if (irq_id) {
88
- s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
89
- qdev_get_gpio_in(extgicdev,
90
- irq_id - 32));
91
+ assert(splitcount < EXYNOS4210_NUM_SPLITTERS);
92
+ splitter = DEVICE(&s->splitter[splitcount]);
93
+ qdev_prop_set_uint16(splitter, "num-lines", 2);
94
+ qdev_realize(splitter, NULL, &error_abort);
95
+ splitcount++;
96
+ s->irq_table[n] = qdev_get_gpio_in(splitter, 0);
97
+ qdev_connect_gpio_out(splitter, 0, is->int_combiner_irq[n]);
98
+ qdev_connect_gpio_out(splitter, 1,
99
+ qdev_get_gpio_in(extgicdev, irq_id - 32));
100
}
101
}
102
+ /*
103
+ * We check this here to avoid a more obscure assert later when
104
+ * qdev_assert_realized_properly() checks that we realized every
105
+ * child object we initialized.
106
+ */
107
+ assert(splitcount == EXYNOS4210_NUM_SPLITTERS);
145
}
108
}
146
109
147
+static inline void tlb_flush_vtlb_page_locked(CPUArchState *env, int mmu_idx,
110
/*
148
+ target_ulong page)
111
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init(Object *obj)
149
+{
112
object_initialize_child(obj, name, &s->cpu_irq_orgate[i], TYPE_OR_IRQ);
150
+ tlb_flush_vtlb_page_mask_locked(env, mmu_idx, page, -1);
113
}
151
+}
114
152
+
115
+ for (i = 0; i < ARRAY_SIZE(s->splitter); i++) {
153
static void tlb_flush_page_locked(CPUArchState *env, int midx,
116
+ g_autofree char *name = g_strdup_printf("irq-splitter%d", i);
154
target_ulong page)
117
+ object_initialize_child(obj, name, &s->splitter[i], TYPE_SPLIT_IRQ);
155
{
156
@@ -XXX,XX +XXX,XX @@ void tlb_flush_page_all_cpus_synced(CPUState *src, target_ulong addr)
157
tlb_flush_page_by_mmuidx_all_cpus_synced(src, addr, ALL_MMUIDX_BITS);
158
}
159
160
+static void tlb_flush_page_bits_locked(CPUArchState *env, int midx,
161
+ target_ulong page, unsigned bits)
162
+{
163
+ CPUTLBDesc *d = &env_tlb(env)->d[midx];
164
+ CPUTLBDescFast *f = &env_tlb(env)->f[midx];
165
+ target_ulong mask = MAKE_64BIT_MASK(0, bits);
166
+
167
+ /*
168
+ * If @bits is smaller than the tlb size, there may be multiple entries
169
+ * within the TLB; otherwise all addresses that match under @mask hit
170
+ * the same TLB entry.
171
+ *
172
+ * TODO: Perhaps allow bits to be a few bits less than the size.
173
+ * For now, just flush the entire TLB.
174
+ */
175
+ if (mask < f->mask) {
176
+ tlb_debug("forcing full flush midx %d ("
177
+ TARGET_FMT_lx "/" TARGET_FMT_lx ")\n",
178
+ midx, page, mask);
179
+ tlb_flush_one_mmuidx_locked(env, midx, get_clock_realtime());
180
+ return;
181
+ }
118
+ }
182
+
119
+
183
+ /* Check if we need to flush due to large pages. */
120
object_initialize_child(obj, "a9mpcore", &s->a9mpcore, TYPE_A9MPCORE_PRIV);
184
+ if ((page & d->large_page_mask) == d->large_page_addr) {
121
object_initialize_child(obj, "ext-gic", &s->ext_gic, TYPE_EXYNOS4210_GIC);
185
+ tlb_debug("forcing full flush midx %d ("
122
}
186
+ TARGET_FMT_lx "/" TARGET_FMT_lx ")\n",
187
+ midx, d->large_page_addr, d->large_page_mask);
188
+ tlb_flush_one_mmuidx_locked(env, midx, get_clock_realtime());
189
+ return;
190
+ }
191
+
192
+ if (tlb_flush_entry_mask_locked(tlb_entry(env, midx, page), page, mask)) {
193
+ tlb_n_used_entries_dec(env, midx);
194
+ }
195
+ tlb_flush_vtlb_page_mask_locked(env, midx, page, mask);
196
+}
197
+
198
+typedef struct {
199
+ target_ulong addr;
200
+ uint16_t idxmap;
201
+ uint16_t bits;
202
+} TLBFlushPageBitsByMMUIdxData;
203
+
204
+static void
205
+tlb_flush_page_bits_by_mmuidx_async_0(CPUState *cpu,
206
+ TLBFlushPageBitsByMMUIdxData d)
207
+{
208
+ CPUArchState *env = cpu->env_ptr;
209
+ int mmu_idx;
210
+
211
+ assert_cpu_is_self(cpu);
212
+
213
+ tlb_debug("page addr:" TARGET_FMT_lx "/%u mmu_map:0x%x\n",
214
+ d.addr, d.bits, d.idxmap);
215
+
216
+ qemu_spin_lock(&env_tlb(env)->c.lock);
217
+ for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) {
218
+ if ((d.idxmap >> mmu_idx) & 1) {
219
+ tlb_flush_page_bits_locked(env, mmu_idx, d.addr, d.bits);
220
+ }
221
+ }
222
+ qemu_spin_unlock(&env_tlb(env)->c.lock);
223
+
224
+ tb_flush_jmp_cache(cpu, d.addr);
225
+}
226
+
227
+static bool encode_pbm_to_runon(run_on_cpu_data *out,
228
+ TLBFlushPageBitsByMMUIdxData d)
229
+{
230
+ /* We need 6 bits to hold to hold @bits up to 63. */
231
+ if (d.idxmap <= MAKE_64BIT_MASK(0, TARGET_PAGE_BITS - 6)) {
232
+ *out = RUN_ON_CPU_TARGET_PTR(d.addr | (d.idxmap << 6) | d.bits);
233
+ return true;
234
+ }
235
+ return false;
236
+}
237
+
238
+static TLBFlushPageBitsByMMUIdxData
239
+decode_runon_to_pbm(run_on_cpu_data data)
240
+{
241
+ target_ulong addr_map_bits = (target_ulong) data.target_ptr;
242
+ return (TLBFlushPageBitsByMMUIdxData){
243
+ .addr = addr_map_bits & TARGET_PAGE_MASK,
244
+ .idxmap = (addr_map_bits & ~TARGET_PAGE_MASK) >> 6,
245
+ .bits = addr_map_bits & 0x3f
246
+ };
247
+}
248
+
249
+static void tlb_flush_page_bits_by_mmuidx_async_1(CPUState *cpu,
250
+ run_on_cpu_data runon)
251
+{
252
+ tlb_flush_page_bits_by_mmuidx_async_0(cpu, decode_runon_to_pbm(runon));
253
+}
254
+
255
+static void tlb_flush_page_bits_by_mmuidx_async_2(CPUState *cpu,
256
+ run_on_cpu_data data)
257
+{
258
+ TLBFlushPageBitsByMMUIdxData *d = data.host_ptr;
259
+ tlb_flush_page_bits_by_mmuidx_async_0(cpu, *d);
260
+ g_free(d);
261
+}
262
+
263
+void tlb_flush_page_bits_by_mmuidx(CPUState *cpu, target_ulong addr,
264
+ uint16_t idxmap, unsigned bits)
265
+{
266
+ TLBFlushPageBitsByMMUIdxData d;
267
+ run_on_cpu_data runon;
268
+
269
+ /* If all bits are significant, this devolves to tlb_flush_page. */
270
+ if (bits >= TARGET_LONG_BITS) {
271
+ tlb_flush_page_by_mmuidx(cpu, addr, idxmap);
272
+ return;
273
+ }
274
+ /* If no page bits are significant, this devolves to tlb_flush. */
275
+ if (bits < TARGET_PAGE_BITS) {
276
+ tlb_flush_by_mmuidx(cpu, idxmap);
277
+ return;
278
+ }
279
+
280
+ /* This should already be page aligned */
281
+ d.addr = addr & TARGET_PAGE_MASK;
282
+ d.idxmap = idxmap;
283
+ d.bits = bits;
284
+
285
+ if (qemu_cpu_is_self(cpu)) {
286
+ tlb_flush_page_bits_by_mmuidx_async_0(cpu, d);
287
+ } else if (encode_pbm_to_runon(&runon, d)) {
288
+ async_run_on_cpu(cpu, tlb_flush_page_bits_by_mmuidx_async_1, runon);
289
+ } else {
290
+ TLBFlushPageBitsByMMUIdxData *p
291
+ = g_new(TLBFlushPageBitsByMMUIdxData, 1);
292
+
293
+ /* Otherwise allocate a structure, freed by the worker. */
294
+ *p = d;
295
+ async_run_on_cpu(cpu, tlb_flush_page_bits_by_mmuidx_async_2,
296
+ RUN_ON_CPU_HOST_PTR(p));
297
+ }
298
+}
299
+
300
+void tlb_flush_page_bits_by_mmuidx_all_cpus(CPUState *src_cpu,
301
+ target_ulong addr,
302
+ uint16_t idxmap,
303
+ unsigned bits)
304
+{
305
+ TLBFlushPageBitsByMMUIdxData d;
306
+ run_on_cpu_data runon;
307
+
308
+ /* If all bits are significant, this devolves to tlb_flush_page. */
309
+ if (bits >= TARGET_LONG_BITS) {
310
+ tlb_flush_page_by_mmuidx_all_cpus(src_cpu, addr, idxmap);
311
+ return;
312
+ }
313
+ /* If no page bits are significant, this devolves to tlb_flush. */
314
+ if (bits < TARGET_PAGE_BITS) {
315
+ tlb_flush_by_mmuidx_all_cpus(src_cpu, idxmap);
316
+ return;
317
+ }
318
+
319
+ /* This should already be page aligned */
320
+ d.addr = addr & TARGET_PAGE_MASK;
321
+ d.idxmap = idxmap;
322
+ d.bits = bits;
323
+
324
+ if (encode_pbm_to_runon(&runon, d)) {
325
+ flush_all_helper(src_cpu, tlb_flush_page_bits_by_mmuidx_async_1, runon);
326
+ } else {
327
+ CPUState *dst_cpu;
328
+ TLBFlushPageBitsByMMUIdxData *p;
329
+
330
+ /* Allocate a separate data block for each destination cpu. */
331
+ CPU_FOREACH(dst_cpu) {
332
+ if (dst_cpu != src_cpu) {
333
+ p = g_new(TLBFlushPageBitsByMMUIdxData, 1);
334
+ *p = d;
335
+ async_run_on_cpu(dst_cpu,
336
+ tlb_flush_page_bits_by_mmuidx_async_2,
337
+ RUN_ON_CPU_HOST_PTR(p));
338
+ }
339
+ }
340
+ }
341
+
342
+ tlb_flush_page_bits_by_mmuidx_async_0(src_cpu, d);
343
+}
344
+
345
+void tlb_flush_page_bits_by_mmuidx_all_cpus_synced(CPUState *src_cpu,
346
+ target_ulong addr,
347
+ uint16_t idxmap,
348
+ unsigned bits)
349
+{
350
+ TLBFlushPageBitsByMMUIdxData d;
351
+ run_on_cpu_data runon;
352
+
353
+ /* If all bits are significant, this devolves to tlb_flush_page. */
354
+ if (bits >= TARGET_LONG_BITS) {
355
+ tlb_flush_page_by_mmuidx_all_cpus_synced(src_cpu, addr, idxmap);
356
+ return;
357
+ }
358
+ /* If no page bits are significant, this devolves to tlb_flush. */
359
+ if (bits < TARGET_PAGE_BITS) {
360
+ tlb_flush_by_mmuidx_all_cpus_synced(src_cpu, idxmap);
361
+ return;
362
+ }
363
+
364
+ /* This should already be page aligned */
365
+ d.addr = addr & TARGET_PAGE_MASK;
366
+ d.idxmap = idxmap;
367
+ d.bits = bits;
368
+
369
+ if (encode_pbm_to_runon(&runon, d)) {
370
+ flush_all_helper(src_cpu, tlb_flush_page_bits_by_mmuidx_async_1, runon);
371
+ async_safe_run_on_cpu(src_cpu, tlb_flush_page_bits_by_mmuidx_async_1,
372
+ runon);
373
+ } else {
374
+ CPUState *dst_cpu;
375
+ TLBFlushPageBitsByMMUIdxData *p;
376
+
377
+ /* Allocate a separate data block for each destination cpu. */
378
+ CPU_FOREACH(dst_cpu) {
379
+ if (dst_cpu != src_cpu) {
380
+ p = g_new(TLBFlushPageBitsByMMUIdxData, 1);
381
+ *p = d;
382
+ async_run_on_cpu(dst_cpu, tlb_flush_page_bits_by_mmuidx_async_2,
383
+ RUN_ON_CPU_HOST_PTR(p));
384
+ }
385
+ }
386
+
387
+ p = g_new(TLBFlushPageBitsByMMUIdxData, 1);
388
+ *p = d;
389
+ async_safe_run_on_cpu(src_cpu, tlb_flush_page_bits_by_mmuidx_async_2,
390
+ RUN_ON_CPU_HOST_PTR(p));
391
+ }
392
+}
393
+
394
/* update the TLBs so that writes to code in the virtual page 'addr'
395
can be detected */
396
void tlb_protect_code(ram_addr_t ram_addr)
397
--
123
--
398
2.20.1
124
2.25.1
399
400
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
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.)
2
8
3
For BTI, we need to know if the executable is static or dynamic,
9
I don't have a reliable datasheet for this SoC, but since we do wire
4
which means looking for PT_INTERP earlier.
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.)
5
16
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
17
This bug didn't have any visible guest effects because the only
7
Message-id: 20201016184207.786698-8-richard.henderson@linaro.org
18
implemented device that was affected was the HDMI I2C controller,
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
19
and we never connect any I2C devices to that bus.
20
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
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
10
---
24
---
11
linux-user/elfload.c | 60 +++++++++++++++++++++++---------------------
25
hw/arm/exynos4210.c | 2 ++
12
1 file changed, 31 insertions(+), 29 deletions(-)
26
1 file changed, 2 insertions(+)
13
27
14
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
28
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
15
index XXXXXXX..XXXXXXX 100644
29
index XXXXXXX..XXXXXXX 100644
16
--- a/linux-user/elfload.c
30
--- a/hw/arm/exynos4210.c
17
+++ b/linux-user/elfload.c
31
+++ b/hw/arm/exynos4210.c
18
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
32
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init_board_irqs(Exynos4210State *s)
19
33
qdev_connect_gpio_out(splitter, 0, is->int_combiner_irq[n]);
20
mmap_lock();
34
qdev_connect_gpio_out(splitter, 1,
21
35
qdev_get_gpio_in(extgicdev, irq_id - 32));
22
- /* Find the maximum size of the image and allocate an appropriate
36
+ } else {
23
- amount of memory to handle that. */
37
+ s->irq_table[n] = is->int_combiner_irq[n];
24
+ /*
25
+ * Find the maximum size of the image and allocate an appropriate
26
+ * amount of memory to handle that. Locate the interpreter, if any.
27
+ */
28
loaddr = -1, hiaddr = 0;
29
info->alignment = 0;
30
for (i = 0; i < ehdr->e_phnum; ++i) {
31
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
32
}
33
++info->nsegs;
34
info->alignment |= eppnt->p_align;
35
+ } else if (eppnt->p_type == PT_INTERP && pinterp_name) {
36
+ g_autofree char *interp_name = NULL;
37
+
38
+ if (*pinterp_name) {
39
+ errmsg = "Multiple PT_INTERP entries";
40
+ goto exit_errmsg;
41
+ }
42
+ interp_name = g_malloc(eppnt->p_filesz);
43
+ if (!interp_name) {
44
+ goto exit_perror;
45
+ }
46
+
47
+ if (eppnt->p_offset + eppnt->p_filesz <= BPRM_BUF_SIZE) {
48
+ memcpy(interp_name, bprm_buf + eppnt->p_offset,
49
+ eppnt->p_filesz);
50
+ } else {
51
+ retval = pread(image_fd, interp_name, eppnt->p_filesz,
52
+ eppnt->p_offset);
53
+ if (retval != eppnt->p_filesz) {
54
+ goto exit_perror;
55
+ }
56
+ }
57
+ if (interp_name[eppnt->p_filesz - 1] != 0) {
58
+ errmsg = "Invalid PT_INTERP entry";
59
+ goto exit_errmsg;
60
+ }
61
+ *pinterp_name = g_steal_pointer(&interp_name);
62
}
38
}
63
}
39
}
64
40
/*
65
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
66
if (vaddr_em > info->brk) {
67
info->brk = vaddr_em;
68
}
69
- } else if (eppnt->p_type == PT_INTERP && pinterp_name) {
70
- g_autofree char *interp_name = NULL;
71
-
72
- if (*pinterp_name) {
73
- errmsg = "Multiple PT_INTERP entries";
74
- goto exit_errmsg;
75
- }
76
- interp_name = g_malloc(eppnt->p_filesz);
77
- if (!interp_name) {
78
- goto exit_perror;
79
- }
80
-
81
- if (eppnt->p_offset + eppnt->p_filesz <= BPRM_BUF_SIZE) {
82
- memcpy(interp_name, bprm_buf + eppnt->p_offset,
83
- eppnt->p_filesz);
84
- } else {
85
- retval = pread(image_fd, interp_name, eppnt->p_filesz,
86
- eppnt->p_offset);
87
- if (retval != eppnt->p_filesz) {
88
- goto exit_perror;
89
- }
90
- }
91
- if (interp_name[eppnt->p_filesz - 1] != 0) {
92
- errmsg = "Invalid PT_INTERP entry";
93
- goto exit_errmsg;
94
- }
95
- *pinterp_name = g_steal_pointer(&interp_name);
96
#ifdef TARGET_MIPS
97
} else if (eppnt->p_type == PT_MIPS_ABIFLAGS) {
98
Mips_elf_abiflags_v0 abiflags;
99
--
41
--
100
2.20.1
42
2.25.1
101
102
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
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.)
2
10
3
The second loop uses a loop induction variable, and the first
11
Wire these interrupts up to both combiners, like the rest.
4
does not. Transform the first to match the second, to simplify
5
a following patch moving code between them.
6
12
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Message-id: 20201016184207.786698-7-richard.henderson@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
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
11
---
16
---
12
linux-user/elfload.c | 9 +++++----
17
hw/arm/exynos4210.c | 7 +++----
13
1 file changed, 5 insertions(+), 4 deletions(-)
18
1 file changed, 3 insertions(+), 4 deletions(-)
14
19
15
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
20
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
16
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
17
--- a/linux-user/elfload.c
22
--- a/hw/arm/exynos4210.c
18
+++ b/linux-user/elfload.c
23
+++ b/hw/arm/exynos4210.c
19
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
24
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init_board_irqs(Exynos4210State *s)
20
loaddr = -1, hiaddr = 0;
25
21
info->alignment = 0;
26
assert(splitcount < EXYNOS4210_NUM_SPLITTERS);
22
for (i = 0; i < ehdr->e_phnum; ++i) {
27
splitter = DEVICE(&s->splitter[splitcount]);
23
- if (phdr[i].p_type == PT_LOAD) {
28
- qdev_prop_set_uint16(splitter, "num-lines", 2);
24
- abi_ulong a = phdr[i].p_vaddr - phdr[i].p_offset;
29
+ qdev_prop_set_uint16(splitter, "num-lines", irq_id ? 3 : 2);
25
+ struct elf_phdr *eppnt = phdr + i;
30
qdev_realize(splitter, NULL, &error_abort);
26
+ if (eppnt->p_type == PT_LOAD) {
31
splitcount++;
27
+ abi_ulong a = eppnt->p_vaddr - eppnt->p_offset;
32
s->irq_table[n] = qdev_get_gpio_in(splitter, 0);
28
if (a < loaddr) {
33
qdev_connect_gpio_out(splitter, 0, is->int_combiner_irq[n]);
29
loaddr = a;
34
+ qdev_connect_gpio_out(splitter, 1, is->ext_combiner_irq[n]);
30
}
35
if (irq_id) {
31
- a = phdr[i].p_vaddr + phdr[i].p_memsz;
36
- qdev_connect_gpio_out(splitter, 1,
32
+ a = eppnt->p_vaddr + eppnt->p_memsz;
37
+ qdev_connect_gpio_out(splitter, 2,
33
if (a > hiaddr) {
38
qdev_get_gpio_in(extgicdev, irq_id - 32));
34
hiaddr = a;
39
- } else {
35
}
40
- qdev_connect_gpio_out(splitter, 1, is->ext_combiner_irq[n]);
36
++info->nsegs;
37
- info->alignment |= phdr[i].p_align;
38
+ info->alignment |= eppnt->p_align;
39
}
41
}
40
}
42
}
41
43
for (; n < EXYNOS4210_MAX_INT_COMBINER_IN_IRQ; n++) {
42
--
44
--
43
2.20.1
45
2.25.1
44
45
diff view generated by jsdifflib
1
The SMLAD instruction is supposed to:
1
The combiner_grp_to_gic_id[] array includes the EXT_GIC_ID_MCT_G0
2
* signed multiply Rn[15:0] * Rm[15:0]
2
and EXT_GIC_ID_MCT_G1 multiple times. This means that we will
3
* signed multiply Rn[31:16] * Rm[31:16]
3
connect multiple IRQs up to the same external GIC input, which
4
* perform a signed addition of the products and Ra
4
is not permitted. We do the same thing in the code in
5
* set Rd to the low 32 bits of the theoretical
5
exynos4210_init_board_irqs() because the conditionals selecting
6
infinite-precision result
6
an irq_id in the first loop match multiple interrupt IDs.
7
* set the Q flag if the sign-extension of Rd
8
would differ from the infinite-precision result
9
(ie on overflow)
10
7
11
Our current implementation doesn't quite do this, though: it performs
8
Overall we do this for interrupt IDs
12
an addition of the products setting Q on overflow, and then it adds
9
(1, 4), (12, 4), (35, 4), (51, 4), (53, 4) for EXT_GIC_ID_MCT_G0
13
Ra, again possibly setting Q. This sometimes incorrectly sets Q when
10
and
14
the architecturally mandated only-check-for-overflow-once algorithm
11
(1, 5), (12, 5), (35, 5), (51, 5), (53, 5) for EXT_GIC_ID_MCT_G1
15
does not. For instance:
16
r1 = 0x80008000; r2 = 0x80008000; r3 = 0xffffffff
17
smlad r0, r1, r2, r3
18
This is (-32768 * -32768) + (-32768 * -32768) - 1
19
12
20
The products are both 0x4000_0000, so when added together as 32-bit
13
These correspond to the cases for the multi-core timer that we are
21
signed numbers they overflow (and QEMU sets Q), but because the
14
wiring up to multiple inputs on the combiner in
22
addition of Ra == -1 brings the total back down to 0x7fff_ffff
15
exynos4210_combiner_get_gpioin(). That code already deals with all
23
there is no overflow for the complete operation and setting Q is
16
these interrupt IDs being the same input source, so we don't need to
24
incorrect.
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.
25
20
26
Fix this edge case by resorting to 64-bit arithmetic for the
21
This bug didn't cause any visible effects, because we only connect
27
case where we need to add three values together.
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.
28
24
29
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
25
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
30
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
26
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
31
Message-id: 20201009144712.11187-1-peter.maydell@linaro.org
27
Message-id: 20220404154658.565020-16-peter.maydell@linaro.org
32
---
28
---
33
target/arm/translate.c | 58 ++++++++++++++++++++++++++++++++++--------
29
include/hw/arm/exynos4210.h | 2 +-
34
1 file changed, 48 insertions(+), 10 deletions(-)
30
hw/arm/exynos4210.c | 12 +++++-------
31
2 files changed, 6 insertions(+), 8 deletions(-)
35
32
36
diff --git a/target/arm/translate.c b/target/arm/translate.c
33
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
37
index XXXXXXX..XXXXXXX 100644
34
index XXXXXXX..XXXXXXX 100644
38
--- a/target/arm/translate.c
35
--- a/include/hw/arm/exynos4210.h
39
+++ b/target/arm/translate.c
36
+++ b/include/hw/arm/exynos4210.h
40
@@ -XXX,XX +XXX,XX @@ static bool op_smlad(DisasContext *s, arg_rrrr *a, bool m_swap, bool sub)
37
@@ -XXX,XX +XXX,XX @@
41
gen_smul_dual(t1, t2);
38
* one for every non-zero entry in combiner_grp_to_gic_id[].
42
39
* We'll assert in exynos4210_init_board_irqs() if this is wrong.
43
if (sub) {
40
*/
44
- /* This subtraction cannot overflow. */
41
-#define EXYNOS4210_NUM_SPLITTERS (EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ + 60)
45
+ /*
42
+#define EXYNOS4210_NUM_SPLITTERS (EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ + 54)
46
+ * This subtraction cannot overflow, so we can do a simple
43
47
+ * 32-bit subtraction and then a possible 32-bit saturating
44
typedef struct Exynos4210Irq {
48
+ * addition of Ra.
45
qemu_irq int_combiner_irq[EXYNOS4210_MAX_INT_COMBINER_IN_IRQ];
49
+ */
46
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
50
tcg_gen_sub_i32(t1, t1, t2);
47
index XXXXXXX..XXXXXXX 100644
51
+ tcg_temp_free_i32(t2);
48
--- a/hw/arm/exynos4210.c
52
+
49
+++ b/hw/arm/exynos4210.c
53
+ if (a->ra != 15) {
50
@@ -XXX,XX +XXX,XX @@ combiner_grp_to_gic_id[64 - EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][8] = {
54
+ t2 = load_reg(s, a->ra);
51
/* int combiner group 34 */
55
+ gen_helper_add_setq(t1, cpu_env, t1, t2);
52
{ EXT_GIC_ID_ONENAND_AUDI, EXT_GIC_ID_NFC },
56
+ tcg_temp_free_i32(t2);
53
/* int combiner group 35 */
57
+ }
54
- { 0, 0, 0, EXT_GIC_ID_MCT_L1, EXT_GIC_ID_MCT_G0, EXT_GIC_ID_MCT_G1 },
58
+ } else if (a->ra == 15) {
55
+ { 0, 0, 0, EXT_GIC_ID_MCT_L1 },
59
+ /* Single saturation-checking addition */
56
/* int combiner group 36 */
60
+ gen_helper_add_setq(t1, cpu_env, t1, t2);
57
{ EXT_GIC_ID_MIXER },
61
+ tcg_temp_free_i32(t2);
58
/* int combiner group 37 */
62
} else {
59
@@ -XXX,XX +XXX,XX @@ combiner_grp_to_gic_id[64 - EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][8] = {
63
/*
60
/* groups 38-50 */
64
- * This addition cannot overflow 32 bits; however it may
61
{ }, { }, { }, { }, { }, { }, { }, { }, { }, { }, { }, { }, { },
65
- * overflow considered as a signed operation, in which case
62
/* int combiner group 51 */
66
- * we must set the Q flag.
63
- { EXT_GIC_ID_MCT_L0, 0, 0, 0, EXT_GIC_ID_MCT_G0, EXT_GIC_ID_MCT_G1 },
67
+ * We need to add the products and Ra together and then
64
+ { EXT_GIC_ID_MCT_L0 },
68
+ * determine whether the final result overflowed. Doing
65
/* group 52 */
69
+ * this as two separate add-and-check-overflow steps incorrectly
66
{ },
70
+ * sets Q for cases like (-32768 * -32768) + (-32768 * -32768) + -1.
67
/* int combiner group 53 */
71
+ * Do all the arithmetic at 64-bits and then check for overflow.
68
- { EXT_GIC_ID_WDT, 0, 0, 0, EXT_GIC_ID_MCT_G0, EXT_GIC_ID_MCT_G1 },
72
*/
69
+ { EXT_GIC_ID_WDT },
73
- gen_helper_add_setq(t1, cpu_env, t1, t2);
70
/* groups 54-63 */
74
- }
71
{ }, { }, { }, { }, { }, { }, { }, { }, { }, { }
75
- tcg_temp_free_i32(t2);
72
};
76
+ TCGv_i64 p64, q64;
73
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init_board_irqs(Exynos4210State *s)
77
+ TCGv_i32 t3, qf, one;
74
78
75
for (n = 0; n < EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ; n++) {
79
- if (a->ra != 15) {
76
irq_id = 0;
80
- t2 = load_reg(s, a->ra);
77
- if (n == EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 4) ||
81
- gen_helper_add_setq(t1, cpu_env, t1, t2);
78
- n == EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 4)) {
82
+ p64 = tcg_temp_new_i64();
79
+ if (n == EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 4)) {
83
+ q64 = tcg_temp_new_i64();
80
/* MCT_G0 is passed to External GIC */
84
+ tcg_gen_ext_i32_i64(p64, t1);
81
irq_id = EXT_GIC_ID_MCT_G0;
85
+ tcg_gen_ext_i32_i64(q64, t2);
82
}
86
+ tcg_gen_add_i64(p64, p64, q64);
83
- if (n == EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 5) ||
87
+ load_reg_var(s, t2, a->ra);
84
- n == EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 5)) {
88
+ tcg_gen_ext_i32_i64(q64, t2);
85
+ if (n == EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 5)) {
89
+ tcg_gen_add_i64(p64, p64, q64);
86
/* MCT_G1 is passed to External and GIC */
90
+ tcg_temp_free_i64(q64);
87
irq_id = EXT_GIC_ID_MCT_G1;
91
+
88
}
92
+ tcg_gen_extr_i64_i32(t1, t2, p64);
93
+ tcg_temp_free_i64(p64);
94
+ /*
95
+ * t1 is the low half of the result which goes into Rd.
96
+ * We have overflow and must set Q if the high half (t2)
97
+ * is different from the sign-extension of t1.
98
+ */
99
+ t3 = tcg_temp_new_i32();
100
+ tcg_gen_sari_i32(t3, t1, 31);
101
+ qf = load_cpu_field(QF);
102
+ one = tcg_const_i32(1);
103
+ tcg_gen_movcond_i32(TCG_COND_NE, qf, t2, t3, one, qf);
104
+ store_cpu_field(qf, QF);
105
+ tcg_temp_free_i32(one);
106
+ tcg_temp_free_i32(t3);
107
tcg_temp_free_i32(t2);
108
}
109
store_reg(s, a->rd, t1);
110
--
89
--
111
2.20.1
90
2.25.1
112
113
diff view generated by jsdifflib
1
v8.1M implements a new 'branch future' feature, which is a
1
At this point, the function exynos4210_init_board_irqs() splits input
2
set of instructions that request the CPU to perform a branch
2
IRQ lines to connect them to the input combiner, output combiner and
3
"in the future", when it reaches a particular execution address.
3
external GIC. The function exynos4210_combiner_get_gpioin() splits
4
In hardware, the expected implementation is that the information
4
some of the combiner input lines further to connect them to multiple
5
about the branch location and destination is cached and then
5
different inputs on the combiner.
6
acted upon when execution reaches the specified address.
6
7
However the architecture permits an implementation to discard
7
Because (unlike qemu_irq_split()) the TYPE_SPLIT_IRQ device has a
8
this cached information at any point, and so guest code must
8
configurable number of outputs, we can do all this in one place, by
9
always include a normal branch insn at the branch point as
9
making exynos4210_init_board_irqs() add extra outputs to the splitter
10
a fallback. In particular, an implementation is specifically
10
device when it must be connected to more than one input on each
11
permitted to treat all BF insns as NOPs (which is equivalent
11
combiner.
12
to discarding the cached information immediately).
12
13
13
We do this with a new data structure, the combinermap, which is an
14
For QEMU, implementing this caching of branch information
14
array each of whose elements is a list of the interrupt IDs on the
15
would be complicated and would not improve the speed of
15
combiner which must be tied together. As we loop through each
16
execution at all, so we make the IMPDEF choice to implement
16
interrupt ID, if we find that it is the first one in one of these
17
all BF insns as NOPs.
17
lists, we configure the splitter device with eonugh extra outputs and
18
18
wire them up to the other interrupt IDs in the list.
19
20
Conveniently, for all the cases where this is necessary, the
21
lowest-numbered interrupt ID in each group is in the range of the
22
external combiner, so we only need to code for this in the first of
23
the two loops in exynos4210_init_board_irqs().
24
25
The old code in exynos4210_combiner_get_gpioin() which is being
26
deleted here had several problems which don't exist in the new code
27
in its handling of the multi-core timer interrupts:
28
(1) the case labels specified bits 4 ... 8, but bit '8' doesn't
29
exist; these should have been 4 ... 7
30
(2) it used the input irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(1, bit + 4)]
31
multiple times as the input of several different splitters,
32
which isn't allowed
33
(3) in an apparent cut-and-paste error, the cases for all the
34
multi-core timer inputs used "bit + 4" even though the
35
bit range for the case was (intended to be) 4 ... 7, which
36
meant it was looking at non-existent bits 8 ... 11.
37
None of these exist in the new code.
38
39
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
40
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
20
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
41
Message-id: 20220404154658.565020-17-peter.maydell@linaro.org
21
Message-id: 20201019151301.2046-7-peter.maydell@linaro.org
22
---
42
---
23
target/arm/cpu.h | 6 ++++++
43
include/hw/arm/exynos4210.h | 6 +-
24
target/arm/t32.decode | 13 ++++++++++++-
44
hw/arm/exynos4210.c | 178 +++++++++++++++++++++++-------------
25
target/arm/translate.c | 20 ++++++++++++++++++++
45
2 files changed, 119 insertions(+), 65 deletions(-)
26
3 files changed, 38 insertions(+), 1 deletion(-)
46
27
47
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
28
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
29
index XXXXXXX..XXXXXXX 100644
48
index XXXXXXX..XXXXXXX 100644
30
--- a/target/arm/cpu.h
49
--- a/include/hw/arm/exynos4210.h
31
+++ b/target/arm/cpu.h
50
+++ b/include/hw/arm/exynos4210.h
32
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa32_arm_div(const ARMISARegisters *id)
51
@@ -XXX,XX +XXX,XX @@
33
return FIELD_EX32(id->id_isar0, ID_ISAR0, DIVIDE) > 1;
52
34
}
53
/*
35
54
* We need one splitter for every external combiner input, plus
36
+static inline bool isar_feature_aa32_lob(const ARMISARegisters *id)
55
- * one for every non-zero entry in combiner_grp_to_gic_id[].
37
+{
56
+ * one for every non-zero entry in combiner_grp_to_gic_id[],
38
+ /* (M-profile) low-overhead loops and branch future */
57
+ * minus one for every external combiner ID in second or later
39
+ return FIELD_EX32(id->id_isar0, ID_ISAR0, CMPBRANCH) >= 3;
58
+ * places in a combinermap[] line.
40
+}
59
* We'll assert in exynos4210_init_board_irqs() if this is wrong.
41
+
60
*/
42
static inline bool isar_feature_aa32_jazelle(const ARMISARegisters *id)
61
-#define EXYNOS4210_NUM_SPLITTERS (EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ + 54)
43
{
62
+#define EXYNOS4210_NUM_SPLITTERS (EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ + 38)
44
return FIELD_EX32(id->id_isar1, ID_ISAR1, JAZELLE) != 0;
63
45
diff --git a/target/arm/t32.decode b/target/arm/t32.decode
64
typedef struct Exynos4210Irq {
65
qemu_irq int_combiner_irq[EXYNOS4210_MAX_INT_COMBINER_IN_IRQ];
66
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
46
index XXXXXXX..XXXXXXX 100644
67
index XXXXXXX..XXXXXXX 100644
47
--- a/target/arm/t32.decode
68
--- a/hw/arm/exynos4210.c
48
+++ b/target/arm/t32.decode
69
+++ b/hw/arm/exynos4210.c
49
@@ -XXX,XX +XXX,XX @@ MRC 1110 1110 ... 1 .... .... .... ... 1 .... @mcr
70
@@ -XXX,XX +XXX,XX @@ combiner_grp_to_gic_id[64 - EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][8] = {
50
71
#define EXYNOS4210_COMBINER_GET_BIT_NUM(irq) \
51
B 1111 0. .......... 10.1 ............ @branch24
72
((irq) - 8 * EXYNOS4210_COMBINER_GET_GRP_NUM(irq))
52
BL 1111 0. .......... 11.1 ............ @branch24
73
53
-BLX_i 1111 0. .......... 11.0 ............ @branch24
74
+/*
54
+{
75
+ * Some interrupt lines go to multiple combiner inputs.
55
+ # BLX_i is non-M-profile only
76
+ * This data structure defines those: each array element is
56
+ BLX_i 1111 0. .......... 11.0 ............ @branch24
77
+ * a list of combiner inputs which are connected together;
57
+ # M-profile only: loop and branch insns
78
+ * the one with the smallest interrupt ID value must be first.
58
+ [
79
+ * As with combiner_grp_to_gic_id[], we rely on (0, 0) not being
59
+ # All these BF insns have boff != 0b0000; we NOP them all
80
+ * wired to anything so we can use 0 as a terminator.
60
+ BF 1111 0 boff:4 ------- 1100 - ---------- 1 # BFL
81
+ */
61
+ BF 1111 0 boff:4 0 ------ 1110 - ---------- 1 # BFCSEL
82
+#define IRQNO(G, B) EXYNOS4210_COMBINER_GET_IRQ_NUM(G, B)
62
+ BF 1111 0 boff:4 10 ----- 1110 - ---------- 1 # BF
83
+#define IRQNONE 0
63
+ BF 1111 0 boff:4 11 ----- 1110 0 0000000000 1 # BFX, BFLX
84
+
64
+ ]
85
+#define COMBINERMAP_SIZE 16
65
+}
86
+
66
diff --git a/target/arm/translate.c b/target/arm/translate.c
87
+static const int combinermap[COMBINERMAP_SIZE][6] = {
67
index XXXXXXX..XXXXXXX 100644
88
+ /* MDNIE_LCD1 */
68
--- a/target/arm/translate.c
89
+ { IRQNO(0, 4), IRQNO(1, 0), IRQNONE },
69
+++ b/target/arm/translate.c
90
+ { IRQNO(0, 5), IRQNO(1, 1), IRQNONE },
70
@@ -XXX,XX +XXX,XX @@ static bool trans_BLX_suffix(DisasContext *s, arg_BLX_suffix *a)
91
+ { IRQNO(0, 6), IRQNO(1, 2), IRQNONE },
71
return true;
92
+ { IRQNO(0, 7), IRQNO(1, 3), IRQNONE },
72
}
93
+ /* TMU */
73
94
+ { IRQNO(2, 4), IRQNO(3, 4), IRQNONE },
74
+static bool trans_BF(DisasContext *s, arg_BF *a)
95
+ { IRQNO(2, 5), IRQNO(3, 5), IRQNONE },
96
+ { IRQNO(2, 6), IRQNO(3, 6), IRQNONE },
97
+ { IRQNO(2, 7), IRQNO(3, 7), IRQNONE },
98
+ /* LCD1 */
99
+ { IRQNO(11, 4), IRQNO(12, 0), IRQNONE },
100
+ { IRQNO(11, 5), IRQNO(12, 1), IRQNONE },
101
+ { IRQNO(11, 6), IRQNO(12, 2), IRQNONE },
102
+ { IRQNO(11, 7), IRQNO(12, 3), IRQNONE },
103
+ /* Multi-core timer */
104
+ { IRQNO(1, 4), IRQNO(12, 4), IRQNO(35, 4), IRQNO(51, 4), IRQNO(53, 4), IRQNONE },
105
+ { IRQNO(1, 5), IRQNO(12, 5), IRQNO(35, 5), IRQNO(51, 5), IRQNO(53, 5), IRQNONE },
106
+ { IRQNO(1, 6), IRQNO(12, 6), IRQNO(35, 6), IRQNO(51, 6), IRQNO(53, 6), IRQNONE },
107
+ { IRQNO(1, 7), IRQNO(12, 7), IRQNO(35, 7), IRQNO(51, 7), IRQNO(53, 7), IRQNONE },
108
+};
109
+
110
+#undef IRQNO
111
+
112
+static const int *combinermap_entry(int irq)
75
+{
113
+{
76
+ /*
114
+ /*
77
+ * M-profile branch future insns. The architecture permits an
115
+ * If the interrupt number passed in is the first entry in some
78
+ * implementation to implement these as NOPs (equivalent to
116
+ * line of the combinermap, return a pointer to that line;
79
+ * discarding the LO_BRANCH_INFO cache immediately), and we
117
+ * otherwise return NULL.
80
+ * take that IMPDEF option because for QEMU a "real" implementation
81
+ * would be complicated and wouldn't execute any faster.
82
+ */
118
+ */
83
+ if (!dc_isar_feature(aa32_lob, s)) {
119
+ int i;
84
+ return false;
120
+ for (i = 0; i < COMBINERMAP_SIZE; i++) {
121
+ if (combinermap[i][0] == irq) {
122
+ return combinermap[i];
123
+ }
85
+ }
124
+ }
86
+ if (a->boff == 0) {
125
+ return NULL;
87
+ /* SEE "Related encodings" (loop insns) */
126
+}
88
+ return false;
127
+
128
+static int mapline_size(const int *mapline)
129
+{
130
+ /* Return number of entries in this mapline in total */
131
+ int i = 0;
132
+
133
+ if (!mapline) {
134
+ /* Not in the map? IRQ goes to exactly one combiner input */
135
+ return 1;
89
+ }
136
+ }
90
+ /* Handle as NOP */
137
+ while (*mapline != IRQNONE) {
91
+ return true;
138
+ mapline++;
139
+ i++;
140
+ }
141
+ return i;
92
+}
142
+}
93
+
143
+
94
static bool op_tbranch(DisasContext *s, arg_tbranch *a, bool half)
144
/*
145
* Initialize board IRQs.
146
* These IRQs contain splitted Int/External Combiner and External Gic IRQs.
147
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init_board_irqs(Exynos4210State *s)
148
DeviceState *extgicdev = DEVICE(&s->ext_gic);
149
int splitcount = 0;
150
DeviceState *splitter;
151
+ const int *mapline;
152
+ int numlines, splitin, in;
153
154
for (n = 0; n < EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ; n++) {
155
irq_id = 0;
156
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init_board_irqs(Exynos4210State *s)
157
irq_id = EXT_GIC_ID_MCT_G1;
158
}
159
160
+ if (s->irq_table[n]) {
161
+ /*
162
+ * This must be some non-first entry in a combinermap line,
163
+ * and we've already filled it in.
164
+ */
165
+ continue;
166
+ }
167
+ mapline = combinermap_entry(n);
168
+ /*
169
+ * We need to connect the IRQ to multiple inputs on both combiners
170
+ * and possibly also to the external GIC.
171
+ */
172
+ numlines = 2 * mapline_size(mapline);
173
+ if (irq_id) {
174
+ numlines++;
175
+ }
176
assert(splitcount < EXYNOS4210_NUM_SPLITTERS);
177
splitter = DEVICE(&s->splitter[splitcount]);
178
- qdev_prop_set_uint16(splitter, "num-lines", irq_id ? 3 : 2);
179
+ qdev_prop_set_uint16(splitter, "num-lines", numlines);
180
qdev_realize(splitter, NULL, &error_abort);
181
splitcount++;
182
- s->irq_table[n] = qdev_get_gpio_in(splitter, 0);
183
- qdev_connect_gpio_out(splitter, 0, is->int_combiner_irq[n]);
184
- qdev_connect_gpio_out(splitter, 1, is->ext_combiner_irq[n]);
185
+
186
+ in = n;
187
+ splitin = 0;
188
+ for (;;) {
189
+ s->irq_table[in] = qdev_get_gpio_in(splitter, 0);
190
+ qdev_connect_gpio_out(splitter, splitin, is->int_combiner_irq[in]);
191
+ qdev_connect_gpio_out(splitter, splitin + 1, is->ext_combiner_irq[in]);
192
+ splitin += 2;
193
+ if (!mapline) {
194
+ break;
195
+ }
196
+ mapline++;
197
+ in = *mapline;
198
+ if (in == IRQNONE) {
199
+ break;
200
+ }
201
+ }
202
if (irq_id) {
203
- qdev_connect_gpio_out(splitter, 2,
204
+ qdev_connect_gpio_out(splitter, splitin,
205
qdev_get_gpio_in(extgicdev, irq_id - 32));
206
}
207
}
208
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init_board_irqs(Exynos4210State *s)
209
irq_id = combiner_grp_to_gic_id[grp -
210
EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][bit];
211
212
+ if (s->irq_table[n]) {
213
+ /*
214
+ * This must be some non-first entry in a combinermap line,
215
+ * and we've already filled it in.
216
+ */
217
+ continue;
218
+ }
219
+
220
if (irq_id) {
221
assert(splitcount < EXYNOS4210_NUM_SPLITTERS);
222
splitter = DEVICE(&s->splitter[splitcount]);
223
@@ -XXX,XX +XXX,XX @@ static void exynos4210_combiner_get_gpioin(Exynos4210Irq *irqs,
224
DeviceState *dev, int ext)
95
{
225
{
96
TCGv_i32 addr, tmp;
226
int n;
227
- int bit;
228
int max;
229
qemu_irq *irq;
230
231
@@ -XXX,XX +XXX,XX @@ static void exynos4210_combiner_get_gpioin(Exynos4210Irq *irqs,
232
EXYNOS4210_MAX_INT_COMBINER_IN_IRQ;
233
irq = ext ? irqs->ext_combiner_irq : irqs->int_combiner_irq;
234
235
- /*
236
- * Some IRQs of Int/External Combiner are going to two Combiners groups,
237
- * so let split them.
238
- */
239
for (n = 0; n < max; n++) {
240
-
241
- bit = EXYNOS4210_COMBINER_GET_BIT_NUM(n);
242
-
243
- switch (n) {
244
- /* MDNIE_LCD1 INTG1 */
245
- case EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 0) ...
246
- EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 3):
247
- irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
248
- irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(0, bit + 4)]);
249
- continue;
250
-
251
- /* TMU INTG3 */
252
- case EXYNOS4210_COMBINER_GET_IRQ_NUM(3, 4):
253
- irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
254
- irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(2, bit)]);
255
- continue;
256
-
257
- /* LCD1 INTG12 */
258
- case EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 0) ...
259
- EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 3):
260
- irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
261
- irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(11, bit + 4)]);
262
- continue;
263
-
264
- /* Multi-Core Timer INTG12 */
265
- case EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 4) ...
266
- EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 8):
267
- irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
268
- irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(1, bit + 4)]);
269
- continue;
270
-
271
- /* Multi-Core Timer INTG35 */
272
- case EXYNOS4210_COMBINER_GET_IRQ_NUM(35, 4) ...
273
- EXYNOS4210_COMBINER_GET_IRQ_NUM(35, 8):
274
- irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
275
- irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(1, bit + 4)]);
276
- continue;
277
-
278
- /* Multi-Core Timer INTG51 */
279
- case EXYNOS4210_COMBINER_GET_IRQ_NUM(51, 4) ...
280
- EXYNOS4210_COMBINER_GET_IRQ_NUM(51, 8):
281
- irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
282
- irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(1, bit + 4)]);
283
- continue;
284
-
285
- /* Multi-Core Timer INTG53 */
286
- case EXYNOS4210_COMBINER_GET_IRQ_NUM(53, 4) ...
287
- EXYNOS4210_COMBINER_GET_IRQ_NUM(53, 8):
288
- irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
289
- irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(1, bit + 4)]);
290
- continue;
291
- }
292
-
293
irq[n] = qdev_get_gpio_in(dev, n);
294
}
295
}
97
--
296
--
98
2.20.1
297
2.25.1
99
100
diff view generated by jsdifflib
1
From: Havard Skinnemoen <hskinnemoen@google.com>
1
Switch the creation of the combiner devices to the new-style
2
"embedded in state struct" approach, so we can easily refer
3
to the object elsewhere during realize.
2
4
3
This test exercises the various modes of the npcm7xx timer. In
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
particular, it triggers the bug found by the fuzzer, as reported here:
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20220404154658.565020-18-peter.maydell@linaro.org
8
---
9
include/hw/arm/exynos4210.h | 3 ++
10
include/hw/intc/exynos4210_combiner.h | 57 +++++++++++++++++++++++++++
11
hw/arm/exynos4210.c | 20 +++++-----
12
hw/intc/exynos4210_combiner.c | 31 +--------------
13
4 files changed, 72 insertions(+), 39 deletions(-)
14
create mode 100644 include/hw/intc/exynos4210_combiner.h
5
15
6
https://lists.gnu.org/archive/html/qemu-devel/2020-09/msg02992.html
16
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
7
17
index XXXXXXX..XXXXXXX 100644
8
It also found several other bugs, especially related to interrupt
18
--- a/include/hw/arm/exynos4210.h
9
handling.
19
+++ b/include/hw/arm/exynos4210.h
10
20
@@ -XXX,XX +XXX,XX @@
11
The test exercises all the timers in all the timer modules, which
21
#include "hw/sysbus.h"
12
expands to 180 test cases in total.
22
#include "hw/cpu/a9mpcore.h"
13
23
#include "hw/intc/exynos4210_gic.h"
14
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
24
+#include "hw/intc/exynos4210_combiner.h"
15
Signed-off-by: Havard Skinnemoen <hskinnemoen@google.com>
25
#include "hw/core/split-irq.h"
16
Message-id: 20201008232154.94221-2-hskinnemoen@google.com
26
#include "target/arm/cpu-qom.h"
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
27
#include "qom/object.h"
18
---
28
@@ -XXX,XX +XXX,XX @@ struct Exynos4210State {
19
tests/qtest/npcm7xx_timer-test.c | 562 +++++++++++++++++++++++++++++++
29
qemu_or_irq cpu_irq_orgate[EXYNOS4210_NCPUS];
20
tests/qtest/meson.build | 1 +
30
A9MPPrivState a9mpcore;
21
2 files changed, 563 insertions(+)
31
Exynos4210GicState ext_gic;
22
create mode 100644 tests/qtest/npcm7xx_timer-test.c
32
+ Exynos4210CombinerState int_combiner;
23
33
+ Exynos4210CombinerState ext_combiner;
24
diff --git a/tests/qtest/npcm7xx_timer-test.c b/tests/qtest/npcm7xx_timer-test.c
34
SplitIRQ splitter[EXYNOS4210_NUM_SPLITTERS];
35
};
36
37
diff --git a/include/hw/intc/exynos4210_combiner.h b/include/hw/intc/exynos4210_combiner.h
25
new file mode 100644
38
new file mode 100644
26
index XXXXXXX..XXXXXXX
39
index XXXXXXX..XXXXXXX
27
--- /dev/null
40
--- /dev/null
28
+++ b/tests/qtest/npcm7xx_timer-test.c
41
+++ b/include/hw/intc/exynos4210_combiner.h
29
@@ -XXX,XX +XXX,XX @@
42
@@ -XXX,XX +XXX,XX @@
30
+/*
43
+/*
31
+ * QTest testcase for the Nuvoton NPCM7xx Timer
44
+ * Samsung exynos4210 Interrupt Combiner
32
+ *
45
+ *
33
+ * Copyright 2020 Google LLC
46
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd.
47
+ * All rights reserved.
48
+ *
49
+ * Evgeny Voevodin <e.voevodin@samsung.com>
34
+ *
50
+ *
35
+ * This program is free software; you can redistribute it and/or modify it
51
+ * This program is free software; you can redistribute it and/or modify it
36
+ * under the terms of the GNU General Public License as published by the
52
+ * under the terms of the GNU General Public License as published by the
37
+ * Free Software Foundation; either version 2 of the License, or
53
+ * Free Software Foundation; either version 2 of the License, or (at your
38
+ * (at your option) any later version.
54
+ * option) any later version.
39
+ *
55
+ *
40
+ * This program is distributed in the hope that it will be useful, but WITHOUT
56
+ * This program is distributed in the hope that it will be useful,
41
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
57
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
42
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
58
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
43
+ * for more details.
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/>.
44
+ */
63
+ */
45
+
64
+
46
+#include "qemu/osdep.h"
65
+#ifndef HW_INTC_EXYNOS4210_COMBINER
47
+#include "qemu/timer.h"
66
+#define HW_INTC_EXYNOS4210_COMBINER
48
+#include "libqtest-single.h"
49
+
67
+
50
+#define TIM_REF_HZ (25000000)
68
+#include "hw/sysbus.h"
51
+
69
+
52
+/* Bits in TCSRx */
70
+/*
53
+#define CEN BIT(30)
71
+ * State for each output signal of internal combiner
54
+#define IE BIT(29)
72
+ */
55
+#define MODE_ONESHOT (0 << 27)
73
+typedef struct CombinerGroupState {
56
+#define MODE_PERIODIC (1 << 27)
74
+ uint8_t src_mask; /* 1 - source enabled, 0 - disabled */
57
+#define CRST BIT(26)
75
+ uint8_t src_pending; /* Pending source interrupts before masking */
58
+#define CACT BIT(25)
76
+} CombinerGroupState;
59
+#define PRESCALE(x) (x)
60
+
77
+
61
+/* Registers shared between all timers in a module. */
78
+#define TYPE_EXYNOS4210_COMBINER "exynos4210.combiner"
62
+#define TISR 0x18
79
+OBJECT_DECLARE_SIMPLE_TYPE(Exynos4210CombinerState, EXYNOS4210_COMBINER)
63
+#define WTCR 0x1c
64
+# define WTCLK(x) ((x) << 10)
65
+
80
+
66
+/* Power-on default; used to re-initialize timers before each test. */
81
+/* Number of groups and total number of interrupts for the internal combiner */
67
+#define TCSR_DEFAULT PRESCALE(5)
82
+#define IIC_NGRP 64
83
+#define IIC_NIRQ (IIC_NGRP * 8)
84
+#define IIC_REGSET_SIZE 0x41
68
+
85
+
69
+/* Register offsets for a timer within a timer block. */
86
+struct Exynos4210CombinerState {
70
+typedef struct Timer {
87
+ SysBusDevice parent_obj;
71
+ unsigned int tcsr_offset;
72
+ unsigned int ticr_offset;
73
+ unsigned int tdr_offset;
74
+} Timer;
75
+
88
+
76
+/* A timer block containing 5 timers. */
89
+ MemoryRegion iomem;
77
+typedef struct TimerBlock {
78
+ int irq_base;
79
+ uint64_t base_addr;
80
+} TimerBlock;
81
+
90
+
82
+/* Testdata for testing a particular timer within a timer block. */
91
+ struct CombinerGroupState group[IIC_NGRP];
83
+typedef struct TestData {
92
+ uint32_t reg_set[IIC_REGSET_SIZE];
84
+ const TimerBlock *tim;
93
+ uint32_t icipsr[2];
85
+ const Timer *timer;
94
+ uint32_t external; /* 1 means that this combiner is external */
86
+} TestData;
87
+
95
+
88
+const TimerBlock timer_block[] = {
96
+ qemu_irq output_irq[IIC_NGRP];
89
+ {
90
+ .irq_base = 32,
91
+ .base_addr = 0xf0008000,
92
+ },
93
+ {
94
+ .irq_base = 37,
95
+ .base_addr = 0xf0009000,
96
+ },
97
+ {
98
+ .irq_base = 42,
99
+ .base_addr = 0xf000a000,
100
+ },
101
+};
97
+};
102
+
98
+
103
+const Timer timer[] = {
99
+#endif
104
+ {
100
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
105
+ .tcsr_offset = 0x00,
106
+ .ticr_offset = 0x08,
107
+ .tdr_offset = 0x10,
108
+ }, {
109
+ .tcsr_offset = 0x04,
110
+ .ticr_offset = 0x0c,
111
+ .tdr_offset = 0x14,
112
+ }, {
113
+ .tcsr_offset = 0x20,
114
+ .ticr_offset = 0x28,
115
+ .tdr_offset = 0x30,
116
+ }, {
117
+ .tcsr_offset = 0x24,
118
+ .ticr_offset = 0x2c,
119
+ .tdr_offset = 0x34,
120
+ }, {
121
+ .tcsr_offset = 0x40,
122
+ .ticr_offset = 0x48,
123
+ .tdr_offset = 0x50,
124
+ },
125
+};
126
+
127
+/* Returns the index of the timer block. */
128
+static int tim_index(const TimerBlock *tim)
129
+{
130
+ ptrdiff_t diff = tim - timer_block;
131
+
132
+ g_assert(diff >= 0 && diff < ARRAY_SIZE(timer_block));
133
+
134
+ return diff;
135
+}
136
+
137
+/* Returns the index of a timer within a timer block. */
138
+static int timer_index(const Timer *t)
139
+{
140
+ ptrdiff_t diff = t - timer;
141
+
142
+ g_assert(diff >= 0 && diff < ARRAY_SIZE(timer));
143
+
144
+ return diff;
145
+}
146
+
147
+/* Returns the irq line for a given timer. */
148
+static int tim_timer_irq(const TestData *td)
149
+{
150
+ return td->tim->irq_base + timer_index(td->timer);
151
+}
152
+
153
+/* Register read/write accessors. */
154
+
155
+static void tim_write(const TestData *td,
156
+ unsigned int offset, uint32_t value)
157
+{
158
+ writel(td->tim->base_addr + offset, value);
159
+}
160
+
161
+static uint32_t tim_read(const TestData *td, unsigned int offset)
162
+{
163
+ return readl(td->tim->base_addr + offset);
164
+}
165
+
166
+static void tim_write_tcsr(const TestData *td, uint32_t value)
167
+{
168
+ tim_write(td, td->timer->tcsr_offset, value);
169
+}
170
+
171
+static uint32_t tim_read_tcsr(const TestData *td)
172
+{
173
+ return tim_read(td, td->timer->tcsr_offset);
174
+}
175
+
176
+static void tim_write_ticr(const TestData *td, uint32_t value)
177
+{
178
+ tim_write(td, td->timer->ticr_offset, value);
179
+}
180
+
181
+static uint32_t tim_read_ticr(const TestData *td)
182
+{
183
+ return tim_read(td, td->timer->ticr_offset);
184
+}
185
+
186
+static uint32_t tim_read_tdr(const TestData *td)
187
+{
188
+ return tim_read(td, td->timer->tdr_offset);
189
+}
190
+
191
+/* Returns the number of nanoseconds to count the given number of cycles. */
192
+static int64_t tim_calculate_step(uint32_t count, uint32_t prescale)
193
+{
194
+ return (1000000000LL / TIM_REF_HZ) * count * (prescale + 1);
195
+}
196
+
197
+/* Returns a bitmask corresponding to the timer under test. */
198
+static uint32_t tim_timer_bit(const TestData *td)
199
+{
200
+ return BIT(timer_index(td->timer));
201
+}
202
+
203
+/* Resets all timers to power-on defaults. */
204
+static void tim_reset(const TestData *td)
205
+{
206
+ int i, j;
207
+
208
+ /* Reset all the timers, in case a previous test left a timer running. */
209
+ for (i = 0; i < ARRAY_SIZE(timer_block); i++) {
210
+ for (j = 0; j < ARRAY_SIZE(timer); j++) {
211
+ writel(timer_block[i].base_addr + timer[j].tcsr_offset,
212
+ CRST | TCSR_DEFAULT);
213
+ }
214
+ writel(timer_block[i].base_addr + TISR, -1);
215
+ }
216
+}
217
+
218
+/* Verifies the reset state of a timer. */
219
+static void test_reset(gconstpointer test_data)
220
+{
221
+ const TestData *td = test_data;
222
+
223
+ tim_reset(td);
224
+
225
+ g_assert_cmphex(tim_read_tcsr(td), ==, TCSR_DEFAULT);
226
+ g_assert_cmphex(tim_read_ticr(td), ==, 0);
227
+ g_assert_cmphex(tim_read_tdr(td), ==, 0);
228
+ g_assert_cmphex(tim_read(td, TISR), ==, 0);
229
+ g_assert_cmphex(tim_read(td, WTCR), ==, WTCLK(1));
230
+}
231
+
232
+/* Verifies that CRST wins if both CEN and CRST are set. */
233
+static void test_reset_overrides_enable(gconstpointer test_data)
234
+{
235
+ const TestData *td = test_data;
236
+
237
+ tim_reset(td);
238
+
239
+ /* CRST should force CEN to 0 */
240
+ tim_write_tcsr(td, CEN | CRST | TCSR_DEFAULT);
241
+
242
+ g_assert_cmphex(tim_read_tcsr(td), ==, TCSR_DEFAULT);
243
+ g_assert_cmphex(tim_read_tdr(td), ==, 0);
244
+ g_assert_cmphex(tim_read(td, TISR), ==, 0);
245
+}
246
+
247
+/* Verifies the behavior when CEN is set and then cleared. */
248
+static void test_oneshot_enable_then_disable(gconstpointer test_data)
249
+{
250
+ const TestData *td = test_data;
251
+
252
+ tim_reset(td);
253
+
254
+ /* Enable the timer with zero initial count, then disable it again. */
255
+ tim_write_tcsr(td, CEN | TCSR_DEFAULT);
256
+ tim_write_tcsr(td, TCSR_DEFAULT);
257
+
258
+ g_assert_cmphex(tim_read_tcsr(td), ==, TCSR_DEFAULT);
259
+ g_assert_cmphex(tim_read_tdr(td), ==, 0);
260
+ /* Timer interrupt flag should be set, but interrupts are not enabled. */
261
+ g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td));
262
+ g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
263
+}
264
+
265
+/* Verifies that a one-shot timer fires when expected with prescaler 5. */
266
+static void test_oneshot_ps5(gconstpointer test_data)
267
+{
268
+ const TestData *td = test_data;
269
+ unsigned int count = 256;
270
+ unsigned int ps = 5;
271
+
272
+ tim_reset(td);
273
+
274
+ tim_write_ticr(td, count);
275
+ tim_write_tcsr(td, CEN | PRESCALE(ps));
276
+ g_assert_cmphex(tim_read_tcsr(td), ==, CEN | CACT | PRESCALE(ps));
277
+ g_assert_cmpuint(tim_read_tdr(td), ==, count);
278
+
279
+ clock_step(tim_calculate_step(count, ps) - 1);
280
+
281
+ g_assert_cmphex(tim_read_tcsr(td), ==, CEN | CACT | PRESCALE(ps));
282
+ g_assert_cmpuint(tim_read_tdr(td), <, count);
283
+ g_assert_cmphex(tim_read(td, TISR), ==, 0);
284
+
285
+ clock_step(1);
286
+
287
+ g_assert_cmphex(tim_read_tcsr(td), ==, PRESCALE(ps));
288
+ g_assert_cmpuint(tim_read_tdr(td), ==, count);
289
+ g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td));
290
+ g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
291
+
292
+ /* Clear the interrupt flag. */
293
+ tim_write(td, TISR, tim_timer_bit(td));
294
+ g_assert_cmphex(tim_read(td, TISR), ==, 0);
295
+ g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
296
+
297
+ /* Verify that this isn't a periodic timer. */
298
+ clock_step(2 * tim_calculate_step(count, ps));
299
+ g_assert_cmphex(tim_read(td, TISR), ==, 0);
300
+ g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
301
+}
302
+
303
+/* Verifies that a one-shot timer fires when expected with prescaler 0. */
304
+static void test_oneshot_ps0(gconstpointer test_data)
305
+{
306
+ const TestData *td = test_data;
307
+ unsigned int count = 1;
308
+ unsigned int ps = 0;
309
+
310
+ tim_reset(td);
311
+
312
+ tim_write_ticr(td, count);
313
+ tim_write_tcsr(td, CEN | PRESCALE(ps));
314
+ g_assert_cmphex(tim_read_tcsr(td), ==, CEN | CACT | PRESCALE(ps));
315
+ g_assert_cmpuint(tim_read_tdr(td), ==, count);
316
+
317
+ clock_step(tim_calculate_step(count, ps) - 1);
318
+
319
+ g_assert_cmphex(tim_read_tcsr(td), ==, CEN | CACT | PRESCALE(ps));
320
+ g_assert_cmpuint(tim_read_tdr(td), <, count);
321
+ g_assert_cmphex(tim_read(td, TISR), ==, 0);
322
+
323
+ clock_step(1);
324
+
325
+ g_assert_cmphex(tim_read_tcsr(td), ==, PRESCALE(ps));
326
+ g_assert_cmpuint(tim_read_tdr(td), ==, count);
327
+ g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td));
328
+ g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
329
+}
330
+
331
+/* Verifies that a one-shot timer fires when expected with highest prescaler. */
332
+static void test_oneshot_ps255(gconstpointer test_data)
333
+{
334
+ const TestData *td = test_data;
335
+ unsigned int count = (1U << 24) - 1;
336
+ unsigned int ps = 255;
337
+
338
+ tim_reset(td);
339
+
340
+ tim_write_ticr(td, count);
341
+ tim_write_tcsr(td, CEN | PRESCALE(ps));
342
+ g_assert_cmphex(tim_read_tcsr(td), ==, CEN | CACT | PRESCALE(ps));
343
+ g_assert_cmpuint(tim_read_tdr(td), ==, count);
344
+
345
+ clock_step(tim_calculate_step(count, ps) - 1);
346
+
347
+ g_assert_cmphex(tim_read_tcsr(td), ==, CEN | CACT | PRESCALE(ps));
348
+ g_assert_cmpuint(tim_read_tdr(td), <, count);
349
+ g_assert_cmphex(tim_read(td, TISR), ==, 0);
350
+
351
+ clock_step(1);
352
+
353
+ g_assert_cmphex(tim_read_tcsr(td), ==, PRESCALE(ps));
354
+ g_assert_cmpuint(tim_read_tdr(td), ==, count);
355
+ g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td));
356
+ g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
357
+}
358
+
359
+/* Verifies that a oneshot timer fires an interrupt when expected. */
360
+static void test_oneshot_interrupt(gconstpointer test_data)
361
+{
362
+ const TestData *td = test_data;
363
+ unsigned int count = 256;
364
+ unsigned int ps = 7;
365
+
366
+ tim_reset(td);
367
+
368
+ tim_write_ticr(td, count);
369
+ tim_write_tcsr(td, IE | CEN | MODE_ONESHOT | PRESCALE(ps));
370
+
371
+ clock_step_next();
372
+
373
+ g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td));
374
+ g_assert_true(qtest_get_irq(global_qtest, tim_timer_irq(td)));
375
+}
376
+
377
+/*
378
+ * Verifies that the timer can be paused and later resumed, and it still fires
379
+ * at the right moment.
380
+ */
381
+static void test_pause_resume(gconstpointer test_data)
382
+{
383
+ const TestData *td = test_data;
384
+ unsigned int count = 256;
385
+ unsigned int ps = 1;
386
+
387
+ tim_reset(td);
388
+
389
+ tim_write_ticr(td, count);
390
+ tim_write_tcsr(td, IE | CEN | MODE_ONESHOT | PRESCALE(ps));
391
+
392
+ /* Pause the timer halfway to expiration. */
393
+ clock_step(tim_calculate_step(count / 2, ps));
394
+ tim_write_tcsr(td, IE | MODE_ONESHOT | PRESCALE(ps));
395
+ g_assert_cmpuint(tim_read_tdr(td), ==, count / 2);
396
+
397
+ /* Counter should not advance during the following step. */
398
+ clock_step(2 * tim_calculate_step(count, ps));
399
+ g_assert_cmpuint(tim_read_tdr(td), ==, count / 2);
400
+ g_assert_cmphex(tim_read(td, TISR), ==, 0);
401
+ g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
402
+
403
+ /* Resume the timer and run _almost_ to expiration. */
404
+ tim_write_tcsr(td, IE | CEN | MODE_ONESHOT | PRESCALE(ps));
405
+ clock_step(tim_calculate_step(count / 2, ps) - 1);
406
+ g_assert_cmpuint(tim_read_tdr(td), <, count);
407
+ g_assert_cmphex(tim_read(td, TISR), ==, 0);
408
+ g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
409
+
410
+ /* Now, run the rest of the way and verify that the interrupt fires. */
411
+ clock_step(1);
412
+ g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td));
413
+ g_assert_true(qtest_get_irq(global_qtest, tim_timer_irq(td)));
414
+}
415
+
416
+/* Verifies that the prescaler can be changed while the timer is runnin. */
417
+static void test_prescaler_change(gconstpointer test_data)
418
+{
419
+ const TestData *td = test_data;
420
+ unsigned int count = 256;
421
+ unsigned int ps = 5;
422
+
423
+ tim_reset(td);
424
+
425
+ tim_write_ticr(td, count);
426
+ tim_write_tcsr(td, CEN | MODE_ONESHOT | PRESCALE(ps));
427
+
428
+ /* Run a quarter of the way, and change the prescaler. */
429
+ clock_step(tim_calculate_step(count / 4, ps));
430
+ g_assert_cmpuint(tim_read_tdr(td), ==, 3 * count / 4);
431
+ ps = 2;
432
+ tim_write_tcsr(td, CEN | MODE_ONESHOT | PRESCALE(ps));
433
+ /* The counter must not change. */
434
+ g_assert_cmpuint(tim_read_tdr(td), ==, 3 * count / 4);
435
+
436
+ /* Run another quarter of the way, and change the prescaler again. */
437
+ clock_step(tim_calculate_step(count / 4, ps));
438
+ g_assert_cmpuint(tim_read_tdr(td), ==, count / 2);
439
+ ps = 8;
440
+ tim_write_tcsr(td, CEN | MODE_ONESHOT | PRESCALE(ps));
441
+ /* The counter must not change. */
442
+ g_assert_cmpuint(tim_read_tdr(td), ==, count / 2);
443
+
444
+ /* Run another quarter of the way, and change the prescaler again. */
445
+ clock_step(tim_calculate_step(count / 4, ps));
446
+ g_assert_cmpuint(tim_read_tdr(td), ==, count / 4);
447
+ ps = 0;
448
+ tim_write_tcsr(td, CEN | MODE_ONESHOT | PRESCALE(ps));
449
+ /* The counter must not change. */
450
+ g_assert_cmpuint(tim_read_tdr(td), ==, count / 4);
451
+
452
+ /* Run almost to expiration, and verify the timer didn't fire yet. */
453
+ clock_step(tim_calculate_step(count / 4, ps) - 1);
454
+ g_assert_cmpuint(tim_read_tdr(td), <, count);
455
+ g_assert_cmphex(tim_read(td, TISR), ==, 0);
456
+
457
+ /* Now, run the rest of the way and verify that the timer fires. */
458
+ clock_step(1);
459
+ g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td));
460
+}
461
+
462
+/* Verifies that a periodic timer automatically restarts after expiration. */
463
+static void test_periodic_no_interrupt(gconstpointer test_data)
464
+{
465
+ const TestData *td = test_data;
466
+ unsigned int count = 2;
467
+ unsigned int ps = 3;
468
+ int i;
469
+
470
+ tim_reset(td);
471
+
472
+ tim_write_ticr(td, count);
473
+ tim_write_tcsr(td, CEN | MODE_PERIODIC | PRESCALE(ps));
474
+
475
+ for (i = 0; i < 4; i++) {
476
+ clock_step_next();
477
+
478
+ g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td));
479
+ g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
480
+
481
+ tim_write(td, TISR, tim_timer_bit(td));
482
+
483
+ g_assert_cmphex(tim_read(td, TISR), ==, 0);
484
+ g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
485
+ }
486
+}
487
+
488
+/* Verifies that a periodict timer fires an interrupt every time it expires. */
489
+static void test_periodic_interrupt(gconstpointer test_data)
490
+{
491
+ const TestData *td = test_data;
492
+ unsigned int count = 65535;
493
+ unsigned int ps = 2;
494
+ int i;
495
+
496
+ tim_reset(td);
497
+
498
+ tim_write_ticr(td, count);
499
+ tim_write_tcsr(td, CEN | IE | MODE_PERIODIC | PRESCALE(ps));
500
+
501
+ for (i = 0; i < 4; i++) {
502
+ clock_step_next();
503
+
504
+ g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td));
505
+ g_assert_true(qtest_get_irq(global_qtest, tim_timer_irq(td)));
506
+
507
+ tim_write(td, TISR, tim_timer_bit(td));
508
+
509
+ g_assert_cmphex(tim_read(td, TISR), ==, 0);
510
+ g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
511
+ }
512
+}
513
+
514
+/*
515
+ * Verifies that the timer behaves correctly when disabled right before and
516
+ * exactly when it's supposed to expire.
517
+ */
518
+static void test_disable_on_expiration(gconstpointer test_data)
519
+{
520
+ const TestData *td = test_data;
521
+ unsigned int count = 8;
522
+ unsigned int ps = 255;
523
+
524
+ tim_reset(td);
525
+
526
+ tim_write_ticr(td, count);
527
+ tim_write_tcsr(td, CEN | MODE_ONESHOT | PRESCALE(ps));
528
+
529
+ clock_step(tim_calculate_step(count, ps) - 1);
530
+
531
+ tim_write_tcsr(td, MODE_ONESHOT | PRESCALE(ps));
532
+ tim_write_tcsr(td, CEN | MODE_ONESHOT | PRESCALE(ps));
533
+ clock_step(1);
534
+ tim_write_tcsr(td, MODE_ONESHOT | PRESCALE(ps));
535
+ g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td));
536
+}
537
+
538
+/*
539
+ * Constructs a name that includes the timer block, timer and testcase name,
540
+ * and adds the test to the test suite.
541
+ */
542
+static void tim_add_test(const char *name, const TestData *td, GTestDataFunc fn)
543
+{
544
+ g_autofree char *full_name;
545
+
546
+ full_name = g_strdup_printf("npcm7xx_timer/tim[%d]/timer[%d]/%s",
547
+ tim_index(td->tim), timer_index(td->timer),
548
+ name);
549
+ qtest_add_data_func(full_name, td, fn);
550
+}
551
+
552
+/* Convenience macro for adding a test with a predictable function name. */
553
+#define add_test(name, td) tim_add_test(#name, td, test_##name)
554
+
555
+int main(int argc, char **argv)
556
+{
557
+ TestData testdata[ARRAY_SIZE(timer_block) * ARRAY_SIZE(timer)];
558
+ int ret;
559
+ int i, j;
560
+
561
+ g_test_init(&argc, &argv, NULL);
562
+ g_test_set_nonfatal_assertions();
563
+
564
+ for (i = 0; i < ARRAY_SIZE(timer_block); i++) {
565
+ for (j = 0; j < ARRAY_SIZE(timer); j++) {
566
+ TestData *td = &testdata[i * ARRAY_SIZE(timer) + j];
567
+ td->tim = &timer_block[i];
568
+ td->timer = &timer[j];
569
+
570
+ add_test(reset, td);
571
+ add_test(reset_overrides_enable, td);
572
+ add_test(oneshot_enable_then_disable, td);
573
+ add_test(oneshot_ps5, td);
574
+ add_test(oneshot_ps0, td);
575
+ add_test(oneshot_ps255, td);
576
+ add_test(oneshot_interrupt, td);
577
+ add_test(pause_resume, td);
578
+ add_test(prescaler_change, td);
579
+ add_test(periodic_no_interrupt, td);
580
+ add_test(periodic_interrupt, td);
581
+ add_test(disable_on_expiration, td);
582
+ }
583
+ }
584
+
585
+ qtest_start("-machine npcm750-evb");
586
+ qtest_irq_intercept_in(global_qtest, "/machine/soc/a9mpcore/gic");
587
+ ret = g_test_run();
588
+ qtest_end();
589
+
590
+ return ret;
591
+}
592
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
593
index XXXXXXX..XXXXXXX 100644
101
index XXXXXXX..XXXXXXX 100644
594
--- a/tests/qtest/meson.build
102
--- a/hw/arm/exynos4210.c
595
+++ b/tests/qtest/meson.build
103
+++ b/hw/arm/exynos4210.c
596
@@ -XXX,XX +XXX,XX @@ qtests_arm = \
104
@@ -XXX,XX +XXX,XX @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
597
['arm-cpu-features',
105
}
598
'microbit-test',
106
599
'm25p80-test',
107
/* Internal Interrupt Combiner */
600
+ 'npcm7xx_timer-test',
108
- dev = qdev_new("exynos4210.combiner");
601
'test-arm-mptimer',
109
- busdev = SYS_BUS_DEVICE(dev);
602
'boot-serial-test',
110
- sysbus_realize_and_unref(busdev, &error_fatal);
603
'hexloader-test']
111
+ busdev = SYS_BUS_DEVICE(&s->int_combiner);
112
+ sysbus_realize(busdev, &error_fatal);
113
for (n = 0; n < EXYNOS4210_MAX_INT_COMBINER_OUT_IRQ; n++) {
114
sysbus_connect_irq(busdev, n,
115
qdev_get_gpio_in(DEVICE(&s->a9mpcore), n));
116
}
117
- exynos4210_combiner_get_gpioin(&s->irqs, dev, 0);
118
+ exynos4210_combiner_get_gpioin(&s->irqs, DEVICE(&s->int_combiner), 0);
119
sysbus_mmio_map(busdev, 0, EXYNOS4210_INT_COMBINER_BASE_ADDR);
120
121
/* External Interrupt Combiner */
122
- dev = qdev_new("exynos4210.combiner");
123
- qdev_prop_set_uint32(dev, "external", 1);
124
- busdev = SYS_BUS_DEVICE(dev);
125
- sysbus_realize_and_unref(busdev, &error_fatal);
126
+ qdev_prop_set_uint32(DEVICE(&s->ext_combiner), "external", 1);
127
+ busdev = SYS_BUS_DEVICE(&s->ext_combiner);
128
+ sysbus_realize(busdev, &error_fatal);
129
for (n = 0; n < EXYNOS4210_MAX_INT_COMBINER_OUT_IRQ; n++) {
130
sysbus_connect_irq(busdev, n, qdev_get_gpio_in(DEVICE(&s->ext_gic), n));
131
}
132
- exynos4210_combiner_get_gpioin(&s->irqs, dev, 1);
133
+ exynos4210_combiner_get_gpioin(&s->irqs, DEVICE(&s->ext_combiner), 1);
134
sysbus_mmio_map(busdev, 0, EXYNOS4210_EXT_COMBINER_BASE_ADDR);
135
136
/* Initialize board IRQs. */
137
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init(Object *obj)
138
139
object_initialize_child(obj, "a9mpcore", &s->a9mpcore, TYPE_A9MPCORE_PRIV);
140
object_initialize_child(obj, "ext-gic", &s->ext_gic, TYPE_EXYNOS4210_GIC);
141
+ object_initialize_child(obj, "int-combiner", &s->int_combiner,
142
+ TYPE_EXYNOS4210_COMBINER);
143
+ object_initialize_child(obj, "ext-combiner", &s->ext_combiner,
144
+ TYPE_EXYNOS4210_COMBINER);
145
}
146
147
static void exynos4210_class_init(ObjectClass *klass, void *data)
148
diff --git a/hw/intc/exynos4210_combiner.c b/hw/intc/exynos4210_combiner.c
149
index XXXXXXX..XXXXXXX 100644
150
--- a/hw/intc/exynos4210_combiner.c
151
+++ b/hw/intc/exynos4210_combiner.c
152
@@ -XXX,XX +XXX,XX @@
153
#include "hw/sysbus.h"
154
#include "migration/vmstate.h"
155
#include "qemu/module.h"
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",
604
--
198
--
605
2.20.1
199
2.25.1
606
607
diff view generated by jsdifflib
1
For AArch32, unlike the VCVT of integer to float, which honours the
1
The only time we use the int_combiner_irq[] and ext_combiner_irq[]
2
rounding mode specified by the FPSCR, VCVT of fixed-point to float is
2
arrays in the Exynos4210Irq struct is during realize of the SoC -- we
3
always round-to-nearest. (AArch64 fixed-point-to-float conversions
3
initialize them with the input IRQs of the combiner devices, and then
4
always honour the FPCR rounding mode.)
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.
5
9
6
Implement this by providing _round_to_nearest versions of the
10
Since these are the only two remaining elements of Exynos4210Irq,
7
relevant helpers which set the rounding mode temporarily when making
11
we can remove that struct entirely.
8
the call to the underlying softfloat function.
9
10
We only need to change the VFP VCVT instructions, because the
11
standard- FPSCR value used by the Neon VCVT is always set to
12
round-to-nearest, so we don't need to do the extra work of saving
13
and restoring the rounding mode.
14
12
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
17
Message-id: 20201013103532.13391-1-peter.maydell@linaro.org
15
Message-id: 20220404154658.565020-19-peter.maydell@linaro.org
18
---
16
---
19
target/arm/helper.h | 13 +++++++++++++
17
include/hw/arm/exynos4210.h | 6 ------
20
target/arm/vfp_helper.c | 23 ++++++++++++++++++++++-
18
hw/arm/exynos4210.c | 34 ++++++++--------------------------
21
target/arm/translate-vfp.c.inc | 24 ++++++++++++------------
19
2 files changed, 8 insertions(+), 32 deletions(-)
22
3 files changed, 47 insertions(+), 13 deletions(-)
23
20
24
diff --git a/target/arm/helper.h b/target/arm/helper.h
21
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
25
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
26
--- a/target/arm/helper.h
23
--- a/include/hw/arm/exynos4210.h
27
+++ b/target/arm/helper.h
24
+++ b/include/hw/arm/exynos4210.h
28
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_3(vfp_ultoh, f16, i32, i32, ptr)
25
@@ -XXX,XX +XXX,XX @@
29
DEF_HELPER_3(vfp_sqtoh, f16, i64, i32, ptr)
26
*/
30
DEF_HELPER_3(vfp_uqtoh, f16, i64, i32, ptr)
27
#define EXYNOS4210_NUM_SPLITTERS (EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ + 38)
31
28
32
+DEF_HELPER_3(vfp_shtos_round_to_nearest, f32, i32, i32, ptr)
29
-typedef struct Exynos4210Irq {
33
+DEF_HELPER_3(vfp_sltos_round_to_nearest, f32, i32, i32, ptr)
30
- qemu_irq int_combiner_irq[EXYNOS4210_MAX_INT_COMBINER_IN_IRQ];
34
+DEF_HELPER_3(vfp_uhtos_round_to_nearest, f32, i32, i32, ptr)
31
- qemu_irq ext_combiner_irq[EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ];
35
+DEF_HELPER_3(vfp_ultos_round_to_nearest, f32, i32, i32, ptr)
32
-} Exynos4210Irq;
36
+DEF_HELPER_3(vfp_shtod_round_to_nearest, f64, i64, i32, ptr)
33
-
37
+DEF_HELPER_3(vfp_sltod_round_to_nearest, f64, i64, i32, ptr)
34
struct Exynos4210State {
38
+DEF_HELPER_3(vfp_uhtod_round_to_nearest, f64, i64, i32, ptr)
35
/*< private >*/
39
+DEF_HELPER_3(vfp_ultod_round_to_nearest, f64, i64, i32, ptr)
36
SysBusDevice parent_obj;
40
+DEF_HELPER_3(vfp_shtoh_round_to_nearest, f16, i32, i32, ptr)
37
/*< public >*/
41
+DEF_HELPER_3(vfp_uhtoh_round_to_nearest, f16, i32, i32, ptr)
38
ARMCPU *cpu[EXYNOS4210_NCPUS];
42
+DEF_HELPER_3(vfp_sltoh_round_to_nearest, f16, i32, i32, ptr)
39
- Exynos4210Irq irqs;
43
+DEF_HELPER_3(vfp_ultoh_round_to_nearest, f16, i32, i32, ptr)
40
qemu_irq irq_table[EXYNOS4210_MAX_INT_COMBINER_IN_IRQ];
44
+
41
45
DEF_HELPER_FLAGS_2(set_rmode, TCG_CALL_NO_RWG, i32, i32, ptr)
42
MemoryRegion chipid_mem;
46
43
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
47
DEF_HELPER_FLAGS_3(vfp_fcvt_f16_to_f32, TCG_CALL_NO_RWG, f32, f16, ptr, i32)
48
diff --git a/target/arm/vfp_helper.c b/target/arm/vfp_helper.c
49
index XXXXXXX..XXXXXXX 100644
44
index XXXXXXX..XXXXXXX 100644
50
--- a/target/arm/vfp_helper.c
45
--- a/hw/arm/exynos4210.c
51
+++ b/target/arm/vfp_helper.c
46
+++ b/hw/arm/exynos4210.c
52
@@ -XXX,XX +XXX,XX @@ float32 VFP_HELPER(fcvts, d)(float64 x, CPUARMState *env)
47
@@ -XXX,XX +XXX,XX @@ static int mapline_size(const int *mapline)
53
return float64_to_float32(x, &env->vfp.fp_status);
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);
54
}
87
}
55
88
56
-/* VFP3 fixed point conversion. */
89
-/*
57
+/*
90
- * Get Combiner input GPIO into irqs structure
58
+ * VFP3 fixed point conversion. The AArch32 versions of fix-to-float
91
- */
59
+ * must always round-to-nearest; the AArch64 ones honour the FPSCR
92
-static void exynos4210_combiner_get_gpioin(Exynos4210Irq *irqs,
60
+ * rounding mode. (For AArch32 Neon the standard-FPSCR is set to
93
- DeviceState *dev, int ext)
61
+ * round-to-nearest so either helper will work.) AArch32 float-to-fix
94
-{
62
+ * must round-to-zero.
95
- int n;
63
+ */
96
- int max;
64
#define VFP_CONV_FIX_FLOAT(name, p, fsz, ftype, isz, itype) \
97
- qemu_irq *irq;
65
ftype HELPER(vfp_##name##to##p)(uint##isz##_t x, uint32_t shift, \
98
-
66
void *fpstp) \
99
- max = ext ? EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ :
67
{ return itype##_to_##float##fsz##_scalbn(x, -shift, fpstp); }
100
- EXYNOS4210_MAX_INT_COMBINER_IN_IRQ;
68
101
- irq = ext ? irqs->ext_combiner_irq : irqs->int_combiner_irq;
69
+#define VFP_CONV_FIX_FLOAT_ROUND(name, p, fsz, ftype, isz, itype) \
102
-
70
+ ftype HELPER(vfp_##name##to##p##_round_to_nearest)(uint##isz##_t x, \
103
- for (n = 0; n < max; n++) {
71
+ uint32_t shift, \
104
- irq[n] = qdev_get_gpio_in(dev, n);
72
+ void *fpstp) \
105
- }
73
+ { \
106
-}
74
+ ftype ret; \
107
-
75
+ float_status *fpst = fpstp; \
108
static uint8_t chipid_and_omr[] = { 0x11, 0x02, 0x21, 0x43,
76
+ FloatRoundMode oldmode = fpst->float_rounding_mode; \
109
0x09, 0x00, 0x00, 0x00 };
77
+ fpst->float_rounding_mode = float_round_nearest_even; \
110
78
+ ret = itype##_to_##float##fsz##_scalbn(x, -shift, fpstp); \
111
@@ -XXX,XX +XXX,XX @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
79
+ fpst->float_rounding_mode = oldmode; \
112
sysbus_connect_irq(busdev, n,
80
+ return ret; \
113
qdev_get_gpio_in(DEVICE(&s->a9mpcore), n));
81
+ }
114
}
82
+
115
- exynos4210_combiner_get_gpioin(&s->irqs, DEVICE(&s->int_combiner), 0);
83
#define VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, ftype, isz, itype, ROUND, suff) \
116
sysbus_mmio_map(busdev, 0, EXYNOS4210_INT_COMBINER_BASE_ADDR);
84
uint##isz##_t HELPER(vfp_to##name##p##suff)(ftype x, uint32_t shift, \
117
85
void *fpst) \
118
/* External Interrupt Combiner */
86
@@ -XXX,XX +XXX,XX @@ uint##isz##_t HELPER(vfp_to##name##p##suff)(ftype x, uint32_t shift, \
119
@@ -XXX,XX +XXX,XX @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
87
120
for (n = 0; n < EXYNOS4210_MAX_INT_COMBINER_OUT_IRQ; n++) {
88
#define VFP_CONV_FIX(name, p, fsz, ftype, isz, itype) \
121
sysbus_connect_irq(busdev, n, qdev_get_gpio_in(DEVICE(&s->ext_gic), n));
89
VFP_CONV_FIX_FLOAT(name, p, fsz, ftype, isz, itype) \
122
}
90
+VFP_CONV_FIX_FLOAT_ROUND(name, p, fsz, ftype, isz, itype) \
123
- exynos4210_combiner_get_gpioin(&s->irqs, DEVICE(&s->ext_combiner), 1);
91
VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, ftype, isz, itype, \
124
sysbus_mmio_map(busdev, 0, EXYNOS4210_EXT_COMBINER_BASE_ADDR);
92
float_round_to_zero, _round_to_zero) \
125
93
VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, ftype, isz, itype, \
126
/* Initialize board IRQs. */
94
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
95
index XXXXXXX..XXXXXXX 100644
96
--- a/target/arm/translate-vfp.c.inc
97
+++ b/target/arm/translate-vfp.c.inc
98
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_fix_hp(DisasContext *s, arg_VCVT_fix_sp *a)
99
/* Switch on op:U:sx bits */
100
switch (a->opc) {
101
case 0:
102
- gen_helper_vfp_shtoh(vd, vd, shift, fpst);
103
+ gen_helper_vfp_shtoh_round_to_nearest(vd, vd, shift, fpst);
104
break;
105
case 1:
106
- gen_helper_vfp_sltoh(vd, vd, shift, fpst);
107
+ gen_helper_vfp_sltoh_round_to_nearest(vd, vd, shift, fpst);
108
break;
109
case 2:
110
- gen_helper_vfp_uhtoh(vd, vd, shift, fpst);
111
+ gen_helper_vfp_uhtoh_round_to_nearest(vd, vd, shift, fpst);
112
break;
113
case 3:
114
- gen_helper_vfp_ultoh(vd, vd, shift, fpst);
115
+ gen_helper_vfp_ultoh_round_to_nearest(vd, vd, shift, fpst);
116
break;
117
case 4:
118
gen_helper_vfp_toshh_round_to_zero(vd, vd, shift, fpst);
119
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_fix_sp(DisasContext *s, arg_VCVT_fix_sp *a)
120
/* Switch on op:U:sx bits */
121
switch (a->opc) {
122
case 0:
123
- gen_helper_vfp_shtos(vd, vd, shift, fpst);
124
+ gen_helper_vfp_shtos_round_to_nearest(vd, vd, shift, fpst);
125
break;
126
case 1:
127
- gen_helper_vfp_sltos(vd, vd, shift, fpst);
128
+ gen_helper_vfp_sltos_round_to_nearest(vd, vd, shift, fpst);
129
break;
130
case 2:
131
- gen_helper_vfp_uhtos(vd, vd, shift, fpst);
132
+ gen_helper_vfp_uhtos_round_to_nearest(vd, vd, shift, fpst);
133
break;
134
case 3:
135
- gen_helper_vfp_ultos(vd, vd, shift, fpst);
136
+ gen_helper_vfp_ultos_round_to_nearest(vd, vd, shift, fpst);
137
break;
138
case 4:
139
gen_helper_vfp_toshs_round_to_zero(vd, vd, shift, fpst);
140
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_fix_dp(DisasContext *s, arg_VCVT_fix_dp *a)
141
/* Switch on op:U:sx bits */
142
switch (a->opc) {
143
case 0:
144
- gen_helper_vfp_shtod(vd, vd, shift, fpst);
145
+ gen_helper_vfp_shtod_round_to_nearest(vd, vd, shift, fpst);
146
break;
147
case 1:
148
- gen_helper_vfp_sltod(vd, vd, shift, fpst);
149
+ gen_helper_vfp_sltod_round_to_nearest(vd, vd, shift, fpst);
150
break;
151
case 2:
152
- gen_helper_vfp_uhtod(vd, vd, shift, fpst);
153
+ gen_helper_vfp_uhtod_round_to_nearest(vd, vd, shift, fpst);
154
break;
155
case 3:
156
- gen_helper_vfp_ultod(vd, vd, shift, fpst);
157
+ gen_helper_vfp_ultod_round_to_nearest(vd, vd, shift, fpst);
158
break;
159
case 4:
160
gen_helper_vfp_toshd_round_to_zero(vd, vd, shift, fpst);
161
--
127
--
162
2.20.1
128
2.25.1
163
164
diff view generated by jsdifflib
1
From: Peng Liang <liangpeng10@huawei.com>
1
From: Zongyuan Li <zongyuan.li@smartx.com>
2
2
3
VMStateDescription.fields should be end with VMSTATE_END_OF_LIST().
3
Signed-off-by: Zongyuan Li <zongyuan.li@smartx.com>
4
However, microbit_i2c_vmstate doesn't follow it. Let's change it.
4
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
5
5
Message-id: 20220324181557.203805-2-zongyuan.li@smartx.com
6
Fixes: 9d68bf564e ("arm: Stub out NRF51 TWI magnetometer/accelerometer detection")
7
Reported-by: Euler Robot <euler.robot@huawei.com>
8
Signed-off-by: Peng Liang <liangpeng10@huawei.com>
9
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
10
Message-id: 20201019093401.2993833-1-liangpeng10@huawei.com
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
7
---
13
hw/i2c/microbit_i2c.c | 1 +
8
hw/arm/realview.c | 33 ++++++++++++++++++++++++---------
14
1 file changed, 1 insertion(+)
9
1 file changed, 24 insertions(+), 9 deletions(-)
15
10
16
diff --git a/hw/i2c/microbit_i2c.c b/hw/i2c/microbit_i2c.c
11
diff --git a/hw/arm/realview.c b/hw/arm/realview.c
17
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/i2c/microbit_i2c.c
13
--- a/hw/arm/realview.c
19
+++ b/hw/i2c/microbit_i2c.c
14
+++ b/hw/arm/realview.c
20
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription microbit_i2c_vmstate = {
15
@@ -XXX,XX +XXX,XX @@
21
.fields = (VMStateField[]) {
16
#include "hw/sysbus.h"
22
VMSTATE_UINT32_ARRAY(regs, MicrobitI2CState, MICROBIT_I2C_NREGS),
17
#include "hw/arm/boot.h"
23
VMSTATE_UINT32(read_idx, MicrobitI2CState),
18
#include "hw/arm/primecell.h"
24
+ VMSTATE_END_OF_LIST()
19
+#include "hw/core/split-irq.h"
25
},
20
#include "hw/net/lan9118.h"
21
#include "hw/net/smc91c111.h"
22
#include "hw/pci/pci.h"
23
+#include "hw/qdev-core.h"
24
#include "net/net.h"
25
#include "sysemu/sysemu.h"
26
#include "hw/boards.h"
27
@@ -XXX,XX +XXX,XX @@ static const int realview_board_id[] = {
28
0x76d
26
};
29
};
27
30
31
+static void split_irq_from_named(DeviceState *src, const char* outname,
32
+ qemu_irq out1, qemu_irq out2) {
33
+ DeviceState *splitter = qdev_new(TYPE_SPLIT_IRQ);
34
+
35
+ qdev_prop_set_uint32(splitter, "num-lines", 2);
36
+
37
+ qdev_realize_and_unref(splitter, NULL, &error_fatal);
38
+
39
+ qdev_connect_gpio_out(splitter, 0, out1);
40
+ qdev_connect_gpio_out(splitter, 1, out2);
41
+ qdev_connect_gpio_out_named(src, outname, 0,
42
+ qdev_get_gpio_in(splitter, 0));
43
+}
44
+
45
static void realview_init(MachineState *machine,
46
enum realview_board_type board_type)
47
{
48
@@ -XXX,XX +XXX,XX @@ static void realview_init(MachineState *machine,
49
DeviceState *dev, *sysctl, *gpio2, *pl041;
50
SysBusDevice *busdev;
51
qemu_irq pic[64];
52
- qemu_irq mmc_irq[2];
53
PCIBus *pci_bus = NULL;
54
NICInfo *nd;
55
DriveInfo *dinfo;
56
@@ -XXX,XX +XXX,XX @@ static void realview_init(MachineState *machine,
57
* and the PL061 has them the other way about. Also the card
58
* detect line is inverted.
59
*/
60
- mmc_irq[0] = qemu_irq_split(
61
- qdev_get_gpio_in(sysctl, ARM_SYSCTL_GPIO_MMC_WPROT),
62
- qdev_get_gpio_in(gpio2, 1));
63
- mmc_irq[1] = qemu_irq_split(
64
- qdev_get_gpio_in(sysctl, ARM_SYSCTL_GPIO_MMC_CARDIN),
65
- qemu_irq_invert(qdev_get_gpio_in(gpio2, 0)));
66
- qdev_connect_gpio_out_named(dev, "card-read-only", 0, mmc_irq[0]);
67
- qdev_connect_gpio_out_named(dev, "card-inserted", 0, mmc_irq[1]);
68
+ split_irq_from_named(dev, "card-read-only",
69
+ qdev_get_gpio_in(sysctl, ARM_SYSCTL_GPIO_MMC_WPROT),
70
+ qdev_get_gpio_in(gpio2, 1));
71
+
72
+ split_irq_from_named(dev, "card-inserted",
73
+ qdev_get_gpio_in(sysctl, ARM_SYSCTL_GPIO_MMC_CARDIN),
74
+ qemu_irq_invert(qdev_get_gpio_in(gpio2, 0)));
75
+
76
dinfo = drive_get(IF_SD, 0, 0);
77
if (dinfo) {
78
DeviceState *card;
28
--
79
--
29
2.20.1
80
2.25.1
30
31
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Zongyuan Li <zongyuan.li@smartx.com>
2
2
3
Fixing this now will clarify following patches.
3
Signed-off-by: Zongyuan Li <zongyuan.li@smartx.com>
4
4
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20220324181557.203805-3-zongyuan.li@smartx.com
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Message-id: 20201016184207.786698-6-richard.henderson@linaro.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
7
---
10
linux-user/elfload.c | 12 +++++++++---
8
hw/arm/stellaris.c | 15 +++++++++++++--
11
1 file changed, 9 insertions(+), 3 deletions(-)
9
1 file changed, 13 insertions(+), 2 deletions(-)
12
10
13
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
11
diff --git a/hw/arm/stellaris.c b/hw/arm/stellaris.c
14
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
15
--- a/linux-user/elfload.c
13
--- a/hw/arm/stellaris.c
16
+++ b/linux-user/elfload.c
14
+++ b/hw/arm/stellaris.c
17
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
15
@@ -XXX,XX +XXX,XX @@
18
abi_ulong vaddr, vaddr_po, vaddr_ps, vaddr_ef, vaddr_em, vaddr_len;
16
19
int elf_prot = 0;
17
#include "qemu/osdep.h"
20
18
#include "qapi/error.h"
21
- if (eppnt->p_flags & PF_R) elf_prot = PROT_READ;
19
+#include "hw/core/split-irq.h"
22
- if (eppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;
20
#include "hw/sysbus.h"
23
- if (eppnt->p_flags & PF_X) elf_prot |= PROT_EXEC;
21
#include "hw/sd/sd.h"
24
+ if (eppnt->p_flags & PF_R) {
22
#include "hw/ssi/ssi.h"
25
+ elf_prot |= PROT_READ;
23
@@ -XXX,XX +XXX,XX @@ static void stellaris_init(MachineState *ms, stellaris_board_info *board)
26
+ }
24
DeviceState *ssddev;
27
+ if (eppnt->p_flags & PF_W) {
25
DriveInfo *dinfo;
28
+ elf_prot |= PROT_WRITE;
26
DeviceState *carddev;
29
+ }
27
+ DeviceState *gpio_d_splitter;
30
+ if (eppnt->p_flags & PF_X) {
28
BlockBackend *blk;
31
+ elf_prot |= PROT_EXEC;
29
32
+ }
30
/*
33
31
@@ -XXX,XX +XXX,XX @@ static void stellaris_init(MachineState *ms, stellaris_board_info *board)
34
vaddr = load_bias + eppnt->p_vaddr;
32
&error_fatal);
35
vaddr_po = TARGET_ELF_PAGEOFFSET(vaddr);
33
34
ssddev = ssi_create_peripheral(bus, "ssd0323");
35
- gpio_out[GPIO_D][0] = qemu_irq_split(
36
- qdev_get_gpio_in_named(sddev, SSI_GPIO_CS, 0),
37
+
38
+ gpio_d_splitter = qdev_new(TYPE_SPLIT_IRQ);
39
+ qdev_prop_set_uint32(gpio_d_splitter, "num-lines", 2);
40
+ qdev_realize_and_unref(gpio_d_splitter, NULL, &error_fatal);
41
+ qdev_connect_gpio_out(
42
+ gpio_d_splitter, 0,
43
+ qdev_get_gpio_in_named(sddev, SSI_GPIO_CS, 0));
44
+ qdev_connect_gpio_out(
45
+ gpio_d_splitter, 1,
46
qdev_get_gpio_in_named(ssddev, SSI_GPIO_CS, 0));
47
+ gpio_out[GPIO_D][0] = qdev_get_gpio_in(gpio_d_splitter, 0);
48
+
49
gpio_out[GPIO_C][7] = qdev_get_gpio_in(ssddev, 0);
50
51
/* Make sure the select pin is high. */
36
--
52
--
37
2.20.1
53
2.25.1
38
39
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
From: Zongyuan Li <zongyuan.li@smartx.com>
2
2
3
Add trace events for GPU and CPU IRQs.
3
Signed-off-by: Zongyuan Li <zongyuan.li@smartx.com>
4
4
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
5
Message-id: 20220324181557.203805-5-zongyuan.li@smartx.com
6
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/811
7
Message-id: 20201017180731.1165871-2-f4bug@amsat.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
8
---
10
hw/intc/bcm2835_ic.c | 4 +++-
9
include/hw/irq.h | 5 -----
11
hw/intc/trace-events | 4 ++++
10
hw/core/irq.c | 15 ---------------
12
2 files changed, 7 insertions(+), 1 deletion(-)
11
2 files changed, 20 deletions(-)
13
12
14
diff --git a/hw/intc/bcm2835_ic.c b/hw/intc/bcm2835_ic.c
13
diff --git a/include/hw/irq.h b/include/hw/irq.h
15
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/intc/bcm2835_ic.c
15
--- a/include/hw/irq.h
17
+++ b/hw/intc/bcm2835_ic.c
16
+++ b/include/hw/irq.h
18
@@ -XXX,XX +XXX,XX @@
17
@@ -XXX,XX +XXX,XX @@ void qemu_free_irq(qemu_irq irq);
19
#include "migration/vmstate.h"
18
/* Returns a new IRQ with opposite polarity. */
20
#include "qemu/log.h"
19
qemu_irq qemu_irq_invert(qemu_irq irq);
21
#include "qemu/module.h"
20
22
+#include "trace.h"
21
-/* Returns a new IRQ which feeds into both the passed IRQs.
23
22
- * It's probably better to use the TYPE_SPLIT_IRQ device instead.
24
#define GPU_IRQS 64
23
- */
25
#define ARM_IRQS 8
24
-qemu_irq qemu_irq_split(qemu_irq irq1, qemu_irq irq2);
26
@@ -XXX,XX +XXX,XX @@ static void bcm2835_ic_update(BCM2835ICState *s)
27
set = (s->gpu_irq_level & s->gpu_irq_enable)
28
|| (s->arm_irq_level & s->arm_irq_enable);
29
qemu_set_irq(s->irq, set);
30
-
25
-
26
/* For internal use in qtest. Similar to qemu_irq_split, but operating
27
on an existing vector of qemu_irq. */
28
void qemu_irq_intercept_in(qemu_irq *gpio_in, qemu_irq_handler handler, int n);
29
diff --git a/hw/core/irq.c b/hw/core/irq.c
30
index XXXXXXX..XXXXXXX 100644
31
--- a/hw/core/irq.c
32
+++ b/hw/core/irq.c
33
@@ -XXX,XX +XXX,XX @@ qemu_irq qemu_irq_invert(qemu_irq irq)
34
return qemu_allocate_irq(qemu_notirq, irq, 0);
31
}
35
}
32
36
33
static void bcm2835_ic_set_gpu_irq(void *opaque, int irq, int level)
37
-static void qemu_splitirq(void *opaque, int line, int level)
34
@@ -XXX,XX +XXX,XX @@ static void bcm2835_ic_set_gpu_irq(void *opaque, int irq, int level)
38
-{
35
BCM2835ICState *s = opaque;
39
- struct IRQState **irq = opaque;
36
40
- irq[0]->handler(irq[0]->opaque, irq[0]->n, level);
37
assert(irq >= 0 && irq < 64);
41
- irq[1]->handler(irq[1]->opaque, irq[1]->n, level);
38
+ trace_bcm2835_ic_set_gpu_irq(irq, level);
42
-}
39
s->gpu_irq_level = deposit64(s->gpu_irq_level, irq, 1, level != 0);
43
-
40
bcm2835_ic_update(s);
44
-qemu_irq qemu_irq_split(qemu_irq irq1, qemu_irq irq2)
41
}
45
-{
42
@@ -XXX,XX +XXX,XX @@ static void bcm2835_ic_set_arm_irq(void *opaque, int irq, int level)
46
- qemu_irq *s = g_new0(qemu_irq, 2);
43
BCM2835ICState *s = opaque;
47
- s[0] = irq1;
44
48
- s[1] = irq2;
45
assert(irq >= 0 && irq < 8);
49
- return qemu_allocate_irq(qemu_splitirq, s, 0);
46
+ trace_bcm2835_ic_set_cpu_irq(irq, level);
50
-}
47
s->arm_irq_level = deposit32(s->arm_irq_level, irq, 1, level != 0);
51
-
48
bcm2835_ic_update(s);
52
void qemu_irq_intercept_in(qemu_irq *gpio_in, qemu_irq_handler handler, int n)
49
}
53
{
50
diff --git a/hw/intc/trace-events b/hw/intc/trace-events
54
int i;
51
index XXXXXXX..XXXXXXX 100644
52
--- a/hw/intc/trace-events
53
+++ b/hw/intc/trace-events
54
@@ -XXX,XX +XXX,XX @@ nvic_sysreg_write(uint64_t addr, uint32_t value, unsigned size) "NVIC sysreg wri
55
heathrow_write(uint64_t addr, unsigned int n, uint64_t value) "0x%"PRIx64" %u: 0x%"PRIx64
56
heathrow_read(uint64_t addr, unsigned int n, uint64_t value) "0x%"PRIx64" %u: 0x%"PRIx64
57
heathrow_set_irq(int num, int level) "set_irq: num=0x%02x level=%d"
58
+
59
+# bcm2835_ic.c
60
+bcm2835_ic_set_gpu_irq(int irq, int level) "GPU irq #%d level %d"
61
+bcm2835_ic_set_cpu_irq(int irq, int level) "CPU irq #%d level %d"
62
--
55
--
63
2.20.1
56
2.25.1
64
65
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
From: Heinrich Schuchardt <heinrich.schuchardt@canonical.com>
2
2
3
The time to transmit a char is expressed in nanoseconds, not in ticks.
3
Describe that the gic-version influences the maximum number of CPUs.
4
4
5
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
5
Signed-off-by: Heinrich Schuchardt <heinrich.schuchardt@canonical.com>
6
Message-id: 20201014213601.205222-1-f4bug@amsat.org
6
Message-id: 20220413231456.35811-1-heinrich.schuchardt@canonical.com
7
[PMM: minor punctuation tweaks]
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Peter Maydell <peter.maydell@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
hw/arm/strongarm.c | 2 +-
11
docs/system/arm/virt.rst | 4 ++--
11
1 file changed, 1 insertion(+), 1 deletion(-)
12
1 file changed, 2 insertions(+), 2 deletions(-)
12
13
13
diff --git a/hw/arm/strongarm.c b/hw/arm/strongarm.c
14
diff --git a/docs/system/arm/virt.rst b/docs/system/arm/virt.rst
14
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/arm/strongarm.c
16
--- a/docs/system/arm/virt.rst
16
+++ b/hw/arm/strongarm.c
17
+++ b/docs/system/arm/virt.rst
17
@@ -XXX,XX +XXX,XX @@ struct StrongARMUARTState {
18
@@ -XXX,XX +XXX,XX @@ gic-version
18
uint8_t rx_start;
19
Valid values are:
19
uint8_t rx_len;
20
20
21
``2``
21
- uint64_t char_transmit_time; /* time to transmit a char in ticks*/
22
- GICv2
22
+ uint64_t char_transmit_time; /* time to transmit a char in nanoseconds */
23
+ GICv2. Note that this limits the number of CPUs to 8.
23
bool wait_break_end;
24
``3``
24
QEMUTimer *rx_timeout_timer;
25
- GICv3
25
QEMUTimer *tx_timer;
26
+ GICv3. This allows up to 512 CPUs.
27
``host``
28
Use the same GIC version the host provides, when using KVM
29
``max``
26
--
30
--
27
2.20.1
31
2.25.1
28
29
diff view generated by jsdifflib
Deleted patch
1
From: Philippe Mathieu-Daudé <philmd@redhat.com>
2
1
3
While APEI is a generic ACPI feature (usable by X86 and ARM64), only
4
the 'virt' machine uses it, by enabling the RAS Virtualization. See
5
commit 2afa8c8519: "hw/arm/virt: Introduce a RAS machine option").
6
7
Restrict the APEI tables generation code to the single user: the virt
8
machine. If another machine wants to use it, it simply has to 'select
9
ACPI_APEI' in its Kconfig.
10
11
Fixes: aa16508f1d ("ACPI: Build related register address fields via hardware error fw_cfg blob")
12
Acked-by: Michael S. Tsirkin <mst@redhat.com>
13
Reviewed-by: Dongjiu Geng <gengdongjiu@huawei.com>
14
Acked-by: Laszlo Ersek <lersek@redhat.com>
15
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
16
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
17
Message-id: 20201008161414.2672569-1-philmd@redhat.com
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
---
20
default-configs/devices/arm-softmmu.mak | 1 -
21
hw/arm/Kconfig | 1 +
22
2 files changed, 1 insertion(+), 1 deletion(-)
23
24
diff --git a/default-configs/devices/arm-softmmu.mak b/default-configs/devices/arm-softmmu.mak
25
index XXXXXXX..XXXXXXX 100644
26
--- a/default-configs/devices/arm-softmmu.mak
27
+++ b/default-configs/devices/arm-softmmu.mak
28
@@ -XXX,XX +XXX,XX @@ CONFIG_FSL_IMX7=y
29
CONFIG_FSL_IMX6UL=y
30
CONFIG_SEMIHOSTING=y
31
CONFIG_ALLWINNER_H3=y
32
-CONFIG_ACPI_APEI=y
33
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
34
index XXXXXXX..XXXXXXX 100644
35
--- a/hw/arm/Kconfig
36
+++ b/hw/arm/Kconfig
37
@@ -XXX,XX +XXX,XX @@ config ARM_VIRT
38
select ACPI_MEMORY_HOTPLUG
39
select ACPI_HW_REDUCED
40
select ACPI_NVDIMM
41
+ select ACPI_APEI
42
43
config CHEETAH
44
bool
45
--
46
2.20.1
47
48
diff view generated by jsdifflib
Deleted patch
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
1
3
The variable holding the CTRL_STATUS register is misnamed
4
'status'. Rename it 'ctrl_status' to make it more obvious
5
this register is also used to control the peripheral.
6
7
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
Message-id: 20201010203709.3116542-3-f4bug@amsat.org
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
13
include/hw/timer/bcm2835_systmr.h | 2 +-
14
hw/timer/bcm2835_systmr.c | 8 ++++----
15
2 files changed, 5 insertions(+), 5 deletions(-)
16
17
diff --git a/include/hw/timer/bcm2835_systmr.h b/include/hw/timer/bcm2835_systmr.h
18
index XXXXXXX..XXXXXXX 100644
19
--- a/include/hw/timer/bcm2835_systmr.h
20
+++ b/include/hw/timer/bcm2835_systmr.h
21
@@ -XXX,XX +XXX,XX @@ struct BCM2835SystemTimerState {
22
qemu_irq irq;
23
24
struct {
25
- uint32_t status;
26
+ uint32_t ctrl_status;
27
uint32_t compare[BCM2835_SYSTIMER_COUNT];
28
} reg;
29
};
30
diff --git a/hw/timer/bcm2835_systmr.c b/hw/timer/bcm2835_systmr.c
31
index XXXXXXX..XXXXXXX 100644
32
--- a/hw/timer/bcm2835_systmr.c
33
+++ b/hw/timer/bcm2835_systmr.c
34
@@ -XXX,XX +XXX,XX @@ REG32(COMPARE3, 0x18)
35
36
static void bcm2835_systmr_update_irq(BCM2835SystemTimerState *s)
37
{
38
- bool enable = !!s->reg.status;
39
+ bool enable = !!s->reg.ctrl_status;
40
41
trace_bcm2835_systmr_irq(enable);
42
qemu_set_irq(s->irq, enable);
43
@@ -XXX,XX +XXX,XX @@ static uint64_t bcm2835_systmr_read(void *opaque, hwaddr offset,
44
45
switch (offset) {
46
case A_CTRL_STATUS:
47
- r = s->reg.status;
48
+ r = s->reg.ctrl_status;
49
break;
50
case A_COMPARE0 ... A_COMPARE3:
51
r = s->reg.compare[(offset - A_COMPARE0) >> 2];
52
@@ -XXX,XX +XXX,XX @@ static void bcm2835_systmr_write(void *opaque, hwaddr offset,
53
trace_bcm2835_systmr_write(offset, value);
54
switch (offset) {
55
case A_CTRL_STATUS:
56
- s->reg.status &= ~value; /* Ack */
57
+ s->reg.ctrl_status &= ~value; /* Ack */
58
bcm2835_systmr_update_irq(s);
59
break;
60
case A_COMPARE0 ... A_COMPARE3:
61
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription bcm2835_systmr_vmstate = {
62
.version_id = 1,
63
.minimum_version_id = 1,
64
.fields = (VMStateField[]) {
65
- VMSTATE_UINT32(reg.status, BCM2835SystemTimerState),
66
+ VMSTATE_UINT32(reg.ctrl_status, BCM2835SystemTimerState),
67
VMSTATE_UINT32_ARRAY(reg.compare, BCM2835SystemTimerState,
68
BCM2835_SYSTIMER_COUNT),
69
VMSTATE_END_OF_LIST()
70
--
71
2.20.1
72
73
diff view generated by jsdifflib
Deleted patch
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
1
3
The SYS_timer is not directly wired to the ARM core, but to the
4
SoC (peripheral) interrupt controller.
5
6
Fixes: 0e5bbd74064 ("hw/arm/bcm2835_peripherals: Use the SYS_timer")
7
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
Message-id: 20201010203709.3116542-5-f4bug@amsat.org
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
13
hw/arm/bcm2835_peripherals.c | 13 +++++++++++--
14
1 file changed, 11 insertions(+), 2 deletions(-)
15
16
diff --git a/hw/arm/bcm2835_peripherals.c b/hw/arm/bcm2835_peripherals.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/arm/bcm2835_peripherals.c
19
+++ b/hw/arm/bcm2835_peripherals.c
20
@@ -XXX,XX +XXX,XX @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
21
memory_region_add_subregion(&s->peri_mr, ST_OFFSET,
22
sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->systmr), 0));
23
sysbus_connect_irq(SYS_BUS_DEVICE(&s->systmr), 0,
24
- qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_ARM_IRQ,
25
- INTERRUPT_ARM_TIMER));
26
+ qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ,
27
+ INTERRUPT_TIMER0));
28
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->systmr), 1,
29
+ qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ,
30
+ INTERRUPT_TIMER1));
31
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->systmr), 2,
32
+ qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ,
33
+ INTERRUPT_TIMER2));
34
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->systmr), 3,
35
+ qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ,
36
+ INTERRUPT_TIMER3));
37
38
/* UART0 */
39
qdev_prop_set_chr(DEVICE(&s->uart0), "chardev", serial_hd(0));
40
--
41
2.20.1
42
43
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Hao Wu <wuhaotsh@google.com>
2
2
3
Transform the prot bit to a qemu internal page bit, and save
3
Similar to the Aspeed code in include/misc/aspeed_scu.h, we define
4
it in the page tables.
4
the PWRON STRAP fields in their corresponding module for NPCM7XX.
5
5
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
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20201016184207.786698-3-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
---
11
include/exec/cpu-all.h | 2 ++
12
include/hw/misc/npcm7xx_gcr.h | 30 ++++++++++++++++++++++++++++++
12
linux-user/syscall_defs.h | 4 ++++
13
1 file changed, 30 insertions(+)
13
target/arm/cpu.h | 5 +++++
14
linux-user/mmap.c | 16 ++++++++++++++++
15
target/arm/translate-a64.c | 6 +++---
16
5 files changed, 30 insertions(+), 3 deletions(-)
17
14
18
diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h
15
diff --git a/include/hw/misc/npcm7xx_gcr.h b/include/hw/misc/npcm7xx_gcr.h
19
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
20
--- a/include/exec/cpu-all.h
17
--- a/include/hw/misc/npcm7xx_gcr.h
21
+++ b/include/exec/cpu-all.h
18
+++ b/include/hw/misc/npcm7xx_gcr.h
22
@@ -XXX,XX +XXX,XX @@ extern intptr_t qemu_host_page_mask;
19
@@ -XXX,XX +XXX,XX @@
23
/* FIXME: Code that sets/uses this is broken and needs to go away. */
20
#include "exec/memory.h"
24
#define PAGE_RESERVED 0x0020
21
#include "hw/sysbus.h"
25
#endif
26
+/* Target-specific bits that will be used via page_get_flags(). */
27
+#define PAGE_TARGET_1 0x0080
28
29
#if defined(CONFIG_USER_ONLY)
30
void page_dump(FILE *f);
31
diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
32
index XXXXXXX..XXXXXXX 100644
33
--- a/linux-user/syscall_defs.h
34
+++ b/linux-user/syscall_defs.h
35
@@ -XXX,XX +XXX,XX @@ struct target_winsize {
36
#define TARGET_PROT_SEM 0x08
37
#endif
38
39
+#ifdef TARGET_AARCH64
40
+#define TARGET_PROT_BTI 0x10
41
+#endif
42
+
43
/* Common */
44
#define TARGET_MAP_SHARED    0x01        /* Share changes */
45
#define TARGET_MAP_PRIVATE    0x02        /* Changes are private */
46
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
47
index XXXXXXX..XXXXXXX 100644
48
--- a/target/arm/cpu.h
49
+++ b/target/arm/cpu.h
50
@@ -XXX,XX +XXX,XX @@ static inline MemTxAttrs *typecheck_memtxattrs(MemTxAttrs *x)
51
#define arm_tlb_bti_gp(x) (typecheck_memtxattrs(x)->target_tlb_bit0)
52
#define arm_tlb_mte_tagged(x) (typecheck_memtxattrs(x)->target_tlb_bit1)
53
22
54
+/*
23
+/*
55
+ * AArch64 usage of the PAGE_TARGET_* bits for linux-user.
24
+ * NPCM7XX PWRON STRAP bit fields
25
+ * 12: SPI0 powered by VSBV3 at 1.8V
26
+ * 11: System flash attached to BMC
27
+ * 10: BSP alternative pins.
28
+ * 9:8: Flash UART command route enabled.
29
+ * 7: Security enabled.
30
+ * 6: HI-Z state control.
31
+ * 5: ECC disabled.
32
+ * 4: Reserved
33
+ * 3: JTAG2 enabled.
34
+ * 2:0: CPU and DRAM clock frequency.
56
+ */
35
+ */
57
+#define PAGE_BTI PAGE_TARGET_1
36
+#define NPCM7XX_PWRON_STRAP_SPI0F18 BIT(12)
37
+#define NPCM7XX_PWRON_STRAP_SFAB BIT(11)
38
+#define NPCM7XX_PWRON_STRAP_BSPA BIT(10)
39
+#define NPCM7XX_PWRON_STRAP_FUP(x) ((x) << 8)
40
+#define FUP_NORM_UART2 3
41
+#define FUP_PROG_UART3 2
42
+#define FUP_PROG_UART2 1
43
+#define FUP_NORM_UART3 0
44
+#define NPCM7XX_PWRON_STRAP_SECEN BIT(7)
45
+#define NPCM7XX_PWRON_STRAP_HIZ BIT(6)
46
+#define NPCM7XX_PWRON_STRAP_ECC BIT(5)
47
+#define NPCM7XX_PWRON_STRAP_RESERVE1 BIT(4)
48
+#define NPCM7XX_PWRON_STRAP_J2EN BIT(3)
49
+#define NPCM7XX_PWRON_STRAP_CKFRQ(x) (x)
50
+#define CKFRQ_SKIPINIT 0x000
51
+#define CKFRQ_DEFAULT 0x111
58
+
52
+
59
/*
53
/*
60
* Naming convention for isar_feature functions:
54
* Number of registers in our device state structure. Don't change this without
61
* Functions which test 32-bit ID registers should have _aa32_ in
55
* incrementing the version_id in the vmstate.
62
diff --git a/linux-user/mmap.c b/linux-user/mmap.c
63
index XXXXXXX..XXXXXXX 100644
64
--- a/linux-user/mmap.c
65
+++ b/linux-user/mmap.c
66
@@ -XXX,XX +XXX,XX @@ static int validate_prot_to_pageflags(int *host_prot, int prot)
67
*host_prot = (prot & (PROT_READ | PROT_WRITE))
68
| (prot & PROT_EXEC ? PROT_READ : 0);
69
70
+#ifdef TARGET_AARCH64
71
+ /*
72
+ * The PROT_BTI bit is only accepted if the cpu supports the feature.
73
+ * Since this is the unusual case, don't bother checking unless
74
+ * the bit has been requested. If set and valid, record the bit
75
+ * within QEMU's page_flags.
76
+ */
77
+ if (prot & TARGET_PROT_BTI) {
78
+ ARMCPU *cpu = ARM_CPU(thread_cpu);
79
+ if (cpu_isar_feature(aa64_bti, cpu)) {
80
+ valid |= TARGET_PROT_BTI;
81
+ page_flags |= PAGE_BTI;
82
+ }
83
+ }
84
+#endif
85
+
86
return prot & ~valid ? 0 : page_flags;
87
}
88
89
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
90
index XXXXXXX..XXXXXXX 100644
91
--- a/target/arm/translate-a64.c
92
+++ b/target/arm/translate-a64.c
93
@@ -XXX,XX +XXX,XX @@ static void disas_data_proc_simd_fp(DisasContext *s, uint32_t insn)
94
*/
95
static bool is_guarded_page(CPUARMState *env, DisasContext *s)
96
{
97
-#ifdef CONFIG_USER_ONLY
98
- return false; /* FIXME */
99
-#else
100
uint64_t addr = s->base.pc_first;
101
+#ifdef CONFIG_USER_ONLY
102
+ return page_get_flags(addr) & PAGE_BTI;
103
+#else
104
int mmu_idx = arm_to_core_mmu_idx(s->mmu_idx);
105
unsigned int index = tlb_index(env, mmu_idx, addr);
106
CPUTLBEntry *entry = tlb_entry(env, mmu_idx, addr);
107
--
56
--
108
2.20.1
57
2.25.1
109
110
diff view generated by jsdifflib
1
From: Emanuele Giuseppe Esposito <e.emanuelegiuseppe@gmail.com>
1
From: Hao Wu <wuhaotsh@google.com>
2
2
3
Current documentation is not too clear on the GETPC usage.
3
This patch uses the defined fields to describe PWRON STRAPs for
4
In particular, when used outside the top level helper function
4
better readability.
5
it causes unexpected behavior.
6
5
7
Signed-off-by: Emanuele Giuseppe Esposito <e.emanuelegiuseppe@gmail.com>
6
Signed-off-by: Hao Wu <wuhaotsh@google.com>
8
Message-id: 20201015095147.1691-1-e.emanuelegiuseppe@gmail.com
7
Reviewed-by: Patrick Venture <venture@google.com>
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
docs/devel/loads-stores.rst | 8 +++++++-
12
hw/arm/npcm7xx_boards.c | 24 +++++++++++++++++++-----
13
1 file changed, 7 insertions(+), 1 deletion(-)
13
1 file changed, 19 insertions(+), 5 deletions(-)
14
14
15
diff --git a/docs/devel/loads-stores.rst b/docs/devel/loads-stores.rst
15
diff --git a/hw/arm/npcm7xx_boards.c b/hw/arm/npcm7xx_boards.c
16
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
17
--- a/docs/devel/loads-stores.rst
17
--- a/hw/arm/npcm7xx_boards.c
18
+++ b/docs/devel/loads-stores.rst
18
+++ b/hw/arm/npcm7xx_boards.c
19
@@ -XXX,XX +XXX,XX @@ guest CPU state in case of a guest CPU exception. This is passed
19
@@ -XXX,XX +XXX,XX @@
20
to ``cpu_restore_state()``. Therefore the value should either be 0,
20
#include "sysemu/sysemu.h"
21
to indicate that the guest CPU state is already synchronized, or
21
#include "sysemu/block-backend.h"
22
the result of ``GETPC()`` from the top level ``HELPER(foo)``
22
23
-function, which is a return address into the generated code.
23
-#define NPCM750_EVB_POWER_ON_STRAPS 0x00001ff7
24
+function, which is a return address into the generated code [#gpc]_.
24
-#define QUANTA_GSJ_POWER_ON_STRAPS 0x00001fff
25
-#define QUANTA_GBS_POWER_ON_STRAPS 0x000017ff
26
-#define KUDO_BMC_POWER_ON_STRAPS 0x00001fff
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))
25
+
39
+
26
+.. [#gpc] Note that ``GETPC()`` should be used with great care: calling
40
+#define NPCM750_EVB_POWER_ON_STRAPS ( \
27
+ it in other functions that are *not* the top level
41
+ NPCM7XX_POWER_ON_STRAPS_DEFAULT & ~NPCM7XX_PWRON_STRAP_J2EN)
28
+ ``HELPER(foo)`` will cause unexpected behavior. Instead, the
42
+#define QUANTA_GSJ_POWER_ON_STRAPS NPCM7XX_POWER_ON_STRAPS_DEFAULT
29
+ value of ``GETPC()`` should be read from the helper and passed
43
+#define QUANTA_GBS_POWER_ON_STRAPS ( \
30
+ if needed to the functions that the helper calls.
44
+ NPCM7XX_POWER_ON_STRAPS_DEFAULT & ~NPCM7XX_PWRON_STRAP_SFAB)
31
45
+#define KUDO_BMC_POWER_ON_STRAPS NPCM7XX_POWER_ON_STRAPS_DEFAULT
32
Function names follow the pattern:
46
+#define MORI_BMC_POWER_ON_STRAPS NPCM7XX_POWER_ON_STRAPS_DEFAULT
47
48
static const char npcm7xx_default_bootrom[] = "npcm7xx_bootrom.bin";
33
49
34
--
50
--
35
2.20.1
51
2.25.1
36
37
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
We already have the full ARMMMUIdx as computed from the
4
function parameter.
5
6
For the purpose of regime_has_2_ranges, we can ignore any
7
difference between AccType_Normal and AccType_Unpriv, which
8
would be the only difference between the passed mmu_idx
9
and arm_mmu_idx_el.
10
11
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
12
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
13
Reviewed-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
14
Tested-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
15
Message-id: 20201008162155.161886-2-richard.henderson@linaro.org
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
---
18
target/arm/mte_helper.c | 3 +--
19
1 file changed, 1 insertion(+), 2 deletions(-)
20
21
diff --git a/target/arm/mte_helper.c b/target/arm/mte_helper.c
22
index XXXXXXX..XXXXXXX 100644
23
--- a/target/arm/mte_helper.c
24
+++ b/target/arm/mte_helper.c
25
@@ -XXX,XX +XXX,XX @@ static void mte_check_fail(CPUARMState *env, uint32_t desc,
26
27
case 2:
28
/* Tag check fail causes asynchronous flag set. */
29
- mmu_idx = arm_mmu_idx_el(env, el);
30
- if (regime_has_2_ranges(mmu_idx)) {
31
+ if (regime_has_2_ranges(arm_mmu_idx)) {
32
select = extract64(dirty_ptr, 55, 1);
33
} else {
34
select = 0;
35
--
36
2.20.1
37
38
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
The reporting in AArch64.TagCheckFail only depends on PSTATE.EL,
4
and not the AccType of the operation. There are two guest
5
visible problems that affect LDTR and STTR because of this:
6
7
(1) Selecting TCF0 vs TCF1 to decide on reporting,
8
(2) Report "data abort same el" not "data abort lower el".
9
10
Reported-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
11
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
12
Reviewed-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
13
Tested-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
14
Message-id: 20201008162155.161886-3-richard.henderson@linaro.org
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
---
17
target/arm/mte_helper.c | 10 +++-------
18
1 file changed, 3 insertions(+), 7 deletions(-)
19
20
diff --git a/target/arm/mte_helper.c b/target/arm/mte_helper.c
21
index XXXXXXX..XXXXXXX 100644
22
--- a/target/arm/mte_helper.c
23
+++ b/target/arm/mte_helper.c
24
@@ -XXX,XX +XXX,XX @@ static void mte_check_fail(CPUARMState *env, uint32_t desc,
25
reg_el = regime_el(env, arm_mmu_idx);
26
sctlr = env->cp15.sctlr_el[reg_el];
27
28
- switch (arm_mmu_idx) {
29
- case ARMMMUIdx_E10_0:
30
- case ARMMMUIdx_E20_0:
31
- el = 0;
32
+ el = arm_current_el(env);
33
+ if (el == 0) {
34
tcf = extract64(sctlr, 38, 2);
35
- break;
36
- default:
37
- el = reg_el;
38
+ } else {
39
tcf = extract64(sctlr, 40, 2);
40
}
41
42
--
43
2.20.1
44
45
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
Unlike many other bits in HCR_EL2, the description for this
4
bit does not contain the phrase "if ... this field behaves
5
as 0 for all purposes other than", so do not squash the bit
6
in arm_hcr_el2_eff.
7
8
Instead, replicate the E2H+TGE test in the two places that
9
require it.
10
11
Reported-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
12
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
13
Reviewed-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
14
Tested-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
15
Message-id: 20201008162155.161886-4-richard.henderson@linaro.org
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
---
18
target/arm/internals.h | 9 +++++----
19
target/arm/helper.c | 9 +++++----
20
2 files changed, 10 insertions(+), 8 deletions(-)
21
22
diff --git a/target/arm/internals.h b/target/arm/internals.h
23
index XXXXXXX..XXXXXXX 100644
24
--- a/target/arm/internals.h
25
+++ b/target/arm/internals.h
26
@@ -XXX,XX +XXX,XX @@ static inline bool allocation_tag_access_enabled(CPUARMState *env, int el,
27
&& !(env->cp15.scr_el3 & SCR_ATA)) {
28
return false;
29
}
30
- if (el < 2
31
- && arm_feature(env, ARM_FEATURE_EL2)
32
- && !(arm_hcr_el2_eff(env) & HCR_ATA)) {
33
- return false;
34
+ if (el < 2 && arm_feature(env, ARM_FEATURE_EL2)) {
35
+ uint64_t hcr = arm_hcr_el2_eff(env);
36
+ if (!(hcr & HCR_ATA) && (!(hcr & HCR_E2H) || !(hcr & HCR_TGE))) {
37
+ return false;
38
+ }
39
}
40
sctlr &= (el == 0 ? SCTLR_ATA0 : SCTLR_ATA);
41
return sctlr != 0;
42
diff --git a/target/arm/helper.c b/target/arm/helper.c
43
index XXXXXXX..XXXXXXX 100644
44
--- a/target/arm/helper.c
45
+++ b/target/arm/helper.c
46
@@ -XXX,XX +XXX,XX @@ static CPAccessResult access_mte(CPUARMState *env, const ARMCPRegInfo *ri,
47
{
48
int el = arm_current_el(env);
49
50
- if (el < 2 &&
51
- arm_feature(env, ARM_FEATURE_EL2) &&
52
- !(arm_hcr_el2_eff(env) & HCR_ATA)) {
53
- return CP_ACCESS_TRAP_EL2;
54
+ if (el < 2 && arm_feature(env, ARM_FEATURE_EL2)) {
55
+ uint64_t hcr = arm_hcr_el2_eff(env);
56
+ if (!(hcr & HCR_ATA) && (!(hcr & HCR_E2H) || !(hcr & HCR_TGE))) {
57
+ return CP_ACCESS_TRAP_EL2;
58
+ }
59
}
60
if (el < 3 &&
61
arm_feature(env, ARM_FEATURE_EL3) &&
62
--
63
2.20.1
64
65
diff view generated by jsdifflib
Deleted patch
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
1
3
Commit 7998beb9c2e removed the ram_size initialization in the
4
arm_boot_info structure, however it is used by arm_load_kernel().
5
6
Initialize the field to fix:
7
8
$ qemu-system-arm -M n800 -append 'console=ttyS1' \
9
-kernel meego-arm-n8x0-1.0.80.20100712.1431-vmlinuz-2.6.35~rc4-129.1-n8x0
10
qemu-system-arm: kernel 'meego-arm-n8x0-1.0.80.20100712.1431-vmlinuz-2.6.35~rc4-129.1-n8x0' is too large to fit in RAM (kernel size 1964608, RAM size 0)
11
12
Noticed while running the test introduced in commit 050a82f0c5b
13
("tests/acceptance: Add a test for the N800 and N810 arm machines").
14
15
Fixes: 7998beb9c2e ("arm/nseries: use memdev for RAM")
16
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
17
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
18
Tested-by: Thomas Huth <thuth@redhat.com>
19
Message-id: 20201019095148.1602119-1-f4bug@amsat.org
20
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
---
22
hw/arm/nseries.c | 1 +
23
1 file changed, 1 insertion(+)
24
25
diff --git a/hw/arm/nseries.c b/hw/arm/nseries.c
26
index XXXXXXX..XXXXXXX 100644
27
--- a/hw/arm/nseries.c
28
+++ b/hw/arm/nseries.c
29
@@ -XXX,XX +XXX,XX @@ static void n8x0_init(MachineState *machine,
30
g_free(sz);
31
exit(EXIT_FAILURE);
32
}
33
+ binfo->ram_size = machine->ram_size;
34
35
memory_region_add_subregion(get_system_memory(), OMAP2_Q2_BASE,
36
machine->ram);
37
--
38
2.20.1
39
40
diff view generated by jsdifflib
Deleted patch
1
The t32 decode has a group which represents a set of insns
2
which overlap with B_cond_thumb because they have [25:23]=111
3
(which is an invalid condition code field for the branch insn).
4
This group is currently defined using the {} overlap-OK syntax,
5
but it is almost entirely non-overlapping patterns. Switch
6
it over to use a non-overlapping group.
7
1
8
For this to be valid syntactically, CPS must move into the same
9
overlapping-group as the hint insns (CPS vs hints was the
10
only actual use of the overlap facility for the group).
11
12
The non-overlapping subgroup for CLREX/DSB/DMB/ISB/SB is no longer
13
necessary and so we can remove it (promoting those insns to
14
be members of the parent group).
15
16
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
Message-id: 20201019151301.2046-5-peter.maydell@linaro.org
19
---
20
target/arm/t32.decode | 26 ++++++++++++--------------
21
1 file changed, 12 insertions(+), 14 deletions(-)
22
23
diff --git a/target/arm/t32.decode b/target/arm/t32.decode
24
index XXXXXXX..XXXXXXX 100644
25
--- a/target/arm/t32.decode
26
+++ b/target/arm/t32.decode
27
@@ -XXX,XX +XXX,XX @@ CLZ 1111 1010 1011 ---- 1111 .... 1000 .... @rdm
28
{
29
# Group insn[25:23] = 111, which is cond=111x for the branch below,
30
# or unconditional, which would be illegal for the branch.
31
- {
32
- # Hints
33
+ [
34
+ # Hints, and CPS
35
{
36
YIELD 1111 0011 1010 1111 1000 0000 0000 0001
37
WFE 1111 0011 1010 1111 1000 0000 0000 0010
38
@@ -XXX,XX +XXX,XX @@ CLZ 1111 1010 1011 ---- 1111 .... 1000 .... @rdm
39
# The canonical nop ends in 0000 0000, but the whole rest
40
# of the space is "reserved hint, behaves as nop".
41
NOP 1111 0011 1010 1111 1000 0000 ---- ----
42
+
43
+ # If imod == '00' && M == '0' then SEE "Hint instructions", above.
44
+ CPS 1111 0011 1010 1111 1000 0 imod:2 M:1 A:1 I:1 F:1 mode:5 \
45
+ &cps
46
}
47
48
- # If imod == '00' && M == '0' then SEE "Hint instructions", above.
49
- CPS 1111 0011 1010 1111 1000 0 imod:2 M:1 A:1 I:1 F:1 mode:5 \
50
- &cps
51
-
52
# Miscellaneous control
53
- [
54
- CLREX 1111 0011 1011 1111 1000 1111 0010 1111
55
- DSB 1111 0011 1011 1111 1000 1111 0100 ----
56
- DMB 1111 0011 1011 1111 1000 1111 0101 ----
57
- ISB 1111 0011 1011 1111 1000 1111 0110 ----
58
- SB 1111 0011 1011 1111 1000 1111 0111 0000
59
- ]
60
+ CLREX 1111 0011 1011 1111 1000 1111 0010 1111
61
+ DSB 1111 0011 1011 1111 1000 1111 0100 ----
62
+ DMB 1111 0011 1011 1111 1000 1111 0101 ----
63
+ ISB 1111 0011 1011 1111 1000 1111 0110 ----
64
+ SB 1111 0011 1011 1111 1000 1111 0111 0000
65
66
# Note that the v7m insn overlaps both the normal and banked insn.
67
{
68
@@ -XXX,XX +XXX,XX @@ CLZ 1111 1010 1011 ---- 1111 .... 1000 .... @rdm
69
HVC 1111 0111 1110 .... 1000 .... .... .... \
70
&i imm=%imm16_16_0
71
UDF 1111 0111 1111 ---- 1010 ---- ---- ----
72
- }
73
+ ]
74
B_cond_thumb 1111 0. cond:4 ...... 10.0 ............ &ci imm=%imm21
75
}
76
77
--
78
2.20.1
79
80
diff view generated by jsdifflib
Deleted patch
1
The BLX immediate insn in the Thumb encoding always performs
2
a switch from Thumb to Arm state. This would be totally useless
3
in M-profile which has no Arm decoder, and so the instruction
4
does not exist at all there. Make the encoding UNDEF for M-profile.
5
1
6
(This part of the encoding space is used for the branch-future
7
and low-overhead-loop insns in v8.1M.)
8
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Message-id: 20201019151301.2046-6-peter.maydell@linaro.org
12
---
13
target/arm/translate.c | 8 ++++++++
14
1 file changed, 8 insertions(+)
15
16
diff --git a/target/arm/translate.c b/target/arm/translate.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/translate.c
19
+++ b/target/arm/translate.c
20
@@ -XXX,XX +XXX,XX @@ static bool trans_BLX_i(DisasContext *s, arg_BLX_i *a)
21
{
22
TCGv_i32 tmp;
23
24
+ /*
25
+ * BLX <imm> would be useless on M-profile; the encoding space
26
+ * is used for other insns from v8.1M onward, and UNDEFs before that.
27
+ */
28
+ if (arm_dc_feature(s, ARM_FEATURE_M)) {
29
+ return false;
30
+ }
31
+
32
/* For A32, ARM_FEATURE_V5 is checked near the start of the uncond block. */
33
if (s->thumb && (a->imm & 2)) {
34
return false;
35
--
36
2.20.1
37
38
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
The kernel sets btype for the signal handler as if for a call.
4
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20201016184207.786698-2-richard.henderson@linaro.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
linux-user/aarch64/signal.c | 10 ++++++++--
11
1 file changed, 8 insertions(+), 2 deletions(-)
12
13
diff --git a/linux-user/aarch64/signal.c b/linux-user/aarch64/signal.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/linux-user/aarch64/signal.c
16
+++ b/linux-user/aarch64/signal.c
17
@@ -XXX,XX +XXX,XX @@ static void target_setup_frame(int usig, struct target_sigaction *ka,
18
+ offsetof(struct target_rt_frame_record, tramp);
19
}
20
env->xregs[0] = usig;
21
- env->xregs[31] = frame_addr;
22
env->xregs[29] = frame_addr + fr_ofs;
23
- env->pc = ka->_sa_handler;
24
env->xregs[30] = return_addr;
25
+ env->xregs[31] = frame_addr;
26
+ env->pc = ka->_sa_handler;
27
+
28
+ /* Invoke the signal handler as if by indirect call. */
29
+ if (cpu_isar_feature(aa64_bti, env_archcpu(env))) {
30
+ env->btype = 2;
31
+ }
32
+
33
if (info) {
34
tswap_siginfo(&frame->info, info);
35
env->xregs[1] = frame_addr + offsetof(struct target_rt_sigframe, info);
36
--
37
2.20.1
38
39
diff view generated by jsdifflib