1
This pullreq is (1) my GICv4 patches (2) most of the first third of RTH's
1
Hi; here's a target-arm pullreq. Mostly this is some decodetree
2
cleanup patchset (3) one patch fixing an smmuv3 bug...
2
conversion patches from me, plus a scattering of other bug fixes.
3
3
4
thanks
4
thanks
5
-- PMM
5
-- PMM
6
6
7
The following changes since commit a74782936dc6e979ce371dabda4b1c05624ea87f:
7
The following changes since commit e3660cc1e3cb136af50c0eaaeac27943c2438d1d:
8
8
9
Merge tag 'pull-migration-20220421a' of https://gitlab.com/dagrh/qemu into staging (2022-04-21 18:48:18 -0700)
9
Merge tag 'pull-loongarch-20230616' of https://gitlab.com/gaosong/qemu into staging (2023-06-16 12:30:16 +0200)
10
10
11
are available in the Git repository at:
11
are available in the Git repository at:
12
12
13
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20220422
13
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20230619
14
14
15
for you to fetch changes up to 9792130613191c1e0c34109918c5e07b9f1429a5:
15
for you to fetch changes up to 074259c0f2ac40042dce766d870318cc22f388eb:
16
16
17
hw/arm/smmuv3: Pass the actual perm to returned IOMMUTLBEntry in smmuv3_translate() (2022-04-22 10:19:15 +0100)
17
hw/misc/bcm2835_property: Handle CORE_CLK_ID firmware property (2023-06-19 15:27:21 +0100)
18
18
19
----------------------------------------------------------------
19
----------------------------------------------------------------
20
target-arm queue:
20
target-arm queue:
21
* Implement GICv4 emulation
21
* Fix return value from LDSMIN/LDSMAX 8/16 bit atomics
22
* Some cleanup patches in target/arm
22
* Return correct result for LDG when ATA=0
23
* hw/arm/smmuv3: Pass the actual perm to returned IOMMUTLBEntry in smmuv3_translate()
23
* Conversion of system insns, loads and stores to decodetree
24
* hw/intc/allwinner-a10-pic: Handle IRQ levels other than 0 or 1
25
* hw/sd/allwinner-sdhost: Don't send non-boolean IRQ line levels
26
* hw/timer/nrf51_timer: Don't lose time when timer is queried in tight loop
27
* hw/arm/Kconfig: sbsa-ref uses Bochs display
28
* imx_serial: set wake bit when we receive a data byte
29
* docs: sbsa: document board to firmware interface
30
* hw/misc/bcm2835_property: avoid hard-coded constants
24
31
25
----------------------------------------------------------------
32
----------------------------------------------------------------
26
Peter Maydell (41):
33
Marcin Juszkiewicz (2):
27
hw/intc/arm_gicv3_its: Add missing blank line
34
hw/arm/Kconfig: sbsa-ref uses Bochs display
28
hw/intc/arm_gicv3: Sanity-check num-cpu property
35
docs: sbsa: document board to firmware interface
29
hw/intc/arm_gicv3: Insist that redist region capacity matches CPU count
30
hw/intc/arm_gicv3: Report correct PIDR0 values for ID registers
31
target/arm/cpu.c: ignore VIRQ and VFIQ if no EL2
32
hw/intc/arm_gicv3_its: Factor out "is intid a valid LPI ID?"
33
hw/intc/arm_gicv3_its: Implement GITS_BASER2 for GICv4
34
hw/intc/arm_gicv3_its: Implement VMAPI and VMAPTI
35
hw/intc/arm_gicv3_its: Implement VMAPP
36
hw/intc/arm_gicv3_its: Distinguish success and error cases of CMD_CONTINUE
37
hw/intc/arm_gicv3_its: Factor out "find ITE given devid, eventid"
38
hw/intc/arm_gicv3_its: Factor out CTE lookup sequence
39
hw/intc/arm_gicv3_its: Split out process_its_cmd() physical interrupt code
40
hw/intc/arm_gicv3_its: Handle virtual interrupts in process_its_cmd()
41
hw/intc/arm_gicv3: Keep pointers to every connected ITS
42
hw/intc/arm_gicv3_its: Implement VMOVP
43
hw/intc/arm_gicv3_its: Implement VSYNC
44
hw/intc/arm_gicv3_its: Implement INV command properly
45
hw/intc/arm_gicv3_its: Implement INV for virtual interrupts
46
hw/intc/arm_gicv3_its: Implement VMOVI
47
hw/intc/arm_gicv3_its: Implement VINVALL
48
hw/intc/arm_gicv3: Implement GICv4's new redistributor frame
49
hw/intc/arm_gicv3: Implement new GICv4 redistributor registers
50
hw/intc/arm_gicv3_cpuif: Split "update vIRQ/vFIQ" from gicv3_cpuif_virt_update()
51
hw/intc/arm_gicv3_cpuif: Support vLPIs
52
hw/intc/arm_gicv3_cpuif: Don't recalculate maintenance irq unnecessarily
53
hw/intc/arm_gicv3_redist: Factor out "update hpplpi for one LPI" logic
54
hw/intc/arm_gicv3_redist: Factor out "update hpplpi for all LPIs" logic
55
hw/intc/arm_gicv3_redist: Recalculate hppvlpi on VPENDBASER writes
56
hw/intc/arm_gicv3_redist: Factor out "update bit in pending table" code
57
hw/intc/arm_gicv3_redist: Implement gicv3_redist_process_vlpi()
58
hw/intc/arm_gicv3_redist: Implement gicv3_redist_vlpi_pending()
59
hw/intc/arm_gicv3_redist: Use set_pending_table_bit() in mov handling
60
hw/intc/arm_gicv3_redist: Implement gicv3_redist_mov_vlpi()
61
hw/intc/arm_gicv3_redist: Implement gicv3_redist_vinvall()
62
hw/intc/arm_gicv3_redist: Implement gicv3_redist_inv_vlpi()
63
hw/intc/arm_gicv3: Update ID and feature registers for GICv4
64
hw/intc/arm_gicv3: Allow 'revision' property to be set to 4
65
hw/arm/virt: Use VIRT_GIC_VERSION_* enum values in create_gic()
66
hw/arm/virt: Abstract out calculation of redistributor region capacity
67
hw/arm/virt: Support TCG GICv4
68
36
69
Richard Henderson (19):
37
Martin Kaiser (1):
70
target/arm: Update ISAR fields for ARMv8.8
38
imx_serial: set wake bit when we receive a data byte
71
target/arm: Update SCR_EL3 bits to ARMv8.8
72
target/arm: Update SCTLR bits to ARMv9.2
73
target/arm: Change DisasContext.aarch64 to bool
74
target/arm: Change CPUArchState.aarch64 to bool
75
target/arm: Extend store_cpu_offset to take field size
76
target/arm: Change DisasContext.thumb to bool
77
target/arm: Change CPUArchState.thumb to bool
78
target/arm: Remove fpexc32_access
79
target/arm: Split out set_btype_raw
80
target/arm: Split out gen_rebuild_hflags
81
target/arm: Simplify GEN_SHIFT in translate.c
82
target/arm: Simplify gen_sar
83
target/arm: Simplify aa32 DISAS_WFI
84
target/arm: Use tcg_constant in translate-m-nocp.c
85
target/arm: Use tcg_constant in translate-neon.c
86
target/arm: Use smin/smax for do_sat_addsub_32
87
target/arm: Use tcg_constant in translate-vfp.c
88
target/arm: Use tcg_constant_i32 in translate.h
89
39
90
Xiang Chen (1):
40
Peter Maydell (26):
91
hw/arm/smmuv3: Pass the actual perm to returned IOMMUTLBEntry in smmuv3_translate()
41
target/arm: Fix return value from LDSMIN/LDSMAX 8/16 bit atomics
42
target/arm: Return correct result for LDG when ATA=0
43
target/arm: Pass memop to gen_mte_check1_mmuidx() in reg_imm9 decode
44
target/arm: Consistently use finalize_memop_asimd() for ASIMD loads/stores
45
target/arm: Convert hint instruction space to decodetree
46
target/arm: Convert barrier insns to decodetree
47
target/arm: Convert CFINV, XAFLAG and AXFLAG to decodetree
48
target/arm: Convert MSR (immediate) to decodetree
49
target/arm: Convert MSR (reg), MRS, SYS, SYSL to decodetree
50
target/arm: Convert exception generation instructions to decodetree
51
target/arm: Convert load/store exclusive and ordered to decodetree
52
target/arm: Convert LDXP, STXP, CASP, CAS to decodetree
53
target/arm: Convert load reg (literal) group to decodetree
54
target/arm: Convert load/store-pair to decodetree
55
target/arm: Convert ld/st reg+imm9 insns to decodetree
56
target/arm: Convert LDR/STR with 12-bit immediate to decodetree
57
target/arm: Convert LDR/STR reg+reg to decodetree
58
target/arm: Convert atomic memory ops to decodetree
59
target/arm: Convert load (pointer auth) insns to decodetree
60
target/arm: Convert LDAPR/STLR (imm) to decodetree
61
target/arm: Convert load/store (multiple structures) to decodetree
62
target/arm: Convert load/store single structure to decodetree
63
target/arm: Convert load/store tags insns to decodetree
64
hw/intc/allwinner-a10-pic: Handle IRQ levels other than 0 or 1
65
hw/sd/allwinner-sdhost: Don't send non-boolean IRQ line levels
66
hw/timer/nrf51_timer: Don't lose time when timer is queried in tight loop
92
67
93
docs/system/arm/virt.rst | 5 +-
68
Sergey Kambalin (4):
94
hw/intc/gicv3_internal.h | 231 ++++++++-
69
hw/arm/raspi: Import Linux raspi definitions as 'raspberrypi-fw-defs.h'
95
include/hw/arm/virt.h | 19 +-
70
hw/misc/bcm2835_property: Use 'raspberrypi-fw-defs.h' definitions
96
include/hw/intc/arm_gicv3_common.h | 13 +
71
hw/misc/bcm2835_property: Replace magic frequency values by definitions
97
include/hw/intc/arm_gicv3_its_common.h | 1 +
72
hw/misc/bcm2835_property: Handle CORE_CLK_ID firmware property
98
target/arm/cpu.h | 59 ++-
73
99
target/arm/translate-a32.h | 13 +-
74
docs/system/arm/sbsa.rst | 38 +-
100
target/arm/translate.h | 17 +-
75
include/hw/arm/raspi_platform.h | 10 +
101
hw/arm/smmuv3.c | 2 +-
76
include/hw/char/imx_serial.h | 1 +
102
hw/arm/virt.c | 102 +++-
77
include/hw/misc/raspberrypi-fw-defs.h | 163 ++
103
hw/intc/arm_gicv3_common.c | 54 +-
78
target/arm/tcg/a64.decode | 403 ++++
104
hw/intc/arm_gicv3_cpuif.c | 195 ++++++--
79
hw/char/imx_serial.c | 5 +-
105
hw/intc/arm_gicv3_dist.c | 7 +-
80
hw/intc/allwinner-a10-pic.c | 2 +-
106
hw/intc/arm_gicv3_its.c | 876 +++++++++++++++++++++++++++------
81
hw/misc/bcm2835_property.c | 112 +-
107
hw/intc/arm_gicv3_its_kvm.c | 2 +
82
hw/sd/allwinner-sdhost.c | 2 +-
108
hw/intc/arm_gicv3_kvm.c | 5 +
83
hw/timer/nrf51_timer.c | 7 +-
109
hw/intc/arm_gicv3_redist.c | 480 +++++++++++++++---
84
target/arm/tcg/translate-a64.c | 3319 +++++++++++++++------------------
110
linux-user/arm/cpu_loop.c | 2 +-
85
hw/arm/Kconfig | 1 +
111
target/arm/cpu.c | 16 +-
86
12 files changed, 2157 insertions(+), 1906 deletions(-)
112
target/arm/helper-a64.c | 4 +-
87
create mode 100644 include/hw/misc/raspberrypi-fw-defs.h
113
target/arm/helper.c | 19 +-
114
target/arm/hvf/hvf.c | 2 +-
115
target/arm/m_helper.c | 6 +-
116
target/arm/op_helper.c | 13 -
117
target/arm/translate-a64.c | 50 +-
118
target/arm/translate-m-nocp.c | 12 +-
119
target/arm/translate-neon.c | 21 +-
120
target/arm/translate-sve.c | 9 +-
121
target/arm/translate-vfp.c | 76 +--
122
target/arm/translate.c | 101 ++--
123
hw/intc/trace-events | 18 +-
124
31 files changed, 1890 insertions(+), 540 deletions(-)
diff view generated by jsdifflib
Deleted patch
1
In commit b6f96009acc we split do_process_its_cmd() from
2
process_its_cmd(), but forgot the usual blank line between function
3
definitions. Add it.
4
1
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20220408141550.1271295-2-peter.maydell@linaro.org
8
---
9
hw/intc/arm_gicv3_its.c | 1 +
10
1 file changed, 1 insertion(+)
11
12
diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/intc/arm_gicv3_its.c
15
+++ b/hw/intc/arm_gicv3_its.c
16
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult do_process_its_cmd(GICv3ITSState *s, uint32_t devid,
17
}
18
return CMD_CONTINUE;
19
}
20
+
21
static ItsCmdResult process_its_cmd(GICv3ITSState *s, const uint64_t *cmdpkt,
22
ItsCmdType cmd)
23
{
24
--
25
2.25.1
diff view generated by jsdifflib
Deleted patch
1
In the GICv3 code we implicitly rely on there being at least one CPU
2
and thus at least one redistributor and CPU interface. Sanity-check
3
that the property the board code sets is not zero.
4
1
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20220408141550.1271295-3-peter.maydell@linaro.org
8
---
9
hw/intc/arm_gicv3_common.c | 4 ++++
10
1 file changed, 4 insertions(+)
11
12
diff --git a/hw/intc/arm_gicv3_common.c b/hw/intc/arm_gicv3_common.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/intc/arm_gicv3_common.c
15
+++ b/hw/intc/arm_gicv3_common.c
16
@@ -XXX,XX +XXX,XX @@ static void arm_gicv3_common_realize(DeviceState *dev, Error **errp)
17
s->num_irq, GIC_INTERNAL);
18
return;
19
}
20
+ if (s->num_cpu == 0) {
21
+ error_setg(errp, "num-cpu must be at least 1");
22
+ return;
23
+ }
24
25
/* ITLinesNumber is represented as (N / 32) - 1, so this is an
26
* implementation imposed restriction, not an architectural one,
27
--
28
2.25.1
diff view generated by jsdifflib
Deleted patch
1
Boards using the GICv3 need to configure it with both the total
2
number of CPUs and also the sizes of all the memory regions which
3
contain redistributors (one redistributor per CPU). At the moment
4
the GICv3 checks that the number of CPUs specified is not too many to
5
fit in the defined redistributor regions, but in fact the code
6
assumes that the two match exactly. For instance when we set the
7
GICR_TYPER.Last bit on the final redistributor in each region, we
8
assume that we don't need to consider the possibility of a region
9
being only half full of redistributors or even completely empty. We
10
also assume in gicv3_redist_read() and gicv3_redist_write() that we
11
can calculate the CPU index from the offset within the MemoryRegion
12
and that this will always be in range.
13
1
14
Fortunately all the board code sets the redistributor region sizes to
15
exactly match the CPU count, so this isn't a visible bug. We could
16
in theory make the GIC code handle non-full redistributor regions, or
17
have it automatically reduce the provided region sizes to match the
18
CPU count, but the simplest thing is just to strengthen the error
19
check and insist that the CPU count and redistributor region size
20
settings match exactly, since all the board code does that anyway.
21
22
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
23
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
24
Message-id: 20220408141550.1271295-4-peter.maydell@linaro.org
25
---
26
hw/intc/arm_gicv3_common.c | 4 ++--
27
1 file changed, 2 insertions(+), 2 deletions(-)
28
29
diff --git a/hw/intc/arm_gicv3_common.c b/hw/intc/arm_gicv3_common.c
30
index XXXXXXX..XXXXXXX 100644
31
--- a/hw/intc/arm_gicv3_common.c
32
+++ b/hw/intc/arm_gicv3_common.c
33
@@ -XXX,XX +XXX,XX @@ static void arm_gicv3_common_realize(DeviceState *dev, Error **errp)
34
for (i = 0; i < s->nb_redist_regions; i++) {
35
rdist_capacity += s->redist_region_count[i];
36
}
37
- if (rdist_capacity < s->num_cpu) {
38
+ if (rdist_capacity != s->num_cpu) {
39
error_setg(errp, "Capacity of the redist regions(%d) "
40
- "is less than number of vcpus(%d)",
41
+ "does not match the number of vcpus(%d)",
42
rdist_capacity, s->num_cpu);
43
return;
44
}
45
--
46
2.25.1
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
The atomic memory operations are supposed to return the old memory
2
data value in the destination register. This value is not
3
sign-extended, even if the operation is the signed minimum or
4
maximum. (In the pseudocode for the instructions the returned data
5
value is passed to ZeroExtend() to create the value in the register.)
2
6
3
This function is incorrect in that it does not properly consider
7
We got this wrong because we were doing a 32-to-64 zero extend on the
4
CPTR_EL2.FPEN. We've already got another mechanism for raising
8
result for 8 and 16 bit data values, rather than the correct amount
5
an FPU access trap: ARM_CP_FPU, so use that instead.
9
of zero extension.
6
10
7
Remove CP_ACCESS_TRAP_FP_EL{2,3}, which becomes unused.
11
Fix the bug by using ext8u and ext16u for the MO_8 and MO_16 data
12
sizes rather than ext32u.
8
13
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
14
Cc: qemu-stable@nongnu.org
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
17
Message-id: 20230602155223.2040685-2-peter.maydell@linaro.org
12
---
18
---
13
target/arm/cpu.h | 5 -----
19
target/arm/tcg/translate-a64.c | 18 ++++++++++++++++--
14
target/arm/helper.c | 17 ++---------------
20
1 file changed, 16 insertions(+), 2 deletions(-)
15
target/arm/op_helper.c | 13 -------------
16
3 files changed, 2 insertions(+), 33 deletions(-)
17
21
18
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
22
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
19
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
20
--- a/target/arm/cpu.h
24
--- a/target/arm/tcg/translate-a64.c
21
+++ b/target/arm/cpu.h
25
+++ b/target/arm/tcg/translate-a64.c
22
@@ -XXX,XX +XXX,XX @@ typedef enum CPAccessResult {
26
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_atomic(DisasContext *s, uint32_t insn,
23
/* As CP_ACCESS_UNCATEGORIZED, but for traps directly to EL2 or EL3 */
27
*/
24
CP_ACCESS_TRAP_UNCATEGORIZED_EL2 = 5,
28
fn(tcg_rt, clean_addr, tcg_rs, get_mem_index(s), mop);
25
CP_ACCESS_TRAP_UNCATEGORIZED_EL3 = 6,
29
26
- /* Access fails and results in an exception syndrome for an FP access,
30
- if ((mop & MO_SIGN) && size != MO_64) {
27
- * trapped directly to EL2 or EL3
31
- tcg_gen_ext32u_i64(tcg_rt, tcg_rt);
28
- */
32
+ if (mop & MO_SIGN) {
29
- CP_ACCESS_TRAP_FP_EL2 = 7,
33
+ switch (size) {
30
- CP_ACCESS_TRAP_FP_EL3 = 8,
34
+ case MO_8:
31
} CPAccessResult;
35
+ tcg_gen_ext8u_i64(tcg_rt, tcg_rt);
32
36
+ break;
33
/* Access functions for coprocessor registers. These cannot fail and
37
+ case MO_16:
34
diff --git a/target/arm/helper.c b/target/arm/helper.c
38
+ tcg_gen_ext16u_i64(tcg_rt, tcg_rt);
35
index XXXXXXX..XXXXXXX 100644
39
+ break;
36
--- a/target/arm/helper.c
40
+ case MO_32:
37
+++ b/target/arm/helper.c
41
+ tcg_gen_ext32u_i64(tcg_rt, tcg_rt);
38
@@ -XXX,XX +XXX,XX @@ static void sctlr_write(CPUARMState *env, const ARMCPRegInfo *ri,
42
+ break;
43
+ case MO_64:
44
+ break;
45
+ default:
46
+ g_assert_not_reached();
47
+ }
39
}
48
}
40
}
49
}
41
50
42
-static CPAccessResult fpexc32_access(CPUARMState *env, const ARMCPRegInfo *ri,
43
- bool isread)
44
-{
45
- if ((env->cp15.cptr_el[2] & CPTR_TFP) && arm_current_el(env) == 2) {
46
- return CP_ACCESS_TRAP_FP_EL2;
47
- }
48
- if (env->cp15.cptr_el[3] & CPTR_TFP) {
49
- return CP_ACCESS_TRAP_FP_EL3;
50
- }
51
- return CP_ACCESS_OK;
52
-}
53
-
54
static void sdcr_write(CPUARMState *env, const ARMCPRegInfo *ri,
55
uint64_t value)
56
{
57
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo v8_cp_reginfo[] = {
58
.access = PL1_RW, .readfn = spsel_read, .writefn = spsel_write },
59
{ .name = "FPEXC32_EL2", .state = ARM_CP_STATE_AA64,
60
.opc0 = 3, .opc1 = 4, .crn = 5, .crm = 3, .opc2 = 0,
61
- .type = ARM_CP_ALIAS,
62
- .fieldoffset = offsetof(CPUARMState, vfp.xregs[ARM_VFP_FPEXC]),
63
- .access = PL2_RW, .accessfn = fpexc32_access },
64
+ .access = PL2_RW, .type = ARM_CP_ALIAS | ARM_CP_FPU,
65
+ .fieldoffset = offsetof(CPUARMState, vfp.xregs[ARM_VFP_FPEXC]) },
66
{ .name = "DACR32_EL2", .state = ARM_CP_STATE_AA64,
67
.opc0 = 3, .opc1 = 4, .crn = 3, .crm = 0, .opc2 = 0,
68
.access = PL2_RW, .resetvalue = 0,
69
diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c
70
index XXXXXXX..XXXXXXX 100644
71
--- a/target/arm/op_helper.c
72
+++ b/target/arm/op_helper.c
73
@@ -XXX,XX +XXX,XX @@ void HELPER(access_check_cp_reg)(CPUARMState *env, void *rip, uint32_t syndrome,
74
target_el = 3;
75
syndrome = syn_uncategorized();
76
break;
77
- case CP_ACCESS_TRAP_FP_EL2:
78
- target_el = 2;
79
- /* Since we are an implementation that takes exceptions on a trapped
80
- * conditional insn only if the insn has passed its condition code
81
- * check, we take the IMPDEF choice to always report CV=1 COND=0xe
82
- * (which is also the required value for AArch64 traps).
83
- */
84
- syndrome = syn_fp_access_trap(1, 0xe, false);
85
- break;
86
- case CP_ACCESS_TRAP_FP_EL3:
87
- target_el = 3;
88
- syndrome = syn_fp_access_trap(1, 0xe, false);
89
- break;
90
default:
91
g_assert_not_reached();
92
}
93
--
51
--
94
2.25.1
52
2.34.1
diff view generated by jsdifflib
1
From: Xiang Chen <chenxiang66@hisilicon.com>
1
The LDG instruction loads the tag from a memory address (identified
2
by [Xn + offset]), and then merges that tag into the destination
3
register Xt. We implemented this correctly for the case when
4
allocation tags are enabled, but didn't get it right when ATA=0:
5
instead of merging the tag bits into Xt, we merged them into the
6
memory address [Xn + offset] and then set Xt to that.
2
7
3
It always calls the IOMMU MR translate() callback with flag=IOMMU_NONE in
8
Merge the tag bits into the old Xt value, as they should be.
4
memory_region_iommu_replay(). Currently, smmuv3_translate() return an
5
IOMMUTLBEntry with perm set to IOMMU_NONE even if the translation success,
6
whereas it is expected to return the actual permission set in the table
7
entry.
8
So pass the actual perm to returned IOMMUTLBEntry in the table entry.
9
9
10
Signed-off-by: Xiang Chen <chenxiang66@hisilicon.com>
10
Cc: qemu-stable@nongnu.org
11
Reviewed-by: Eric Auger <eric.auger@redhat.com>
11
Fixes: c15294c1e36a7dd9b25 ("target/arm: Implement LDG, STG, ST2G instructions")
12
Message-id: 1650094695-121918-1-git-send-email-chenxiang66@hisilicon.com
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
14
---
15
hw/arm/smmuv3.c | 2 +-
15
target/arm/tcg/translate-a64.c | 6 +++++-
16
1 file changed, 1 insertion(+), 1 deletion(-)
16
1 file changed, 5 insertions(+), 1 deletion(-)
17
17
18
diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c
18
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
19
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
20
--- a/hw/arm/smmuv3.c
20
--- a/target/arm/tcg/translate-a64.c
21
+++ b/hw/arm/smmuv3.c
21
+++ b/target/arm/tcg/translate-a64.c
22
@@ -XXX,XX +XXX,XX @@ epilogue:
22
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_tag(DisasContext *s, uint32_t insn)
23
qemu_mutex_unlock(&s->mutex);
23
if (s->ata) {
24
switch (status) {
24
gen_helper_ldg(tcg_rt, cpu_env, addr, tcg_rt);
25
case SMMU_TRANS_SUCCESS:
25
} else {
26
- entry.perm = flag;
26
+ /*
27
+ entry.perm = cached_entry->entry.perm;
27
+ * Tag access disabled: we must check for aborts on the load
28
entry.translated_addr = cached_entry->entry.translated_addr +
28
+ * load from [rn+offset], and then insert a 0 tag into rt.
29
(addr & cached_entry->entry.addr_mask);
29
+ */
30
entry.addr_mask = cached_entry->entry.addr_mask;
30
clean_addr = clean_data_tbi(s, addr);
31
gen_probe_access(s, clean_addr, MMU_DATA_LOAD, MO_8);
32
- gen_address_with_allocation_tag0(tcg_rt, addr);
33
+ gen_address_with_allocation_tag0(tcg_rt, tcg_rt);
34
}
35
} else {
36
tcg_rt = cpu_reg_sp(s, rt);
31
--
37
--
32
2.25.1
38
2.34.1
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
In disas_ldst_reg_imm9() we missed one place where a call to
2
a gen_mte_check* function should now be passed the memop we
3
have created rather than just being passed the size. Fix this.
2
4
3
Bool is a more appropriate type for this value.
5
Fixes: 0a9091424d ("target/arm: Pass memop to gen_mte_check1*")
4
Adjust the assignments to use true/false.
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
9
---
10
target/arm/tcg/translate-a64.c | 2 +-
11
1 file changed, 1 insertion(+), 1 deletion(-)
5
12
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
13
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
7
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
target/arm/cpu.h | 2 +-
11
target/arm/cpu.c | 2 +-
12
target/arm/helper-a64.c | 4 ++--
13
target/arm/helper.c | 2 +-
14
target/arm/hvf/hvf.c | 2 +-
15
5 files changed, 6 insertions(+), 6 deletions(-)
16
17
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
18
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/cpu.h
15
--- a/target/arm/tcg/translate-a64.c
20
+++ b/target/arm/cpu.h
16
+++ b/target/arm/tcg/translate-a64.c
21
@@ -XXX,XX +XXX,XX @@ typedef struct CPUArchState {
17
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_reg_imm9(DisasContext *s, uint32_t insn,
22
* all other bits are stored in their correct places in env->pstate
18
23
*/
19
clean_addr = gen_mte_check1_mmuidx(s, dirty_addr, is_store,
24
uint32_t pstate;
20
writeback || rn != 31,
25
- uint32_t aarch64; /* 1 if CPU is in aarch64 state; inverse of PSTATE.nRW */
21
- size, is_unpriv, memidx);
26
+ bool aarch64; /* True if CPU is in aarch64 state; inverse of PSTATE.nRW */
22
+ memop, is_unpriv, memidx);
27
23
28
/* Cached TBFLAGS state. See below for which bits are included. */
24
if (is_vector) {
29
CPUARMTBFlags hflags;
25
if (is_store) {
30
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
31
index XXXXXXX..XXXXXXX 100644
32
--- a/target/arm/cpu.c
33
+++ b/target/arm/cpu.c
34
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_reset(DeviceState *dev)
35
36
if (arm_feature(env, ARM_FEATURE_AARCH64)) {
37
/* 64 bit CPUs always start in 64 bit mode */
38
- env->aarch64 = 1;
39
+ env->aarch64 = true;
40
#if defined(CONFIG_USER_ONLY)
41
env->pstate = PSTATE_MODE_EL0t;
42
/* Userspace expects access to DC ZVA, CTL_EL0 and the cache ops */
43
diff --git a/target/arm/helper-a64.c b/target/arm/helper-a64.c
44
index XXXXXXX..XXXXXXX 100644
45
--- a/target/arm/helper-a64.c
46
+++ b/target/arm/helper-a64.c
47
@@ -XXX,XX +XXX,XX @@ void HELPER(exception_return)(CPUARMState *env, uint64_t new_pc)
48
qemu_mutex_unlock_iothread();
49
50
if (!return_to_aa64) {
51
- env->aarch64 = 0;
52
+ env->aarch64 = false;
53
/* We do a raw CPSR write because aarch64_sync_64_to_32()
54
* will sort the register banks out for us, and we've already
55
* caught all the bad-mode cases in el_from_spsr().
56
@@ -XXX,XX +XXX,XX @@ void HELPER(exception_return)(CPUARMState *env, uint64_t new_pc)
57
} else {
58
int tbii;
59
60
- env->aarch64 = 1;
61
+ env->aarch64 = true;
62
spsr &= aarch64_pstate_valid_mask(&env_archcpu(env)->isar);
63
pstate_write(env, spsr);
64
if (!arm_singlestep_active(env)) {
65
diff --git a/target/arm/helper.c b/target/arm/helper.c
66
index XXXXXXX..XXXXXXX 100644
67
--- a/target/arm/helper.c
68
+++ b/target/arm/helper.c
69
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_do_interrupt_aarch64(CPUState *cs)
70
}
71
72
pstate_write(env, PSTATE_DAIF | new_mode);
73
- env->aarch64 = 1;
74
+ env->aarch64 = true;
75
aarch64_restore_sp(env, new_el);
76
helper_rebuild_hflags_a64(env, new_el);
77
78
diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c
79
index XXXXXXX..XXXXXXX 100644
80
--- a/target/arm/hvf/hvf.c
81
+++ b/target/arm/hvf/hvf.c
82
@@ -XXX,XX +XXX,XX @@ int hvf_arch_init_vcpu(CPUState *cpu)
83
hv_return_t ret;
84
int i;
85
86
- env->aarch64 = 1;
87
+ env->aarch64 = true;
88
asm volatile("mrs %0, cntfrq_el0" : "=r"(arm_cpu->gt_cntfrq_hz));
89
90
/* Allocate enough space for our sysreg sync */
91
--
26
--
92
2.25.1
27
2.34.1
93
28
94
29
diff view generated by jsdifflib
1
Split the part of process_its_cmd() which is specific to physical
1
In the recent refactoring we missed a few places which should be
2
interrupts into its own function. This is the part which starts by
2
calling finalize_memop_asimd() for ASIMD loads and stores but
3
taking the ICID and looking it up in the collection table. The
3
instead are just calling finalize_memop(); fix these.
4
handling of virtual interrupts is significantly different (involving
5
a lookup in the vPE table) so structuring the code with one
6
sub-function for the physical interrupt case and one for the virtual
7
interrupt case will be clearer than putting both cases in one large
8
function.
9
4
10
The code for handling the "remove mapping from ITE" for the DISCARD
5
For the disas_ldst_single_struct() and disas_ldst_multiple_struct()
11
command remains in process_its_cmd() because it is common to both
6
cases, this is not a behaviour change because there the size
12
virtual and physical interrupts.
7
is never MO_128 and the two finalize functions do the same thing.
13
8
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
16
Message-id: 20220408141550.1271295-14-peter.maydell@linaro.org
17
---
11
---
18
hw/intc/arm_gicv3_its.c | 51 ++++++++++++++++++++++++++---------------
12
target/arm/tcg/translate-a64.c | 10 ++++++----
19
1 file changed, 33 insertions(+), 18 deletions(-)
13
1 file changed, 6 insertions(+), 4 deletions(-)
20
14
21
diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
15
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
22
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
23
--- a/hw/intc/arm_gicv3_its.c
17
--- a/target/arm/tcg/translate-a64.c
24
+++ b/hw/intc/arm_gicv3_its.c
18
+++ b/target/arm/tcg/translate-a64.c
25
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult lookup_cte(GICv3ITSState *s, const char *who,
19
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_reg_roffset(DisasContext *s, uint32_t insn,
26
return CMD_CONTINUE_OK;
20
if (!fp_access_check(s)) {
27
}
21
return;
28
22
}
29
+static ItsCmdResult process_its_cmd_phys(GICv3ITSState *s, const ITEntry *ite,
23
+ memop = finalize_memop_asimd(s, size);
30
+ int irqlevel)
24
} else {
31
+{
25
if (size == 3 && opc == 2) {
32
+ CTEntry cte;
26
/* PRFM - prefetch */
33
+ ItsCmdResult cmdres;
27
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_reg_roffset(DisasContext *s, uint32_t insn,
34
+
28
is_store = (opc == 0);
35
+ cmdres = lookup_cte(s, __func__, ite->icid, &cte);
29
is_signed = !is_store && extract32(opc, 1, 1);
36
+ if (cmdres != CMD_CONTINUE_OK) {
30
is_extended = (size < 3) && extract32(opc, 0, 1);
37
+ return cmdres;
31
+ memop = finalize_memop(s, size + is_signed * MO_SIGN);
38
+ }
39
+ gicv3_redist_process_lpi(&s->gicv3->cpu[cte.rdbase], ite->intid, irqlevel);
40
+ return CMD_CONTINUE_OK;
41
+}
42
43
/*
44
* This function handles the processing of following commands based on
45
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult do_process_its_cmd(GICv3ITSState *s, uint32_t devid,
46
uint32_t eventid, ItsCmdType cmd)
47
{
48
DTEntry dte;
49
- CTEntry cte;
50
ITEntry ite;
51
ItsCmdResult cmdres;
52
+ int irqlevel;
53
54
cmdres = lookup_ite(s, __func__, devid, eventid, &ite, &dte);
55
if (cmdres != CMD_CONTINUE_OK) {
56
return cmdres;
57
}
32
}
58
33
59
- if (ite.inttype != ITE_INTTYPE_PHYSICAL) {
34
if (rn == 31) {
60
- qemu_log_mask(LOG_GUEST_ERROR,
35
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_reg_roffset(DisasContext *s, uint32_t insn,
61
- "%s: invalid command attributes: invalid ITE\n",
36
62
- __func__);
37
tcg_gen_add_i64(dirty_addr, dirty_addr, tcg_rm);
63
- return CMD_CONTINUE;
38
64
+ irqlevel = (cmd == CLEAR || cmd == DISCARD) ? 0 : 1;
39
- memop = finalize_memop(s, size + is_signed * MO_SIGN);
65
+
40
clean_addr = gen_mte_check1(s, dirty_addr, is_store, true, memop);
66
+ switch (ite.inttype) {
41
67
+ case ITE_INTTYPE_PHYSICAL:
42
if (is_vector) {
68
+ cmdres = process_its_cmd_phys(s, &ite, irqlevel);
43
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_reg_unsigned_imm(DisasContext *s, uint32_t insn,
69
+ break;
44
if (!fp_access_check(s)) {
70
+ case ITE_INTTYPE_VIRTUAL:
45
return;
71
+ if (!its_feature_virtual(s)) {
46
}
72
+ /* Can't happen unless guest is illegally writing to table memory */
47
+ memop = finalize_memop_asimd(s, size);
73
+ qemu_log_mask(LOG_GUEST_ERROR,
48
} else {
74
+ "%s: invalid type %d in ITE (table corrupted?)\n",
49
if (size == 3 && opc == 2) {
75
+ __func__, ite.inttype);
50
/* PRFM - prefetch */
76
+ return CMD_CONTINUE;
51
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_reg_unsigned_imm(DisasContext *s, uint32_t insn,
77
+ }
52
is_store = (opc == 0);
78
+ /* The GICv4 virtual interrupt handling will go here */
53
is_signed = !is_store && extract32(opc, 1, 1);
79
+ g_assert_not_reached();
54
is_extended = (size < 3) && extract32(opc, 0, 1);
80
+ default:
55
+ memop = finalize_memop(s, size + is_signed * MO_SIGN);
81
+ g_assert_not_reached();
82
}
56
}
83
57
84
- cmdres = lookup_cte(s, __func__, ite.icid, &cte);
58
if (rn == 31) {
85
- if (cmdres != CMD_CONTINUE_OK) {
59
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_reg_unsigned_imm(DisasContext *s, uint32_t insn,
86
- return cmdres;
60
offset = imm12 << size;
87
- }
61
tcg_gen_addi_i64(dirty_addr, dirty_addr, offset);
88
-
62
89
- if ((cmd == CLEAR) || (cmd == DISCARD)) {
63
- memop = finalize_memop(s, size + is_signed * MO_SIGN);
90
- gicv3_redist_process_lpi(&s->gicv3->cpu[cte.rdbase], ite.intid, 0);
64
clean_addr = gen_mte_check1(s, dirty_addr, is_store, rn != 31, memop);
91
- } else {
65
92
- gicv3_redist_process_lpi(&s->gicv3->cpu[cte.rdbase], ite.intid, 1);
66
if (is_vector) {
93
- }
67
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_multiple_struct(DisasContext *s, uint32_t insn)
94
-
68
* promote consecutive little-endian elements below.
95
- if (cmd == DISCARD) {
69
*/
96
+ if (cmdres == CMD_CONTINUE_OK && cmd == DISCARD) {
70
clean_addr = gen_mte_checkN(s, tcg_rn, is_store, is_postidx || rn != 31,
97
ITEntry ite = {};
71
- total, finalize_memop(s, size));
98
/* remove mapping from interrupt translation table */
72
+ total, finalize_memop_asimd(s, size));
99
ite.valid = false;
73
74
/*
75
* Consecutive little-endian elements from a single register
76
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_single_struct(DisasContext *s, uint32_t insn)
77
total = selem << scale;
78
tcg_rn = cpu_reg_sp(s, rn);
79
80
- mop = finalize_memop(s, scale);
81
+ mop = finalize_memop_asimd(s, scale);
82
83
clean_addr = gen_mte_checkN(s, tcg_rn, !is_load, is_postidx || rn != 31,
84
total, mop);
100
--
85
--
101
2.25.1
86
2.34.1
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
Convert the various instructions in the hint instruction space
2
to decodetree.
2
3
3
Use tcg_constant_{i32,i64} as appropriate throughout.
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20230602155223.2040685-3-peter.maydell@linaro.org
7
---
8
target/arm/tcg/a64.decode | 31 ++++
9
target/arm/tcg/translate-a64.c | 277 ++++++++++++++++++---------------
10
2 files changed, 185 insertions(+), 123 deletions(-)
4
11
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
12
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
---
9
target/arm/translate-neon.c | 21 +++++++--------------
10
1 file changed, 7 insertions(+), 14 deletions(-)
11
12
diff --git a/target/arm/translate-neon.c b/target/arm/translate-neon.c
13
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/translate-neon.c
14
--- a/target/arm/tcg/a64.decode
15
+++ b/target/arm/translate-neon.c
15
+++ b/target/arm/tcg/a64.decode
16
@@ -XXX,XX +XXX,XX @@ static bool trans_VLDST_multiple(DisasContext *s, arg_VLDST_multiple *a)
16
@@ -XXX,XX +XXX,XX @@ ERETA 1101011 0100 11111 00001 m:1 11111 11111 &reta # ERETAA, ERETAB
17
int mmu_idx = get_mem_index(s);
17
# the processor is in halting debug state (which we don't implement).
18
int size = a->size;
18
# The pattern is listed here as documentation.
19
TCGv_i64 tmp64;
19
# DRPS 1101011 0101 11111 000000 11111 00000
20
- TCGv_i32 addr, tmp;
20
+
21
+ TCGv_i32 addr;
21
+# Hint instruction group
22
22
+{
23
if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
23
+ [
24
return false;
24
+ YIELD 1101 0101 0000 0011 0010 0000 001 11111
25
@@ -XXX,XX +XXX,XX @@ static bool trans_VLDST_multiple(DisasContext *s, arg_VLDST_multiple *a)
25
+ WFE 1101 0101 0000 0011 0010 0000 010 11111
26
26
+ WFI 1101 0101 0000 0011 0010 0000 011 11111
27
tmp64 = tcg_temp_new_i64();
27
+ # We implement WFE to never block, so our SEV/SEVL are NOPs
28
addr = tcg_temp_new_i32();
28
+ # SEV 1101 0101 0000 0011 0010 0000 100 11111
29
- tmp = tcg_const_i32(1 << size);
29
+ # SEVL 1101 0101 0000 0011 0010 0000 101 11111
30
load_reg_var(s, addr, a->rn);
30
+ # Our DGL is a NOP because we don't merge memory accesses anyway.
31
31
+ # DGL 1101 0101 0000 0011 0010 0000 110 11111
32
mop = endian | size | align;
32
+ XPACLRI 1101 0101 0000 0011 0010 0000 111 11111
33
@@ -XXX,XX +XXX,XX @@ static bool trans_VLDST_multiple(DisasContext *s, arg_VLDST_multiple *a)
33
+ PACIA1716 1101 0101 0000 0011 0010 0001 000 11111
34
neon_load_element64(tmp64, tt, n, size);
34
+ PACIB1716 1101 0101 0000 0011 0010 0001 010 11111
35
gen_aa32_st_internal_i64(s, tmp64, addr, mmu_idx, mop);
35
+ AUTIA1716 1101 0101 0000 0011 0010 0001 100 11111
36
}
36
+ AUTIB1716 1101 0101 0000 0011 0010 0001 110 11111
37
- tcg_gen_add_i32(addr, addr, tmp);
37
+ ESB 1101 0101 0000 0011 0010 0010 000 11111
38
+ tcg_gen_addi_i32(addr, addr, 1 << size);
38
+ PACIAZ 1101 0101 0000 0011 0010 0011 000 11111
39
39
+ PACIASP 1101 0101 0000 0011 0010 0011 001 11111
40
/* Subsequent memory operations inherit alignment */
40
+ PACIBZ 1101 0101 0000 0011 0010 0011 010 11111
41
mop &= ~MO_AMASK;
41
+ PACIBSP 1101 0101 0000 0011 0010 0011 011 11111
42
@@ -XXX,XX +XXX,XX @@ static bool trans_VLDST_multiple(DisasContext *s, arg_VLDST_multiple *a)
42
+ AUTIAZ 1101 0101 0000 0011 0010 0011 100 11111
43
}
43
+ AUTIASP 1101 0101 0000 0011 0010 0011 101 11111
44
}
44
+ AUTIBZ 1101 0101 0000 0011 0010 0011 110 11111
45
tcg_temp_free_i32(addr);
45
+ AUTIBSP 1101 0101 0000 0011 0010 0011 111 11111
46
- tcg_temp_free_i32(tmp);
46
+ ]
47
tcg_temp_free_i64(tmp64);
47
+ # The canonical NOP has CRm == op2 == 0, but all of the space
48
48
+ # that isn't specifically allocated to an instruction must NOP
49
gen_neon_ldst_base_update(s, a->rm, a->rn, nregs * interleave * 8);
49
+ NOP 1101 0101 0000 0011 0010 ---- --- 11111
50
@@ -XXX,XX +XXX,XX @@ static bool do_2shift_env_64(DisasContext *s, arg_2reg_shift *a,
50
+}
51
* To avoid excessive duplication of ops we implement shift
51
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
52
* by immediate using the variable shift operations.
52
index XXXXXXX..XXXXXXX 100644
53
*/
53
--- a/target/arm/tcg/translate-a64.c
54
- constimm = tcg_const_i64(dup_const(a->size, a->shift));
54
+++ b/target/arm/tcg/translate-a64.c
55
+ constimm = tcg_constant_i64(dup_const(a->size, a->shift));
55
@@ -XXX,XX +XXX,XX @@ static bool trans_ERETA(DisasContext *s, arg_reta *a)
56
57
for (pass = 0; pass < a->q + 1; pass++) {
58
TCGv_i64 tmp = tcg_temp_new_i64();
59
@@ -XXX,XX +XXX,XX @@ static bool do_2shift_env_64(DisasContext *s, arg_2reg_shift *a,
60
write_neon_element64(tmp, a->vd, pass, MO_64);
61
tcg_temp_free_i64(tmp);
62
}
63
- tcg_temp_free_i64(constimm);
64
return true;
56
return true;
65
}
57
}
66
58
67
@@ -XXX,XX +XXX,XX @@ static bool do_2shift_env_32(DisasContext *s, arg_2reg_shift *a,
59
-/* HINT instruction group, including various allocated HINTs */
68
* To avoid excessive duplication of ops we implement shift
60
-static void handle_hint(DisasContext *s, uint32_t insn,
69
* by immediate using the variable shift operations.
61
- unsigned int op1, unsigned int op2, unsigned int crm)
70
*/
62
+static bool trans_NOP(DisasContext *s, arg_NOP *a)
71
- constimm = tcg_const_i32(dup_const(a->size, a->shift));
63
{
72
+ constimm = tcg_constant_i32(dup_const(a->size, a->shift));
64
- unsigned int selector = crm << 3 | op2;
73
tmp = tcg_temp_new_i32();
65
+ return true;
74
66
+}
75
for (pass = 0; pass < (a->q ? 4 : 2); pass++) {
67
76
@@ -XXX,XX +XXX,XX @@ static bool do_2shift_env_32(DisasContext *s, arg_2reg_shift *a,
68
- if (op1 != 3) {
77
write_neon_element32(tmp, a->vd, pass, MO_32);
69
- unallocated_encoding(s);
70
- return;
71
+static bool trans_YIELD(DisasContext *s, arg_YIELD *a)
72
+{
73
+ /*
74
+ * When running in MTTCG we don't generate jumps to the yield and
75
+ * WFE helpers as it won't affect the scheduling of other vCPUs.
76
+ * If we wanted to more completely model WFE/SEV so we don't busy
77
+ * spin unnecessarily we would need to do something more involved.
78
+ */
79
+ if (!(tb_cflags(s->base.tb) & CF_PARALLEL)) {
80
+ s->base.is_jmp = DISAS_YIELD;
78
}
81
}
79
tcg_temp_free_i32(tmp);
82
+ return true;
80
- tcg_temp_free_i32(constimm);
83
+}
81
return true;
84
85
- switch (selector) {
86
- case 0b00000: /* NOP */
87
- break;
88
- case 0b00011: /* WFI */
89
- s->base.is_jmp = DISAS_WFI;
90
- break;
91
- case 0b00001: /* YIELD */
92
- /* When running in MTTCG we don't generate jumps to the yield and
93
- * WFE helpers as it won't affect the scheduling of other vCPUs.
94
- * If we wanted to more completely model WFE/SEV so we don't busy
95
- * spin unnecessarily we would need to do something more involved.
96
+static bool trans_WFI(DisasContext *s, arg_WFI *a)
97
+{
98
+ s->base.is_jmp = DISAS_WFI;
99
+ return true;
100
+}
101
+
102
+static bool trans_WFE(DisasContext *s, arg_WFI *a)
103
+{
104
+ /*
105
+ * When running in MTTCG we don't generate jumps to the yield and
106
+ * WFE helpers as it won't affect the scheduling of other vCPUs.
107
+ * If we wanted to more completely model WFE/SEV so we don't busy
108
+ * spin unnecessarily we would need to do something more involved.
109
+ */
110
+ if (!(tb_cflags(s->base.tb) & CF_PARALLEL)) {
111
+ s->base.is_jmp = DISAS_WFE;
112
+ }
113
+ return true;
114
+}
115
+
116
+static bool trans_XPACLRI(DisasContext *s, arg_XPACLRI *a)
117
+{
118
+ if (s->pauth_active) {
119
+ gen_helper_xpaci(cpu_X[30], cpu_env, cpu_X[30]);
120
+ }
121
+ return true;
122
+}
123
+
124
+static bool trans_PACIA1716(DisasContext *s, arg_PACIA1716 *a)
125
+{
126
+ if (s->pauth_active) {
127
+ gen_helper_pacia(cpu_X[17], cpu_env, cpu_X[17], cpu_X[16]);
128
+ }
129
+ return true;
130
+}
131
+
132
+static bool trans_PACIB1716(DisasContext *s, arg_PACIB1716 *a)
133
+{
134
+ if (s->pauth_active) {
135
+ gen_helper_pacib(cpu_X[17], cpu_env, cpu_X[17], cpu_X[16]);
136
+ }
137
+ return true;
138
+}
139
+
140
+static bool trans_AUTIA1716(DisasContext *s, arg_AUTIA1716 *a)
141
+{
142
+ if (s->pauth_active) {
143
+ gen_helper_autia(cpu_X[17], cpu_env, cpu_X[17], cpu_X[16]);
144
+ }
145
+ return true;
146
+}
147
+
148
+static bool trans_AUTIB1716(DisasContext *s, arg_AUTIB1716 *a)
149
+{
150
+ if (s->pauth_active) {
151
+ gen_helper_autib(cpu_X[17], cpu_env, cpu_X[17], cpu_X[16]);
152
+ }
153
+ return true;
154
+}
155
+
156
+static bool trans_ESB(DisasContext *s, arg_ESB *a)
157
+{
158
+ /* Without RAS, we must implement this as NOP. */
159
+ if (dc_isar_feature(aa64_ras, s)) {
160
+ /*
161
+ * QEMU does not have a source of physical SErrors,
162
+ * so we are only concerned with virtual SErrors.
163
+ * The pseudocode in the ARM for this case is
164
+ * if PSTATE.EL IN {EL0, EL1} && EL2Enabled() then
165
+ * AArch64.vESBOperation();
166
+ * Most of the condition can be evaluated at translation time.
167
+ * Test for EL2 present, and defer test for SEL2 to runtime.
168
*/
169
- if (!(tb_cflags(s->base.tb) & CF_PARALLEL)) {
170
- s->base.is_jmp = DISAS_YIELD;
171
+ if (s->current_el <= 1 && arm_dc_feature(s, ARM_FEATURE_EL2)) {
172
+ gen_helper_vesb(cpu_env);
173
}
174
- break;
175
- case 0b00010: /* WFE */
176
- if (!(tb_cflags(s->base.tb) & CF_PARALLEL)) {
177
- s->base.is_jmp = DISAS_WFE;
178
- }
179
- break;
180
- case 0b00100: /* SEV */
181
- case 0b00101: /* SEVL */
182
- case 0b00110: /* DGH */
183
- /* we treat all as NOP at least for now */
184
- break;
185
- case 0b00111: /* XPACLRI */
186
- if (s->pauth_active) {
187
- gen_helper_xpaci(cpu_X[30], cpu_env, cpu_X[30]);
188
- }
189
- break;
190
- case 0b01000: /* PACIA1716 */
191
- if (s->pauth_active) {
192
- gen_helper_pacia(cpu_X[17], cpu_env, cpu_X[17], cpu_X[16]);
193
- }
194
- break;
195
- case 0b01010: /* PACIB1716 */
196
- if (s->pauth_active) {
197
- gen_helper_pacib(cpu_X[17], cpu_env, cpu_X[17], cpu_X[16]);
198
- }
199
- break;
200
- case 0b01100: /* AUTIA1716 */
201
- if (s->pauth_active) {
202
- gen_helper_autia(cpu_X[17], cpu_env, cpu_X[17], cpu_X[16]);
203
- }
204
- break;
205
- case 0b01110: /* AUTIB1716 */
206
- if (s->pauth_active) {
207
- gen_helper_autib(cpu_X[17], cpu_env, cpu_X[17], cpu_X[16]);
208
- }
209
- break;
210
- case 0b10000: /* ESB */
211
- /* Without RAS, we must implement this as NOP. */
212
- if (dc_isar_feature(aa64_ras, s)) {
213
- /*
214
- * QEMU does not have a source of physical SErrors,
215
- * so we are only concerned with virtual SErrors.
216
- * The pseudocode in the ARM for this case is
217
- * if PSTATE.EL IN {EL0, EL1} && EL2Enabled() then
218
- * AArch64.vESBOperation();
219
- * Most of the condition can be evaluated at translation time.
220
- * Test for EL2 present, and defer test for SEL2 to runtime.
221
- */
222
- if (s->current_el <= 1 && arm_dc_feature(s, ARM_FEATURE_EL2)) {
223
- gen_helper_vesb(cpu_env);
224
- }
225
- }
226
- break;
227
- case 0b11000: /* PACIAZ */
228
- if (s->pauth_active) {
229
- gen_helper_pacia(cpu_X[30], cpu_env, cpu_X[30],
230
- tcg_constant_i64(0));
231
- }
232
- break;
233
- case 0b11001: /* PACIASP */
234
- if (s->pauth_active) {
235
- gen_helper_pacia(cpu_X[30], cpu_env, cpu_X[30], cpu_X[31]);
236
- }
237
- break;
238
- case 0b11010: /* PACIBZ */
239
- if (s->pauth_active) {
240
- gen_helper_pacib(cpu_X[30], cpu_env, cpu_X[30],
241
- tcg_constant_i64(0));
242
- }
243
- break;
244
- case 0b11011: /* PACIBSP */
245
- if (s->pauth_active) {
246
- gen_helper_pacib(cpu_X[30], cpu_env, cpu_X[30], cpu_X[31]);
247
- }
248
- break;
249
- case 0b11100: /* AUTIAZ */
250
- if (s->pauth_active) {
251
- gen_helper_autia(cpu_X[30], cpu_env, cpu_X[30],
252
- tcg_constant_i64(0));
253
- }
254
- break;
255
- case 0b11101: /* AUTIASP */
256
- if (s->pauth_active) {
257
- gen_helper_autia(cpu_X[30], cpu_env, cpu_X[30], cpu_X[31]);
258
- }
259
- break;
260
- case 0b11110: /* AUTIBZ */
261
- if (s->pauth_active) {
262
- gen_helper_autib(cpu_X[30], cpu_env, cpu_X[30],
263
- tcg_constant_i64(0));
264
- }
265
- break;
266
- case 0b11111: /* AUTIBSP */
267
- if (s->pauth_active) {
268
- gen_helper_autib(cpu_X[30], cpu_env, cpu_X[30], cpu_X[31]);
269
- }
270
- break;
271
- default:
272
- /* default specified as NOP equivalent */
273
- break;
274
}
275
+ return true;
276
+}
277
+
278
+static bool trans_PACIAZ(DisasContext *s, arg_PACIAZ *a)
279
+{
280
+ if (s->pauth_active) {
281
+ gen_helper_pacia(cpu_X[30], cpu_env, cpu_X[30], tcg_constant_i64(0));
282
+ }
283
+ return true;
284
+}
285
+
286
+static bool trans_PACIASP(DisasContext *s, arg_PACIASP *a)
287
+{
288
+ if (s->pauth_active) {
289
+ gen_helper_pacia(cpu_X[30], cpu_env, cpu_X[30], cpu_X[31]);
290
+ }
291
+ return true;
292
+}
293
+
294
+static bool trans_PACIBZ(DisasContext *s, arg_PACIBZ *a)
295
+{
296
+ if (s->pauth_active) {
297
+ gen_helper_pacib(cpu_X[30], cpu_env, cpu_X[30], tcg_constant_i64(0));
298
+ }
299
+ return true;
300
+}
301
+
302
+static bool trans_PACIBSP(DisasContext *s, arg_PACIBSP *a)
303
+{
304
+ if (s->pauth_active) {
305
+ gen_helper_pacib(cpu_X[30], cpu_env, cpu_X[30], cpu_X[31]);
306
+ }
307
+ return true;
308
+}
309
+
310
+static bool trans_AUTIAZ(DisasContext *s, arg_AUTIAZ *a)
311
+{
312
+ if (s->pauth_active) {
313
+ gen_helper_autia(cpu_X[30], cpu_env, cpu_X[30], tcg_constant_i64(0));
314
+ }
315
+ return true;
316
+}
317
+
318
+static bool trans_AUTIASP(DisasContext *s, arg_AUTIASP *a)
319
+{
320
+ if (s->pauth_active) {
321
+ gen_helper_autia(cpu_X[30], cpu_env, cpu_X[30], cpu_X[31]);
322
+ }
323
+ return true;
324
+}
325
+
326
+static bool trans_AUTIBZ(DisasContext *s, arg_AUTIBZ *a)
327
+{
328
+ if (s->pauth_active) {
329
+ gen_helper_autib(cpu_X[30], cpu_env, cpu_X[30], tcg_constant_i64(0));
330
+ }
331
+ return true;
332
+}
333
+
334
+static bool trans_AUTIBSP(DisasContext *s, arg_AUTIBSP *a)
335
+{
336
+ if (s->pauth_active) {
337
+ gen_helper_autib(cpu_X[30], cpu_env, cpu_X[30], cpu_X[31]);
338
+ }
339
+ return true;
82
}
340
}
83
341
84
@@ -XXX,XX +XXX,XX @@ static bool do_2shift_narrow_64(DisasContext *s, arg_2reg_shift *a,
342
static void gen_clrex(DisasContext *s, uint32_t insn)
85
* This is always a right shift, and the shiftfn is always a
343
@@ -XXX,XX +XXX,XX @@ static void disas_system(DisasContext *s, uint32_t insn)
86
* left-shift helper, which thus needs the negated shift count.
344
return;
87
*/
345
}
88
- constimm = tcg_const_i64(-a->shift);
346
switch (crn) {
89
+ constimm = tcg_constant_i64(-a->shift);
347
- case 2: /* HINT (including allocated hints like NOP, YIELD, etc) */
90
rm1 = tcg_temp_new_i64();
348
- handle_hint(s, insn, op1, op2, crm);
91
rm2 = tcg_temp_new_i64();
349
- break;
92
rd = tcg_temp_new_i32();
350
case 3: /* CLREX, DSB, DMB, ISB */
93
@@ -XXX,XX +XXX,XX @@ static bool do_2shift_narrow_64(DisasContext *s, arg_2reg_shift *a,
351
handle_sync(s, insn, op1, op2, crm);
94
tcg_temp_free_i32(rd);
352
break;
95
tcg_temp_free_i64(rm1);
96
tcg_temp_free_i64(rm2);
97
- tcg_temp_free_i64(constimm);
98
99
return true;
100
}
101
@@ -XXX,XX +XXX,XX @@ static bool do_2shift_narrow_32(DisasContext *s, arg_2reg_shift *a,
102
/* size == 2 */
103
imm = -a->shift;
104
}
105
- constimm = tcg_const_i32(imm);
106
+ constimm = tcg_constant_i32(imm);
107
108
/* Load all inputs first to avoid potential overwrite */
109
rm1 = tcg_temp_new_i32();
110
@@ -XXX,XX +XXX,XX @@ static bool do_2shift_narrow_32(DisasContext *s, arg_2reg_shift *a,
111
112
shiftfn(rm3, rm3, constimm);
113
shiftfn(rm4, rm4, constimm);
114
- tcg_temp_free_i32(constimm);
115
116
tcg_gen_concat_i32_i64(rtmp, rm3, rm4);
117
tcg_temp_free_i32(rm4);
118
@@ -XXX,XX +XXX,XX @@ static bool trans_VTBL(DisasContext *s, arg_VTBL *a)
119
return true;
120
}
121
122
- desc = tcg_const_i32((a->vn << 2) | a->len);
123
+ desc = tcg_constant_i32((a->vn << 2) | a->len);
124
def = tcg_temp_new_i64();
125
if (a->op) {
126
read_neon_element64(def, a->vd, 0, MO_64);
127
@@ -XXX,XX +XXX,XX @@ static bool trans_VTBL(DisasContext *s, arg_VTBL *a)
128
129
tcg_temp_free_i64(def);
130
tcg_temp_free_i64(val);
131
- tcg_temp_free_i32(desc);
132
return true;
133
}
134
135
--
353
--
136
2.25.1
354
2.34.1
diff view generated by jsdifflib
1
The maintenance interrupt state depends only on:
1
Convert the insns in the "Barriers" instruction class to
2
* ICH_HCR_EL2
2
decodetree: CLREX, DSB, DMB, ISB and SB.
3
* ICH_LR<n>_EL2
4
* ICH_VMCR_EL2 fields VENG0 and VENG1
5
6
Now we have a separate function that updates only the vIRQ and vFIQ
7
lines, use that in places that only change state that affects vIRQ
8
and vFIQ but not the maintenance interrupt.
9
3
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20220408141550.1271295-27-peter.maydell@linaro.org
6
Message-id: 20230602155223.2040685-4-peter.maydell@linaro.org
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
13
---
8
---
14
hw/intc/arm_gicv3_cpuif.c | 10 +++++-----
9
target/arm/tcg/a64.decode | 7 +++
15
1 file changed, 5 insertions(+), 5 deletions(-)
10
target/arm/tcg/translate-a64.c | 92 ++++++++++++++--------------------
11
2 files changed, 46 insertions(+), 53 deletions(-)
16
12
17
diff --git a/hw/intc/arm_gicv3_cpuif.c b/hw/intc/arm_gicv3_cpuif.c
13
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
18
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/intc/arm_gicv3_cpuif.c
15
--- a/target/arm/tcg/a64.decode
20
+++ b/hw/intc/arm_gicv3_cpuif.c
16
+++ b/target/arm/tcg/a64.decode
21
@@ -XXX,XX +XXX,XX @@ static void icv_ap_write(CPUARMState *env, const ARMCPRegInfo *ri,
17
@@ -XXX,XX +XXX,XX @@ ERETA 1101011 0100 11111 00001 m:1 11111 11111 &reta # ERETAA, ERETAB
22
18
# that isn't specifically allocated to an instruction must NOP
23
cs->ich_apr[grp][regno] = value & 0xFFFFFFFFU;
19
NOP 1101 0101 0000 0011 0010 ---- --- 11111
24
25
- gicv3_cpuif_virt_update(cs);
26
+ gicv3_cpuif_virt_irq_fiq_update(cs);
27
return;
28
}
20
}
29
21
+
30
@@ -XXX,XX +XXX,XX @@ static void icv_bpr_write(CPUARMState *env, const ARMCPRegInfo *ri,
22
+# Barriers
31
23
+
32
write_vbpr(cs, grp, value);
24
+CLREX 1101 0101 0000 0011 0011 ---- 010 11111
33
25
+DSB_DMB 1101 0101 0000 0011 0011 domain:2 types:2 10- 11111
34
- gicv3_cpuif_virt_update(cs);
26
+ISB 1101 0101 0000 0011 0011 ---- 110 11111
35
+ gicv3_cpuif_virt_irq_fiq_update(cs);
27
+SB 1101 0101 0000 0011 0011 0000 111 11111
28
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
29
index XXXXXXX..XXXXXXX 100644
30
--- a/target/arm/tcg/translate-a64.c
31
+++ b/target/arm/tcg/translate-a64.c
32
@@ -XXX,XX +XXX,XX @@ static bool trans_AUTIBSP(DisasContext *s, arg_AUTIBSP *a)
33
return true;
36
}
34
}
37
35
38
static uint64_t icv_pmr_read(CPUARMState *env, const ARMCPRegInfo *ri)
36
-static void gen_clrex(DisasContext *s, uint32_t insn)
39
@@ -XXX,XX +XXX,XX @@ static void icv_pmr_write(CPUARMState *env, const ARMCPRegInfo *ri,
37
+static bool trans_CLREX(DisasContext *s, arg_CLREX *a)
40
cs->ich_vmcr_el2 = deposit64(cs->ich_vmcr_el2, ICH_VMCR_EL2_VPMR_SHIFT,
38
{
41
ICH_VMCR_EL2_VPMR_LENGTH, value);
39
tcg_gen_movi_i64(cpu_exclusive_addr, -1);
42
40
+ return true;
43
- gicv3_cpuif_virt_update(cs);
44
+ gicv3_cpuif_virt_irq_fiq_update(cs);
45
}
41
}
46
42
47
static uint64_t icv_igrpen_read(CPUARMState *env, const ARMCPRegInfo *ri)
43
-/* CLREX, DSB, DMB, ISB */
48
@@ -XXX,XX +XXX,XX @@ static void icv_ctlr_write(CPUARMState *env, const ARMCPRegInfo *ri,
44
-static void handle_sync(DisasContext *s, uint32_t insn,
49
cs->ich_vmcr_el2 = deposit64(cs->ich_vmcr_el2, ICH_VMCR_EL2_VEOIM_SHIFT,
45
- unsigned int op1, unsigned int op2, unsigned int crm)
50
1, value & ICC_CTLR_EL1_EOIMODE ? 1 : 0);
46
+static bool trans_DSB_DMB(DisasContext *s, arg_DSB_DMB *a)
51
47
{
52
- gicv3_cpuif_virt_update(cs);
48
+ /* We handle DSB and DMB the same way */
53
+ gicv3_cpuif_virt_irq_fiq_update(cs);
49
TCGBar bar;
50
51
- if (op1 != 3) {
52
- unallocated_encoding(s);
53
- return;
54
+ switch (a->types) {
55
+ case 1: /* MBReqTypes_Reads */
56
+ bar = TCG_BAR_SC | TCG_MO_LD_LD | TCG_MO_LD_ST;
57
+ break;
58
+ case 2: /* MBReqTypes_Writes */
59
+ bar = TCG_BAR_SC | TCG_MO_ST_ST;
60
+ break;
61
+ default: /* MBReqTypes_All */
62
+ bar = TCG_BAR_SC | TCG_MO_ALL;
63
+ break;
64
}
65
+ tcg_gen_mb(bar);
66
+ return true;
67
+}
68
69
- switch (op2) {
70
- case 2: /* CLREX */
71
- gen_clrex(s, insn);
72
- return;
73
- case 4: /* DSB */
74
- case 5: /* DMB */
75
- switch (crm & 3) {
76
- case 1: /* MBReqTypes_Reads */
77
- bar = TCG_BAR_SC | TCG_MO_LD_LD | TCG_MO_LD_ST;
78
- break;
79
- case 2: /* MBReqTypes_Writes */
80
- bar = TCG_BAR_SC | TCG_MO_ST_ST;
81
- break;
82
- default: /* MBReqTypes_All */
83
- bar = TCG_BAR_SC | TCG_MO_ALL;
84
- break;
85
- }
86
- tcg_gen_mb(bar);
87
- return;
88
- case 6: /* ISB */
89
- /* We need to break the TB after this insn to execute
90
- * a self-modified code correctly and also to take
91
- * any pending interrupts immediately.
92
- */
93
- reset_btype(s);
94
- gen_goto_tb(s, 0, 4);
95
- return;
96
+static bool trans_ISB(DisasContext *s, arg_ISB *a)
97
+{
98
+ /*
99
+ * We need to break the TB after this insn to execute
100
+ * self-modifying code correctly and also to take
101
+ * any pending interrupts immediately.
102
+ */
103
+ reset_btype(s);
104
+ gen_goto_tb(s, 0, 4);
105
+ return true;
106
+}
107
108
- case 7: /* SB */
109
- if (crm != 0 || !dc_isar_feature(aa64_sb, s)) {
110
- goto do_unallocated;
111
- }
112
- /*
113
- * TODO: There is no speculation barrier opcode for TCG;
114
- * MB and end the TB instead.
115
- */
116
- tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
117
- gen_goto_tb(s, 0, 4);
118
- return;
119
-
120
- default:
121
- do_unallocated:
122
- unallocated_encoding(s);
123
- return;
124
+static bool trans_SB(DisasContext *s, arg_SB *a)
125
+{
126
+ if (!dc_isar_feature(aa64_sb, s)) {
127
+ return false;
128
}
129
+ /*
130
+ * TODO: There is no speculation barrier opcode for TCG;
131
+ * MB and end the TB instead.
132
+ */
133
+ tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
134
+ gen_goto_tb(s, 0, 4);
135
+ return true;
54
}
136
}
55
137
56
static uint64_t icv_rpr_read(CPUARMState *env, const ARMCPRegInfo *ri)
138
static void gen_xaflag(void)
57
@@ -XXX,XX +XXX,XX @@ static void ich_ap_write(CPUARMState *env, const ARMCPRegInfo *ri,
139
@@ -XXX,XX +XXX,XX @@ static void disas_system(DisasContext *s, uint32_t insn)
58
trace_gicv3_ich_ap_write(ri->crm & 1, regno, gicv3_redist_affid(cs), value);
140
return;
59
141
}
60
cs->ich_apr[grp][regno] = value & 0xFFFFFFFFU;
142
switch (crn) {
61
- gicv3_cpuif_virt_update(cs);
143
- case 3: /* CLREX, DSB, DMB, ISB */
62
+ gicv3_cpuif_virt_irq_fiq_update(cs);
144
- handle_sync(s, insn, op1, op2, crm);
63
}
145
- break;
64
146
case 4: /* MSR (immediate) */
65
static uint64_t ich_hcr_read(CPUARMState *env, const ARMCPRegInfo *ri)
147
handle_msr_i(s, insn, op1, op2, crm);
148
break;
66
--
149
--
67
2.25.1
150
2.34.1
151
152
diff view generated by jsdifflib
1
Implement the function gicv3_redist_process_vlpi(), which was left as
1
Convert the CFINV, XAFLAG and AXFLAG insns to decodetree.
2
just a stub earlier. This function deals with being handed a VLPI by
2
The old decoder handles these in handle_msr_i(), but
3
the ITS. It must set the bit in the pending table. If the vCPU is
3
the architecture defines them as separate instructions
4
currently resident we must recalculate the highest priority pending
4
from MSR (immediate).
5
vLPI; otherwise we may need to ring a "doorbell" interrupt to let the
6
hypervisor know it might want to reschedule the vCPU.
7
5
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20220408141550.1271295-32-peter.maydell@linaro.org
8
Message-id: 20230602155223.2040685-5-peter.maydell@linaro.org
11
---
9
---
12
hw/intc/arm_gicv3_redist.c | 48 ++++++++++++++++++++++++++++++++++----
10
target/arm/tcg/a64.decode | 6 ++++
13
1 file changed, 44 insertions(+), 4 deletions(-)
11
target/arm/tcg/translate-a64.c | 53 +++++++++++++++++-----------------
12
2 files changed, 32 insertions(+), 27 deletions(-)
14
13
15
diff --git a/hw/intc/arm_gicv3_redist.c b/hw/intc/arm_gicv3_redist.c
14
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
16
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/intc/arm_gicv3_redist.c
16
--- a/target/arm/tcg/a64.decode
18
+++ b/hw/intc/arm_gicv3_redist.c
17
+++ b/target/arm/tcg/a64.decode
19
@@ -XXX,XX +XXX,XX @@ static uint32_t gicr_read_bitmap_reg(GICv3CPUState *cs, MemTxAttrs attrs,
18
@@ -XXX,XX +XXX,XX @@ CLREX 1101 0101 0000 0011 0011 ---- 010 11111
20
return reg;
19
DSB_DMB 1101 0101 0000 0011 0011 domain:2 types:2 10- 11111
20
ISB 1101 0101 0000 0011 0011 ---- 110 11111
21
SB 1101 0101 0000 0011 0011 0000 111 11111
22
+
23
+# PSTATE
24
+
25
+CFINV 1101 0101 0000 0 000 0100 0000 000 11111
26
+XAFLAG 1101 0101 0000 0 000 0100 0000 001 11111
27
+AXFLAG 1101 0101 0000 0 000 0100 0000 010 11111
28
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
29
index XXXXXXX..XXXXXXX 100644
30
--- a/target/arm/tcg/translate-a64.c
31
+++ b/target/arm/tcg/translate-a64.c
32
@@ -XXX,XX +XXX,XX @@ static bool trans_SB(DisasContext *s, arg_SB *a)
33
return true;
21
}
34
}
22
35
23
+static bool vcpu_resident(GICv3CPUState *cs, uint64_t vptaddr)
36
-static void gen_xaflag(void)
24
+{
37
+static bool trans_CFINV(DisasContext *s, arg_CFINV *a)
25
+ /*
38
{
26
+ * Return true if a vCPU is resident, which is defined by
39
- TCGv_i32 z = tcg_temp_new_i32();
27
+ * whether the GICR_VPENDBASER register is marked VALID and
40
+ if (!dc_isar_feature(aa64_condm_4, s)) {
28
+ * has the right virtual pending table address.
29
+ */
30
+ if (!FIELD_EX64(cs->gicr_vpendbaser, GICR_VPENDBASER, VALID)) {
31
+ return false;
41
+ return false;
32
+ }
42
+ }
33
+ return vptaddr == (cs->gicr_vpendbaser & R_GICR_VPENDBASER_PHYADDR_MASK);
43
+ tcg_gen_xori_i32(cpu_CF, cpu_CF, 1);
44
+ return true;
34
+}
45
+}
35
+
46
+
36
/**
47
+static bool trans_XAFLAG(DisasContext *s, arg_XAFLAG *a)
37
* update_for_one_lpi: Update pending information if this LPI is better
48
+{
38
*
49
+ TCGv_i32 z;
39
@@ -XXX,XX +XXX,XX @@ void gicv3_redist_vlpi_pending(GICv3CPUState *cs, int irq, int level)
40
void gicv3_redist_process_vlpi(GICv3CPUState *cs, int irq, uint64_t vptaddr,
41
int doorbell, int level)
42
{
43
- /*
44
- * The redistributor handling for being handed a VLPI by the ITS
45
- * will be added in a subsequent commit.
46
- */
47
+ bool bit_changed;
48
+ bool resident = vcpu_resident(cs, vptaddr);
49
+ uint64_t ctbase;
50
+
50
+
51
+ if (resident) {
51
+ if (!dc_isar_feature(aa64_condm_5, s)) {
52
+ uint32_t idbits = FIELD_EX64(cs->gicr_vpropbaser, GICR_VPROPBASER, IDBITS);
52
+ return false;
53
+ if (irq >= (1ULL << (idbits + 1))) {
54
+ return;
55
+ }
56
+ }
53
+ }
57
+
54
+
58
+ bit_changed = set_pending_table_bit(cs, vptaddr, irq, level);
55
+ z = tcg_temp_new_i32();
59
+ if (resident && bit_changed) {
56
60
+ if (level) {
57
tcg_gen_setcondi_i32(TCG_COND_EQ, z, cpu_ZF, 0);
61
+ /* Check whether this vLPI is now the best */
58
62
+ ctbase = cs->gicr_vpropbaser & R_GICR_VPROPBASER_PHYADDR_MASK;
59
@@ -XXX,XX +XXX,XX @@ static void gen_xaflag(void)
63
+ update_for_one_lpi(cs, irq, ctbase, true, &cs->hppvlpi);
60
64
+ gicv3_cpuif_virt_irq_fiq_update(cs);
61
/* C | Z */
65
+ } else {
62
tcg_gen_or_i32(cpu_CF, cpu_CF, z);
66
+ /* Only need to recalculate if this was previously the best vLPI */
63
+
67
+ if (irq == cs->hppvlpi.irq) {
64
+ return true;
68
+ gicv3_redist_update_vlpi(cs);
65
}
69
+ }
66
70
+ }
67
-static void gen_axflag(void)
68
+static bool trans_AXFLAG(DisasContext *s, arg_AXFLAG *a)
69
{
70
+ if (!dc_isar_feature(aa64_condm_5, s)) {
71
+ return false;
71
+ }
72
+ }
72
+
73
+
73
+ if (!resident && level && doorbell != INTID_SPURIOUS &&
74
tcg_gen_sari_i32(cpu_VF, cpu_VF, 31); /* V ? -1 : 0 */
74
+ (cs->gicr_ctlr & GICR_CTLR_ENABLE_LPIS)) {
75
tcg_gen_andc_i32(cpu_CF, cpu_CF, cpu_VF); /* C & !V */
75
+ /* vCPU is not currently resident: ring the doorbell */
76
76
+ gicv3_redist_process_lpi(cs, doorbell, 1);
77
@@ -XXX,XX +XXX,XX @@ static void gen_axflag(void)
77
+ }
78
79
tcg_gen_movi_i32(cpu_NF, 0);
80
tcg_gen_movi_i32(cpu_VF, 0);
81
+
82
+ return true;
78
}
83
}
79
84
80
void gicv3_redist_mov_vlpi(GICv3CPUState *src, uint64_t src_vptaddr,
85
/* MSR (immediate) - move immediate to processor state field */
86
@@ -XXX,XX +XXX,XX @@ static void handle_msr_i(DisasContext *s, uint32_t insn,
87
s->base.is_jmp = DISAS_TOO_MANY;
88
89
switch (op) {
90
- case 0x00: /* CFINV */
91
- if (crm != 0 || !dc_isar_feature(aa64_condm_4, s)) {
92
- goto do_unallocated;
93
- }
94
- tcg_gen_xori_i32(cpu_CF, cpu_CF, 1);
95
- s->base.is_jmp = DISAS_NEXT;
96
- break;
97
-
98
- case 0x01: /* XAFlag */
99
- if (crm != 0 || !dc_isar_feature(aa64_condm_5, s)) {
100
- goto do_unallocated;
101
- }
102
- gen_xaflag();
103
- s->base.is_jmp = DISAS_NEXT;
104
- break;
105
-
106
- case 0x02: /* AXFlag */
107
- if (crm != 0 || !dc_isar_feature(aa64_condm_5, s)) {
108
- goto do_unallocated;
109
- }
110
- gen_axflag();
111
- s->base.is_jmp = DISAS_NEXT;
112
- break;
113
-
114
case 0x03: /* UAO */
115
if (!dc_isar_feature(aa64_uao, s) || s->current_el == 0) {
116
goto do_unallocated;
81
--
117
--
82
2.25.1
118
2.34.1
diff view generated by jsdifflib
1
We were previously implementing INV (like INVALL) to just blow away
1
Convert the MSR (immediate) insn to decodetree. Our implementation
2
cached highest-priority-pending-LPI information on all connected
2
has basically no commonality between the different destinations,
3
redistributors. For GICv4.0, this isn't going to be sufficient,
3
so we decode the destination register in a64.decode.
4
because the LPI we are invalidating cached information for might be
5
either physical or virtual, and the required action is different for
6
those two cases. So we need to do the full process of looking up the
7
ITE from the devid and eventid. This also means we can do the error
8
checks that the spec lists for this command.
9
10
Split out INV handling into a process_inv() function like our other
11
command-processing functions. For the moment, stick to handling only
12
physical LPIs; we will add the vLPI parts later.
13
4
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
16
Message-id: 20220408141550.1271295-19-peter.maydell@linaro.org
7
Message-id: 20230602155223.2040685-6-peter.maydell@linaro.org
17
---
8
---
18
hw/intc/gicv3_internal.h | 12 +++++++++
9
target/arm/tcg/a64.decode | 13 ++
19
hw/intc/arm_gicv3_its.c | 50 +++++++++++++++++++++++++++++++++++++-
10
target/arm/tcg/translate-a64.c | 251 ++++++++++++++++-----------------
20
hw/intc/arm_gicv3_redist.c | 11 +++++++++
11
2 files changed, 136 insertions(+), 128 deletions(-)
21
hw/intc/trace-events | 3 ++-
22
4 files changed, 74 insertions(+), 2 deletions(-)
23
12
24
diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h
13
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
25
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
26
--- a/hw/intc/gicv3_internal.h
15
--- a/target/arm/tcg/a64.decode
27
+++ b/hw/intc/gicv3_internal.h
16
+++ b/target/arm/tcg/a64.decode
28
@@ -XXX,XX +XXX,XX @@ FIELD(MOVI_0, DEVICEID, 32, 32)
17
@@ -XXX,XX +XXX,XX @@ SB 1101 0101 0000 0011 0011 0000 111 11111
29
FIELD(MOVI_1, EVENTID, 0, 32)
18
CFINV 1101 0101 0000 0 000 0100 0000 000 11111
30
FIELD(MOVI_2, ICID, 0, 16)
19
XAFLAG 1101 0101 0000 0 000 0100 0000 001 11111
31
20
AXFLAG 1101 0101 0000 0 000 0100 0000 010 11111
32
+/* INV command fields */
21
+
33
+FIELD(INV_0, DEVICEID, 32, 32)
22
+# These are architecturally all "MSR (immediate)"; we decode the destination
34
+FIELD(INV_1, EVENTID, 0, 32)
23
+# register too because there is no commonality in our implementation.
35
+
24
+@msr_i .... .... .... . ... .... imm:4 ... .....
36
/* VMAPI, VMAPTI command fields */
25
+MSR_i_UAO 1101 0101 0000 0 000 0100 .... 011 11111 @msr_i
37
FIELD(VMAPTI_0, DEVICEID, 32, 32)
26
+MSR_i_PAN 1101 0101 0000 0 000 0100 .... 100 11111 @msr_i
38
FIELD(VMAPTI_1, EVENTID, 0, 32)
27
+MSR_i_SPSEL 1101 0101 0000 0 000 0100 .... 101 11111 @msr_i
39
@@ -XXX,XX +XXX,XX @@ void gicv3_redist_update_lpi(GICv3CPUState *cs);
28
+MSR_i_SBSS 1101 0101 0000 0 011 0100 .... 001 11111 @msr_i
40
* an incoming migration has loaded new state.
29
+MSR_i_DIT 1101 0101 0000 0 011 0100 .... 010 11111 @msr_i
41
*/
30
+MSR_i_TCO 1101 0101 0000 0 011 0100 .... 100 11111 @msr_i
42
void gicv3_redist_update_lpi_only(GICv3CPUState *cs);
31
+MSR_i_DAIFSET 1101 0101 0000 0 011 0100 .... 110 11111 @msr_i
43
+/**
32
+MSR_i_DAIFCLEAR 1101 0101 0000 0 011 0100 .... 111 11111 @msr_i
44
+ * gicv3_redist_inv_lpi:
33
+MSR_i_SVCR 1101 0101 0000 0 011 0100 0 mask:2 imm:1 011 11111
45
+ * @cs: GICv3CPUState
34
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
46
+ * @irq: LPI to invalidate cached information for
47
+ *
48
+ * Forget or update any cached information associated with this LPI.
49
+ */
50
+void gicv3_redist_inv_lpi(GICv3CPUState *cs, int irq);
51
/**
52
* gicv3_redist_mov_lpi:
53
* @src: source redistributor
54
diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
55
index XXXXXXX..XXXXXXX 100644
35
index XXXXXXX..XXXXXXX 100644
56
--- a/hw/intc/arm_gicv3_its.c
36
--- a/target/arm/tcg/translate-a64.c
57
+++ b/hw/intc/arm_gicv3_its.c
37
+++ b/target/arm/tcg/translate-a64.c
58
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_vmovp(GICv3ITSState *s, const uint64_t *cmdpkt)
38
@@ -XXX,XX +XXX,XX @@ static bool trans_AXFLAG(DisasContext *s, arg_AXFLAG *a)
59
return cbdata.result;
39
return true;
60
}
40
}
61
41
62
+static ItsCmdResult process_inv(GICv3ITSState *s, const uint64_t *cmdpkt)
42
-/* MSR (immediate) - move immediate to processor state field */
63
+{
43
-static void handle_msr_i(DisasContext *s, uint32_t insn,
64
+ uint32_t devid, eventid;
44
- unsigned int op1, unsigned int op2, unsigned int crm)
65
+ ITEntry ite;
45
+static bool trans_MSR_i_UAO(DisasContext *s, arg_i *a)
66
+ DTEntry dte;
46
{
67
+ CTEntry cte;
47
- int op = op1 << 3 | op2;
68
+ ItsCmdResult cmdres;
48
-
69
+
49
- /* End the TB by default, chaining is ok. */
70
+ devid = FIELD_EX64(cmdpkt[0], INV_0, DEVICEID);
50
- s->base.is_jmp = DISAS_TOO_MANY;
71
+ eventid = FIELD_EX64(cmdpkt[1], INV_1, EVENTID);
51
-
72
+
52
- switch (op) {
73
+ trace_gicv3_its_cmd_inv(devid, eventid);
53
- case 0x03: /* UAO */
74
+
54
- if (!dc_isar_feature(aa64_uao, s) || s->current_el == 0) {
75
+ cmdres = lookup_ite(s, __func__, devid, eventid, &ite, &dte);
55
- goto do_unallocated;
76
+ if (cmdres != CMD_CONTINUE_OK) {
56
- }
77
+ return cmdres;
57
- if (crm & 1) {
78
+ }
58
- set_pstate_bits(PSTATE_UAO);
79
+
59
- } else {
80
+ switch (ite.inttype) {
60
- clear_pstate_bits(PSTATE_UAO);
81
+ case ITE_INTTYPE_PHYSICAL:
61
- }
82
+ cmdres = lookup_cte(s, __func__, ite.icid, &cte);
62
- gen_rebuild_hflags(s);
83
+ if (cmdres != CMD_CONTINUE_OK) {
63
- break;
84
+ return cmdres;
64
-
65
- case 0x04: /* PAN */
66
- if (!dc_isar_feature(aa64_pan, s) || s->current_el == 0) {
67
- goto do_unallocated;
68
- }
69
- if (crm & 1) {
70
- set_pstate_bits(PSTATE_PAN);
71
- } else {
72
- clear_pstate_bits(PSTATE_PAN);
73
- }
74
- gen_rebuild_hflags(s);
75
- break;
76
-
77
- case 0x05: /* SPSel */
78
- if (s->current_el == 0) {
79
- goto do_unallocated;
80
- }
81
- gen_helper_msr_i_spsel(cpu_env, tcg_constant_i32(crm & PSTATE_SP));
82
- break;
83
-
84
- case 0x19: /* SSBS */
85
- if (!dc_isar_feature(aa64_ssbs, s)) {
86
- goto do_unallocated;
87
- }
88
- if (crm & 1) {
89
- set_pstate_bits(PSTATE_SSBS);
90
- } else {
91
- clear_pstate_bits(PSTATE_SSBS);
92
- }
93
- /* Don't need to rebuild hflags since SSBS is a nop */
94
- break;
95
-
96
- case 0x1a: /* DIT */
97
- if (!dc_isar_feature(aa64_dit, s)) {
98
- goto do_unallocated;
99
- }
100
- if (crm & 1) {
101
- set_pstate_bits(PSTATE_DIT);
102
- } else {
103
- clear_pstate_bits(PSTATE_DIT);
104
- }
105
- /* There's no need to rebuild hflags because DIT is a nop */
106
- break;
107
-
108
- case 0x1e: /* DAIFSet */
109
- gen_helper_msr_i_daifset(cpu_env, tcg_constant_i32(crm));
110
- break;
111
-
112
- case 0x1f: /* DAIFClear */
113
- gen_helper_msr_i_daifclear(cpu_env, tcg_constant_i32(crm));
114
- /* For DAIFClear, exit the cpu loop to re-evaluate pending IRQs. */
115
- s->base.is_jmp = DISAS_UPDATE_EXIT;
116
- break;
117
-
118
- case 0x1c: /* TCO */
119
- if (dc_isar_feature(aa64_mte, s)) {
120
- /* Full MTE is enabled -- set the TCO bit as directed. */
121
- if (crm & 1) {
122
- set_pstate_bits(PSTATE_TCO);
123
- } else {
124
- clear_pstate_bits(PSTATE_TCO);
125
- }
126
- gen_rebuild_hflags(s);
127
- /* Many factors, including TCO, go into MTE_ACTIVE. */
128
- s->base.is_jmp = DISAS_UPDATE_NOCHAIN;
129
- } else if (dc_isar_feature(aa64_mte_insn_reg, s)) {
130
- /* Only "instructions accessible at EL0" -- PSTATE.TCO is WI. */
131
- s->base.is_jmp = DISAS_NEXT;
132
- } else {
133
- goto do_unallocated;
134
- }
135
- break;
136
-
137
- case 0x1b: /* SVCR* */
138
- if (!dc_isar_feature(aa64_sme, s) || crm < 2 || crm > 7) {
139
- goto do_unallocated;
140
- }
141
- if (sme_access_check(s)) {
142
- int old = s->pstate_sm | (s->pstate_za << 1);
143
- int new = (crm & 1) * 3;
144
- int msk = (crm >> 1) & 3;
145
-
146
- if ((old ^ new) & msk) {
147
- /* At least one bit changes. */
148
- gen_helper_set_svcr(cpu_env, tcg_constant_i32(new),
149
- tcg_constant_i32(msk));
150
- } else {
151
- s->base.is_jmp = DISAS_NEXT;
152
- }
153
- }
154
- break;
155
-
156
- default:
157
- do_unallocated:
158
- unallocated_encoding(s);
159
- return;
160
+ if (!dc_isar_feature(aa64_uao, s) || s->current_el == 0) {
161
+ return false;
162
}
163
+ if (a->imm & 1) {
164
+ set_pstate_bits(PSTATE_UAO);
165
+ } else {
166
+ clear_pstate_bits(PSTATE_UAO);
167
+ }
168
+ gen_rebuild_hflags(s);
169
+ s->base.is_jmp = DISAS_TOO_MANY;
170
+ return true;
171
+}
172
+
173
+static bool trans_MSR_i_PAN(DisasContext *s, arg_i *a)
174
+{
175
+ if (!dc_isar_feature(aa64_pan, s) || s->current_el == 0) {
176
+ return false;
177
+ }
178
+ if (a->imm & 1) {
179
+ set_pstate_bits(PSTATE_PAN);
180
+ } else {
181
+ clear_pstate_bits(PSTATE_PAN);
182
+ }
183
+ gen_rebuild_hflags(s);
184
+ s->base.is_jmp = DISAS_TOO_MANY;
185
+ return true;
186
+}
187
+
188
+static bool trans_MSR_i_SPSEL(DisasContext *s, arg_i *a)
189
+{
190
+ if (s->current_el == 0) {
191
+ return false;
192
+ }
193
+ gen_helper_msr_i_spsel(cpu_env, tcg_constant_i32(a->imm & PSTATE_SP));
194
+ s->base.is_jmp = DISAS_TOO_MANY;
195
+ return true;
196
+}
197
+
198
+static bool trans_MSR_i_SBSS(DisasContext *s, arg_i *a)
199
+{
200
+ if (!dc_isar_feature(aa64_ssbs, s)) {
201
+ return false;
202
+ }
203
+ if (a->imm & 1) {
204
+ set_pstate_bits(PSTATE_SSBS);
205
+ } else {
206
+ clear_pstate_bits(PSTATE_SSBS);
207
+ }
208
+ /* Don't need to rebuild hflags since SSBS is a nop */
209
+ s->base.is_jmp = DISAS_TOO_MANY;
210
+ return true;
211
+}
212
+
213
+static bool trans_MSR_i_DIT(DisasContext *s, arg_i *a)
214
+{
215
+ if (!dc_isar_feature(aa64_dit, s)) {
216
+ return false;
217
+ }
218
+ if (a->imm & 1) {
219
+ set_pstate_bits(PSTATE_DIT);
220
+ } else {
221
+ clear_pstate_bits(PSTATE_DIT);
222
+ }
223
+ /* There's no need to rebuild hflags because DIT is a nop */
224
+ s->base.is_jmp = DISAS_TOO_MANY;
225
+ return true;
226
+}
227
+
228
+static bool trans_MSR_i_TCO(DisasContext *s, arg_i *a)
229
+{
230
+ if (dc_isar_feature(aa64_mte, s)) {
231
+ /* Full MTE is enabled -- set the TCO bit as directed. */
232
+ if (a->imm & 1) {
233
+ set_pstate_bits(PSTATE_TCO);
234
+ } else {
235
+ clear_pstate_bits(PSTATE_TCO);
85
+ }
236
+ }
86
+ gicv3_redist_inv_lpi(&s->gicv3->cpu[cte.rdbase], ite.intid);
237
+ gen_rebuild_hflags(s);
87
+ break;
238
+ /* Many factors, including TCO, go into MTE_ACTIVE. */
88
+ case ITE_INTTYPE_VIRTUAL:
239
+ s->base.is_jmp = DISAS_UPDATE_NOCHAIN;
89
+ if (!its_feature_virtual(s)) {
240
+ return true;
90
+ /* Can't happen unless guest is illegally writing to table memory */
241
+ } else if (dc_isar_feature(aa64_mte_insn_reg, s)) {
91
+ qemu_log_mask(LOG_GUEST_ERROR,
242
+ /* Only "instructions accessible at EL0" -- PSTATE.TCO is WI. */
92
+ "%s: invalid type %d in ITE (table corrupted?)\n",
243
+ return true;
93
+ __func__, ite.inttype);
244
+ } else {
94
+ return CMD_CONTINUE;
245
+ /* Insn not present */
246
+ return false;
247
+ }
248
+}
249
+
250
+static bool trans_MSR_i_DAIFSET(DisasContext *s, arg_i *a)
251
+{
252
+ gen_helper_msr_i_daifset(cpu_env, tcg_constant_i32(a->imm));
253
+ s->base.is_jmp = DISAS_TOO_MANY;
254
+ return true;
255
+}
256
+
257
+static bool trans_MSR_i_DAIFCLEAR(DisasContext *s, arg_i *a)
258
+{
259
+ gen_helper_msr_i_daifclear(cpu_env, tcg_constant_i32(a->imm));
260
+ /* Exit the cpu loop to re-evaluate pending IRQs. */
261
+ s->base.is_jmp = DISAS_UPDATE_EXIT;
262
+ return true;
263
+}
264
+
265
+static bool trans_MSR_i_SVCR(DisasContext *s, arg_MSR_i_SVCR *a)
266
+{
267
+ if (!dc_isar_feature(aa64_sme, s) || a->mask == 0) {
268
+ return false;
269
+ }
270
+ if (sme_access_check(s)) {
271
+ int old = s->pstate_sm | (s->pstate_za << 1);
272
+ int new = a->imm * 3;
273
+
274
+ if ((old ^ new) & a->mask) {
275
+ /* At least one bit changes. */
276
+ gen_helper_set_svcr(cpu_env, tcg_constant_i32(new),
277
+ tcg_constant_i32(a->mask));
278
+ s->base.is_jmp = DISAS_TOO_MANY;
95
+ }
279
+ }
96
+ /* We will implement the vLPI invalidation in a later commit */
280
+ }
97
+ g_assert_not_reached();
281
+ return true;
98
+ break;
99
+ default:
100
+ g_assert_not_reached();
101
+ }
102
+
103
+ return CMD_CONTINUE_OK;
104
+}
105
+
106
/*
107
* Current implementation blocks until all
108
* commands are processed
109
@@ -XXX,XX +XXX,XX @@ static void process_cmdq(GICv3ITSState *s)
110
result = process_its_cmd(s, cmdpkt, DISCARD);
111
break;
112
case GITS_CMD_INV:
113
+ result = process_inv(s, cmdpkt);
114
+ break;
115
case GITS_CMD_INVALL:
116
/*
117
* Current implementation doesn't cache any ITS tables,
118
* but the calculated lpi priority information. We only
119
* need to trigger lpi priority re-calculation to be in
120
* sync with LPI config table or pending table changes.
121
+ * INVALL operates on a collection specified by ICID so
122
+ * it only affects physical LPIs.
123
*/
124
- trace_gicv3_its_cmd_inv();
125
+ trace_gicv3_its_cmd_invall();
126
for (i = 0; i < s->gicv3->num_cpu; i++) {
127
gicv3_redist_update_lpi(&s->gicv3->cpu[i]);
128
}
129
diff --git a/hw/intc/arm_gicv3_redist.c b/hw/intc/arm_gicv3_redist.c
130
index XXXXXXX..XXXXXXX 100644
131
--- a/hw/intc/arm_gicv3_redist.c
132
+++ b/hw/intc/arm_gicv3_redist.c
133
@@ -XXX,XX +XXX,XX @@ void gicv3_redist_process_lpi(GICv3CPUState *cs, int irq, int level)
134
gicv3_redist_lpi_pending(cs, irq, level);
135
}
282
}
136
283
137
+void gicv3_redist_inv_lpi(GICv3CPUState *cs, int irq)
284
static void gen_get_nzcv(TCGv_i64 tcg_rt)
138
+{
285
@@ -XXX,XX +XXX,XX @@ static void disas_system(DisasContext *s, uint32_t insn)
139
+ /*
286
rt = extract32(insn, 0, 5);
140
+ * The only cached information for LPIs we have is the HPPLPI.
287
141
+ * We could be cleverer about identifying when we don't need
288
if (op0 == 0) {
142
+ * to do a full rescan of the pending table, but until we find
289
- if (l || rt != 31) {
143
+ * this is a performance issue, just always recalculate.
290
- unallocated_encoding(s);
144
+ */
291
- return;
145
+ gicv3_redist_update_lpi(cs);
292
- }
146
+}
293
- switch (crn) {
147
+
294
- case 4: /* MSR (immediate) */
148
void gicv3_redist_mov_lpi(GICv3CPUState *src, GICv3CPUState *dest, int irq)
295
- handle_msr_i(s, insn, op1, op2, crm);
149
{
296
- break;
150
/*
297
- default:
151
diff --git a/hw/intc/trace-events b/hw/intc/trace-events
298
- unallocated_encoding(s);
152
index XXXXXXX..XXXXXXX 100644
299
- break;
153
--- a/hw/intc/trace-events
300
- }
154
+++ b/hw/intc/trace-events
301
+ unallocated_encoding(s);
155
@@ -XXX,XX +XXX,XX @@ gicv3_its_cmd_mapd(uint32_t devid, uint32_t size, uint64_t ittaddr, int valid) "
302
return;
156
gicv3_its_cmd_mapc(uint32_t icid, uint64_t rdbase, int valid) "GICv3 ITS: command MAPC ICID 0x%x RDbase 0x%" PRIx64 " V %d"
303
}
157
gicv3_its_cmd_mapi(uint32_t devid, uint32_t eventid, uint32_t icid) "GICv3 ITS: command MAPI DeviceID 0x%x EventID 0x%x ICID 0x%x"
304
handle_sys(s, insn, l, op0, op1, op2, crn, crm, rt);
158
gicv3_its_cmd_mapti(uint32_t devid, uint32_t eventid, uint32_t icid, uint32_t intid) "GICv3 ITS: command MAPTI DeviceID 0x%x EventID 0x%x ICID 0x%x pINTID 0x%x"
159
-gicv3_its_cmd_inv(void) "GICv3 ITS: command INV or INVALL"
160
+gicv3_its_cmd_inv(uint32_t devid, uint32_t eventid) "GICv3 ITS: command INV DeviceID 0x%x EventID 0x%x"
161
+gicv3_its_cmd_invall(void) "GICv3 ITS: command INVALL"
162
gicv3_its_cmd_movall(uint64_t rd1, uint64_t rd2) "GICv3 ITS: command MOVALL RDbase1 0x%" PRIx64 " RDbase2 0x%" PRIx64
163
gicv3_its_cmd_movi(uint32_t devid, uint32_t eventid, uint32_t icid) "GICv3 ITS: command MOVI DeviceID 0x%x EventID 0x%x ICID 0x%x"
164
gicv3_its_cmd_vmapi(uint32_t devid, uint32_t eventid, uint32_t vpeid, uint32_t doorbell) "GICv3 ITS: command VMAPI DeviceID 0x%x EventID 0x%x vPEID 0x%x Dbell_pINTID 0x%x"
165
--
305
--
166
2.25.1
306
2.34.1
diff view generated by jsdifflib
1
Factor out the common part of gicv3_redist_update_lpi_only() into
1
Convert MSR (reg), MRS, SYS, SYSL to decodetree. For QEMU these are
2
a new function update_for_all_lpis(), which does a full rescan
2
all essentially the same instruction (system register access).
3
of an LPI Pending table and sets the specified PendingIrq struct
4
with the highest priority pending enabled LPI it finds.
5
3
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20220408141550.1271295-29-peter.maydell@linaro.org
6
Message-id: 20230602155223.2040685-7-peter.maydell@linaro.org
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
9
---
8
---
10
hw/intc/arm_gicv3_redist.c | 66 ++++++++++++++++++++++++++------------
9
target/arm/tcg/a64.decode | 8 ++++++++
11
1 file changed, 46 insertions(+), 20 deletions(-)
10
target/arm/tcg/translate-a64.c | 32 +++++---------------------------
11
2 files changed, 13 insertions(+), 27 deletions(-)
12
12
13
diff --git a/hw/intc/arm_gicv3_redist.c b/hw/intc/arm_gicv3_redist.c
13
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
14
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/intc/arm_gicv3_redist.c
15
--- a/target/arm/tcg/a64.decode
16
+++ b/hw/intc/arm_gicv3_redist.c
16
+++ b/target/arm/tcg/a64.decode
17
@@ -XXX,XX +XXX,XX @@ static void update_for_one_lpi(GICv3CPUState *cs, int irq,
17
@@ -XXX,XX +XXX,XX @@ MSR_i_TCO 1101 0101 0000 0 011 0100 .... 100 11111 @msr_i
18
MSR_i_DAIFSET 1101 0101 0000 0 011 0100 .... 110 11111 @msr_i
19
MSR_i_DAIFCLEAR 1101 0101 0000 0 011 0100 .... 111 11111 @msr_i
20
MSR_i_SVCR 1101 0101 0000 0 011 0100 0 mask:2 imm:1 011 11111
21
+
22
+# MRS, MSR (register), SYS, SYSL. These are all essentially the
23
+# same instruction as far as QEMU is concerned.
24
+# NB: op0 is bits [20:19], but op0=0b00 is other insns, so we have
25
+# to hand-decode it.
26
+SYS 1101 0101 00 l:1 01 op1:3 crn:4 crm:4 op2:3 rt:5 op0=1
27
+SYS 1101 0101 00 l:1 10 op1:3 crn:4 crm:4 op2:3 rt:5 op0=2
28
+SYS 1101 0101 00 l:1 11 op1:3 crn:4 crm:4 op2:3 rt:5 op0=3
29
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
30
index XXXXXXX..XXXXXXX 100644
31
--- a/target/arm/tcg/translate-a64.c
32
+++ b/target/arm/tcg/translate-a64.c
33
@@ -XXX,XX +XXX,XX @@ static void gen_sysreg_undef(DisasContext *s, bool isread,
34
* These are all essentially the same insn in 'read' and 'write'
35
* versions, with varying op0 fields.
36
*/
37
-static void handle_sys(DisasContext *s, uint32_t insn, bool isread,
38
+static void handle_sys(DisasContext *s, bool isread,
39
unsigned int op0, unsigned int op1, unsigned int op2,
40
unsigned int crn, unsigned int crm, unsigned int rt)
41
{
42
@@ -XXX,XX +XXX,XX @@ static void handle_sys(DisasContext *s, uint32_t insn, bool isread,
18
}
43
}
19
}
44
}
20
45
21
+/**
46
-/* System
22
+ * update_for_all_lpis: Fully scan LPI tables and find best pending LPI
47
- * 31 22 21 20 19 18 16 15 12 11 8 7 5 4 0
23
+ *
48
- * +---------------------+---+-----+-----+-------+-------+-----+------+
24
+ * @cs: GICv3CPUState
49
- * | 1 1 0 1 0 1 0 1 0 0 | L | op0 | op1 | CRn | CRm | op2 | Rt |
25
+ * @ptbase: physical address of LPI Pending table
50
- * +---------------------+---+-----+-----+-------+-------+-----+------+
26
+ * @ctbase: physical address of LPI Configuration table
51
- */
27
+ * @ptsizebits: size of tables, specified as number of interrupt ID bits minus 1
52
-static void disas_system(DisasContext *s, uint32_t insn)
28
+ * @ds: true if priority value should not be shifted
53
+static bool trans_SYS(DisasContext *s, arg_SYS *a)
29
+ * @hpp: points to pending information to set
30
+ *
31
+ * Recalculate the highest priority pending enabled LPI from scratch,
32
+ * and set @hpp accordingly.
33
+ *
34
+ * We scan the LPI pending table @ptbase; for each pending LPI, we read the
35
+ * corresponding entry in the LPI configuration table @ctbase to extract
36
+ * the priority and enabled information.
37
+ *
38
+ * We take @ptsizebits in the form idbits-1 because this is the way that
39
+ * LPI table sizes are architecturally specified in GICR_PROPBASER.IDBits
40
+ * and in the VMAPP command's VPT_size field.
41
+ */
42
+static void update_for_all_lpis(GICv3CPUState *cs, uint64_t ptbase,
43
+ uint64_t ctbase, unsigned ptsizebits,
44
+ bool ds, PendingIrq *hpp)
45
+{
46
+ AddressSpace *as = &cs->gic->dma_as;
47
+ uint8_t pend;
48
+ uint32_t pendt_size = (1ULL << (ptsizebits + 1));
49
+ int i, bit;
50
+
51
+ hpp->prio = 0xff;
52
+
53
+ for (i = GICV3_LPI_INTID_START / 8; i < pendt_size / 8; i++) {
54
+ address_space_read(as, ptbase + i, MEMTXATTRS_UNSPECIFIED, &pend, 1);
55
+ while (pend) {
56
+ bit = ctz32(pend);
57
+ update_for_one_lpi(cs, i * 8 + bit, ctbase, ds, hpp);
58
+ pend &= ~(1 << bit);
59
+ }
60
+ }
61
+}
62
+
63
static uint8_t gicr_read_ipriorityr(GICv3CPUState *cs, MemTxAttrs attrs,
64
int irq)
65
{
54
{
66
@@ -XXX,XX +XXX,XX @@ void gicv3_redist_update_lpi_only(GICv3CPUState *cs)
55
- unsigned int l, op0, op1, crn, crm, op2, rt;
67
* priority is lower than the last computed high priority lpi interrupt.
56
- l = extract32(insn, 21, 1);
68
* If yes, replace current LPI as the new high priority lpi interrupt.
57
- op0 = extract32(insn, 19, 2);
69
*/
58
- op1 = extract32(insn, 16, 3);
70
- AddressSpace *as = &cs->gic->dma_as;
59
- crn = extract32(insn, 12, 4);
71
- uint64_t lpipt_baddr;
60
- crm = extract32(insn, 8, 4);
72
- uint32_t pendt_size = 0;
61
- op2 = extract32(insn, 5, 3);
73
- uint8_t pend;
62
- rt = extract32(insn, 0, 5);
74
- int i, bit;
75
+ uint64_t lpipt_baddr, lpict_baddr;
76
uint64_t idbits;
77
78
idbits = MIN(FIELD_EX64(cs->gicr_propbaser, GICR_PROPBASER, IDBITS),
79
@@ -XXX,XX +XXX,XX @@ void gicv3_redist_update_lpi_only(GICv3CPUState *cs)
80
return;
81
}
82
83
- cs->hpplpi.prio = 0xff;
84
-
63
-
85
lpipt_baddr = cs->gicr_pendbaser & R_GICR_PENDBASER_PHYADDR_MASK;
64
- if (op0 == 0) {
86
+ lpict_baddr = cs->gicr_propbaser & R_GICR_PROPBASER_PHYADDR_MASK;
65
- unallocated_encoding(s);
87
66
- return;
88
- /* Determine the highest priority pending interrupt among LPIs */
89
- pendt_size = (1ULL << (idbits + 1));
90
-
91
- for (i = GICV3_LPI_INTID_START / 8; i < pendt_size / 8; i++) {
92
- address_space_read(as, lpipt_baddr + i, MEMTXATTRS_UNSPECIFIED, &pend,
93
- sizeof(pend));
94
-
95
- while (pend) {
96
- bit = ctz32(pend);
97
- gicv3_redist_check_lpi_priority(cs, i * 8 + bit);
98
- pend &= ~(1 << bit);
99
- }
100
- }
67
- }
101
+ update_for_all_lpis(cs, lpipt_baddr, lpict_baddr, idbits,
68
- handle_sys(s, insn, l, op0, op1, op2, crn, crm, rt);
102
+ cs->gic->gicd_ctlr & GICD_CTLR_DS, &cs->hpplpi);
69
+ handle_sys(s, a->l, a->op0, a->op1, a->op2, a->crn, a->crm, a->rt);
70
+ return true;
103
}
71
}
104
72
105
void gicv3_redist_update_lpi(GICv3CPUState *cs)
73
/* Exception generation
74
@@ -XXX,XX +XXX,XX @@ static void disas_b_exc_sys(DisasContext *s, uint32_t insn)
75
switch (extract32(insn, 25, 7)) {
76
case 0x6a: /* Exception generation / System */
77
if (insn & (1 << 24)) {
78
- if (extract32(insn, 22, 2) == 0) {
79
- disas_system(s, insn);
80
- } else {
81
- unallocated_encoding(s);
82
- }
83
+ unallocated_encoding(s);
84
} else {
85
disas_exc(s, insn);
86
}
106
--
87
--
107
2.25.1
88
2.34.1
89
90
diff view generated by jsdifflib
1
For GICv4, interrupt table entries read by process_its_cmd() may
1
Convert the exception generation instructions SVC, HVC, SMC, BRK and
2
indicate virtual LPIs which are to be directly injected into a VM.
2
HLT to decodetree.
3
Implement the ITS side of the code for handling this. This is
4
similar to the existing handling of physical LPIs, but instead of
5
looking up a collection ID in a collection table, we look up a vPEID
6
in a vPE table. As with the physical LPIs, we leave the rest of the
7
work to code in the redistributor device.
8
3
9
The redistributor half will be implemented in a later commit;
4
The old decoder decoded the halting-debug insnns DCPS1, DCPS2 and
10
for now we just provide a stub function which does nothing.
5
DCPS3 just in order to then make them UNDEF; as with DRPS, we don't
6
bother to decode them, but document the patterns in a64.decode.
11
7
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
14
Message-id: 20220408141550.1271295-15-peter.maydell@linaro.org
10
Message-id: 20230602155223.2040685-8-peter.maydell@linaro.org
15
---
11
---
16
hw/intc/gicv3_internal.h | 17 +++++++
12
target/arm/tcg/a64.decode | 15 +++
17
hw/intc/arm_gicv3_its.c | 99 +++++++++++++++++++++++++++++++++++++-
13
target/arm/tcg/translate-a64.c | 173 ++++++++++++---------------------
18
hw/intc/arm_gicv3_redist.c | 9 ++++
14
2 files changed, 79 insertions(+), 109 deletions(-)
19
hw/intc/trace-events | 2 +
20
4 files changed, 125 insertions(+), 2 deletions(-)
21
15
22
diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h
16
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
23
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
24
--- a/hw/intc/gicv3_internal.h
18
--- a/target/arm/tcg/a64.decode
25
+++ b/hw/intc/gicv3_internal.h
19
+++ b/target/arm/tcg/a64.decode
26
@@ -XXX,XX +XXX,XX @@ MemTxResult gicv3_redist_write(void *opaque, hwaddr offset, uint64_t data,
20
@@ -XXX,XX +XXX,XX @@ MSR_i_SVCR 1101 0101 0000 0 011 0100 0 mask:2 imm:1 011 11111
27
void gicv3_dist_set_irq(GICv3State *s, int irq, int level);
21
SYS 1101 0101 00 l:1 01 op1:3 crn:4 crm:4 op2:3 rt:5 op0=1
28
void gicv3_redist_set_irq(GICv3CPUState *cs, int irq, int level);
22
SYS 1101 0101 00 l:1 10 op1:3 crn:4 crm:4 op2:3 rt:5 op0=2
29
void gicv3_redist_process_lpi(GICv3CPUState *cs, int irq, int level);
23
SYS 1101 0101 00 l:1 11 op1:3 crn:4 crm:4 op2:3 rt:5 op0=3
30
+/**
24
+
31
+ * gicv3_redist_process_vlpi:
25
+# Exception generation
32
+ * @cs: GICv3CPUState
26
+
33
+ * @irq: (virtual) interrupt number
27
+@i16 .... .... ... imm:16 ... .. &i
34
+ * @vptaddr: (guest) address of VLPI table
28
+SVC 1101 0100 000 ................ 000 01 @i16
35
+ * @doorbell: doorbell (physical) interrupt number (1023 for "no doorbell")
29
+HVC 1101 0100 000 ................ 000 10 @i16
36
+ * @level: level to set @irq to
30
+SMC 1101 0100 000 ................ 000 11 @i16
37
+ *
31
+BRK 1101 0100 001 ................ 000 00 @i16
38
+ * Process a virtual LPI being directly injected by the ITS. This function
32
+HLT 1101 0100 010 ................ 000 00 @i16
39
+ * will update the VLPI table specified by @vptaddr and @vptsize. If the
33
+# These insns always UNDEF unless in halting debug state, which
40
+ * vCPU corresponding to that VLPI table is currently running on
34
+# we don't implement. So we don't need to decode them. The patterns
41
+ * the CPU associated with this redistributor, directly inject the VLPI
35
+# are listed here as documentation.
42
+ * @irq. If the vCPU is not running on this CPU, raise the doorbell
36
+# DCPS1 1101 0100 101 ................ 000 01 @i16
43
+ * interrupt instead.
37
+# DCPS2 1101 0100 101 ................ 000 10 @i16
44
+ */
38
+# DCPS3 1101 0100 101 ................ 000 11 @i16
45
+void gicv3_redist_process_vlpi(GICv3CPUState *cs, int irq, uint64_t vptaddr,
39
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
46
+ int doorbell, int level);
47
void gicv3_redist_lpi_pending(GICv3CPUState *cs, int irq, int level);
48
/**
49
* gicv3_redist_update_lpi:
50
diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
51
index XXXXXXX..XXXXXXX 100644
40
index XXXXXXX..XXXXXXX 100644
52
--- a/hw/intc/arm_gicv3_its.c
41
--- a/target/arm/tcg/translate-a64.c
53
+++ b/hw/intc/arm_gicv3_its.c
42
+++ b/target/arm/tcg/translate-a64.c
54
@@ -XXX,XX +XXX,XX @@ out:
43
@@ -XXX,XX +XXX,XX @@ static bool trans_SYS(DisasContext *s, arg_SYS *a)
55
return res;
44
return true;
56
}
45
}
57
46
58
+/*
47
-/* Exception generation
59
+ * Read the vPE Table entry at index @vpeid. On success (including
48
- *
60
+ * successfully determining that there is no valid entry for this index),
49
- * 31 24 23 21 20 5 4 2 1 0
61
+ * we return MEMTX_OK and populate the VTEntry struct accordingly.
50
- * +-----------------+-----+------------------------+-----+----+
62
+ * If there is an error reading memory then we return the error code.
51
- * | 1 1 0 1 0 1 0 0 | opc | imm16 | op2 | LL |
63
+ */
52
- * +-----------------------+------------------------+----------+
64
+static MemTxResult get_vte(GICv3ITSState *s, uint32_t vpeid, VTEntry *vte)
53
- */
54
-static void disas_exc(DisasContext *s, uint32_t insn)
55
+static bool trans_SVC(DisasContext *s, arg_i *a)
56
{
57
- int opc = extract32(insn, 21, 3);
58
- int op2_ll = extract32(insn, 0, 5);
59
- int imm16 = extract32(insn, 5, 16);
60
- uint32_t syndrome;
61
-
62
- switch (opc) {
63
- case 0:
64
- /* For SVC, HVC and SMC we advance the single-step state
65
- * machine before taking the exception. This is architecturally
66
- * mandated, to ensure that single-stepping a system call
67
- * instruction works properly.
68
- */
69
- switch (op2_ll) {
70
- case 1: /* SVC */
71
- syndrome = syn_aa64_svc(imm16);
72
- if (s->fgt_svc) {
73
- gen_exception_insn_el(s, 0, EXCP_UDEF, syndrome, 2);
74
- break;
75
- }
76
- gen_ss_advance(s);
77
- gen_exception_insn(s, 4, EXCP_SWI, syndrome);
78
- break;
79
- case 2: /* HVC */
80
- if (s->current_el == 0) {
81
- unallocated_encoding(s);
82
- break;
83
- }
84
- /* The pre HVC helper handles cases when HVC gets trapped
85
- * as an undefined insn by runtime configuration.
86
- */
87
- gen_a64_update_pc(s, 0);
88
- gen_helper_pre_hvc(cpu_env);
89
- gen_ss_advance(s);
90
- gen_exception_insn_el(s, 4, EXCP_HVC, syn_aa64_hvc(imm16), 2);
91
- break;
92
- case 3: /* SMC */
93
- if (s->current_el == 0) {
94
- unallocated_encoding(s);
95
- break;
96
- }
97
- gen_a64_update_pc(s, 0);
98
- gen_helper_pre_smc(cpu_env, tcg_constant_i32(syn_aa64_smc(imm16)));
99
- gen_ss_advance(s);
100
- gen_exception_insn_el(s, 4, EXCP_SMC, syn_aa64_smc(imm16), 3);
101
- break;
102
- default:
103
- unallocated_encoding(s);
104
- break;
105
- }
106
- break;
107
- case 1:
108
- if (op2_ll != 0) {
109
- unallocated_encoding(s);
110
- break;
111
- }
112
- /* BRK */
113
- gen_exception_bkpt_insn(s, syn_aa64_bkpt(imm16));
114
- break;
115
- case 2:
116
- if (op2_ll != 0) {
117
- unallocated_encoding(s);
118
- break;
119
- }
120
- /* HLT. This has two purposes.
121
- * Architecturally, it is an external halting debug instruction.
122
- * Since QEMU doesn't implement external debug, we treat this as
123
- * it is required for halting debug disabled: it will UNDEF.
124
- * Secondly, "HLT 0xf000" is the A64 semihosting syscall instruction.
125
- */
126
- if (semihosting_enabled(s->current_el == 0) && imm16 == 0xf000) {
127
- gen_exception_internal_insn(s, EXCP_SEMIHOST);
128
- } else {
129
- unallocated_encoding(s);
130
- }
131
- break;
132
- case 5:
133
- if (op2_ll < 1 || op2_ll > 3) {
134
- unallocated_encoding(s);
135
- break;
136
- }
137
- /* DCPS1, DCPS2, DCPS3 */
138
- unallocated_encoding(s);
139
- break;
140
- default:
141
- unallocated_encoding(s);
142
- break;
143
+ /*
144
+ * For SVC, HVC and SMC we advance the single-step state
145
+ * machine before taking the exception. This is architecturally
146
+ * mandated, to ensure that single-stepping a system call
147
+ * instruction works properly.
148
+ */
149
+ uint32_t syndrome = syn_aa64_svc(a->imm);
150
+ if (s->fgt_svc) {
151
+ gen_exception_insn_el(s, 0, EXCP_UDEF, syndrome, 2);
152
+ return true;
153
}
154
+ gen_ss_advance(s);
155
+ gen_exception_insn(s, 4, EXCP_SWI, syndrome);
156
+ return true;
157
}
158
159
-/* Branches, exception generating and system instructions */
160
-static void disas_b_exc_sys(DisasContext *s, uint32_t insn)
161
+static bool trans_HVC(DisasContext *s, arg_i *a)
162
{
163
- switch (extract32(insn, 25, 7)) {
164
- case 0x6a: /* Exception generation / System */
165
- if (insn & (1 << 24)) {
166
- unallocated_encoding(s);
167
- } else {
168
- disas_exc(s, insn);
169
- }
170
- break;
171
- default:
172
+ if (s->current_el == 0) {
173
unallocated_encoding(s);
174
- break;
175
+ return true;
176
}
177
+ /*
178
+ * The pre HVC helper handles cases when HVC gets trapped
179
+ * as an undefined insn by runtime configuration.
180
+ */
181
+ gen_a64_update_pc(s, 0);
182
+ gen_helper_pre_hvc(cpu_env);
183
+ /* Architecture requires ss advance before we do the actual work */
184
+ gen_ss_advance(s);
185
+ gen_exception_insn_el(s, 4, EXCP_HVC, syn_aa64_hvc(a->imm), 2);
186
+ return true;
187
+}
188
+
189
+static bool trans_SMC(DisasContext *s, arg_i *a)
65
+{
190
+{
66
+ MemTxResult res = MEMTX_OK;
191
+ if (s->current_el == 0) {
67
+ AddressSpace *as = &s->gicv3->dma_as;
192
+ unallocated_encoding(s);
68
+ uint64_t entry_addr = table_entry_addr(s, &s->vpet, vpeid, &res);
193
+ return true;
69
+ uint64_t vteval;
70
+
71
+ if (entry_addr == -1) {
72
+ /* No L2 table entry, i.e. no valid VTE, or a memory error */
73
+ vte->valid = false;
74
+ goto out;
75
+ }
194
+ }
76
+ vteval = address_space_ldq_le(as, entry_addr, MEMTXATTRS_UNSPECIFIED, &res);
195
+ gen_a64_update_pc(s, 0);
77
+ if (res != MEMTX_OK) {
196
+ gen_helper_pre_smc(cpu_env, tcg_constant_i32(syn_aa64_smc(a->imm)));
78
+ goto out;
197
+ /* Architecture requires ss advance before we do the actual work */
79
+ }
198
+ gen_ss_advance(s);
80
+ vte->valid = FIELD_EX64(vteval, VTE, VALID);
199
+ gen_exception_insn_el(s, 4, EXCP_SMC, syn_aa64_smc(a->imm), 3);
81
+ vte->vptsize = FIELD_EX64(vteval, VTE, VPTSIZE);
200
+ return true;
82
+ vte->vptaddr = FIELD_EX64(vteval, VTE, VPTADDR);
83
+ vte->rdbase = FIELD_EX64(vteval, VTE, RDBASE);
84
+out:
85
+ if (res != MEMTX_OK) {
86
+ trace_gicv3_its_vte_read_fault(vpeid);
87
+ } else {
88
+ trace_gicv3_its_vte_read(vpeid, vte->valid, vte->vptsize,
89
+ vte->vptaddr, vte->rdbase);
90
+ }
91
+ return res;
92
+}
201
+}
93
+
202
+
94
/*
203
+static bool trans_BRK(DisasContext *s, arg_i *a)
95
* Given a (DeviceID, EventID), look up the corresponding ITE, including
96
* checking for the various invalid-value cases. If we find a valid ITE,
97
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult lookup_cte(GICv3ITSState *s, const char *who,
98
return CMD_CONTINUE_OK;
99
}
100
101
+/*
102
+ * Given a VPEID, look up the corresponding VTE, including checking
103
+ * for various invalid-value cases. if we find a valid VTE, fill in @vte
104
+ * and return CMD_CONTINUE_OK; otherwise return CMD_STALL or CMD_CONTINUE
105
+ * (and the contents of @vte should not be relied on).
106
+ *
107
+ * The string @who is purely for the LOG_GUEST_ERROR messages,
108
+ * and should indicate the name of the calling function or similar.
109
+ */
110
+static ItsCmdResult lookup_vte(GICv3ITSState *s, const char *who,
111
+ uint32_t vpeid, VTEntry *vte)
112
+{
204
+{
113
+ if (vpeid >= s->vpet.num_entries) {
205
+ gen_exception_bkpt_insn(s, syn_aa64_bkpt(a->imm));
114
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid VPEID 0x%x\n", who, vpeid);
206
+ return true;
115
+ return CMD_CONTINUE;
116
+ }
117
+
118
+ if (get_vte(s, vpeid, vte) != MEMTX_OK) {
119
+ return CMD_STALL;
120
+ }
121
+ if (!vte->valid) {
122
+ qemu_log_mask(LOG_GUEST_ERROR,
123
+ "%s: invalid VTE for VPEID 0x%x\n", who, vpeid);
124
+ return CMD_CONTINUE;
125
+ }
126
+
127
+ if (vte->rdbase >= s->gicv3->num_cpu) {
128
+ return CMD_CONTINUE;
129
+ }
130
+ return CMD_CONTINUE_OK;
131
+}
207
+}
132
+
208
+
133
static ItsCmdResult process_its_cmd_phys(GICv3ITSState *s, const ITEntry *ite,
209
+static bool trans_HLT(DisasContext *s, arg_i *a)
134
int irqlevel)
135
{
136
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_its_cmd_phys(GICv3ITSState *s, const ITEntry *ite,
137
return CMD_CONTINUE_OK;
138
}
139
140
+static ItsCmdResult process_its_cmd_virt(GICv3ITSState *s, const ITEntry *ite,
141
+ int irqlevel)
142
+{
143
+ VTEntry vte;
144
+ ItsCmdResult cmdres;
145
+
146
+ cmdres = lookup_vte(s, __func__, ite->vpeid, &vte);
147
+ if (cmdres != CMD_CONTINUE_OK) {
148
+ return cmdres;
149
+ }
150
+
151
+ if (!intid_in_lpi_range(ite->intid) ||
152
+ ite->intid >= (1ULL << (vte.vptsize + 1))) {
153
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: intid 0x%x out of range\n",
154
+ __func__, ite->intid);
155
+ return CMD_CONTINUE;
156
+ }
157
+
158
+ /*
159
+ * For QEMU the actual pending of the vLPI is handled in the
160
+ * redistributor code
161
+ */
162
+ gicv3_redist_process_vlpi(&s->gicv3->cpu[vte.rdbase], ite->intid,
163
+ vte.vptaddr << 16, ite->doorbell, irqlevel);
164
+ return CMD_CONTINUE_OK;
165
+}
166
+
167
/*
168
* This function handles the processing of following commands based on
169
* the ItsCmdType parameter passed:-
170
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult do_process_its_cmd(GICv3ITSState *s, uint32_t devid,
171
__func__, ite.inttype);
172
return CMD_CONTINUE;
173
}
174
- /* The GICv4 virtual interrupt handling will go here */
175
- g_assert_not_reached();
176
+ cmdres = process_its_cmd_virt(s, &ite, irqlevel);
177
+ break;
178
default:
179
g_assert_not_reached();
180
}
181
diff --git a/hw/intc/arm_gicv3_redist.c b/hw/intc/arm_gicv3_redist.c
182
index XXXXXXX..XXXXXXX 100644
183
--- a/hw/intc/arm_gicv3_redist.c
184
+++ b/hw/intc/arm_gicv3_redist.c
185
@@ -XXX,XX +XXX,XX @@ void gicv3_redist_movall_lpis(GICv3CPUState *src, GICv3CPUState *dest)
186
gicv3_redist_update_lpi(dest);
187
}
188
189
+void gicv3_redist_process_vlpi(GICv3CPUState *cs, int irq, uint64_t vptaddr,
190
+ int doorbell, int level)
191
+{
210
+{
192
+ /*
211
+ /*
193
+ * The redistributor handling for being handed a VLPI by the ITS
212
+ * HLT. This has two purposes.
194
+ * will be added in a subsequent commit.
213
+ * Architecturally, it is an external halting debug instruction.
214
+ * Since QEMU doesn't implement external debug, we treat this as
215
+ * it is required for halting debug disabled: it will UNDEF.
216
+ * Secondly, "HLT 0xf000" is the A64 semihosting syscall instruction.
195
+ */
217
+ */
196
+}
218
+ if (semihosting_enabled(s->current_el == 0) && a->imm == 0xf000) {
197
+
219
+ gen_exception_internal_insn(s, EXCP_SEMIHOST);
198
void gicv3_redist_set_irq(GICv3CPUState *cs, int irq, int level)
220
+ } else {
221
+ unallocated_encoding(s);
222
+ }
223
+ return true;
224
}
225
226
/*
227
@@ -XXX,XX +XXX,XX @@ static bool btype_destination_ok(uint32_t insn, bool bt, int btype)
228
static void disas_a64_legacy(DisasContext *s, uint32_t insn)
199
{
229
{
200
/* Update redistributor state for a change in an external PPI input line */
230
switch (extract32(insn, 25, 4)) {
201
diff --git a/hw/intc/trace-events b/hw/intc/trace-events
231
- case 0xa: case 0xb: /* Branch, exception generation and system insns */
202
index XXXXXXX..XXXXXXX 100644
232
- disas_b_exc_sys(s, insn);
203
--- a/hw/intc/trace-events
233
- break;
204
+++ b/hw/intc/trace-events
234
case 0x4:
205
@@ -XXX,XX +XXX,XX @@ gicv3_its_ite_write(uint64_t ittaddr, uint32_t eventid, int valid, int inttype,
235
case 0x6:
206
gicv3_its_dte_read(uint32_t devid, int valid, uint32_t size, uint64_t ittaddr) "GICv3 ITS: Device Table read for DeviceID 0x%x: valid %d size 0x%x ITTaddr 0x%" PRIx64
236
case 0xc:
207
gicv3_its_dte_write(uint32_t devid, int valid, uint32_t size, uint64_t ittaddr) "GICv3 ITS: Device Table write for DeviceID 0x%x: valid %d size 0x%x ITTaddr 0x%" PRIx64
208
gicv3_its_dte_read_fault(uint32_t devid) "GICv3 ITS: Device Table read for DeviceID 0x%x: faulted"
209
+gicv3_its_vte_read(uint32_t vpeid, int valid, uint32_t vptsize, uint64_t vptaddr, uint32_t rdbase) "GICv3 ITS: vPE Table read for vPEID 0x%x: valid %d VPTsize 0x%x VPTaddr 0x%" PRIx64 " RDbase 0x%x"
210
+gicv3_its_vte_read_fault(uint32_t vpeid) "GICv3 ITS: vPE Table read for vPEID 0x%x: faulted"
211
gicv3_its_vte_write(uint32_t vpeid, int valid, uint32_t vptsize, uint64_t vptaddr, uint32_t rdbase) "GICv3 ITS: vPE Table write for vPEID 0x%x: valid %d VPTsize 0x%x VPTaddr 0x%" PRIx64 " RDbase 0x%x"
212
213
# armv7m_nvic.c
214
--
237
--
215
2.25.1
238
2.34.1
diff view generated by jsdifflib
1
Implement the GICv4 VMOVI command, which moves the pending state
1
Convert the instructions in the load/store exclusive (STXR,
2
of a virtual interrupt from one redistributor to another. As with
2
STLXR, LDXR, LDAXR) and load/store ordered (STLR, STLLR,
3
MOVI, we handle the "parse and validate command arguments and
3
LDAR, LDLAR) to decodetree.
4
table lookups" part in the ITS source file, and pass the final
4
5
results to a function in the redistributor which will do the
5
Note that for STLR, STLLR, LDAR, LDLAR this fixes an under-decoding
6
actual operation. As with the "make a VLPI pending" change,
6
in the legacy decoder where we were not checking that the RES1 bits
7
for the moment we leave that redistributor function as a stub,
7
in the Rs and Rt2 fields were set.
8
to be implemented in a later commit.
8
9
The new function ldst_iss_sf() is equivalent to the existing
10
disas_ldst_compute_iss_sf(), but it takes the pre-decoded 'ext' field
11
rather than taking an undecoded two-bit opc field and extracting
12
'ext' from it. Once all the loads and stores have been converted
13
to decodetree disas_ldst_compute_iss_sf() will be unused and
14
can be deleted.
9
15
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
17
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20220408141550.1271295-21-peter.maydell@linaro.org
18
Message-id: 20230602155223.2040685-9-peter.maydell@linaro.org
13
---
19
---
14
hw/intc/gicv3_internal.h | 23 +++++++++++
20
target/arm/tcg/a64.decode | 11 +++
15
hw/intc/arm_gicv3_its.c | 82 ++++++++++++++++++++++++++++++++++++++
21
target/arm/tcg/translate-a64.c | 154 ++++++++++++++++++++-------------
16
hw/intc/arm_gicv3_redist.c | 10 +++++
22
2 files changed, 103 insertions(+), 62 deletions(-)
17
hw/intc/trace-events | 1 +
23
18
4 files changed, 116 insertions(+)
24
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
19
20
diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h
21
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
22
--- a/hw/intc/gicv3_internal.h
26
--- a/target/arm/tcg/a64.decode
23
+++ b/hw/intc/gicv3_internal.h
27
+++ b/target/arm/tcg/a64.decode
24
@@ -XXX,XX +XXX,XX @@ FIELD(GITS_TYPER, CIL, 36, 1)
28
@@ -XXX,XX +XXX,XX @@ HLT 1101 0100 010 ................ 000 00 @i16
25
#define GITS_CMD_INVALL 0x0D
29
# DCPS1 1101 0100 101 ................ 000 01 @i16
26
#define GITS_CMD_MOVALL 0x0E
30
# DCPS2 1101 0100 101 ................ 000 10 @i16
27
#define GITS_CMD_DISCARD 0x0F
31
# DCPS3 1101 0100 101 ................ 000 11 @i16
28
+#define GITS_CMD_VMOVI 0x21
32
+
29
#define GITS_CMD_VMOVP 0x22
33
+# Loads and stores
30
#define GITS_CMD_VSYNC 0x25
34
+
31
#define GITS_CMD_VMAPP 0x29
35
+&stxr rn rt rt2 rs sz lasr
32
@@ -XXX,XX +XXX,XX @@ FIELD(VMOVP_2, RDBASE, 16, 36)
36
+&stlr rn rt sz lasr
33
FIELD(VMOVP_2, DB, 63, 1) /* GICv4.1 only */
37
+@stxr sz:2 ...... ... rs:5 lasr:1 rt2:5 rn:5 rt:5 &stxr
34
FIELD(VMOVP_3, DEFAULT_DOORBELL, 0, 32) /* GICv4.1 only */
38
+@stlr sz:2 ...... ... ..... lasr:1 ..... rn:5 rt:5 &stlr
35
39
+STXR .. 001000 000 ..... . ..... ..... ..... @stxr # inc STLXR
36
+/* VMOVI command fields */
40
+LDXR .. 001000 010 ..... . ..... ..... ..... @stxr # inc LDAXR
37
+FIELD(VMOVI_0, DEVICEID, 32, 32)
41
+STLR .. 001000 100 11111 . 11111 ..... ..... @stlr # inc STLLR
38
+FIELD(VMOVI_1, EVENTID, 0, 32)
42
+LDAR .. 001000 110 11111 . 11111 ..... ..... @stlr # inc LDLAR
39
+FIELD(VMOVI_1, VPEID, 32, 16)
43
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
40
+FIELD(VMOVI_2, D, 0, 1)
41
+FIELD(VMOVI_2, DOORBELL, 32, 32)
42
+
43
/*
44
* 12 bytes Interrupt translation Table Entry size
45
* as per Table 5.3 in GICv3 spec
46
@@ -XXX,XX +XXX,XX @@ void gicv3_redist_mov_lpi(GICv3CPUState *src, GICv3CPUState *dest, int irq);
47
* by the ITS MOVALL command.
48
*/
49
void gicv3_redist_movall_lpis(GICv3CPUState *src, GICv3CPUState *dest);
50
+/**
51
+ * gicv3_redist_mov_vlpi:
52
+ * @src: source redistributor
53
+ * @src_vptaddr: (guest) address of source VLPI table
54
+ * @dest: destination redistributor
55
+ * @dest_vptaddr: (guest) address of destination VLPI table
56
+ * @irq: VLPI to update
57
+ * @doorbell: doorbell for destination (1023 for "no doorbell")
58
+ *
59
+ * Move the pending state of the specified VLPI from @src to @dest,
60
+ * as required by the ITS VMOVI command.
61
+ */
62
+void gicv3_redist_mov_vlpi(GICv3CPUState *src, uint64_t src_vptaddr,
63
+ GICv3CPUState *dest, uint64_t dest_vptaddr,
64
+ int irq, int doorbell);
65
66
void gicv3_redist_send_sgi(GICv3CPUState *cs, int grp, int irq, bool ns);
67
void gicv3_init_cpuif(GICv3State *s);
68
diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
69
index XXXXXXX..XXXXXXX 100644
44
index XXXXXXX..XXXXXXX 100644
70
--- a/hw/intc/arm_gicv3_its.c
45
--- a/target/arm/tcg/translate-a64.c
71
+++ b/hw/intc/arm_gicv3_its.c
46
+++ b/target/arm/tcg/translate-a64.c
72
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_vmovp(GICv3ITSState *s, const uint64_t *cmdpkt)
47
@@ -XXX,XX +XXX,XX @@ static bool disas_ldst_compute_iss_sf(int size, bool is_signed, int opc)
73
return cbdata.result;
48
return regsize == 64;
74
}
49
}
75
50
76
+static ItsCmdResult process_vmovi(GICv3ITSState *s, const uint64_t *cmdpkt)
51
+static bool ldst_iss_sf(int size, bool sign, bool ext)
77
+{
52
+{
78
+ uint32_t devid, eventid, vpeid, doorbell;
53
+
79
+ bool doorbell_valid;
54
+ if (sign) {
80
+ DTEntry dte;
55
+ /*
81
+ ITEntry ite;
56
+ * Signed loads are 64 bit results if we are not going to
82
+ VTEntry old_vte, new_vte;
57
+ * do a zero-extend from 32 to 64 after the load.
83
+ ItsCmdResult cmdres;
58
+ * (For a store, sign and ext are always false.)
84
+
59
+ */
85
+ if (!its_feature_virtual(s)) {
60
+ return !ext;
86
+ return CMD_CONTINUE;
61
+ } else {
87
+ }
62
+ /* Unsigned loads/stores work at the specified size */
88
+
63
+ return size == MO_64;
89
+ devid = FIELD_EX64(cmdpkt[0], VMOVI_0, DEVICEID);
64
+ }
90
+ eventid = FIELD_EX64(cmdpkt[1], VMOVI_1, EVENTID);
65
+}
91
+ vpeid = FIELD_EX64(cmdpkt[1], VMOVI_1, VPEID);
66
+
92
+ doorbell_valid = FIELD_EX64(cmdpkt[2], VMOVI_2, D);
67
+static bool trans_STXR(DisasContext *s, arg_stxr *a)
93
+ doorbell = FIELD_EX64(cmdpkt[2], VMOVI_2, DOORBELL);
68
+{
94
+
69
+ if (a->rn == 31) {
95
+ trace_gicv3_its_cmd_vmovi(devid, eventid, vpeid, doorbell_valid, doorbell);
70
+ gen_check_sp_alignment(s);
96
+
71
+ }
97
+ if (doorbell_valid && !valid_doorbell(doorbell)) {
72
+ if (a->lasr) {
98
+ qemu_log_mask(LOG_GUEST_ERROR,
73
+ tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
99
+ "%s: invalid doorbell 0x%x\n", __func__, doorbell);
74
+ }
100
+ return CMD_CONTINUE;
75
+ gen_store_exclusive(s, a->rs, a->rt, a->rt2, a->rn, a->sz, false);
101
+ }
76
+ return true;
102
+
77
+}
103
+ cmdres = lookup_ite(s, __func__, devid, eventid, &ite, &dte);
78
+
104
+ if (cmdres != CMD_CONTINUE_OK) {
79
+static bool trans_LDXR(DisasContext *s, arg_stxr *a)
105
+ return cmdres;
80
+{
106
+ }
81
+ if (a->rn == 31) {
107
+
82
+ gen_check_sp_alignment(s);
108
+ if (ite.inttype != ITE_INTTYPE_VIRTUAL) {
83
+ }
109
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: ITE is not for virtual interrupt\n",
84
+ gen_load_exclusive(s, a->rt, a->rt2, a->rn, a->sz, false);
110
+ __func__);
85
+ if (a->lasr) {
111
+ return CMD_CONTINUE;
86
+ tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ);
112
+ }
87
+ }
113
+
88
+ return true;
114
+ cmdres = lookup_vte(s, __func__, ite.vpeid, &old_vte);
89
+}
115
+ if (cmdres != CMD_CONTINUE_OK) {
90
+
116
+ return cmdres;
91
+static bool trans_STLR(DisasContext *s, arg_stlr *a)
117
+ }
92
+{
118
+ cmdres = lookup_vte(s, __func__, vpeid, &new_vte);
93
+ TCGv_i64 clean_addr;
119
+ if (cmdres != CMD_CONTINUE_OK) {
94
+ MemOp memop;
120
+ return cmdres;
95
+ bool iss_sf = ldst_iss_sf(a->sz, false, false);
121
+ }
122
+
123
+ if (!intid_in_lpi_range(ite.intid) ||
124
+ ite.intid >= (1ULL << (old_vte.vptsize + 1)) ||
125
+ ite.intid >= (1ULL << (new_vte.vptsize + 1))) {
126
+ qemu_log_mask(LOG_GUEST_ERROR,
127
+ "%s: ITE intid 0x%x out of range\n",
128
+ __func__, ite.intid);
129
+ return CMD_CONTINUE;
130
+ }
131
+
132
+ ite.vpeid = vpeid;
133
+ if (doorbell_valid) {
134
+ ite.doorbell = doorbell;
135
+ }
136
+
96
+
137
+ /*
97
+ /*
138
+ * Move the LPI from the old redistributor to the new one. We don't
98
+ * StoreLORelease is the same as Store-Release for QEMU, but
139
+ * need to do anything if the guest somehow specified the
99
+ * needs the feature-test.
140
+ * same pending table for source and destination.
141
+ */
100
+ */
142
+ if (old_vte.vptaddr != new_vte.vptaddr) {
101
+ if (!a->lasr && !dc_isar_feature(aa64_lor, s)) {
143
+ gicv3_redist_mov_vlpi(&s->gicv3->cpu[old_vte.rdbase],
102
+ return false;
144
+ old_vte.vptaddr << 16,
103
+ }
145
+ &s->gicv3->cpu[new_vte.rdbase],
104
+ /* Generate ISS for non-exclusive accesses including LASR. */
146
+ new_vte.vptaddr << 16,
105
+ if (a->rn == 31) {
147
+ ite.intid,
106
+ gen_check_sp_alignment(s);
148
+ ite.doorbell);
107
+ }
149
+ }
108
+ tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
150
+
109
+ memop = check_ordered_align(s, a->rn, 0, true, a->sz);
151
+ /* Update the ITE to the new VPEID and possibly doorbell values */
110
+ clean_addr = gen_mte_check1(s, cpu_reg_sp(s, a->rn),
152
+ return update_ite(s, eventid, &dte, &ite) ? CMD_CONTINUE_OK : CMD_STALL;
111
+ true, a->rn != 31, memop);
153
+}
112
+ do_gpr_st(s, cpu_reg(s, a->rt), clean_addr, memop, true, a->rt,
154
+
113
+ iss_sf, a->lasr);
155
static ItsCmdResult process_inv(GICv3ITSState *s, const uint64_t *cmdpkt)
114
+ return true;
156
{
115
+}
157
uint32_t devid, eventid;
116
+
158
@@ -XXX,XX +XXX,XX @@ static void process_cmdq(GICv3ITSState *s)
117
+static bool trans_LDAR(DisasContext *s, arg_stlr *a)
159
case GITS_CMD_VMOVP:
118
+{
160
result = process_vmovp(s, cmdpkt);
119
+ TCGv_i64 clean_addr;
161
break;
120
+ MemOp memop;
162
+ case GITS_CMD_VMOVI:
121
+ bool iss_sf = ldst_iss_sf(a->sz, false, false);
163
+ result = process_vmovi(s, cmdpkt);
122
+
164
+ break;
123
+ /* LoadLOAcquire is the same as Load-Acquire for QEMU. */
165
default:
124
+ if (!a->lasr && !dc_isar_feature(aa64_lor, s)) {
166
trace_gicv3_its_cmd_unknown(cmd);
125
+ return false;
167
break;
126
+ }
168
diff --git a/hw/intc/arm_gicv3_redist.c b/hw/intc/arm_gicv3_redist.c
127
+ /* Generate ISS for non-exclusive accesses including LASR. */
169
index XXXXXXX..XXXXXXX 100644
128
+ if (a->rn == 31) {
170
--- a/hw/intc/arm_gicv3_redist.c
129
+ gen_check_sp_alignment(s);
171
+++ b/hw/intc/arm_gicv3_redist.c
130
+ }
172
@@ -XXX,XX +XXX,XX @@ void gicv3_redist_process_vlpi(GICv3CPUState *cs, int irq, uint64_t vptaddr,
131
+ memop = check_ordered_align(s, a->rn, 0, false, a->sz);
173
*/
132
+ clean_addr = gen_mte_check1(s, cpu_reg_sp(s, a->rn),
133
+ false, a->rn != 31, memop);
134
+ do_gpr_ld(s, cpu_reg(s, a->rt), clean_addr, memop, false, true,
135
+ a->rt, iss_sf, a->lasr);
136
+ tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ);
137
+ return true;
138
+}
139
+
140
/* Load/store exclusive
141
*
142
* 31 30 29 24 23 22 21 20 16 15 14 10 9 5 4 0
143
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_excl(DisasContext *s, uint32_t insn)
144
int is_lasr = extract32(insn, 15, 1);
145
int o2_L_o1_o0 = extract32(insn, 21, 3) * 2 | is_lasr;
146
int size = extract32(insn, 30, 2);
147
- TCGv_i64 clean_addr;
148
- MemOp memop;
149
150
switch (o2_L_o1_o0) {
151
- case 0x0: /* STXR */
152
- case 0x1: /* STLXR */
153
- if (rn == 31) {
154
- gen_check_sp_alignment(s);
155
- }
156
- if (is_lasr) {
157
- tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
158
- }
159
- gen_store_exclusive(s, rs, rt, rt2, rn, size, false);
160
- return;
161
-
162
- case 0x4: /* LDXR */
163
- case 0x5: /* LDAXR */
164
- if (rn == 31) {
165
- gen_check_sp_alignment(s);
166
- }
167
- gen_load_exclusive(s, rt, rt2, rn, size, false);
168
- if (is_lasr) {
169
- tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ);
170
- }
171
- return;
172
-
173
- case 0x8: /* STLLR */
174
- if (!dc_isar_feature(aa64_lor, s)) {
175
- break;
176
- }
177
- /* StoreLORelease is the same as Store-Release for QEMU. */
178
- /* fall through */
179
- case 0x9: /* STLR */
180
- /* Generate ISS for non-exclusive accesses including LASR. */
181
- if (rn == 31) {
182
- gen_check_sp_alignment(s);
183
- }
184
- tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
185
- memop = check_ordered_align(s, rn, 0, true, size);
186
- clean_addr = gen_mte_check1(s, cpu_reg_sp(s, rn),
187
- true, rn != 31, memop);
188
- do_gpr_st(s, cpu_reg(s, rt), clean_addr, memop, true, rt,
189
- disas_ldst_compute_iss_sf(size, false, 0), is_lasr);
190
- return;
191
-
192
- case 0xc: /* LDLAR */
193
- if (!dc_isar_feature(aa64_lor, s)) {
194
- break;
195
- }
196
- /* LoadLOAcquire is the same as Load-Acquire for QEMU. */
197
- /* fall through */
198
- case 0xd: /* LDAR */
199
- /* Generate ISS for non-exclusive accesses including LASR. */
200
- if (rn == 31) {
201
- gen_check_sp_alignment(s);
202
- }
203
- memop = check_ordered_align(s, rn, 0, false, size);
204
- clean_addr = gen_mte_check1(s, cpu_reg_sp(s, rn),
205
- false, rn != 31, memop);
206
- do_gpr_ld(s, cpu_reg(s, rt), clean_addr, memop, false, true,
207
- rt, disas_ldst_compute_iss_sf(size, false, 0), is_lasr);
208
- tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ);
209
- return;
210
-
211
case 0x2: case 0x3: /* CASP / STXP */
212
if (size & 2) { /* STXP / STLXP */
213
if (rn == 31) {
214
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_excl(DisasContext *s, uint32_t insn)
215
return;
216
}
217
break;
218
+ default:
219
+ /* Handled in decodetree */
220
+ break;
221
}
222
unallocated_encoding(s);
174
}
223
}
175
176
+void gicv3_redist_mov_vlpi(GICv3CPUState *src, uint64_t src_vptaddr,
177
+ GICv3CPUState *dest, uint64_t dest_vptaddr,
178
+ int irq, int doorbell)
179
+{
180
+ /*
181
+ * The redistributor handling for moving a VLPI will be added
182
+ * in a subsequent commit.
183
+ */
184
+}
185
+
186
void gicv3_redist_inv_vlpi(GICv3CPUState *cs, int irq, uint64_t vptaddr)
187
{
188
/*
189
diff --git a/hw/intc/trace-events b/hw/intc/trace-events
190
index XXXXXXX..XXXXXXX 100644
191
--- a/hw/intc/trace-events
192
+++ b/hw/intc/trace-events
193
@@ -XXX,XX +XXX,XX @@ gicv3_its_cmd_vmapti(uint32_t devid, uint32_t eventid, uint32_t vpeid, uint32_t
194
gicv3_its_cmd_vmapp(uint32_t vpeid, uint64_t rdbase, int valid, uint64_t vptaddr, uint32_t vptsize) "GICv3 ITS: command VMAPP vPEID 0x%x RDbase 0x%" PRIx64 " V %d VPT_addr 0x%" PRIx64 " VPT_size 0x%x"
195
gicv3_its_cmd_vmovp(uint32_t vpeid, uint64_t rdbase) "GICv3 ITS: command VMOVP vPEID 0x%x RDbase 0x%" PRIx64
196
gicv3_its_cmd_vsync(void) "GICv3 ITS: command VSYNC"
197
+gicv3_its_cmd_vmovi(uint32_t devid, uint32_t eventid, uint32_t vpeid, int dbvalid, uint32_t doorbell) "GICv3 ITS: command VMOVI DeviceID 0x%x EventID 0x%x vPEID 0x%x D %d Dbell_pINTID 0x%x"
198
gicv3_its_cmd_unknown(unsigned cmd) "GICv3 ITS: unknown command 0x%x"
199
gicv3_its_cte_read(uint32_t icid, int valid, uint32_t rdbase) "GICv3 ITS: Collection Table read for ICID 0x%x: valid %d RDBase 0x%x"
200
gicv3_its_cte_write(uint32_t icid, int valid, uint32_t rdbase) "GICv3 ITS: Collection Table write for ICID 0x%x: valid %d RDBase 0x%x"
201
--
224
--
202
2.25.1
225
2.34.1
diff view generated by jsdifflib
1
Implement the GICv4 VMOVP command, which updates an entry in the vPE
1
Convert the load/store exclusive pair (LDXP, STXP, LDAXP, STLXP),
2
table to change its rdbase field. This command is unique in the ITS
2
compare-and-swap pair (CASP, CASPA, CASPAL, CASPL), and compare-and
3
command set because its effects must be propagated to all the other
3
swap (CAS, CASA, CASAL, CASL) instructions to decodetree.
4
ITSes connected to the same GIC as the ITS which executes the VMOVP
5
command.
6
7
The GICv4 spec allows two implementation choices for handling the
8
propagation to other ITSes:
9
* If GITS_TYPER.VMOVP is 1, the guest only needs to issue the command
10
on one ITS, and the implementation handles the propagation to
11
all ITSes
12
* If GITS_TYPER.VMOVP is 0, the guest must issue the command on
13
every ITS, and arrange for the ITSes to synchronize the updates
14
with each other by setting ITSList and Sequence Number fields
15
in the command packets
16
17
We choose the GITS_TYPER.VMOVP = 1 approach, and synchronously
18
execute the update on every ITS.
19
20
For GICv4.1 this command has extra fields in the command packet and
21
additional behaviour. We define the 4.1-only fields with the FIELD
22
macro, but only implement the GICv4.0 version of the command.
23
24
Note that we don't update the reported GITS_TYPER value here;
25
we'll do that later in a commit which updates all the reported
26
feature bit and ID register values for GICv4.
27
4
28
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
29
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
30
Message-id: 20220408141550.1271295-17-peter.maydell@linaro.org
7
Message-id: 20230602155223.2040685-10-peter.maydell@linaro.org
31
---
8
---
32
hw/intc/gicv3_internal.h | 18 ++++++++++
9
target/arm/tcg/a64.decode | 11 +++
33
hw/intc/arm_gicv3_its.c | 75 ++++++++++++++++++++++++++++++++++++++++
10
target/arm/tcg/translate-a64.c | 121 ++++++++++++---------------------
34
hw/intc/trace-events | 1 +
11
2 files changed, 53 insertions(+), 79 deletions(-)
35
3 files changed, 94 insertions(+)
36
12
37
diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h
13
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
38
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
39
--- a/hw/intc/gicv3_internal.h
15
--- a/target/arm/tcg/a64.decode
40
+++ b/hw/intc/gicv3_internal.h
16
+++ b/target/arm/tcg/a64.decode
41
@@ -XXX,XX +XXX,XX @@ FIELD(GITS_TYPER, CIL, 36, 1)
17
@@ -XXX,XX +XXX,XX @@ HLT 1101 0100 010 ................ 000 00 @i16
42
#define GITS_CMD_INVALL 0x0D
18
&stlr rn rt sz lasr
43
#define GITS_CMD_MOVALL 0x0E
19
@stxr sz:2 ...... ... rs:5 lasr:1 rt2:5 rn:5 rt:5 &stxr
44
#define GITS_CMD_DISCARD 0x0F
20
@stlr sz:2 ...... ... ..... lasr:1 ..... rn:5 rt:5 &stlr
45
+#define GITS_CMD_VMOVP 0x22
21
+%imm1_30_p2 30:1 !function=plus_2
46
#define GITS_CMD_VMAPP 0x29
22
+@stxp .. ...... ... rs:5 lasr:1 rt2:5 rn:5 rt:5 &stxr sz=%imm1_30_p2
47
#define GITS_CMD_VMAPTI 0x2A
23
STXR .. 001000 000 ..... . ..... ..... ..... @stxr # inc STLXR
48
#define GITS_CMD_VMAPI 0x2B
24
LDXR .. 001000 010 ..... . ..... ..... ..... @stxr # inc LDAXR
49
@@ -XXX,XX +XXX,XX @@ FIELD(VMAPP_2, V, 63, 1)
25
STLR .. 001000 100 11111 . 11111 ..... ..... @stlr # inc STLLR
50
FIELD(VMAPP_3, VPTSIZE, 0, 8) /* For GICv4.0, bits [7:6] are RES0 */
26
LDAR .. 001000 110 11111 . 11111 ..... ..... @stlr # inc LDLAR
51
FIELD(VMAPP_3, VPTADDR, 16, 36)
52
53
+/* VMOVP command fields */
54
+FIELD(VMOVP_0, SEQNUM, 32, 16) /* not used for GITS_TYPER.VMOVP == 1 */
55
+FIELD(VMOVP_1, ITSLIST, 0, 16) /* not used for GITS_TYPER.VMOVP == 1 */
56
+FIELD(VMOVP_1, VPEID, 32, 16)
57
+FIELD(VMOVP_2, RDBASE, 16, 36)
58
+FIELD(VMOVP_2, DB, 63, 1) /* GICv4.1 only */
59
+FIELD(VMOVP_3, DEFAULT_DOORBELL, 0, 32) /* GICv4.1 only */
60
+
27
+
61
/*
28
+STXP 1 . 001000 001 ..... . ..... ..... ..... @stxp # inc STLXP
62
* 12 bytes Interrupt translation Table Entry size
29
+LDXP 1 . 001000 011 ..... . ..... ..... ..... @stxp # inc LDAXP
63
* as per Table 5.3 in GICv3 spec
30
+
64
@@ -XXX,XX +XXX,XX @@ static inline void gicv3_add_its(GICv3State *s, DeviceState *its)
31
+# CASP, CASPA, CASPAL, CASPL (we don't decode the bits that determine
65
g_ptr_array_add(s->itslist, its);
32
+# acquire/release semantics because QEMU's cmpxchg always has those)
33
+CASP 0 . 001000 0 - 1 rs:5 - 11111 rn:5 rt:5 sz=%imm1_30_p2
34
+# CAS, CASA, CASAL, CASL
35
+CAS sz:2 001000 1 - 1 rs:5 - 11111 rn:5 rt:5
36
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
37
index XXXXXXX..XXXXXXX 100644
38
--- a/target/arm/tcg/translate-a64.c
39
+++ b/target/arm/tcg/translate-a64.c
40
@@ -XXX,XX +XXX,XX @@ static bool trans_LDAR(DisasContext *s, arg_stlr *a)
41
return true;
66
}
42
}
67
43
68
+/*
44
-/* Load/store exclusive
69
+ * The ITS can use this for operations that must be performed on
45
- *
70
+ * every ITS connected to the same GIC that it is
46
- * 31 30 29 24 23 22 21 20 16 15 14 10 9 5 4 0
71
+ */
47
- * +-----+-------------+----+---+----+------+----+-------+------+------+
72
+static inline void gicv3_foreach_its(GICv3State *s, GFunc func, void *opaque)
48
- * | sz | 0 0 1 0 0 0 | o2 | L | o1 | Rs | o0 | Rt2 | Rn | Rt |
73
+{
49
- * +-----+-------------+----+---+----+------+----+-------+------+------+
74
+ g_ptr_array_foreach(s->itslist, func, opaque);
50
- *
51
- * sz: 00 -> 8 bit, 01 -> 16 bit, 10 -> 32 bit, 11 -> 64 bit
52
- * L: 0 -> store, 1 -> load
53
- * o2: 0 -> exclusive, 1 -> not
54
- * o1: 0 -> single register, 1 -> register pair
55
- * o0: 1 -> load-acquire/store-release, 0 -> not
56
- */
57
-static void disas_ldst_excl(DisasContext *s, uint32_t insn)
58
+static bool trans_STXP(DisasContext *s, arg_stxr *a)
59
{
60
- int rt = extract32(insn, 0, 5);
61
- int rn = extract32(insn, 5, 5);
62
- int rt2 = extract32(insn, 10, 5);
63
- int rs = extract32(insn, 16, 5);
64
- int is_lasr = extract32(insn, 15, 1);
65
- int o2_L_o1_o0 = extract32(insn, 21, 3) * 2 | is_lasr;
66
- int size = extract32(insn, 30, 2);
67
-
68
- switch (o2_L_o1_o0) {
69
- case 0x2: case 0x3: /* CASP / STXP */
70
- if (size & 2) { /* STXP / STLXP */
71
- if (rn == 31) {
72
- gen_check_sp_alignment(s);
73
- }
74
- if (is_lasr) {
75
- tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
76
- }
77
- gen_store_exclusive(s, rs, rt, rt2, rn, size, true);
78
- return;
79
- }
80
- if (rt2 == 31
81
- && ((rt | rs) & 1) == 0
82
- && dc_isar_feature(aa64_atomics, s)) {
83
- /* CASP / CASPL */
84
- gen_compare_and_swap_pair(s, rs, rt, rn, size | 2);
85
- return;
86
- }
87
- break;
88
-
89
- case 0x6: case 0x7: /* CASPA / LDXP */
90
- if (size & 2) { /* LDXP / LDAXP */
91
- if (rn == 31) {
92
- gen_check_sp_alignment(s);
93
- }
94
- gen_load_exclusive(s, rt, rt2, rn, size, true);
95
- if (is_lasr) {
96
- tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ);
97
- }
98
- return;
99
- }
100
- if (rt2 == 31
101
- && ((rt | rs) & 1) == 0
102
- && dc_isar_feature(aa64_atomics, s)) {
103
- /* CASPA / CASPAL */
104
- gen_compare_and_swap_pair(s, rs, rt, rn, size | 2);
105
- return;
106
- }
107
- break;
108
-
109
- case 0xa: /* CAS */
110
- case 0xb: /* CASL */
111
- case 0xe: /* CASA */
112
- case 0xf: /* CASAL */
113
- if (rt2 == 31 && dc_isar_feature(aa64_atomics, s)) {
114
- gen_compare_and_swap(s, rs, rt, rn, size);
115
- return;
116
- }
117
- break;
118
- default:
119
- /* Handled in decodetree */
120
- break;
121
+ if (a->rn == 31) {
122
+ gen_check_sp_alignment(s);
123
}
124
- unallocated_encoding(s);
125
+ if (a->lasr) {
126
+ tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
127
+ }
128
+ gen_store_exclusive(s, a->rs, a->rt, a->rt2, a->rn, a->sz, true);
129
+ return true;
75
+}
130
+}
76
+
131
+
77
#endif /* QEMU_ARM_GICV3_INTERNAL_H */
132
+static bool trans_LDXP(DisasContext *s, arg_stxr *a)
78
diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
133
+{
79
index XXXXXXX..XXXXXXX 100644
134
+ if (a->rn == 31) {
80
--- a/hw/intc/arm_gicv3_its.c
135
+ gen_check_sp_alignment(s);
81
+++ b/hw/intc/arm_gicv3_its.c
136
+ }
82
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_vmapp(GICv3ITSState *s, const uint64_t *cmdpkt)
137
+ gen_load_exclusive(s, a->rt, a->rt2, a->rn, a->sz, true);
83
return update_vte(s, vpeid, &vte) ? CMD_CONTINUE_OK : CMD_STALL;
138
+ if (a->lasr) {
84
}
139
+ tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ);
85
140
+ }
86
+typedef struct VmovpCallbackData {
141
+ return true;
87
+ uint64_t rdbase;
142
+}
88
+ uint32_t vpeid;
89
+ /*
90
+ * Overall command result. If more than one callback finds an
91
+ * error, STALL beats CONTINUE.
92
+ */
93
+ ItsCmdResult result;
94
+} VmovpCallbackData;
95
+
143
+
96
+static void vmovp_callback(gpointer data, gpointer opaque)
144
+static bool trans_CASP(DisasContext *s, arg_CASP *a)
97
+{
145
+{
98
+ /*
146
+ if (!dc_isar_feature(aa64_atomics, s)) {
99
+ * This function is called to update the VPEID field in a VPE
147
+ return false;
100
+ * table entry for this ITS. This might be because of a VMOVP
148
+ }
101
+ * command executed on any ITS that is connected to the same GIC
149
+ if (((a->rt | a->rs) & 1) != 0) {
102
+ * as this ITS. We need to read the VPE table entry for the VPEID
150
+ return false;
103
+ * and update its RDBASE field.
104
+ */
105
+ GICv3ITSState *s = data;
106
+ VmovpCallbackData *cbdata = opaque;
107
+ VTEntry vte;
108
+ ItsCmdResult cmdres;
109
+
110
+ cmdres = lookup_vte(s, __func__, cbdata->vpeid, &vte);
111
+ switch (cmdres) {
112
+ case CMD_STALL:
113
+ cbdata->result = CMD_STALL;
114
+ return;
115
+ case CMD_CONTINUE:
116
+ if (cbdata->result != CMD_STALL) {
117
+ cbdata->result = CMD_CONTINUE;
118
+ }
119
+ return;
120
+ case CMD_CONTINUE_OK:
121
+ break;
122
+ }
151
+ }
123
+
152
+
124
+ vte.rdbase = cbdata->rdbase;
153
+ gen_compare_and_swap_pair(s, a->rs, a->rt, a->rn, a->sz);
125
+ if (!update_vte(s, cbdata->vpeid, &vte)) {
154
+ return true;
126
+ cbdata->result = CMD_STALL;
127
+ }
128
+}
155
+}
129
+
156
+
130
+static ItsCmdResult process_vmovp(GICv3ITSState *s, const uint64_t *cmdpkt)
157
+static bool trans_CAS(DisasContext *s, arg_CAS *a)
131
+{
158
+{
132
+ VmovpCallbackData cbdata;
159
+ if (!dc_isar_feature(aa64_atomics, s)) {
133
+
160
+ return false;
134
+ if (!its_feature_virtual(s)) {
135
+ return CMD_CONTINUE;
136
+ }
161
+ }
137
+
162
+ gen_compare_and_swap(s, a->rs, a->rt, a->rn, a->sz);
138
+ cbdata.vpeid = FIELD_EX64(cmdpkt[1], VMOVP_1, VPEID);
163
+ return true;
139
+ cbdata.rdbase = FIELD_EX64(cmdpkt[2], VMOVP_2, RDBASE);
164
}
140
+
165
141
+ trace_gicv3_its_cmd_vmovp(cbdata.vpeid, cbdata.rdbase);
142
+
143
+ if (cbdata.rdbase >= s->gicv3->num_cpu) {
144
+ return CMD_CONTINUE;
145
+ }
146
+
147
+ /*
148
+ * Our ITS implementation reports GITS_TYPER.VMOVP == 1, which means
149
+ * that when the VMOVP command is executed on an ITS to change the
150
+ * VPEID field in a VPE table entry the change must be propagated
151
+ * to all the ITSes connected to the same GIC.
152
+ */
153
+ cbdata.result = CMD_CONTINUE_OK;
154
+ gicv3_foreach_its(s->gicv3, vmovp_callback, &cbdata);
155
+ return cbdata.result;
156
+}
157
+
158
/*
166
/*
159
* Current implementation blocks until all
167
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_tag(DisasContext *s, uint32_t insn)
160
* commands are processed
168
static void disas_ldst(DisasContext *s, uint32_t insn)
161
@@ -XXX,XX +XXX,XX @@ static void process_cmdq(GICv3ITSState *s)
169
{
162
case GITS_CMD_VMAPP:
170
switch (extract32(insn, 24, 6)) {
163
result = process_vmapp(s, cmdpkt);
171
- case 0x08: /* Load/store exclusive */
164
break;
172
- disas_ldst_excl(s, insn);
165
+ case GITS_CMD_VMOVP:
173
- break;
166
+ result = process_vmovp(s, cmdpkt);
174
case 0x18: case 0x1c: /* Load register (literal) */
167
+ break;
175
disas_ld_lit(s, insn);
168
default:
176
break;
169
trace_gicv3_its_cmd_unknown(cmd);
170
break;
171
diff --git a/hw/intc/trace-events b/hw/intc/trace-events
172
index XXXXXXX..XXXXXXX 100644
173
--- a/hw/intc/trace-events
174
+++ b/hw/intc/trace-events
175
@@ -XXX,XX +XXX,XX @@ gicv3_its_cmd_movi(uint32_t devid, uint32_t eventid, uint32_t icid) "GICv3 ITS:
176
gicv3_its_cmd_vmapi(uint32_t devid, uint32_t eventid, uint32_t vpeid, uint32_t doorbell) "GICv3 ITS: command VMAPI DeviceID 0x%x EventID 0x%x vPEID 0x%x Dbell_pINTID 0x%x"
177
gicv3_its_cmd_vmapti(uint32_t devid, uint32_t eventid, uint32_t vpeid, uint32_t vintid, uint32_t doorbell) "GICv3 ITS: command VMAPI DeviceID 0x%x EventID 0x%x vPEID 0x%x vINTID 0x%x Dbell_pINTID 0x%x"
178
gicv3_its_cmd_vmapp(uint32_t vpeid, uint64_t rdbase, int valid, uint64_t vptaddr, uint32_t vptsize) "GICv3 ITS: command VMAPP vPEID 0x%x RDbase 0x%" PRIx64 " V %d VPT_addr 0x%" PRIx64 " VPT_size 0x%x"
179
+gicv3_its_cmd_vmovp(uint32_t vpeid, uint64_t rdbase) "GICv3 ITS: command VMOVP vPEID 0x%x RDbase 0x%" PRIx64
180
gicv3_its_cmd_unknown(unsigned cmd) "GICv3 ITS: unknown command 0x%x"
181
gicv3_its_cte_read(uint32_t icid, int valid, uint32_t rdbase) "GICv3 ITS: Collection Table read for ICID 0x%x: valid %d RDBase 0x%x"
182
gicv3_its_cte_write(uint32_t icid, int valid, uint32_t rdbase) "GICv3 ITS: Collection Table write for ICID 0x%x: valid %d RDBase 0x%x"
183
--
177
--
184
2.25.1
178
2.34.1
diff view generated by jsdifflib
1
Factor out the sequence of looking up a CTE from an ICID including
1
Convert the "Load register (literal)" instruction class to
2
the validity and error checks.
2
decodetree.
3
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20220408141550.1271295-13-peter.maydell@linaro.org
6
Message-id: 20230602155223.2040685-11-peter.maydell@linaro.org
7
---
7
---
8
hw/intc/arm_gicv3_its.c | 109 ++++++++++++++--------------------------
8
target/arm/tcg/a64.decode | 13 ++++++
9
1 file changed, 39 insertions(+), 70 deletions(-)
9
target/arm/tcg/translate-a64.c | 76 ++++++++++------------------------
10
2 files changed, 35 insertions(+), 54 deletions(-)
10
11
11
diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
12
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
12
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
13
--- a/hw/intc/arm_gicv3_its.c
14
--- a/target/arm/tcg/a64.decode
14
+++ b/hw/intc/arm_gicv3_its.c
15
+++ b/target/arm/tcg/a64.decode
15
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult lookup_ite(GICv3ITSState *s, const char *who,
16
@@ -XXX,XX +XXX,XX @@ LDXP 1 . 001000 011 ..... . ..... ..... ..... @stxp # inc LDAXP
16
return CMD_CONTINUE_OK;
17
CASP 0 . 001000 0 - 1 rs:5 - 11111 rn:5 rt:5 sz=%imm1_30_p2
18
# CAS, CASA, CASAL, CASL
19
CAS sz:2 001000 1 - 1 rs:5 - 11111 rn:5 rt:5
20
+
21
+&ldlit rt imm sz sign
22
+@ldlit .. ... . .. ................... rt:5 &ldlit imm=%imm19
23
+
24
+LD_lit 00 011 0 00 ................... ..... @ldlit sz=2 sign=0
25
+LD_lit 01 011 0 00 ................... ..... @ldlit sz=3 sign=0
26
+LD_lit 10 011 0 00 ................... ..... @ldlit sz=2 sign=1
27
+LD_lit_v 00 011 1 00 ................... ..... @ldlit sz=2 sign=0
28
+LD_lit_v 01 011 1 00 ................... ..... @ldlit sz=3 sign=0
29
+LD_lit_v 10 011 1 00 ................... ..... @ldlit sz=4 sign=0
30
+
31
+# PRFM
32
+NOP 11 011 0 00 ------------------- -----
33
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
34
index XXXXXXX..XXXXXXX 100644
35
--- a/target/arm/tcg/translate-a64.c
36
+++ b/target/arm/tcg/translate-a64.c
37
@@ -XXX,XX +XXX,XX @@ static bool trans_CAS(DisasContext *s, arg_CAS *a)
38
return true;
17
}
39
}
18
40
19
+/*
41
-/*
20
+ * Given an ICID, look up the corresponding CTE, including checking for various
42
- * Load register (literal)
21
+ * invalid-value cases. If we find a valid CTE, fill in @cte and return
43
- *
22
+ * CMD_CONTINUE_OK; otherwise return CMD_STALL or CMD_CONTINUE (and the
44
- * 31 30 29 27 26 25 24 23 5 4 0
23
+ * contents of @cte should not be relied on).
45
- * +-----+-------+---+-----+-------------------+-------+
24
+ *
46
- * | opc | 0 1 1 | V | 0 0 | imm19 | Rt |
25
+ * The string @who is purely for the LOG_GUEST_ERROR messages,
47
- * +-----+-------+---+-----+-------------------+-------+
26
+ * and should indicate the name of the calling function or similar.
48
- *
27
+ */
49
- * V: 1 -> vector (simd/fp)
28
+static ItsCmdResult lookup_cte(GICv3ITSState *s, const char *who,
50
- * opc (non-vector): 00 -> 32 bit, 01 -> 64 bit,
29
+ uint32_t icid, CTEntry *cte)
51
- * 10-> 32 bit signed, 11 -> prefetch
30
+{
52
- * opc (vector): 00 -> 32 bit, 01 -> 64 bit, 10 -> 128 bit (11 unallocated)
31
+ if (icid >= s->ct.num_entries) {
53
- */
32
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid ICID 0x%x\n", who, icid);
54
-static void disas_ld_lit(DisasContext *s, uint32_t insn)
33
+ return CMD_CONTINUE;
55
+static bool trans_LD_lit(DisasContext *s, arg_ldlit *a)
34
+ }
56
{
35
+ if (get_cte(s, icid, cte) != MEMTX_OK) {
57
- int rt = extract32(insn, 0, 5);
36
+ return CMD_STALL;
58
- int64_t imm = sextract32(insn, 5, 19) << 2;
37
+ }
59
- bool is_vector = extract32(insn, 26, 1);
38
+ if (!cte->valid) {
60
- int opc = extract32(insn, 30, 2);
39
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid CTE\n", who);
61
- bool is_signed = false;
40
+ return CMD_CONTINUE;
62
- int size = 2;
41
+ }
63
- TCGv_i64 tcg_rt, clean_addr;
42
+ if (cte->rdbase >= s->gicv3->num_cpu) {
64
+ bool iss_sf = ldst_iss_sf(a->sz, a->sign, false);
43
+ return CMD_CONTINUE;
65
+ TCGv_i64 tcg_rt = cpu_reg(s, a->rt);
44
+ }
66
+ TCGv_i64 clean_addr = tcg_temp_new_i64();
45
+ return CMD_CONTINUE_OK;
67
+ MemOp memop = finalize_memop(s, a->sz + a->sign * MO_SIGN);
68
+
69
+ gen_pc_plus_diff(s, clean_addr, a->imm);
70
+ do_gpr_ld(s, tcg_rt, clean_addr, memop,
71
+ false, true, a->rt, iss_sf, false);
72
+ return true;
46
+}
73
+}
47
+
74
+
48
+
75
+static bool trans_LD_lit_v(DisasContext *s, arg_ldlit *a)
49
/*
76
+{
50
* This function handles the processing of following commands based on
77
+ /* Load register (literal), vector version */
51
* the ItsCmdType parameter passed:-
78
+ TCGv_i64 clean_addr;
52
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult do_process_its_cmd(GICv3ITSState *s, uint32_t devid,
79
MemOp memop;
53
return CMD_CONTINUE;
80
54
}
81
- if (is_vector) {
55
82
- if (opc == 3) {
56
- if (ite.icid >= s->ct.num_entries) {
83
- unallocated_encoding(s);
57
- qemu_log_mask(LOG_GUEST_ERROR,
84
- return;
58
- "%s: invalid ICID 0x%x in ITE (table corrupted?)\n",
85
- }
59
- __func__, ite.icid);
86
- size = 2 + opc;
60
- return CMD_CONTINUE;
87
- if (!fp_access_check(s)) {
61
- }
88
- return;
62
-
89
- }
63
- if (get_cte(s, ite.icid, &cte) != MEMTX_OK) {
90
- memop = finalize_memop_asimd(s, size);
64
- return CMD_STALL;
91
- } else {
65
- }
92
- if (opc == 3) {
66
- if (!cte.valid) {
93
- /* PRFM (literal) : prefetch */
67
- qemu_log_mask(LOG_GUEST_ERROR,
94
- return;
68
- "%s: invalid command attributes: invalid CTE\n",
95
- }
69
- __func__);
96
- size = 2 + extract32(opc, 0, 1);
70
- return CMD_CONTINUE;
97
- is_signed = extract32(opc, 1, 1);
71
- }
98
- memop = finalize_memop(s, size + is_signed * MO_SIGN);
72
-
99
+ if (!fp_access_check(s)) {
73
- /*
100
+ return true;
74
- * Current implementation only supports rdbase == procnum
75
- * Hence rdbase physical address is ignored
76
- */
77
- if (cte.rdbase >= s->gicv3->num_cpu) {
78
- return CMD_CONTINUE;
79
+ cmdres = lookup_cte(s, __func__, ite.icid, &cte);
80
+ if (cmdres != CMD_CONTINUE_OK) {
81
+ return cmdres;
82
}
83
84
if ((cmd == CLEAR) || (cmd == DISCARD)) {
85
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_movi(GICv3ITSState *s, const uint64_t *cmdpkt)
86
return CMD_CONTINUE;
87
}
88
89
- if (old_ite.icid >= s->ct.num_entries) {
90
- qemu_log_mask(LOG_GUEST_ERROR,
91
- "%s: invalid ICID 0x%x in ITE (table corrupted?)\n",
92
- __func__, old_ite.icid);
93
- return CMD_CONTINUE;
94
+ cmdres = lookup_cte(s, __func__, old_ite.icid, &old_cte);
95
+ if (cmdres != CMD_CONTINUE_OK) {
96
+ return cmdres;
97
}
101
}
98
-
102
-
99
- if (new_icid >= s->ct.num_entries) {
103
- tcg_rt = cpu_reg(s, rt);
100
- qemu_log_mask(LOG_GUEST_ERROR,
104
-
101
- "%s: invalid command attributes: ICID 0x%x\n",
105
+ memop = finalize_memop_asimd(s, a->sz);
102
- __func__, new_icid);
106
clean_addr = tcg_temp_new_i64();
103
- return CMD_CONTINUE;
107
- gen_pc_plus_diff(s, clean_addr, imm);
108
-
109
- if (is_vector) {
110
- do_fp_ld(s, rt, clean_addr, memop);
111
- } else {
112
- /* Only unsigned 32bit loads target 32bit registers. */
113
- bool iss_sf = opc != 0;
114
- do_gpr_ld(s, tcg_rt, clean_addr, memop, false, true, rt, iss_sf, false);
104
- }
115
- }
105
-
116
+ gen_pc_plus_diff(s, clean_addr, a->imm);
106
- if (get_cte(s, old_ite.icid, &old_cte) != MEMTX_OK) {
117
+ do_fp_ld(s, a->rt, clean_addr, memop);
107
- return CMD_STALL;
118
+ return true;
108
- }
119
}
109
- if (!old_cte.valid) {
120
110
- qemu_log_mask(LOG_GUEST_ERROR,
121
/*
111
- "%s: invalid command attributes: "
122
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_tag(DisasContext *s, uint32_t insn)
112
- "invalid CTE for old ICID 0x%x\n",
123
static void disas_ldst(DisasContext *s, uint32_t insn)
113
- __func__, old_ite.icid);
124
{
114
- return CMD_CONTINUE;
125
switch (extract32(insn, 24, 6)) {
115
- }
126
- case 0x18: case 0x1c: /* Load register (literal) */
116
-
127
- disas_ld_lit(s, insn);
117
- if (get_cte(s, new_icid, &new_cte) != MEMTX_OK) {
128
- break;
118
- return CMD_STALL;
129
case 0x28: case 0x29:
119
- }
130
case 0x2c: case 0x2d: /* Load/store pair (all forms) */
120
- if (!new_cte.valid) {
131
disas_ldst_pair(s, insn);
121
- qemu_log_mask(LOG_GUEST_ERROR,
122
- "%s: invalid command attributes: "
123
- "invalid CTE for new ICID 0x%x\n",
124
- __func__, new_icid);
125
- return CMD_CONTINUE;
126
- }
127
-
128
- if (old_cte.rdbase >= s->gicv3->num_cpu) {
129
- qemu_log_mask(LOG_GUEST_ERROR,
130
- "%s: CTE has invalid rdbase 0x%x\n",
131
- __func__, old_cte.rdbase);
132
- return CMD_CONTINUE;
133
- }
134
-
135
- if (new_cte.rdbase >= s->gicv3->num_cpu) {
136
- qemu_log_mask(LOG_GUEST_ERROR,
137
- "%s: CTE has invalid rdbase 0x%x\n",
138
- __func__, new_cte.rdbase);
139
- return CMD_CONTINUE;
140
+ cmdres = lookup_cte(s, __func__, new_icid, &new_cte);
141
+ if (cmdres != CMD_CONTINUE_OK) {
142
+ return cmdres;
143
}
144
145
if (old_cte.rdbase != new_cte.rdbase) {
146
--
132
--
147
2.25.1
133
2.34.1
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
Convert the load/store register pair insns (LDP, STP,
2
LDNP, STNP, LDPSW, STGP) to decodetree.
2
3
3
For aa32, the function has a parameter to use the new el.
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
For aa64, that never happens.
5
Message-id: 20230602155223.2040685-12-peter.maydell@linaro.org
5
Use tcg_constant_i32 while we're at it.
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
---
8
target/arm/tcg/a64.decode | 61 +++++
9
target/arm/tcg/translate-a64.c | 422 ++++++++++++++++-----------------
10
2 files changed, 268 insertions(+), 215 deletions(-)
6
11
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
12
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
target/arm/translate-a64.c | 21 +++++++++-----------
12
target/arm/translate.c | 40 +++++++++++++++++++++++---------------
13
2 files changed, 33 insertions(+), 28 deletions(-)
14
15
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
16
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/translate-a64.c
14
--- a/target/arm/tcg/a64.decode
18
+++ b/target/arm/translate-a64.c
15
+++ b/target/arm/tcg/a64.decode
19
@@ -XXX,XX +XXX,XX @@ static void a64_free_cc(DisasCompare64 *c64)
16
@@ -XXX,XX +XXX,XX @@ LD_lit_v 10 011 1 00 ................... ..... @ldlit sz=4 sign=0
20
tcg_temp_free_i64(c64->value);
17
18
# PRFM
19
NOP 11 011 0 00 ------------------- -----
20
+
21
+&ldstpair rt2 rt rn imm sz sign w p
22
+@ldstpair .. ... . ... . imm:s7 rt2:5 rn:5 rt:5 &ldstpair
23
+
24
+# STNP, LDNP: Signed offset, non-temporal hint. We don't emulate caches
25
+# so we ignore hints about data access patterns, and handle these like
26
+# plain signed offset.
27
+STP 00 101 0 000 0 ....... ..... ..... ..... @ldstpair sz=2 sign=0 p=0 w=0
28
+LDP 00 101 0 000 1 ....... ..... ..... ..... @ldstpair sz=2 sign=0 p=0 w=0
29
+STP 10 101 0 000 0 ....... ..... ..... ..... @ldstpair sz=3 sign=0 p=0 w=0
30
+LDP 10 101 0 000 1 ....... ..... ..... ..... @ldstpair sz=3 sign=0 p=0 w=0
31
+STP_v 00 101 1 000 0 ....... ..... ..... ..... @ldstpair sz=2 sign=0 p=0 w=0
32
+LDP_v 00 101 1 000 1 ....... ..... ..... ..... @ldstpair sz=2 sign=0 p=0 w=0
33
+STP_v 01 101 1 000 0 ....... ..... ..... ..... @ldstpair sz=3 sign=0 p=0 w=0
34
+LDP_v 01 101 1 000 1 ....... ..... ..... ..... @ldstpair sz=3 sign=0 p=0 w=0
35
+STP_v 10 101 1 000 0 ....... ..... ..... ..... @ldstpair sz=4 sign=0 p=0 w=0
36
+LDP_v 10 101 1 000 1 ....... ..... ..... ..... @ldstpair sz=4 sign=0 p=0 w=0
37
+
38
+# STP and LDP: post-indexed
39
+STP 00 101 0 001 0 ....... ..... ..... ..... @ldstpair sz=2 sign=0 p=1 w=1
40
+LDP 00 101 0 001 1 ....... ..... ..... ..... @ldstpair sz=2 sign=0 p=1 w=1
41
+LDP 01 101 0 001 1 ....... ..... ..... ..... @ldstpair sz=2 sign=1 p=1 w=1
42
+STP 10 101 0 001 0 ....... ..... ..... ..... @ldstpair sz=3 sign=0 p=1 w=1
43
+LDP 10 101 0 001 1 ....... ..... ..... ..... @ldstpair sz=3 sign=0 p=1 w=1
44
+STP_v 00 101 1 001 0 ....... ..... ..... ..... @ldstpair sz=2 sign=0 p=1 w=1
45
+LDP_v 00 101 1 001 1 ....... ..... ..... ..... @ldstpair sz=2 sign=0 p=1 w=1
46
+STP_v 01 101 1 001 0 ....... ..... ..... ..... @ldstpair sz=3 sign=0 p=1 w=1
47
+LDP_v 01 101 1 001 1 ....... ..... ..... ..... @ldstpair sz=3 sign=0 p=1 w=1
48
+STP_v 10 101 1 001 0 ....... ..... ..... ..... @ldstpair sz=4 sign=0 p=1 w=1
49
+LDP_v 10 101 1 001 1 ....... ..... ..... ..... @ldstpair sz=4 sign=0 p=1 w=1
50
+
51
+# STP and LDP: offset
52
+STP 00 101 0 010 0 ....... ..... ..... ..... @ldstpair sz=2 sign=0 p=0 w=0
53
+LDP 00 101 0 010 1 ....... ..... ..... ..... @ldstpair sz=2 sign=0 p=0 w=0
54
+LDP 01 101 0 010 1 ....... ..... ..... ..... @ldstpair sz=2 sign=1 p=0 w=0
55
+STP 10 101 0 010 0 ....... ..... ..... ..... @ldstpair sz=3 sign=0 p=0 w=0
56
+LDP 10 101 0 010 1 ....... ..... ..... ..... @ldstpair sz=3 sign=0 p=0 w=0
57
+STP_v 00 101 1 010 0 ....... ..... ..... ..... @ldstpair sz=2 sign=0 p=0 w=0
58
+LDP_v 00 101 1 010 1 ....... ..... ..... ..... @ldstpair sz=2 sign=0 p=0 w=0
59
+STP_v 01 101 1 010 0 ....... ..... ..... ..... @ldstpair sz=3 sign=0 p=0 w=0
60
+LDP_v 01 101 1 010 1 ....... ..... ..... ..... @ldstpair sz=3 sign=0 p=0 w=0
61
+STP_v 10 101 1 010 0 ....... ..... ..... ..... @ldstpair sz=4 sign=0 p=0 w=0
62
+LDP_v 10 101 1 010 1 ....... ..... ..... ..... @ldstpair sz=4 sign=0 p=0 w=0
63
+
64
+# STP and LDP: pre-indexed
65
+STP 00 101 0 011 0 ....... ..... ..... ..... @ldstpair sz=2 sign=0 p=0 w=1
66
+LDP 00 101 0 011 1 ....... ..... ..... ..... @ldstpair sz=2 sign=0 p=0 w=1
67
+LDP 01 101 0 011 1 ....... ..... ..... ..... @ldstpair sz=2 sign=1 p=0 w=1
68
+STP 10 101 0 011 0 ....... ..... ..... ..... @ldstpair sz=3 sign=0 p=0 w=1
69
+LDP 10 101 0 011 1 ....... ..... ..... ..... @ldstpair sz=3 sign=0 p=0 w=1
70
+STP_v 00 101 1 011 0 ....... ..... ..... ..... @ldstpair sz=2 sign=0 p=0 w=1
71
+LDP_v 00 101 1 011 1 ....... ..... ..... ..... @ldstpair sz=2 sign=0 p=0 w=1
72
+STP_v 01 101 1 011 0 ....... ..... ..... ..... @ldstpair sz=3 sign=0 p=0 w=1
73
+LDP_v 01 101 1 011 1 ....... ..... ..... ..... @ldstpair sz=3 sign=0 p=0 w=1
74
+STP_v 10 101 1 011 0 ....... ..... ..... ..... @ldstpair sz=4 sign=0 p=0 w=1
75
+LDP_v 10 101 1 011 1 ....... ..... ..... ..... @ldstpair sz=4 sign=0 p=0 w=1
76
+
77
+# STGP: store tag and pair
78
+STGP 01 101 0 001 0 ....... ..... ..... ..... @ldstpair sz=3 sign=0 p=1 w=1
79
+STGP 01 101 0 010 0 ....... ..... ..... ..... @ldstpair sz=3 sign=0 p=0 w=0
80
+STGP 01 101 0 011 0 ....... ..... ..... ..... @ldstpair sz=3 sign=0 p=0 w=1
81
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
82
index XXXXXXX..XXXXXXX 100644
83
--- a/target/arm/tcg/translate-a64.c
84
+++ b/target/arm/tcg/translate-a64.c
85
@@ -XXX,XX +XXX,XX @@ static bool trans_LD_lit_v(DisasContext *s, arg_ldlit *a)
86
return true;
21
}
87
}
22
88
23
+static void gen_rebuild_hflags(DisasContext *s)
89
-/*
90
- * LDNP (Load Pair - non-temporal hint)
91
- * LDP (Load Pair - non vector)
92
- * LDPSW (Load Pair Signed Word - non vector)
93
- * STNP (Store Pair - non-temporal hint)
94
- * STP (Store Pair - non vector)
95
- * LDNP (Load Pair of SIMD&FP - non-temporal hint)
96
- * LDP (Load Pair of SIMD&FP)
97
- * STNP (Store Pair of SIMD&FP - non-temporal hint)
98
- * STP (Store Pair of SIMD&FP)
99
- *
100
- * 31 30 29 27 26 25 24 23 22 21 15 14 10 9 5 4 0
101
- * +-----+-------+---+---+-------+---+-----------------------------+
102
- * | opc | 1 0 1 | V | 0 | index | L | imm7 | Rt2 | Rn | Rt |
103
- * +-----+-------+---+---+-------+---+-------+-------+------+------+
104
- *
105
- * opc: LDP/STP/LDNP/STNP 00 -> 32 bit, 10 -> 64 bit
106
- * LDPSW/STGP 01
107
- * LDP/STP/LDNP/STNP (SIMD) 00 -> 32 bit, 01 -> 64 bit, 10 -> 128 bit
108
- * V: 0 -> GPR, 1 -> Vector
109
- * idx: 00 -> signed offset with non-temporal hint, 01 -> post-index,
110
- * 10 -> signed offset, 11 -> pre-index
111
- * L: 0 -> Store 1 -> Load
112
- *
113
- * Rt, Rt2 = GPR or SIMD registers to be stored
114
- * Rn = general purpose register containing address
115
- * imm7 = signed offset (multiple of 4 or 8 depending on size)
116
- */
117
-static void disas_ldst_pair(DisasContext *s, uint32_t insn)
118
+static void op_addr_ldstpair_pre(DisasContext *s, arg_ldstpair *a,
119
+ TCGv_i64 *clean_addr, TCGv_i64 *dirty_addr,
120
+ uint64_t offset, bool is_store, MemOp mop)
121
{
122
- int rt = extract32(insn, 0, 5);
123
- int rn = extract32(insn, 5, 5);
124
- int rt2 = extract32(insn, 10, 5);
125
- uint64_t offset = sextract64(insn, 15, 7);
126
- int index = extract32(insn, 23, 2);
127
- bool is_vector = extract32(insn, 26, 1);
128
- bool is_load = extract32(insn, 22, 1);
129
- int opc = extract32(insn, 30, 2);
130
- bool is_signed = false;
131
- bool postindex = false;
132
- bool wback = false;
133
- bool set_tag = false;
134
- TCGv_i64 clean_addr, dirty_addr;
135
- MemOp mop;
136
- int size;
137
-
138
- if (opc == 3) {
139
- unallocated_encoding(s);
140
- return;
141
- }
142
-
143
- if (is_vector) {
144
- size = 2 + opc;
145
- } else if (opc == 1 && !is_load) {
146
- /* STGP */
147
- if (!dc_isar_feature(aa64_mte_insn_reg, s) || index == 0) {
148
- unallocated_encoding(s);
149
- return;
150
- }
151
- size = 3;
152
- set_tag = true;
153
- } else {
154
- size = 2 + extract32(opc, 1, 1);
155
- is_signed = extract32(opc, 0, 1);
156
- if (!is_load && is_signed) {
157
- unallocated_encoding(s);
158
- return;
159
- }
160
- }
161
-
162
- switch (index) {
163
- case 1: /* post-index */
164
- postindex = true;
165
- wback = true;
166
- break;
167
- case 0:
168
- /* signed offset with "non-temporal" hint. Since we don't emulate
169
- * caches we don't care about hints to the cache system about
170
- * data access patterns, and handle this identically to plain
171
- * signed offset.
172
- */
173
- if (is_signed) {
174
- /* There is no non-temporal-hint version of LDPSW */
175
- unallocated_encoding(s);
176
- return;
177
- }
178
- postindex = false;
179
- break;
180
- case 2: /* signed offset, rn not updated */
181
- postindex = false;
182
- break;
183
- case 3: /* pre-index */
184
- postindex = false;
185
- wback = true;
186
- break;
187
- }
188
-
189
- if (is_vector && !fp_access_check(s)) {
190
- return;
191
- }
192
-
193
- offset <<= (set_tag ? LOG2_TAG_GRANULE : size);
194
-
195
- if (rn == 31) {
196
+ if (a->rn == 31) {
197
gen_check_sp_alignment(s);
198
}
199
200
- dirty_addr = read_cpu_reg_sp(s, rn, 1);
201
- if (!postindex) {
202
+ *dirty_addr = read_cpu_reg_sp(s, a->rn, 1);
203
+ if (!a->p) {
204
+ tcg_gen_addi_i64(*dirty_addr, *dirty_addr, offset);
205
+ }
206
+
207
+ *clean_addr = gen_mte_checkN(s, *dirty_addr, is_store,
208
+ (a->w || a->rn != 31), 2 << a->sz, mop);
209
+}
210
+
211
+static void op_addr_ldstpair_post(DisasContext *s, arg_ldstpair *a,
212
+ TCGv_i64 dirty_addr, uint64_t offset)
24
+{
213
+{
25
+ gen_helper_rebuild_hflags_a64(cpu_env, tcg_constant_i32(s->current_el));
214
+ if (a->w) {
215
+ if (a->p) {
216
+ tcg_gen_addi_i64(dirty_addr, dirty_addr, offset);
217
+ }
218
+ tcg_gen_mov_i64(cpu_reg_sp(s, a->rn), dirty_addr);
219
+ }
26
+}
220
+}
27
+
221
+
28
static void gen_exception_internal(int excp)
222
+static bool trans_STP(DisasContext *s, arg_ldstpair *a)
29
{
30
TCGv_i32 tcg_excp = tcg_const_i32(excp);
31
@@ -XXX,XX +XXX,XX @@ static void handle_msr_i(DisasContext *s, uint32_t insn,
32
} else {
33
clear_pstate_bits(PSTATE_UAO);
34
}
35
- t1 = tcg_const_i32(s->current_el);
36
- gen_helper_rebuild_hflags_a64(cpu_env, t1);
37
- tcg_temp_free_i32(t1);
38
+ gen_rebuild_hflags(s);
39
break;
40
41
case 0x04: /* PAN */
42
@@ -XXX,XX +XXX,XX @@ static void handle_msr_i(DisasContext *s, uint32_t insn,
43
} else {
44
clear_pstate_bits(PSTATE_PAN);
45
}
46
- t1 = tcg_const_i32(s->current_el);
47
- gen_helper_rebuild_hflags_a64(cpu_env, t1);
48
- tcg_temp_free_i32(t1);
49
+ gen_rebuild_hflags(s);
50
break;
51
52
case 0x05: /* SPSel */
53
@@ -XXX,XX +XXX,XX @@ static void handle_msr_i(DisasContext *s, uint32_t insn,
54
} else {
55
clear_pstate_bits(PSTATE_TCO);
56
}
57
- t1 = tcg_const_i32(s->current_el);
58
- gen_helper_rebuild_hflags_a64(cpu_env, t1);
59
- tcg_temp_free_i32(t1);
60
+ gen_rebuild_hflags(s);
61
/* Many factors, including TCO, go into MTE_ACTIVE. */
62
s->base.is_jmp = DISAS_UPDATE_NOCHAIN;
63
} else if (dc_isar_feature(aa64_mte_insn_reg, s)) {
64
@@ -XXX,XX +XXX,XX @@ static void handle_sys(DisasContext *s, uint32_t insn, bool isread,
65
* A write to any coprocessor regiser that ends a TB
66
* must rebuild the hflags for the next TB.
67
*/
68
- TCGv_i32 tcg_el = tcg_const_i32(s->current_el);
69
- gen_helper_rebuild_hflags_a64(cpu_env, tcg_el);
70
- tcg_temp_free_i32(tcg_el);
71
+ gen_rebuild_hflags(s);
72
/*
73
* We default to ending the TB on a coprocessor register write,
74
* but allow this to be suppressed by the register definition
75
diff --git a/target/arm/translate.c b/target/arm/translate.c
76
index XXXXXXX..XXXXXXX 100644
77
--- a/target/arm/translate.c
78
+++ b/target/arm/translate.c
79
@@ -XXX,XX +XXX,XX @@ void gen_set_cpsr(TCGv_i32 var, uint32_t mask)
80
tcg_temp_free_i32(tmp_mask);
81
}
82
83
+static void gen_rebuild_hflags(DisasContext *s, bool new_el)
84
+{
223
+{
85
+ bool m_profile = arm_dc_feature(s, ARM_FEATURE_M);
224
+ uint64_t offset = a->imm << a->sz;
86
+
225
+ TCGv_i64 clean_addr, dirty_addr, tcg_rt, tcg_rt2;
87
+ if (new_el) {
226
+ MemOp mop = finalize_memop(s, a->sz);
88
+ if (m_profile) {
227
+
89
+ gen_helper_rebuild_hflags_m32_newel(cpu_env);
228
+ op_addr_ldstpair_pre(s, a, &clean_addr, &dirty_addr, offset, true, mop);
229
+ tcg_rt = cpu_reg(s, a->rt);
230
+ tcg_rt2 = cpu_reg(s, a->rt2);
231
+ /*
232
+ * We built mop above for the single logical access -- rebuild it
233
+ * now for the paired operation.
234
+ *
235
+ * With LSE2, non-sign-extending pairs are treated atomically if
236
+ * aligned, and if unaligned one of the pair will be completely
237
+ * within a 16-byte block and that element will be atomic.
238
+ * Otherwise each element is separately atomic.
239
+ * In all cases, issue one operation with the correct atomicity.
240
+ */
241
+ mop = a->sz + 1;
242
+ if (s->align_mem) {
243
+ mop |= (a->sz == 2 ? MO_ALIGN_4 : MO_ALIGN_8);
244
+ }
245
+ mop = finalize_memop_pair(s, mop);
246
+ if (a->sz == 2) {
247
+ TCGv_i64 tmp = tcg_temp_new_i64();
248
+
249
+ if (s->be_data == MO_LE) {
250
+ tcg_gen_concat32_i64(tmp, tcg_rt, tcg_rt2);
90
+ } else {
251
+ } else {
91
+ gen_helper_rebuild_hflags_a32_newel(cpu_env);
252
+ tcg_gen_concat32_i64(tmp, tcg_rt2, tcg_rt);
253
+ }
254
+ tcg_gen_qemu_st_i64(tmp, clean_addr, get_mem_index(s), mop);
255
+ } else {
256
+ TCGv_i128 tmp = tcg_temp_new_i128();
257
+
258
+ if (s->be_data == MO_LE) {
259
+ tcg_gen_concat_i64_i128(tmp, tcg_rt, tcg_rt2);
260
+ } else {
261
+ tcg_gen_concat_i64_i128(tmp, tcg_rt2, tcg_rt);
262
+ }
263
+ tcg_gen_qemu_st_i128(tmp, clean_addr, get_mem_index(s), mop);
264
+ }
265
+ op_addr_ldstpair_post(s, a, dirty_addr, offset);
266
+ return true;
267
+}
268
+
269
+static bool trans_LDP(DisasContext *s, arg_ldstpair *a)
270
+{
271
+ uint64_t offset = a->imm << a->sz;
272
+ TCGv_i64 clean_addr, dirty_addr, tcg_rt, tcg_rt2;
273
+ MemOp mop = finalize_memop(s, a->sz);
274
+
275
+ op_addr_ldstpair_pre(s, a, &clean_addr, &dirty_addr, offset, false, mop);
276
+ tcg_rt = cpu_reg(s, a->rt);
277
+ tcg_rt2 = cpu_reg(s, a->rt2);
278
+
279
+ /*
280
+ * We built mop above for the single logical access -- rebuild it
281
+ * now for the paired operation.
282
+ *
283
+ * With LSE2, non-sign-extending pairs are treated atomically if
284
+ * aligned, and if unaligned one of the pair will be completely
285
+ * within a 16-byte block and that element will be atomic.
286
+ * Otherwise each element is separately atomic.
287
+ * In all cases, issue one operation with the correct atomicity.
288
+ *
289
+ * This treats sign-extending loads like zero-extending loads,
290
+ * since that reuses the most code below.
291
+ */
292
+ mop = a->sz + 1;
293
+ if (s->align_mem) {
294
+ mop |= (a->sz == 2 ? MO_ALIGN_4 : MO_ALIGN_8);
295
+ }
296
+ mop = finalize_memop_pair(s, mop);
297
+ if (a->sz == 2) {
298
+ int o2 = s->be_data == MO_LE ? 32 : 0;
299
+ int o1 = o2 ^ 32;
300
+
301
+ tcg_gen_qemu_ld_i64(tcg_rt, clean_addr, get_mem_index(s), mop);
302
+ if (a->sign) {
303
+ tcg_gen_sextract_i64(tcg_rt2, tcg_rt, o2, 32);
304
+ tcg_gen_sextract_i64(tcg_rt, tcg_rt, o1, 32);
305
+ } else {
306
+ tcg_gen_extract_i64(tcg_rt2, tcg_rt, o2, 32);
307
+ tcg_gen_extract_i64(tcg_rt, tcg_rt, o1, 32);
92
+ }
308
+ }
93
+ } else {
309
+ } else {
94
+ TCGv_i32 tcg_el = tcg_constant_i32(s->current_el);
310
+ TCGv_i128 tmp = tcg_temp_new_i128();
95
+ if (m_profile) {
311
+
96
+ gen_helper_rebuild_hflags_m32(cpu_env, tcg_el);
312
+ tcg_gen_qemu_ld_i128(tmp, clean_addr, get_mem_index(s), mop);
313
+ if (s->be_data == MO_LE) {
314
+ tcg_gen_extr_i128_i64(tcg_rt, tcg_rt2, tmp);
97
+ } else {
315
+ } else {
98
+ gen_helper_rebuild_hflags_a32(cpu_env, tcg_el);
316
+ tcg_gen_extr_i128_i64(tcg_rt2, tcg_rt, tmp);
99
+ }
317
+ }
100
+ }
318
+ }
319
+ op_addr_ldstpair_post(s, a, dirty_addr, offset);
320
+ return true;
101
+}
321
+}
102
+
322
+
103
static void gen_exception_internal(int excp)
323
+static bool trans_STP_v(DisasContext *s, arg_ldstpair *a)
104
{
324
+{
105
TCGv_i32 tcg_excp = tcg_const_i32(excp);
325
+ uint64_t offset = a->imm << a->sz;
106
@@ -XXX,XX +XXX,XX @@ static void do_coproc_insn(DisasContext *s, int cpnum, int is64,
326
+ TCGv_i64 clean_addr, dirty_addr;
107
* A write to any coprocessor register that ends a TB
327
+ MemOp mop;
108
* must rebuild the hflags for the next TB.
328
+
109
*/
329
+ if (!fp_access_check(s)) {
110
- TCGv_i32 tcg_el = tcg_const_i32(s->current_el);
330
+ return true;
111
- if (arm_dc_feature(s, ARM_FEATURE_M)) {
331
+ }
112
- gen_helper_rebuild_hflags_m32(cpu_env, tcg_el);
332
+
333
+ /* LSE2 does not merge FP pairs; leave these as separate operations. */
334
+ mop = finalize_memop_asimd(s, a->sz);
335
+ op_addr_ldstpair_pre(s, a, &clean_addr, &dirty_addr, offset, true, mop);
336
+ do_fp_st(s, a->rt, clean_addr, mop);
337
+ tcg_gen_addi_i64(clean_addr, clean_addr, 1 << a->sz);
338
+ do_fp_st(s, a->rt2, clean_addr, mop);
339
+ op_addr_ldstpair_post(s, a, dirty_addr, offset);
340
+ return true;
341
+}
342
+
343
+static bool trans_LDP_v(DisasContext *s, arg_ldstpair *a)
344
+{
345
+ uint64_t offset = a->imm << a->sz;
346
+ TCGv_i64 clean_addr, dirty_addr;
347
+ MemOp mop;
348
+
349
+ if (!fp_access_check(s)) {
350
+ return true;
351
+ }
352
+
353
+ /* LSE2 does not merge FP pairs; leave these as separate operations. */
354
+ mop = finalize_memop_asimd(s, a->sz);
355
+ op_addr_ldstpair_pre(s, a, &clean_addr, &dirty_addr, offset, false, mop);
356
+ do_fp_ld(s, a->rt, clean_addr, mop);
357
+ tcg_gen_addi_i64(clean_addr, clean_addr, 1 << a->sz);
358
+ do_fp_ld(s, a->rt2, clean_addr, mop);
359
+ op_addr_ldstpair_post(s, a, dirty_addr, offset);
360
+ return true;
361
+}
362
+
363
+static bool trans_STGP(DisasContext *s, arg_ldstpair *a)
364
+{
365
+ TCGv_i64 clean_addr, dirty_addr, tcg_rt, tcg_rt2;
366
+ uint64_t offset = a->imm << LOG2_TAG_GRANULE;
367
+ MemOp mop;
368
+ TCGv_i128 tmp;
369
+
370
+ if (!dc_isar_feature(aa64_mte_insn_reg, s)) {
371
+ return false;
372
+ }
373
+
374
+ if (a->rn == 31) {
375
+ gen_check_sp_alignment(s);
376
+ }
377
+
378
+ dirty_addr = read_cpu_reg_sp(s, a->rn, 1);
379
+ if (!a->p) {
380
tcg_gen_addi_i64(dirty_addr, dirty_addr, offset);
381
}
382
383
- if (set_tag) {
384
- if (!s->ata) {
385
- /*
386
- * TODO: We could rely on the stores below, at least for
387
- * system mode, if we arrange to add MO_ALIGN_16.
388
- */
389
- gen_helper_stg_stub(cpu_env, dirty_addr);
390
- } else if (tb_cflags(s->base.tb) & CF_PARALLEL) {
391
- gen_helper_stg_parallel(cpu_env, dirty_addr, dirty_addr);
392
- } else {
393
- gen_helper_stg(cpu_env, dirty_addr, dirty_addr);
394
- }
395
- }
396
-
397
- if (is_vector) {
398
- mop = finalize_memop_asimd(s, size);
399
- } else {
400
- mop = finalize_memop(s, size);
401
- }
402
- clean_addr = gen_mte_checkN(s, dirty_addr, !is_load,
403
- (wback || rn != 31) && !set_tag,
404
- 2 << size, mop);
405
-
406
- if (is_vector) {
407
- /* LSE2 does not merge FP pairs; leave these as separate operations. */
408
- if (is_load) {
409
- do_fp_ld(s, rt, clean_addr, mop);
410
- } else {
411
- do_fp_st(s, rt, clean_addr, mop);
412
- }
413
- tcg_gen_addi_i64(clean_addr, clean_addr, 1 << size);
414
- if (is_load) {
415
- do_fp_ld(s, rt2, clean_addr, mop);
416
- } else {
417
- do_fp_st(s, rt2, clean_addr, mop);
418
- }
419
- } else {
420
- TCGv_i64 tcg_rt = cpu_reg(s, rt);
421
- TCGv_i64 tcg_rt2 = cpu_reg(s, rt2);
422
-
423
+ if (!s->ata) {
424
/*
425
- * We built mop above for the single logical access -- rebuild it
426
- * now for the paired operation.
427
- *
428
- * With LSE2, non-sign-extending pairs are treated atomically if
429
- * aligned, and if unaligned one of the pair will be completely
430
- * within a 16-byte block and that element will be atomic.
431
- * Otherwise each element is separately atomic.
432
- * In all cases, issue one operation with the correct atomicity.
433
- *
434
- * This treats sign-extending loads like zero-extending loads,
435
- * since that reuses the most code below.
436
+ * TODO: We could rely on the stores below, at least for
437
+ * system mode, if we arrange to add MO_ALIGN_16.
438
*/
439
- mop = size + 1;
440
- if (s->align_mem) {
441
- mop |= (size == 2 ? MO_ALIGN_4 : MO_ALIGN_8);
442
- }
443
- mop = finalize_memop_pair(s, mop);
444
-
445
- if (is_load) {
446
- if (size == 2) {
447
- int o2 = s->be_data == MO_LE ? 32 : 0;
448
- int o1 = o2 ^ 32;
449
-
450
- tcg_gen_qemu_ld_i64(tcg_rt, clean_addr, get_mem_index(s), mop);
451
- if (is_signed) {
452
- tcg_gen_sextract_i64(tcg_rt2, tcg_rt, o2, 32);
453
- tcg_gen_sextract_i64(tcg_rt, tcg_rt, o1, 32);
454
- } else {
455
- tcg_gen_extract_i64(tcg_rt2, tcg_rt, o2, 32);
456
- tcg_gen_extract_i64(tcg_rt, tcg_rt, o1, 32);
457
- }
113
- } else {
458
- } else {
114
- if (ri->type & ARM_CP_NEWEL) {
459
- TCGv_i128 tmp = tcg_temp_new_i128();
115
- gen_helper_rebuild_hflags_a32_newel(cpu_env);
460
-
461
- tcg_gen_qemu_ld_i128(tmp, clean_addr, get_mem_index(s), mop);
462
- if (s->be_data == MO_LE) {
463
- tcg_gen_extr_i128_i64(tcg_rt, tcg_rt2, tmp);
116
- } else {
464
- } else {
117
- gen_helper_rebuild_hflags_a32(cpu_env, tcg_el);
465
- tcg_gen_extr_i128_i64(tcg_rt2, tcg_rt, tmp);
118
- }
466
- }
119
- }
467
- }
120
- tcg_temp_free_i32(tcg_el);
468
- } else {
121
+ gen_rebuild_hflags(s, ri->type & ARM_CP_NEWEL);
469
- if (size == 2) {
122
/*
470
- TCGv_i64 tmp = tcg_temp_new_i64();
123
* We default to ending the TB on a coprocessor register write,
471
-
124
* but allow this to be suppressed by the register definition
472
- if (s->be_data == MO_LE) {
125
@@ -XXX,XX +XXX,XX @@ static bool trans_MSR_v7m(DisasContext *s, arg_MSR_v7m *a)
473
- tcg_gen_concat32_i64(tmp, tcg_rt, tcg_rt2);
126
tcg_temp_free_i32(addr);
474
- } else {
127
tcg_temp_free_i32(reg);
475
- tcg_gen_concat32_i64(tmp, tcg_rt2, tcg_rt);
128
/* If we wrote to CONTROL, the EL might have changed */
476
- }
129
- gen_helper_rebuild_hflags_m32_newel(cpu_env);
477
- tcg_gen_qemu_st_i64(tmp, clean_addr, get_mem_index(s), mop);
130
+ gen_rebuild_hflags(s, true);
478
- } else {
131
gen_lookup_tb(s);
479
- TCGv_i128 tmp = tcg_temp_new_i128();
132
return true;
480
-
481
- if (s->be_data == MO_LE) {
482
- tcg_gen_concat_i64_i128(tmp, tcg_rt, tcg_rt2);
483
- } else {
484
- tcg_gen_concat_i64_i128(tmp, tcg_rt2, tcg_rt);
485
- }
486
- tcg_gen_qemu_st_i128(tmp, clean_addr, get_mem_index(s), mop);
487
- }
488
- }
489
+ gen_helper_stg_stub(cpu_env, dirty_addr);
490
+ } else if (tb_cflags(s->base.tb) & CF_PARALLEL) {
491
+ gen_helper_stg_parallel(cpu_env, dirty_addr, dirty_addr);
492
+ } else {
493
+ gen_helper_stg(cpu_env, dirty_addr, dirty_addr);
494
}
495
496
- if (wback) {
497
- if (postindex) {
498
- tcg_gen_addi_i64(dirty_addr, dirty_addr, offset);
499
- }
500
- tcg_gen_mov_i64(cpu_reg_sp(s, rn), dirty_addr);
501
+ mop = finalize_memop(s, a->sz);
502
+ clean_addr = gen_mte_checkN(s, dirty_addr, true, false, 2 << a->sz, mop);
503
+
504
+ tcg_rt = cpu_reg(s, a->rt);
505
+ tcg_rt2 = cpu_reg(s, a->rt2);
506
+
507
+ assert(a->sz == 3);
508
+
509
+ tmp = tcg_temp_new_i128();
510
+ if (s->be_data == MO_LE) {
511
+ tcg_gen_concat_i64_i128(tmp, tcg_rt, tcg_rt2);
512
+ } else {
513
+ tcg_gen_concat_i64_i128(tmp, tcg_rt2, tcg_rt);
514
}
515
+ tcg_gen_qemu_st_i128(tmp, clean_addr, get_mem_index(s), mop);
516
+
517
+ op_addr_ldstpair_post(s, a, dirty_addr, offset);
518
+ return true;
133
}
519
}
134
@@ -XXX,XX +XXX,XX @@ static bool trans_CPS(DisasContext *s, arg_CPS *a)
520
135
521
/*
136
static bool trans_CPS_v7m(DisasContext *s, arg_CPS_v7m *a)
522
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_tag(DisasContext *s, uint32_t insn)
523
static void disas_ldst(DisasContext *s, uint32_t insn)
137
{
524
{
138
- TCGv_i32 tmp, addr, el;
525
switch (extract32(insn, 24, 6)) {
139
+ TCGv_i32 tmp, addr;
526
- case 0x28: case 0x29:
140
527
- case 0x2c: case 0x2d: /* Load/store pair (all forms) */
141
if (!arm_dc_feature(s, ARM_FEATURE_M)) {
528
- disas_ldst_pair(s, insn);
142
return false;
529
- break;
143
@@ -XXX,XX +XXX,XX @@ static bool trans_CPS_v7m(DisasContext *s, arg_CPS_v7m *a)
530
case 0x38: case 0x39:
144
gen_helper_v7m_msr(cpu_env, addr, tmp);
531
case 0x3c: case 0x3d: /* Load/store register (all forms) */
145
tcg_temp_free_i32(addr);
532
disas_ldst_reg(s, insn);
146
}
147
- el = tcg_const_i32(s->current_el);
148
- gen_helper_rebuild_hflags_m32(cpu_env, el);
149
- tcg_temp_free_i32(el);
150
+ gen_rebuild_hflags(s, false);
151
tcg_temp_free_i32(tmp);
152
gen_lookup_tb(s);
153
return true;
154
--
533
--
155
2.25.1
534
2.34.1
diff view generated by jsdifflib
1
We use the common function gicv3_idreg() to supply the CoreSight ID
1
Convert the load and store instructions which use a 9-bit
2
register values for the GICv3 for the copies of these ID registers in
2
immediate offset to decodetree.
3
the distributor, redistributor and ITS register frames. This isn't
4
quite correct, because while most of the register values are the
5
same, the PIDR0 value should vary to indicate which of these three
6
frames it is. (You can see this and also the correct values of these
7
PIDR0 registers by looking at the GIC-600 or GIC-700 TRMs, for
8
example.)
9
10
Make gicv3_idreg() take an extra argument for the PIDR0 value.
11
3
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
14
Message-id: 20220408141550.1271295-5-peter.maydell@linaro.org
6
Message-id: 20230602155223.2040685-13-peter.maydell@linaro.org
15
---
7
---
16
hw/intc/gicv3_internal.h | 15 +++++++++++++--
8
target/arm/tcg/a64.decode | 69 +++++++++++
17
hw/intc/arm_gicv3_dist.c | 2 +-
9
target/arm/tcg/translate-a64.c | 206 ++++++++++++++-------------------
18
hw/intc/arm_gicv3_its.c | 2 +-
10
2 files changed, 153 insertions(+), 122 deletions(-)
19
hw/intc/arm_gicv3_redist.c | 2 +-
20
4 files changed, 16 insertions(+), 5 deletions(-)
21
11
22
diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h
12
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
23
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
24
--- a/hw/intc/gicv3_internal.h
14
--- a/target/arm/tcg/a64.decode
25
+++ b/hw/intc/gicv3_internal.h
15
+++ b/target/arm/tcg/a64.decode
26
@@ -XXX,XX +XXX,XX @@ static inline uint32_t gicv3_iidr(void)
16
@@ -XXX,XX +XXX,XX @@ LDP_v 10 101 1 011 1 ....... ..... ..... ..... @ldstpair sz=4 sign=0 p
27
return 0x43b;
17
STGP 01 101 0 001 0 ....... ..... ..... ..... @ldstpair sz=3 sign=0 p=1 w=1
18
STGP 01 101 0 010 0 ....... ..... ..... ..... @ldstpair sz=3 sign=0 p=0 w=0
19
STGP 01 101 0 011 0 ....... ..... ..... ..... @ldstpair sz=3 sign=0 p=0 w=1
20
+
21
+# Load/store register (unscaled immediate)
22
+&ldst_imm rt rn imm sz sign w p unpriv ext
23
+@ldst_imm .. ... . .. .. . imm:s9 .. rn:5 rt:5 &ldst_imm unpriv=0 p=0 w=0
24
+@ldst_imm_pre .. ... . .. .. . imm:s9 .. rn:5 rt:5 &ldst_imm unpriv=0 p=0 w=1
25
+@ldst_imm_post .. ... . .. .. . imm:s9 .. rn:5 rt:5 &ldst_imm unpriv=0 p=1 w=1
26
+@ldst_imm_user .. ... . .. .. . imm:s9 .. rn:5 rt:5 &ldst_imm unpriv=1 p=0 w=0
27
+
28
+STR_i sz:2 111 0 00 00 0 ......... 00 ..... ..... @ldst_imm sign=0 ext=0
29
+LDR_i 00 111 0 00 01 0 ......... 00 ..... ..... @ldst_imm sign=0 ext=1 sz=0
30
+LDR_i 01 111 0 00 01 0 ......... 00 ..... ..... @ldst_imm sign=0 ext=1 sz=1
31
+LDR_i 10 111 0 00 01 0 ......... 00 ..... ..... @ldst_imm sign=0 ext=1 sz=2
32
+LDR_i 11 111 0 00 01 0 ......... 00 ..... ..... @ldst_imm sign=0 ext=0 sz=3
33
+LDR_i 00 111 0 00 10 0 ......... 00 ..... ..... @ldst_imm sign=1 ext=0 sz=0
34
+LDR_i 01 111 0 00 10 0 ......... 00 ..... ..... @ldst_imm sign=1 ext=0 sz=1
35
+LDR_i 10 111 0 00 10 0 ......... 00 ..... ..... @ldst_imm sign=1 ext=0 sz=2
36
+LDR_i 00 111 0 00 11 0 ......... 00 ..... ..... @ldst_imm sign=1 ext=1 sz=0
37
+LDR_i 01 111 0 00 11 0 ......... 00 ..... ..... @ldst_imm sign=1 ext=1 sz=1
38
+
39
+STR_i sz:2 111 0 00 00 0 ......... 01 ..... ..... @ldst_imm_post sign=0 ext=0
40
+LDR_i 00 111 0 00 01 0 ......... 01 ..... ..... @ldst_imm_post sign=0 ext=1 sz=0
41
+LDR_i 01 111 0 00 01 0 ......... 01 ..... ..... @ldst_imm_post sign=0 ext=1 sz=1
42
+LDR_i 10 111 0 00 01 0 ......... 01 ..... ..... @ldst_imm_post sign=0 ext=1 sz=2
43
+LDR_i 11 111 0 00 01 0 ......... 01 ..... ..... @ldst_imm_post sign=0 ext=0 sz=3
44
+LDR_i 00 111 0 00 10 0 ......... 01 ..... ..... @ldst_imm_post sign=1 ext=0 sz=0
45
+LDR_i 01 111 0 00 10 0 ......... 01 ..... ..... @ldst_imm_post sign=1 ext=0 sz=1
46
+LDR_i 10 111 0 00 10 0 ......... 01 ..... ..... @ldst_imm_post sign=1 ext=0 sz=2
47
+LDR_i 00 111 0 00 11 0 ......... 01 ..... ..... @ldst_imm_post sign=1 ext=1 sz=0
48
+LDR_i 01 111 0 00 11 0 ......... 01 ..... ..... @ldst_imm_post sign=1 ext=1 sz=1
49
+
50
+STR_i sz:2 111 0 00 00 0 ......... 10 ..... ..... @ldst_imm_user sign=0 ext=0
51
+LDR_i 00 111 0 00 01 0 ......... 10 ..... ..... @ldst_imm_user sign=0 ext=1 sz=0
52
+LDR_i 01 111 0 00 01 0 ......... 10 ..... ..... @ldst_imm_user sign=0 ext=1 sz=1
53
+LDR_i 10 111 0 00 01 0 ......... 10 ..... ..... @ldst_imm_user sign=0 ext=1 sz=2
54
+LDR_i 11 111 0 00 01 0 ......... 10 ..... ..... @ldst_imm_user sign=0 ext=0 sz=3
55
+LDR_i 00 111 0 00 10 0 ......... 10 ..... ..... @ldst_imm_user sign=1 ext=0 sz=0
56
+LDR_i 01 111 0 00 10 0 ......... 10 ..... ..... @ldst_imm_user sign=1 ext=0 sz=1
57
+LDR_i 10 111 0 00 10 0 ......... 10 ..... ..... @ldst_imm_user sign=1 ext=0 sz=2
58
+LDR_i 00 111 0 00 11 0 ......... 10 ..... ..... @ldst_imm_user sign=1 ext=1 sz=0
59
+LDR_i 01 111 0 00 11 0 ......... 10 ..... ..... @ldst_imm_user sign=1 ext=1 sz=1
60
+
61
+STR_i sz:2 111 0 00 00 0 ......... 11 ..... ..... @ldst_imm_pre sign=0 ext=0
62
+LDR_i 00 111 0 00 01 0 ......... 11 ..... ..... @ldst_imm_pre sign=0 ext=1 sz=0
63
+LDR_i 01 111 0 00 01 0 ......... 11 ..... ..... @ldst_imm_pre sign=0 ext=1 sz=1
64
+LDR_i 10 111 0 00 01 0 ......... 11 ..... ..... @ldst_imm_pre sign=0 ext=1 sz=2
65
+LDR_i 11 111 0 00 01 0 ......... 11 ..... ..... @ldst_imm_pre sign=0 ext=0 sz=3
66
+LDR_i 00 111 0 00 10 0 ......... 11 ..... ..... @ldst_imm_pre sign=1 ext=0 sz=0
67
+LDR_i 01 111 0 00 10 0 ......... 11 ..... ..... @ldst_imm_pre sign=1 ext=0 sz=1
68
+LDR_i 10 111 0 00 10 0 ......... 11 ..... ..... @ldst_imm_pre sign=1 ext=0 sz=2
69
+LDR_i 00 111 0 00 11 0 ......... 11 ..... ..... @ldst_imm_pre sign=1 ext=1 sz=0
70
+LDR_i 01 111 0 00 11 0 ......... 11 ..... ..... @ldst_imm_pre sign=1 ext=1 sz=1
71
+
72
+# PRFM : prefetch memory: a no-op for QEMU
73
+NOP 11 111 0 00 10 0 --------- 00 ----- -----
74
+
75
+STR_v_i sz:2 111 1 00 00 0 ......... 00 ..... ..... @ldst_imm sign=0 ext=0
76
+STR_v_i 00 111 1 00 10 0 ......... 00 ..... ..... @ldst_imm sign=0 ext=0 sz=4
77
+LDR_v_i sz:2 111 1 00 01 0 ......... 00 ..... ..... @ldst_imm sign=0 ext=0
78
+LDR_v_i 00 111 1 00 11 0 ......... 00 ..... ..... @ldst_imm sign=0 ext=0 sz=4
79
+
80
+STR_v_i sz:2 111 1 00 00 0 ......... 01 ..... ..... @ldst_imm_post sign=0 ext=0
81
+STR_v_i 00 111 1 00 10 0 ......... 01 ..... ..... @ldst_imm_post sign=0 ext=0 sz=4
82
+LDR_v_i sz:2 111 1 00 01 0 ......... 01 ..... ..... @ldst_imm_post sign=0 ext=0
83
+LDR_v_i 00 111 1 00 11 0 ......... 01 ..... ..... @ldst_imm_post sign=0 ext=0 sz=4
84
+
85
+STR_v_i sz:2 111 1 00 00 0 ......... 11 ..... ..... @ldst_imm_pre sign=0 ext=0
86
+STR_v_i 00 111 1 00 10 0 ......... 11 ..... ..... @ldst_imm_pre sign=0 ext=0 sz=4
87
+LDR_v_i sz:2 111 1 00 01 0 ......... 11 ..... ..... @ldst_imm_pre sign=0 ext=0
88
+LDR_v_i 00 111 1 00 11 0 ......... 11 ..... ..... @ldst_imm_pre sign=0 ext=0 sz=4
89
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
90
index XXXXXXX..XXXXXXX 100644
91
--- a/target/arm/tcg/translate-a64.c
92
+++ b/target/arm/tcg/translate-a64.c
93
@@ -XXX,XX +XXX,XX @@ static bool trans_STGP(DisasContext *s, arg_ldstpair *a)
94
return true;
28
}
95
}
29
96
30
-static inline uint32_t gicv3_idreg(int regoffset)
97
-/*
31
+/* CoreSight PIDR0 values for ARM GICv3 implementations */
98
- * Load/store (immediate post-indexed)
32
+#define GICV3_PIDR0_DIST 0x92
99
- * Load/store (immediate pre-indexed)
33
+#define GICV3_PIDR0_REDIST 0x93
100
- * Load/store (unscaled immediate)
34
+#define GICV3_PIDR0_ITS 0x94
101
- *
35
+
102
- * 31 30 29 27 26 25 24 23 22 21 20 12 11 10 9 5 4 0
36
+static inline uint32_t gicv3_idreg(int regoffset, uint8_t pidr0)
103
- * +----+-------+---+-----+-----+---+--------+-----+------+------+
104
- * |size| 1 1 1 | V | 0 0 | opc | 0 | imm9 | idx | Rn | Rt |
105
- * +----+-------+---+-----+-----+---+--------+-----+------+------+
106
- *
107
- * idx = 01 -> post-indexed, 11 pre-indexed, 00 unscaled imm. (no writeback)
108
- 10 -> unprivileged
109
- * V = 0 -> non-vector
110
- * size: 00 -> 8 bit, 01 -> 16 bit, 10 -> 32 bit, 11 -> 64bit
111
- * opc: 00 -> store, 01 -> loadu, 10 -> loads 64, 11 -> loads 32
112
- */
113
-static void disas_ldst_reg_imm9(DisasContext *s, uint32_t insn,
114
- int opc,
115
- int size,
116
- int rt,
117
- bool is_vector)
118
+static void op_addr_ldst_imm_pre(DisasContext *s, arg_ldst_imm *a,
119
+ TCGv_i64 *clean_addr, TCGv_i64 *dirty_addr,
120
+ uint64_t offset, bool is_store, MemOp mop)
37
{
121
{
38
/* Return the value of the CoreSight ID register at the specified
122
- int rn = extract32(insn, 5, 5);
39
* offset from the first ID register (as found in the distributor
123
- int imm9 = sextract32(insn, 12, 9);
40
@@ -XXX,XX +XXX,XX @@ static inline uint32_t gicv3_idreg(int regoffset)
124
- int idx = extract32(insn, 10, 2);
41
static const uint8_t gicd_ids[] = {
125
- bool is_signed = false;
42
0x44, 0x00, 0x00, 0x00, 0x92, 0xB4, 0x3B, 0x00, 0x0D, 0xF0, 0x05, 0xB1
126
- bool is_store = false;
43
};
127
- bool is_extended = false;
44
- return gicd_ids[regoffset / 4];
128
- bool is_unpriv = (idx == 2);
45
+
129
- bool iss_valid;
46
+ regoffset /= 4;
130
- bool post_index;
47
+
131
- bool writeback;
48
+ if (regoffset == 4) {
132
int memidx;
49
+ return pidr0;
133
- MemOp memop;
134
- TCGv_i64 clean_addr, dirty_addr;
135
136
- if (is_vector) {
137
- size |= (opc & 2) << 1;
138
- if (size > 4 || is_unpriv) {
139
- unallocated_encoding(s);
140
- return;
141
- }
142
- is_store = ((opc & 1) == 0);
143
- if (!fp_access_check(s)) {
144
- return;
145
- }
146
- memop = finalize_memop_asimd(s, size);
147
- } else {
148
- if (size == 3 && opc == 2) {
149
- /* PRFM - prefetch */
150
- if (idx != 0) {
151
- unallocated_encoding(s);
152
- return;
153
- }
154
- return;
155
- }
156
- if (opc == 3 && size > 1) {
157
- unallocated_encoding(s);
158
- return;
159
- }
160
- is_store = (opc == 0);
161
- is_signed = !is_store && extract32(opc, 1, 1);
162
- is_extended = (size < 3) && extract32(opc, 0, 1);
163
- memop = finalize_memop(s, size + is_signed * MO_SIGN);
164
- }
165
-
166
- switch (idx) {
167
- case 0:
168
- case 2:
169
- post_index = false;
170
- writeback = false;
171
- break;
172
- case 1:
173
- post_index = true;
174
- writeback = true;
175
- break;
176
- case 3:
177
- post_index = false;
178
- writeback = true;
179
- break;
180
- default:
181
- g_assert_not_reached();
182
- }
183
-
184
- iss_valid = !is_vector && !writeback;
185
-
186
- if (rn == 31) {
187
+ if (a->rn == 31) {
188
gen_check_sp_alignment(s);
189
}
190
191
- dirty_addr = read_cpu_reg_sp(s, rn, 1);
192
- if (!post_index) {
193
- tcg_gen_addi_i64(dirty_addr, dirty_addr, imm9);
194
+ *dirty_addr = read_cpu_reg_sp(s, a->rn, 1);
195
+ if (!a->p) {
196
+ tcg_gen_addi_i64(*dirty_addr, *dirty_addr, offset);
197
}
198
+ memidx = a->unpriv ? get_a64_user_mem_index(s) : get_mem_index(s);
199
+ *clean_addr = gen_mte_check1_mmuidx(s, *dirty_addr, is_store,
200
+ a->w || a->rn != 31,
201
+ mop, a->unpriv, memidx);
202
+}
203
204
- memidx = is_unpriv ? get_a64_user_mem_index(s) : get_mem_index(s);
205
-
206
- clean_addr = gen_mte_check1_mmuidx(s, dirty_addr, is_store,
207
- writeback || rn != 31,
208
- memop, is_unpriv, memidx);
209
-
210
- if (is_vector) {
211
- if (is_store) {
212
- do_fp_st(s, rt, clean_addr, memop);
213
- } else {
214
- do_fp_ld(s, rt, clean_addr, memop);
215
- }
216
- } else {
217
- TCGv_i64 tcg_rt = cpu_reg(s, rt);
218
- bool iss_sf = disas_ldst_compute_iss_sf(size, is_signed, opc);
219
-
220
- if (is_store) {
221
- do_gpr_st_memidx(s, tcg_rt, clean_addr, memop, memidx,
222
- iss_valid, rt, iss_sf, false);
223
- } else {
224
- do_gpr_ld_memidx(s, tcg_rt, clean_addr, memop,
225
- is_extended, memidx,
226
- iss_valid, rt, iss_sf, false);
227
+static void op_addr_ldst_imm_post(DisasContext *s, arg_ldst_imm *a,
228
+ TCGv_i64 dirty_addr, uint64_t offset)
229
+{
230
+ if (a->w) {
231
+ if (a->p) {
232
+ tcg_gen_addi_i64(dirty_addr, dirty_addr, offset);
233
}
234
+ tcg_gen_mov_i64(cpu_reg_sp(s, a->rn), dirty_addr);
235
}
236
+}
237
238
- if (writeback) {
239
- TCGv_i64 tcg_rn = cpu_reg_sp(s, rn);
240
- if (post_index) {
241
- tcg_gen_addi_i64(dirty_addr, dirty_addr, imm9);
242
- }
243
- tcg_gen_mov_i64(tcg_rn, dirty_addr);
244
+static bool trans_STR_i(DisasContext *s, arg_ldst_imm *a)
245
+{
246
+ bool iss_sf, iss_valid = !a->w;
247
+ TCGv_i64 clean_addr, dirty_addr, tcg_rt;
248
+ int memidx = a->unpriv ? get_a64_user_mem_index(s) : get_mem_index(s);
249
+ MemOp mop = finalize_memop(s, a->sz + a->sign * MO_SIGN);
250
+
251
+ op_addr_ldst_imm_pre(s, a, &clean_addr, &dirty_addr, a->imm, true, mop);
252
+
253
+ tcg_rt = cpu_reg(s, a->rt);
254
+ iss_sf = ldst_iss_sf(a->sz, a->sign, a->ext);
255
+
256
+ do_gpr_st_memidx(s, tcg_rt, clean_addr, mop, memidx,
257
+ iss_valid, a->rt, iss_sf, false);
258
+ op_addr_ldst_imm_post(s, a, dirty_addr, a->imm);
259
+ return true;
260
+}
261
+
262
+static bool trans_LDR_i(DisasContext *s, arg_ldst_imm *a)
263
+{
264
+ bool iss_sf, iss_valid = !a->w;
265
+ TCGv_i64 clean_addr, dirty_addr, tcg_rt;
266
+ int memidx = a->unpriv ? get_a64_user_mem_index(s) : get_mem_index(s);
267
+ MemOp mop = finalize_memop(s, a->sz + a->sign * MO_SIGN);
268
+
269
+ op_addr_ldst_imm_pre(s, a, &clean_addr, &dirty_addr, a->imm, false, mop);
270
+
271
+ tcg_rt = cpu_reg(s, a->rt);
272
+ iss_sf = ldst_iss_sf(a->sz, a->sign, a->ext);
273
+
274
+ do_gpr_ld_memidx(s, tcg_rt, clean_addr, mop,
275
+ a->ext, memidx, iss_valid, a->rt, iss_sf, false);
276
+ op_addr_ldst_imm_post(s, a, dirty_addr, a->imm);
277
+ return true;
278
+}
279
+
280
+static bool trans_STR_v_i(DisasContext *s, arg_ldst_imm *a)
281
+{
282
+ TCGv_i64 clean_addr, dirty_addr;
283
+ MemOp mop;
284
+
285
+ if (!fp_access_check(s)) {
286
+ return true;
287
}
288
+ mop = finalize_memop_asimd(s, a->sz);
289
+ op_addr_ldst_imm_pre(s, a, &clean_addr, &dirty_addr, a->imm, true, mop);
290
+ do_fp_st(s, a->rt, clean_addr, mop);
291
+ op_addr_ldst_imm_post(s, a, dirty_addr, a->imm);
292
+ return true;
293
+}
294
+
295
+static bool trans_LDR_v_i(DisasContext *s, arg_ldst_imm *a)
296
+{
297
+ TCGv_i64 clean_addr, dirty_addr;
298
+ MemOp mop;
299
+
300
+ if (!fp_access_check(s)) {
301
+ return true;
50
+ }
302
+ }
51
+ return gicd_ids[regoffset];
303
+ mop = finalize_memop_asimd(s, a->sz);
304
+ op_addr_ldst_imm_pre(s, a, &clean_addr, &dirty_addr, a->imm, false, mop);
305
+ do_fp_ld(s, a->rt, clean_addr, mop);
306
+ op_addr_ldst_imm_post(s, a, dirty_addr, a->imm);
307
+ return true;
52
}
308
}
53
309
54
/**
310
/*
55
diff --git a/hw/intc/arm_gicv3_dist.c b/hw/intc/arm_gicv3_dist.c
311
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_reg(DisasContext *s, uint32_t insn)
56
index XXXXXXX..XXXXXXX 100644
312
switch (extract32(insn, 24, 2)) {
57
--- a/hw/intc/arm_gicv3_dist.c
313
case 0:
58
+++ b/hw/intc/arm_gicv3_dist.c
314
if (extract32(insn, 21, 1) == 0) {
59
@@ -XXX,XX +XXX,XX @@ static bool gicd_readl(GICv3State *s, hwaddr offset,
315
- /* Load/store register (unscaled immediate)
60
}
316
- * Load/store immediate pre/post-indexed
61
case GICD_IDREGS ... GICD_IDREGS + 0x2f:
317
- * Load/store register unprivileged
62
/* ID registers */
318
- */
63
- *data = gicv3_idreg(offset - GICD_IDREGS);
319
- disas_ldst_reg_imm9(s, insn, opc, size, rt, is_vector);
64
+ *data = gicv3_idreg(offset - GICD_IDREGS, GICV3_PIDR0_DIST);
320
- return;
65
return true;
321
+ break;
66
case GICD_SGIR:
322
}
67
/* WO registers, return unknown value */
323
switch (extract32(insn, 10, 2)) {
68
diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
324
case 0:
69
index XXXXXXX..XXXXXXX 100644
70
--- a/hw/intc/arm_gicv3_its.c
71
+++ b/hw/intc/arm_gicv3_its.c
72
@@ -XXX,XX +XXX,XX @@ static bool its_readl(GICv3ITSState *s, hwaddr offset,
73
break;
74
case GITS_IDREGS ... GITS_IDREGS + 0x2f:
75
/* ID registers */
76
- *data = gicv3_idreg(offset - GITS_IDREGS);
77
+ *data = gicv3_idreg(offset - GITS_IDREGS, GICV3_PIDR0_ITS);
78
break;
79
case GITS_TYPER:
80
*data = extract64(s->typer, 0, 32);
81
diff --git a/hw/intc/arm_gicv3_redist.c b/hw/intc/arm_gicv3_redist.c
82
index XXXXXXX..XXXXXXX 100644
83
--- a/hw/intc/arm_gicv3_redist.c
84
+++ b/hw/intc/arm_gicv3_redist.c
85
@@ -XXX,XX +XXX,XX @@ static MemTxResult gicr_readl(GICv3CPUState *cs, hwaddr offset,
86
*data = cs->gicr_nsacr;
87
return MEMTX_OK;
88
case GICR_IDREGS ... GICR_IDREGS + 0x2f:
89
- *data = gicv3_idreg(offset - GICR_IDREGS);
90
+ *data = gicv3_idreg(offset - GICR_IDREGS, GICV3_PIDR0_REDIST);
91
return MEMTX_OK;
92
default:
93
return MEMTX_ERROR;
94
--
325
--
95
2.25.1
326
2.34.1
diff view generated by jsdifflib
Deleted patch
1
In a GICv3, it is impossible for the GIC to deliver a VIRQ or VFIQ to
2
the CPU unless the CPU has EL2, because VIRQ and VFIQ are only
3
configurable via EL2-only system registers. Moreover, in our
4
implementation we were only calculating and updating the state of the
5
VIRQ and VFIQ lines in gicv3_cpuif_virt_irq_fiq_update() when those
6
EL2 system registers changed. We were therefore able to assert in
7
arm_cpu_set_irq() that we didn't see a VIRQ or VFIQ line update if
8
EL2 wasn't present.
9
1
10
This assumption no longer holds with GICv4:
11
* even if the CPU does not have EL2 the guest is able to cause the
12
GIC to deliver a virtual LPI by programming the ITS (which is a
13
silly thing for it to do, but possible)
14
* because we now need to recalculate the state of the VIRQ and VFIQ
15
lines in more cases than just "some EL2 GIC sysreg was written",
16
we will see calls to arm_cpu_set_irq() for "VIRQ is 0, VFIQ is 0"
17
even if the guest is not using the virtual LPI parts of the ITS
18
19
Remove the assertions, and instead simply ignore the state of the
20
VIRQ and VFIQ lines if the CPU does not have EL2.
21
22
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
23
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
24
Message-id: 20220408141550.1271295-6-peter.maydell@linaro.org
25
---
26
target/arm/cpu.c | 12 ++++++++++--
27
1 file changed, 10 insertions(+), 2 deletions(-)
28
29
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
30
index XXXXXXX..XXXXXXX 100644
31
--- a/target/arm/cpu.c
32
+++ b/target/arm/cpu.c
33
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_set_irq(void *opaque, int irq, int level)
34
[ARM_CPU_VFIQ] = CPU_INTERRUPT_VFIQ
35
};
36
37
+ if (!arm_feature(env, ARM_FEATURE_EL2) &&
38
+ (irq == ARM_CPU_VIRQ || irq == ARM_CPU_VFIQ)) {
39
+ /*
40
+ * The GIC might tell us about VIRQ and VFIQ state, but if we don't
41
+ * have EL2 support we don't care. (Unless the guest is doing something
42
+ * silly this will only be calls saying "level is still 0".)
43
+ */
44
+ return;
45
+ }
46
+
47
if (level) {
48
env->irq_line_state |= mask[irq];
49
} else {
50
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_set_irq(void *opaque, int irq, int level)
51
52
switch (irq) {
53
case ARM_CPU_VIRQ:
54
- assert(arm_feature(env, ARM_FEATURE_EL2));
55
arm_cpu_update_virq(cpu);
56
break;
57
case ARM_CPU_VFIQ:
58
- assert(arm_feature(env, ARM_FEATURE_EL2));
59
arm_cpu_update_vfiq(cpu);
60
break;
61
case ARM_CPU_IRQ:
62
--
63
2.25.1
diff view generated by jsdifflib
Deleted patch
1
In process_mapti() we check interrupt IDs to see whether they are
2
in the valid LPI range. Factor this out into its own utility
3
function, as we're going to want it elsewhere too for GICv4.
4
1
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20220408141550.1271295-7-peter.maydell@linaro.org
8
---
9
hw/intc/arm_gicv3_its.c | 10 +++++++---
10
1 file changed, 7 insertions(+), 3 deletions(-)
11
12
diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/intc/arm_gicv3_its.c
15
+++ b/hw/intc/arm_gicv3_its.c
16
@@ -XXX,XX +XXX,XX @@ typedef enum ItsCmdResult {
17
CMD_CONTINUE = 1,
18
} ItsCmdResult;
19
20
+static inline bool intid_in_lpi_range(uint32_t id)
21
+{
22
+ return id >= GICV3_LPI_INTID_START &&
23
+ id < (1 << (GICD_TYPER_IDBITS + 1));
24
+}
25
+
26
static uint64_t baser_base_addr(uint64_t value, uint32_t page_sz)
27
{
28
uint64_t result = 0;
29
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_mapti(GICv3ITSState *s, const uint64_t *cmdpkt,
30
uint32_t devid, eventid;
31
uint32_t pIntid = 0;
32
uint64_t num_eventids;
33
- uint32_t num_intids;
34
uint16_t icid = 0;
35
DTEntry dte;
36
ITEntry ite;
37
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_mapti(GICv3ITSState *s, const uint64_t *cmdpkt,
38
return CMD_STALL;
39
}
40
num_eventids = 1ULL << (dte.size + 1);
41
- num_intids = 1ULL << (GICD_TYPER_IDBITS + 1);
42
43
if (icid >= s->ct.num_entries) {
44
qemu_log_mask(LOG_GUEST_ERROR,
45
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_mapti(GICv3ITSState *s, const uint64_t *cmdpkt,
46
return CMD_CONTINUE;
47
}
48
49
- if (pIntid < GICV3_LPI_INTID_START || pIntid >= num_intids) {
50
+ if (!intid_in_lpi_range(pIntid)) {
51
qemu_log_mask(LOG_GUEST_ERROR,
52
"%s: invalid interrupt ID 0x%x\n", __func__, pIntid);
53
return CMD_CONTINUE;
54
--
55
2.25.1
diff view generated by jsdifflib
Deleted patch
1
The GICv4 defines a new in-guest-memory table for the ITS: this is
2
the vPE table. Implement the new GITS_BASER2 register which the
3
guest uses to tell the ITS where the vPE table is located, including
4
the decode of the register fields into the TableDesc structure which
5
we do for the GITS_BASER<n> when the guest enables the ITS.
6
1
7
We guard provision of the new register with the its_feature_virtual()
8
function, which does a check of the GITS_TYPER.Virtual bit which
9
indicates presence of ITS support for virtual LPIs. Since this bit
10
is currently always zero, GICv4-specific features will not be
11
accessible to the guest yet.
12
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
Message-id: 20220408141550.1271295-8-peter.maydell@linaro.org
16
---
17
hw/intc/gicv3_internal.h | 16 ++++++++++++++++
18
include/hw/intc/arm_gicv3_its_common.h | 1 +
19
hw/intc/arm_gicv3_its.c | 25 +++++++++++++++++++++++++
20
3 files changed, 42 insertions(+)
21
22
diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h
23
index XXXXXXX..XXXXXXX 100644
24
--- a/hw/intc/gicv3_internal.h
25
+++ b/hw/intc/gicv3_internal.h
26
@@ -XXX,XX +XXX,XX @@ FIELD(GITS_CTLR, ENABLED, 0, 1)
27
FIELD(GITS_CTLR, QUIESCENT, 31, 1)
28
29
FIELD(GITS_TYPER, PHYSICAL, 0, 1)
30
+FIELD(GITS_TYPER, VIRTUAL, 1, 1)
31
FIELD(GITS_TYPER, ITT_ENTRY_SIZE, 4, 4)
32
FIELD(GITS_TYPER, IDBITS, 8, 5)
33
FIELD(GITS_TYPER, DEVBITS, 13, 5)
34
@@ -XXX,XX +XXX,XX @@ FIELD(GITS_TYPER, CIL, 36, 1)
35
#define GITS_BASER_PAGESIZE_64K 2
36
37
#define GITS_BASER_TYPE_DEVICE 1ULL
38
+#define GITS_BASER_TYPE_VPE 2ULL
39
#define GITS_BASER_TYPE_COLLECTION 4ULL
40
41
#define GITS_PAGE_SIZE_4K 0x1000
42
@@ -XXX,XX +XXX,XX @@ FIELD(DTE, ITTADDR, 6, 44)
43
FIELD(CTE, VALID, 0, 1)
44
FIELD(CTE, RDBASE, 1, RDBASE_PROCNUM_LENGTH)
45
46
+/*
47
+ * 8 bytes VPE table entry size:
48
+ * Valid = 1 bit, VPTsize = 5 bits, VPTaddr = 36 bits, RDbase = 16 bits
49
+ *
50
+ * Field sizes for Valid and size are mandated; field sizes for RDbase
51
+ * and VPT_addr are IMPDEF.
52
+ */
53
+#define GITS_VPE_SIZE 0x8ULL
54
+
55
+FIELD(VTE, VALID, 0, 1)
56
+FIELD(VTE, VPTSIZE, 1, 5)
57
+FIELD(VTE, VPTADDR, 6, 36)
58
+FIELD(VTE, RDBASE, 42, RDBASE_PROCNUM_LENGTH)
59
+
60
/* Special interrupt IDs */
61
#define INTID_SECURE 1020
62
#define INTID_NONSECURE 1021
63
diff --git a/include/hw/intc/arm_gicv3_its_common.h b/include/hw/intc/arm_gicv3_its_common.h
64
index XXXXXXX..XXXXXXX 100644
65
--- a/include/hw/intc/arm_gicv3_its_common.h
66
+++ b/include/hw/intc/arm_gicv3_its_common.h
67
@@ -XXX,XX +XXX,XX @@ struct GICv3ITSState {
68
69
TableDesc dt;
70
TableDesc ct;
71
+ TableDesc vpet;
72
CmdQDesc cq;
73
74
Error *migration_blocker;
75
diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
76
index XXXXXXX..XXXXXXX 100644
77
--- a/hw/intc/arm_gicv3_its.c
78
+++ b/hw/intc/arm_gicv3_its.c
79
@@ -XXX,XX +XXX,XX @@ typedef enum ItsCmdResult {
80
CMD_CONTINUE = 1,
81
} ItsCmdResult;
82
83
+/* True if the ITS supports the GICv4 virtual LPI feature */
84
+static bool its_feature_virtual(GICv3ITSState *s)
85
+{
86
+ return s->typer & R_GITS_TYPER_VIRTUAL_MASK;
87
+}
88
+
89
static inline bool intid_in_lpi_range(uint32_t id)
90
{
91
return id >= GICV3_LPI_INTID_START &&
92
@@ -XXX,XX +XXX,XX @@ static void extract_table_params(GICv3ITSState *s)
93
idbits = 16;
94
}
95
break;
96
+ case GITS_BASER_TYPE_VPE:
97
+ td = &s->vpet;
98
+ /*
99
+ * For QEMU vPEIDs are always 16 bits. (GICv4.1 allows an
100
+ * implementation to implement fewer bits and report this
101
+ * via GICD_TYPER2.)
102
+ */
103
+ idbits = 16;
104
+ break;
105
default:
106
/*
107
* GITS_BASER<n>.TYPE is read-only, so GITS_BASER_RO_MASK
108
@@ -XXX,XX +XXX,XX @@ static void gicv3_its_reset(DeviceState *dev)
109
/*
110
* setting GITS_BASER0.Type = 0b001 (Device)
111
* GITS_BASER1.Type = 0b100 (Collection Table)
112
+ * GITS_BASER2.Type = 0b010 (vPE) for GICv4 and later
113
* GITS_BASER<n>.Type,where n = 3 to 7 are 0b00 (Unimplemented)
114
* GITS_BASER<0,1>.Page_Size = 64KB
115
* and default translation table entry size to 16 bytes
116
@@ -XXX,XX +XXX,XX @@ static void gicv3_its_reset(DeviceState *dev)
117
GITS_BASER_PAGESIZE_64K);
118
s->baser[1] = FIELD_DP64(s->baser[1], GITS_BASER, ENTRYSIZE,
119
GITS_CTE_SIZE - 1);
120
+
121
+ if (its_feature_virtual(s)) {
122
+ s->baser[2] = FIELD_DP64(s->baser[2], GITS_BASER, TYPE,
123
+ GITS_BASER_TYPE_VPE);
124
+ s->baser[2] = FIELD_DP64(s->baser[2], GITS_BASER, PAGESIZE,
125
+ GITS_BASER_PAGESIZE_64K);
126
+ s->baser[2] = FIELD_DP64(s->baser[2], GITS_BASER, ENTRYSIZE,
127
+ GITS_VPE_SIZE - 1);
128
+ }
129
}
130
131
static void gicv3_its_post_load(GICv3ITSState *s)
132
--
133
2.25.1
diff view generated by jsdifflib
1
The operation of finding an interrupt table entry given a (DeviceID,
1
Convert the LDR and STR instructions which use a 12-bit immediate
2
EventID) pair is necessary in multiple different ITS commands. The
2
offset to decodetree. We can reuse the existing LDR and STR
3
process requires first using the DeviceID as an index into the device
3
trans functions for these.
4
table to find the DTE, and then useng the EventID as an index into
5
the interrupt table specified by that DTE to find the ITE. We also
6
need to handle all the possible error cases: indexes out of range,
7
table memory not readable, table entries not valid.
8
9
Factor this out into a separate lookup_ite() function which we
10
can then call from the places where we were previously open-coding
11
this sequence. We'll also need this for some of the new GICv4.0
12
commands.
13
4
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
16
Message-id: 20220408141550.1271295-12-peter.maydell@linaro.org
7
Message-id: 20230602155223.2040685-14-peter.maydell@linaro.org
17
---
8
---
18
hw/intc/arm_gicv3_its.c | 124 +++++++++++++++++++++-------------------
9
target/arm/tcg/a64.decode | 25 ++++++++
19
1 file changed, 64 insertions(+), 60 deletions(-)
10
target/arm/tcg/translate-a64.c | 104 +++++----------------------------
11
2 files changed, 41 insertions(+), 88 deletions(-)
20
12
21
diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
13
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
22
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
23
--- a/hw/intc/arm_gicv3_its.c
15
--- a/target/arm/tcg/a64.decode
24
+++ b/hw/intc/arm_gicv3_its.c
16
+++ b/target/arm/tcg/a64.decode
25
@@ -XXX,XX +XXX,XX @@ out:
17
@@ -XXX,XX +XXX,XX @@ STR_v_i sz:2 111 1 00 00 0 ......... 11 ..... ..... @ldst_imm_pre sign=0
26
return res;
18
STR_v_i 00 111 1 00 10 0 ......... 11 ..... ..... @ldst_imm_pre sign=0 ext=0 sz=4
27
}
19
LDR_v_i sz:2 111 1 00 01 0 ......... 11 ..... ..... @ldst_imm_pre sign=0 ext=0
20
LDR_v_i 00 111 1 00 11 0 ......... 11 ..... ..... @ldst_imm_pre sign=0 ext=0 sz=4
21
+
22
+# Load/store with an unsigned 12 bit immediate, which is scaled by the
23
+# element size. The function gets the sz:imm and returns the scaled immediate.
24
+%uimm_scaled 10:12 sz:3 !function=uimm_scaled
25
+
26
+@ldst_uimm .. ... . .. .. ............ rn:5 rt:5 &ldst_imm unpriv=0 p=0 w=0 imm=%uimm_scaled
27
+
28
+STR_i sz:2 111 0 01 00 ............ ..... ..... @ldst_uimm sign=0 ext=0
29
+LDR_i 00 111 0 01 01 ............ ..... ..... @ldst_uimm sign=0 ext=1 sz=0
30
+LDR_i 01 111 0 01 01 ............ ..... ..... @ldst_uimm sign=0 ext=1 sz=1
31
+LDR_i 10 111 0 01 01 ............ ..... ..... @ldst_uimm sign=0 ext=1 sz=2
32
+LDR_i 11 111 0 01 01 ............ ..... ..... @ldst_uimm sign=0 ext=0 sz=3
33
+LDR_i 00 111 0 01 10 ............ ..... ..... @ldst_uimm sign=1 ext=0 sz=0
34
+LDR_i 01 111 0 01 10 ............ ..... ..... @ldst_uimm sign=1 ext=0 sz=1
35
+LDR_i 10 111 0 01 10 ............ ..... ..... @ldst_uimm sign=1 ext=0 sz=2
36
+LDR_i 00 111 0 01 11 ............ ..... ..... @ldst_uimm sign=1 ext=1 sz=0
37
+LDR_i 01 111 0 01 11 ............ ..... ..... @ldst_uimm sign=1 ext=1 sz=1
38
+
39
+# PRFM
40
+NOP 11 111 0 01 10 ------------ ----- -----
41
+
42
+STR_v_i sz:2 111 1 01 00 ............ ..... ..... @ldst_uimm sign=0 ext=0
43
+STR_v_i 00 111 1 01 10 ............ ..... ..... @ldst_uimm sign=0 ext=0 sz=4
44
+LDR_v_i sz:2 111 1 01 01 ............ ..... ..... @ldst_uimm sign=0 ext=0
45
+LDR_v_i 00 111 1 01 11 ............ ..... ..... @ldst_uimm sign=0 ext=0 sz=4
46
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
47
index XXXXXXX..XXXXXXX 100644
48
--- a/target/arm/tcg/translate-a64.c
49
+++ b/target/arm/tcg/translate-a64.c
50
@@ -XXX,XX +XXX,XX @@ enum a64_shift_type {
51
A64_SHIFT_TYPE_ROR = 3
52
};
28
53
29
+/*
54
+/*
30
+ * Given a (DeviceID, EventID), look up the corresponding ITE, including
55
+ * Helpers for extracting complex instruction fields
31
+ * checking for the various invalid-value cases. If we find a valid ITE,
32
+ * fill in @ite and @dte and return CMD_CONTINUE_OK. Otherwise return
33
+ * CMD_STALL or CMD_CONTINUE as appropriate (and the contents of @ite
34
+ * should not be relied on).
35
+ *
36
+ * The string @who is purely for the LOG_GUEST_ERROR messages,
37
+ * and should indicate the name of the calling function or similar.
38
+ */
56
+ */
39
+static ItsCmdResult lookup_ite(GICv3ITSState *s, const char *who,
57
+
40
+ uint32_t devid, uint32_t eventid, ITEntry *ite,
58
+/*
41
+ DTEntry *dte)
59
+ * For load/store with an unsigned 12 bit immediate scaled by the element
60
+ * size. The input has the immediate field in bits [14:3] and the element
61
+ * size in [2:0].
62
+ */
63
+static int uimm_scaled(DisasContext *s, int x)
42
+{
64
+{
43
+ uint64_t num_eventids;
65
+ unsigned imm = x >> 3;
44
+
66
+ unsigned scale = extract32(x, 0, 3);
45
+ if (devid >= s->dt.num_entries) {
67
+ return imm << scale;
46
+ qemu_log_mask(LOG_GUEST_ERROR,
47
+ "%s: invalid command attributes: devid %d>=%d",
48
+ who, devid, s->dt.num_entries);
49
+ return CMD_CONTINUE;
50
+ }
51
+
52
+ if (get_dte(s, devid, dte) != MEMTX_OK) {
53
+ return CMD_STALL;
54
+ }
55
+ if (!dte->valid) {
56
+ qemu_log_mask(LOG_GUEST_ERROR,
57
+ "%s: invalid command attributes: "
58
+ "invalid dte for %d\n", who, devid);
59
+ return CMD_CONTINUE;
60
+ }
61
+
62
+ num_eventids = 1ULL << (dte->size + 1);
63
+ if (eventid >= num_eventids) {
64
+ qemu_log_mask(LOG_GUEST_ERROR,
65
+ "%s: invalid command attributes: eventid %d >= %"
66
+ PRId64 "\n", who, eventid, num_eventids);
67
+ return CMD_CONTINUE;
68
+ }
69
+
70
+ if (get_ite(s, eventid, dte, ite) != MEMTX_OK) {
71
+ return CMD_STALL;
72
+ }
73
+
74
+ if (!ite->valid) {
75
+ qemu_log_mask(LOG_GUEST_ERROR,
76
+ "%s: invalid command attributes: invalid ITE\n", who);
77
+ return CMD_CONTINUE;
78
+ }
79
+
80
+ return CMD_CONTINUE_OK;
81
+}
68
+}
82
+
69
+
83
/*
70
/*
84
* This function handles the processing of following commands based on
71
* Include the generated decoders.
85
* the ItsCmdType parameter passed:-
72
*/
86
@@ -XXX,XX +XXX,XX @@ out:
73
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_reg_roffset(DisasContext *s, uint32_t insn,
87
static ItsCmdResult do_process_its_cmd(GICv3ITSState *s, uint32_t devid,
88
uint32_t eventid, ItsCmdType cmd)
89
{
90
- uint64_t num_eventids;
91
DTEntry dte;
92
CTEntry cte;
93
ITEntry ite;
94
+ ItsCmdResult cmdres;
95
96
- if (devid >= s->dt.num_entries) {
97
- qemu_log_mask(LOG_GUEST_ERROR,
98
- "%s: invalid command attributes: devid %d>=%d",
99
- __func__, devid, s->dt.num_entries);
100
- return CMD_CONTINUE;
101
+ cmdres = lookup_ite(s, __func__, devid, eventid, &ite, &dte);
102
+ if (cmdres != CMD_CONTINUE_OK) {
103
+ return cmdres;
104
}
74
}
105
75
}
106
- if (get_dte(s, devid, &dte) != MEMTX_OK) {
76
107
- return CMD_STALL;
77
-/*
108
- }
78
- * Load/store (unsigned immediate)
109
- if (!dte.valid) {
79
- *
110
- qemu_log_mask(LOG_GUEST_ERROR,
80
- * 31 30 29 27 26 25 24 23 22 21 10 9 5
111
- "%s: invalid command attributes: "
81
- * +----+-------+---+-----+-----+------------+-------+------+
112
- "invalid dte for %d\n", __func__, devid);
82
- * |size| 1 1 1 | V | 0 1 | opc | imm12 | Rn | Rt |
113
- return CMD_CONTINUE;
83
- * +----+-------+---+-----+-----+------------+-------+------+
84
- *
85
- * For non-vector:
86
- * size: 00-> byte, 01 -> 16 bit, 10 -> 32bit, 11 -> 64bit
87
- * opc: 00 -> store, 01 -> loadu, 10 -> loads 64, 11 -> loads 32
88
- * For vector:
89
- * size is opc<1>:size<1:0> so 100 -> 128 bit; 110 and 111 unallocated
90
- * opc<0>: 0 -> store, 1 -> load
91
- * Rn: base address register (inc SP)
92
- * Rt: target register
93
- */
94
-static void disas_ldst_reg_unsigned_imm(DisasContext *s, uint32_t insn,
95
- int opc,
96
- int size,
97
- int rt,
98
- bool is_vector)
99
-{
100
- int rn = extract32(insn, 5, 5);
101
- unsigned int imm12 = extract32(insn, 10, 12);
102
- unsigned int offset;
103
- TCGv_i64 clean_addr, dirty_addr;
104
- bool is_store;
105
- bool is_signed = false;
106
- bool is_extended = false;
107
- MemOp memop;
108
-
109
- if (is_vector) {
110
- size |= (opc & 2) << 1;
111
- if (size > 4) {
112
- unallocated_encoding(s);
113
- return;
114
- }
115
- is_store = !extract32(opc, 0, 1);
116
- if (!fp_access_check(s)) {
117
- return;
118
- }
119
- memop = finalize_memop_asimd(s, size);
120
- } else {
121
- if (size == 3 && opc == 2) {
122
- /* PRFM - prefetch */
123
- return;
124
- }
125
- if (opc == 3 && size > 1) {
126
- unallocated_encoding(s);
127
- return;
128
- }
129
- is_store = (opc == 0);
130
- is_signed = !is_store && extract32(opc, 1, 1);
131
- is_extended = (size < 3) && extract32(opc, 0, 1);
132
- memop = finalize_memop(s, size + is_signed * MO_SIGN);
114
- }
133
- }
115
-
134
-
116
- num_eventids = 1ULL << (dte.size + 1);
135
- if (rn == 31) {
117
- if (eventid >= num_eventids) {
136
- gen_check_sp_alignment(s);
118
- qemu_log_mask(LOG_GUEST_ERROR,
119
- "%s: invalid command attributes: eventid %d >= %"
120
- PRId64 "\n",
121
- __func__, eventid, num_eventids);
122
- return CMD_CONTINUE;
123
- }
137
- }
138
- dirty_addr = read_cpu_reg_sp(s, rn, 1);
139
- offset = imm12 << size;
140
- tcg_gen_addi_i64(dirty_addr, dirty_addr, offset);
124
-
141
-
125
- if (get_ite(s, eventid, &dte, &ite) != MEMTX_OK) {
142
- clean_addr = gen_mte_check1(s, dirty_addr, is_store, rn != 31, memop);
126
- return CMD_STALL;
143
-
144
- if (is_vector) {
145
- if (is_store) {
146
- do_fp_st(s, rt, clean_addr, memop);
147
- } else {
148
- do_fp_ld(s, rt, clean_addr, memop);
149
- }
150
- } else {
151
- TCGv_i64 tcg_rt = cpu_reg(s, rt);
152
- bool iss_sf = disas_ldst_compute_iss_sf(size, is_signed, opc);
153
- if (is_store) {
154
- do_gpr_st(s, tcg_rt, clean_addr, memop, true, rt, iss_sf, false);
155
- } else {
156
- do_gpr_ld(s, tcg_rt, clean_addr, memop,
157
- is_extended, true, rt, iss_sf, false);
158
- }
127
- }
159
- }
160
-}
128
-
161
-
129
- if (!ite.valid || ite.inttype != ITE_INTTYPE_PHYSICAL) {
162
/* Atomic memory operations
130
+ if (ite.inttype != ITE_INTTYPE_PHYSICAL) {
163
*
131
qemu_log_mask(LOG_GUEST_ERROR,
164
* 31 30 27 26 24 22 21 16 15 12 10 5 0
132
"%s: invalid command attributes: invalid ITE\n",
165
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_reg(DisasContext *s, uint32_t insn)
133
__func__);
166
return;
134
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_movi(GICv3ITSState *s, const uint64_t *cmdpkt)
167
}
135
{
168
break;
136
uint32_t devid, eventid;
169
- case 1:
137
uint16_t new_icid;
170
- disas_ldst_reg_unsigned_imm(s, insn, opc, size, rt, is_vector);
138
- uint64_t num_eventids;
171
- return;
139
DTEntry dte;
140
CTEntry old_cte, new_cte;
141
ITEntry old_ite;
142
+ ItsCmdResult cmdres;
143
144
devid = FIELD_EX64(cmdpkt[0], MOVI_0, DEVICEID);
145
eventid = FIELD_EX64(cmdpkt[1], MOVI_1, EVENTID);
146
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_movi(GICv3ITSState *s, const uint64_t *cmdpkt)
147
148
trace_gicv3_its_cmd_movi(devid, eventid, new_icid);
149
150
- if (devid >= s->dt.num_entries) {
151
- qemu_log_mask(LOG_GUEST_ERROR,
152
- "%s: invalid command attributes: devid %d>=%d",
153
- __func__, devid, s->dt.num_entries);
154
- return CMD_CONTINUE;
155
- }
156
- if (get_dte(s, devid, &dte) != MEMTX_OK) {
157
- return CMD_STALL;
158
+ cmdres = lookup_ite(s, __func__, devid, eventid, &old_ite, &dte);
159
+ if (cmdres != CMD_CONTINUE_OK) {
160
+ return cmdres;
161
}
172
}
162
173
unallocated_encoding(s);
163
- if (!dte.valid) {
174
}
164
- qemu_log_mask(LOG_GUEST_ERROR,
165
- "%s: invalid command attributes: "
166
- "invalid dte for %d\n", __func__, devid);
167
- return CMD_CONTINUE;
168
- }
169
-
170
- num_eventids = 1ULL << (dte.size + 1);
171
- if (eventid >= num_eventids) {
172
- qemu_log_mask(LOG_GUEST_ERROR,
173
- "%s: invalid command attributes: eventid %d >= %"
174
- PRId64 "\n",
175
- __func__, eventid, num_eventids);
176
- return CMD_CONTINUE;
177
- }
178
-
179
- if (get_ite(s, eventid, &dte, &old_ite) != MEMTX_OK) {
180
- return CMD_STALL;
181
- }
182
-
183
- if (!old_ite.valid || old_ite.inttype != ITE_INTTYPE_PHYSICAL) {
184
+ if (old_ite.inttype != ITE_INTTYPE_PHYSICAL) {
185
qemu_log_mask(LOG_GUEST_ERROR,
186
"%s: invalid command attributes: invalid ITE\n",
187
__func__);
188
--
175
--
189
2.25.1
176
2.34.1
diff view generated by jsdifflib
1
Implement the GICv4 VMAPI and VMAPTI commands. These write
1
Convert the LDR and STR instructions which take a register
2
an interrupt translation table entry that maps (DeviceID,EventID)
2
plus register offset to decodetree.
3
to (vPEID,vINTID,doorbell). The only difference between VMAPI
4
and VMAPTI is that VMAPI assumes vINTID == EventID rather than
5
both being specified in the command packet.
6
7
(This code won't be reachable until we allow the GIC version to be
8
set to 4. Support for reading this new virtual-interrupt DTE and
9
handling it correctly will be implemented in a later commit.)
10
3
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
13
Message-id: 20220408141550.1271295-9-peter.maydell@linaro.org
6
Message-id: 20230602155223.2040685-15-peter.maydell@linaro.org
14
---
7
---
15
hw/intc/gicv3_internal.h | 9 ++++
8
target/arm/tcg/a64.decode | 22 +++++
16
hw/intc/arm_gicv3_its.c | 91 ++++++++++++++++++++++++++++++++++++++++
9
target/arm/tcg/translate-a64.c | 173 +++++++++++++++------------------
17
hw/intc/trace-events | 2 +
10
2 files changed, 103 insertions(+), 92 deletions(-)
18
3 files changed, 102 insertions(+)
19
11
20
diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h
12
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
21
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
22
--- a/hw/intc/gicv3_internal.h
14
--- a/target/arm/tcg/a64.decode
23
+++ b/hw/intc/gicv3_internal.h
15
+++ b/target/arm/tcg/a64.decode
24
@@ -XXX,XX +XXX,XX @@ FIELD(GITS_TYPER, CIL, 36, 1)
16
@@ -XXX,XX +XXX,XX @@ STR_v_i sz:2 111 1 01 00 ............ ..... ..... @ldst_uimm sign=0 ext=
25
#define GITS_CMD_INVALL 0x0D
17
STR_v_i 00 111 1 01 10 ............ ..... ..... @ldst_uimm sign=0 ext=0 sz=4
26
#define GITS_CMD_MOVALL 0x0E
18
LDR_v_i sz:2 111 1 01 01 ............ ..... ..... @ldst_uimm sign=0 ext=0
27
#define GITS_CMD_DISCARD 0x0F
19
LDR_v_i 00 111 1 01 11 ............ ..... ..... @ldst_uimm sign=0 ext=0 sz=4
28
+#define GITS_CMD_VMAPTI 0x2A
20
+
29
+#define GITS_CMD_VMAPI 0x2B
21
+# Load/store with register offset
30
22
+&ldst rm rn rt sign ext sz opt s
31
/* MAPC command fields */
23
+@ldst .. ... . .. .. . rm:5 opt:3 s:1 .. rn:5 rt:5 &ldst
32
#define ICID_LENGTH 16
24
+STR sz:2 111 0 00 00 1 ..... ... . 10 ..... ..... @ldst sign=0 ext=0
33
@@ -XXX,XX +XXX,XX @@ FIELD(MOVI_0, DEVICEID, 32, 32)
25
+LDR 00 111 0 00 01 1 ..... ... . 10 ..... ..... @ldst sign=0 ext=1 sz=0
34
FIELD(MOVI_1, EVENTID, 0, 32)
26
+LDR 01 111 0 00 01 1 ..... ... . 10 ..... ..... @ldst sign=0 ext=1 sz=1
35
FIELD(MOVI_2, ICID, 0, 16)
27
+LDR 10 111 0 00 01 1 ..... ... . 10 ..... ..... @ldst sign=0 ext=1 sz=2
36
28
+LDR 11 111 0 00 01 1 ..... ... . 10 ..... ..... @ldst sign=0 ext=0 sz=3
37
+/* VMAPI, VMAPTI command fields */
29
+LDR 00 111 0 00 10 1 ..... ... . 10 ..... ..... @ldst sign=1 ext=0 sz=0
38
+FIELD(VMAPTI_0, DEVICEID, 32, 32)
30
+LDR 01 111 0 00 10 1 ..... ... . 10 ..... ..... @ldst sign=1 ext=0 sz=1
39
+FIELD(VMAPTI_1, EVENTID, 0, 32)
31
+LDR 10 111 0 00 10 1 ..... ... . 10 ..... ..... @ldst sign=1 ext=0 sz=2
40
+FIELD(VMAPTI_1, VPEID, 32, 16)
32
+LDR 00 111 0 00 11 1 ..... ... . 10 ..... ..... @ldst sign=1 ext=1 sz=0
41
+FIELD(VMAPTI_2, VINTID, 0, 32) /* VMAPTI only */
33
+LDR 01 111 0 00 11 1 ..... ... . 10 ..... ..... @ldst sign=1 ext=1 sz=1
42
+FIELD(VMAPTI_2, DOORBELL, 32, 32)
34
+
43
+
35
+# PRFM
44
/*
36
+NOP 11 111 0 00 10 1 ----- -1- - 10 ----- -----
45
* 12 bytes Interrupt translation Table Entry size
37
+
46
* as per Table 5.3 in GICv3 spec
38
+STR_v sz:2 111 1 00 00 1 ..... ... . 10 ..... ..... @ldst sign=0 ext=0
47
diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
39
+STR_v 00 111 1 00 10 1 ..... ... . 10 ..... ..... @ldst sign=0 ext=0 sz=4
40
+LDR_v sz:2 111 1 00 01 1 ..... ... . 10 ..... ..... @ldst sign=0 ext=0
41
+LDR_v 00 111 1 00 11 1 ..... ... . 10 ..... ..... @ldst sign=0 ext=0 sz=4
42
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
48
index XXXXXXX..XXXXXXX 100644
43
index XXXXXXX..XXXXXXX 100644
49
--- a/hw/intc/arm_gicv3_its.c
44
--- a/target/arm/tcg/translate-a64.c
50
+++ b/hw/intc/arm_gicv3_its.c
45
+++ b/target/arm/tcg/translate-a64.c
51
@@ -XXX,XX +XXX,XX @@ static inline bool intid_in_lpi_range(uint32_t id)
46
@@ -XXX,XX +XXX,XX @@ static bool trans_LDR_v_i(DisasContext *s, arg_ldst_imm *a)
52
id < (1 << (GICD_TYPER_IDBITS + 1));
47
return true;
53
}
48
}
54
49
55
+static inline bool valid_doorbell(uint32_t id)
50
-/*
56
+{
51
- * Load/store (register offset)
57
+ /* Doorbell fields may be an LPI, or 1023 to mean "no doorbell" */
52
- *
58
+ return id == INTID_SPURIOUS || intid_in_lpi_range(id);
53
- * 31 30 29 27 26 25 24 23 22 21 20 16 15 13 12 11 10 9 5 4 0
59
+}
54
- * +----+-------+---+-----+-----+---+------+-----+--+-----+----+----+
60
+
55
- * |size| 1 1 1 | V | 0 0 | opc | 1 | Rm | opt | S| 1 0 | Rn | Rt |
61
static uint64_t baser_base_addr(uint64_t value, uint32_t page_sz)
56
- * +----+-------+---+-----+-----+---+------+-----+--+-----+----+----+
57
- *
58
- * For non-vector:
59
- * size: 00-> byte, 01 -> 16 bit, 10 -> 32bit, 11 -> 64bit
60
- * opc: 00 -> store, 01 -> loadu, 10 -> loads 64, 11 -> loads 32
61
- * For vector:
62
- * size is opc<1>:size<1:0> so 100 -> 128 bit; 110 and 111 unallocated
63
- * opc<0>: 0 -> store, 1 -> load
64
- * V: 1 -> vector/simd
65
- * opt: extend encoding (see DecodeRegExtend)
66
- * S: if S=1 then scale (essentially index by sizeof(size))
67
- * Rt: register to transfer into/out of
68
- * Rn: address register or SP for base
69
- * Rm: offset register or ZR for offset
70
- */
71
-static void disas_ldst_reg_roffset(DisasContext *s, uint32_t insn,
72
- int opc,
73
- int size,
74
- int rt,
75
- bool is_vector)
76
+static void op_addr_ldst_pre(DisasContext *s, arg_ldst *a,
77
+ TCGv_i64 *clean_addr, TCGv_i64 *dirty_addr,
78
+ bool is_store, MemOp memop)
62
{
79
{
63
uint64_t result = 0;
80
- int rn = extract32(insn, 5, 5);
64
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_mapti(GICv3ITSState *s, const uint64_t *cmdpkt,
81
- int shift = extract32(insn, 12, 1);
65
return update_ite(s, eventid, &dte, &ite) ? CMD_CONTINUE : CMD_STALL;
82
- int rm = extract32(insn, 16, 5);
83
- int opt = extract32(insn, 13, 3);
84
- bool is_signed = false;
85
- bool is_store = false;
86
- bool is_extended = false;
87
- TCGv_i64 tcg_rm, clean_addr, dirty_addr;
88
- MemOp memop;
89
+ TCGv_i64 tcg_rm;
90
91
- if (extract32(opt, 1, 1) == 0) {
92
- unallocated_encoding(s);
93
- return;
94
- }
95
-
96
- if (is_vector) {
97
- size |= (opc & 2) << 1;
98
- if (size > 4) {
99
- unallocated_encoding(s);
100
- return;
101
- }
102
- is_store = !extract32(opc, 0, 1);
103
- if (!fp_access_check(s)) {
104
- return;
105
- }
106
- memop = finalize_memop_asimd(s, size);
107
- } else {
108
- if (size == 3 && opc == 2) {
109
- /* PRFM - prefetch */
110
- return;
111
- }
112
- if (opc == 3 && size > 1) {
113
- unallocated_encoding(s);
114
- return;
115
- }
116
- is_store = (opc == 0);
117
- is_signed = !is_store && extract32(opc, 1, 1);
118
- is_extended = (size < 3) && extract32(opc, 0, 1);
119
- memop = finalize_memop(s, size + is_signed * MO_SIGN);
120
- }
121
-
122
- if (rn == 31) {
123
+ if (a->rn == 31) {
124
gen_check_sp_alignment(s);
125
}
126
- dirty_addr = read_cpu_reg_sp(s, rn, 1);
127
+ *dirty_addr = read_cpu_reg_sp(s, a->rn, 1);
128
129
- tcg_rm = read_cpu_reg(s, rm, 1);
130
- ext_and_shift_reg(tcg_rm, tcg_rm, opt, shift ? size : 0);
131
+ tcg_rm = read_cpu_reg(s, a->rm, 1);
132
+ ext_and_shift_reg(tcg_rm, tcg_rm, a->opt, a->s ? a->sz : 0);
133
134
- tcg_gen_add_i64(dirty_addr, dirty_addr, tcg_rm);
135
+ tcg_gen_add_i64(*dirty_addr, *dirty_addr, tcg_rm);
136
+ *clean_addr = gen_mte_check1(s, *dirty_addr, is_store, true, memop);
137
+}
138
139
- clean_addr = gen_mte_check1(s, dirty_addr, is_store, true, memop);
140
+static bool trans_LDR(DisasContext *s, arg_ldst *a)
141
+{
142
+ TCGv_i64 clean_addr, dirty_addr, tcg_rt;
143
+ bool iss_sf = ldst_iss_sf(a->sz, a->sign, a->ext);
144
+ MemOp memop;
145
146
- if (is_vector) {
147
- if (is_store) {
148
- do_fp_st(s, rt, clean_addr, memop);
149
- } else {
150
- do_fp_ld(s, rt, clean_addr, memop);
151
- }
152
- } else {
153
- TCGv_i64 tcg_rt = cpu_reg(s, rt);
154
- bool iss_sf = disas_ldst_compute_iss_sf(size, is_signed, opc);
155
-
156
- if (is_store) {
157
- do_gpr_st(s, tcg_rt, clean_addr, memop,
158
- true, rt, iss_sf, false);
159
- } else {
160
- do_gpr_ld(s, tcg_rt, clean_addr, memop,
161
- is_extended, true, rt, iss_sf, false);
162
- }
163
+ if (extract32(a->opt, 1, 1) == 0) {
164
+ return false;
165
}
166
+
167
+ memop = finalize_memop(s, a->sz + a->sign * MO_SIGN);
168
+ op_addr_ldst_pre(s, a, &clean_addr, &dirty_addr, false, memop);
169
+ tcg_rt = cpu_reg(s, a->rt);
170
+ do_gpr_ld(s, tcg_rt, clean_addr, memop,
171
+ a->ext, true, a->rt, iss_sf, false);
172
+ return true;
173
+}
174
+
175
+static bool trans_STR(DisasContext *s, arg_ldst *a)
176
+{
177
+ TCGv_i64 clean_addr, dirty_addr, tcg_rt;
178
+ bool iss_sf = ldst_iss_sf(a->sz, a->sign, a->ext);
179
+ MemOp memop;
180
+
181
+ if (extract32(a->opt, 1, 1) == 0) {
182
+ return false;
183
+ }
184
+
185
+ memop = finalize_memop(s, a->sz);
186
+ op_addr_ldst_pre(s, a, &clean_addr, &dirty_addr, true, memop);
187
+ tcg_rt = cpu_reg(s, a->rt);
188
+ do_gpr_st(s, tcg_rt, clean_addr, memop, true, a->rt, iss_sf, false);
189
+ return true;
190
+}
191
+
192
+static bool trans_LDR_v(DisasContext *s, arg_ldst *a)
193
+{
194
+ TCGv_i64 clean_addr, dirty_addr;
195
+ MemOp memop;
196
+
197
+ if (extract32(a->opt, 1, 1) == 0) {
198
+ return false;
199
+ }
200
+
201
+ if (!fp_access_check(s)) {
202
+ return true;
203
+ }
204
+
205
+ memop = finalize_memop_asimd(s, a->sz);
206
+ op_addr_ldst_pre(s, a, &clean_addr, &dirty_addr, false, memop);
207
+ do_fp_ld(s, a->rt, clean_addr, memop);
208
+ return true;
209
+}
210
+
211
+static bool trans_STR_v(DisasContext *s, arg_ldst *a)
212
+{
213
+ TCGv_i64 clean_addr, dirty_addr;
214
+ MemOp memop;
215
+
216
+ if (extract32(a->opt, 1, 1) == 0) {
217
+ return false;
218
+ }
219
+
220
+ if (!fp_access_check(s)) {
221
+ return true;
222
+ }
223
+
224
+ memop = finalize_memop_asimd(s, a->sz);
225
+ op_addr_ldst_pre(s, a, &clean_addr, &dirty_addr, true, memop);
226
+ do_fp_st(s, a->rt, clean_addr, memop);
227
+ return true;
66
}
228
}
67
229
68
+static ItsCmdResult process_vmapti(GICv3ITSState *s, const uint64_t *cmdpkt,
230
/* Atomic memory operations
69
+ bool ignore_vintid)
231
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_ldapr_stlr(DisasContext *s, uint32_t insn)
70
+{
232
static void disas_ldst_reg(DisasContext *s, uint32_t insn)
71
+ uint32_t devid, eventid, vintid, doorbell, vpeid;
233
{
72
+ uint32_t num_eventids;
234
int rt = extract32(insn, 0, 5);
73
+ DTEntry dte;
235
- int opc = extract32(insn, 22, 2);
74
+ ITEntry ite;
236
bool is_vector = extract32(insn, 26, 1);
75
+
237
int size = extract32(insn, 30, 2);
76
+ if (!its_feature_virtual(s)) {
238
77
+ return CMD_CONTINUE;
239
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_reg(DisasContext *s, uint32_t insn)
78
+ }
240
disas_ldst_atomic(s, insn, size, rt, is_vector);
79
+
241
return;
80
+ devid = FIELD_EX64(cmdpkt[0], VMAPTI_0, DEVICEID);
242
case 2:
81
+ eventid = FIELD_EX64(cmdpkt[1], VMAPTI_1, EVENTID);
243
- disas_ldst_reg_roffset(s, insn, opc, size, rt, is_vector);
82
+ vpeid = FIELD_EX64(cmdpkt[1], VMAPTI_1, VPEID);
244
- return;
83
+ doorbell = FIELD_EX64(cmdpkt[2], VMAPTI_2, DOORBELL);
84
+ if (ignore_vintid) {
85
+ vintid = eventid;
86
+ trace_gicv3_its_cmd_vmapi(devid, eventid, vpeid, doorbell);
87
+ } else {
88
+ vintid = FIELD_EX64(cmdpkt[2], VMAPTI_2, VINTID);
89
+ trace_gicv3_its_cmd_vmapti(devid, eventid, vpeid, vintid, doorbell);
90
+ }
91
+
92
+ if (devid >= s->dt.num_entries) {
93
+ qemu_log_mask(LOG_GUEST_ERROR,
94
+ "%s: invalid DeviceID 0x%x (must be less than 0x%x)\n",
95
+ __func__, devid, s->dt.num_entries);
96
+ return CMD_CONTINUE;
97
+ }
98
+
99
+ if (get_dte(s, devid, &dte) != MEMTX_OK) {
100
+ return CMD_STALL;
101
+ }
102
+
103
+ if (!dte.valid) {
104
+ qemu_log_mask(LOG_GUEST_ERROR,
105
+ "%s: no entry in device table for DeviceID 0x%x\n",
106
+ __func__, devid);
107
+ return CMD_CONTINUE;
108
+ }
109
+
110
+ num_eventids = 1ULL << (dte.size + 1);
111
+
112
+ if (eventid >= num_eventids) {
113
+ qemu_log_mask(LOG_GUEST_ERROR,
114
+ "%s: EventID 0x%x too large for DeviceID 0x%x "
115
+ "(must be less than 0x%x)\n",
116
+ __func__, eventid, devid, num_eventids);
117
+ return CMD_CONTINUE;
118
+ }
119
+ if (!intid_in_lpi_range(vintid)) {
120
+ qemu_log_mask(LOG_GUEST_ERROR,
121
+ "%s: VIntID 0x%x not a valid LPI\n",
122
+ __func__, vintid);
123
+ return CMD_CONTINUE;
124
+ }
125
+ if (!valid_doorbell(doorbell)) {
126
+ qemu_log_mask(LOG_GUEST_ERROR,
127
+ "%s: Doorbell %d not 1023 and not a valid LPI\n",
128
+ __func__, doorbell);
129
+ return CMD_CONTINUE;
130
+ }
131
+ if (vpeid >= s->vpet.num_entries) {
132
+ qemu_log_mask(LOG_GUEST_ERROR,
133
+ "%s: VPEID 0x%x out of range (must be less than 0x%x)\n",
134
+ __func__, vpeid, s->vpet.num_entries);
135
+ return CMD_CONTINUE;
136
+ }
137
+ /* add ite entry to interrupt translation table */
138
+ ite.valid = true;
139
+ ite.inttype = ITE_INTTYPE_VIRTUAL;
140
+ ite.intid = vintid;
141
+ ite.icid = 0;
142
+ ite.doorbell = doorbell;
143
+ ite.vpeid = vpeid;
144
+ return update_ite(s, eventid, &dte, &ite) ? CMD_CONTINUE : CMD_STALL;
145
+}
146
+
147
/*
148
* Update the Collection Table entry for @icid to @cte. Returns true
149
* on success, false if there was a memory access error.
150
@@ -XXX,XX +XXX,XX @@ static void process_cmdq(GICv3ITSState *s)
151
case GITS_CMD_MOVALL:
152
result = process_movall(s, cmdpkt);
153
break;
154
+ case GITS_CMD_VMAPTI:
155
+ result = process_vmapti(s, cmdpkt, false);
156
+ break;
157
+ case GITS_CMD_VMAPI:
158
+ result = process_vmapti(s, cmdpkt, true);
159
+ break;
245
+ break;
160
default:
246
default:
161
trace_gicv3_its_cmd_unknown(cmd);
247
disas_ldst_pac(s, insn, size, rt, is_vector);
162
break;
248
return;
163
diff --git a/hw/intc/trace-events b/hw/intc/trace-events
164
index XXXXXXX..XXXXXXX 100644
165
--- a/hw/intc/trace-events
166
+++ b/hw/intc/trace-events
167
@@ -XXX,XX +XXX,XX @@ gicv3_its_cmd_mapti(uint32_t devid, uint32_t eventid, uint32_t icid, uint32_t in
168
gicv3_its_cmd_inv(void) "GICv3 ITS: command INV or INVALL"
169
gicv3_its_cmd_movall(uint64_t rd1, uint64_t rd2) "GICv3 ITS: command MOVALL RDbase1 0x%" PRIx64 " RDbase2 0x%" PRIx64
170
gicv3_its_cmd_movi(uint32_t devid, uint32_t eventid, uint32_t icid) "GICv3 ITS: command MOVI DeviceID 0x%x EventID 0x%x ICID 0x%x"
171
+gicv3_its_cmd_vmapi(uint32_t devid, uint32_t eventid, uint32_t vpeid, uint32_t doorbell) "GICv3 ITS: command VMAPI DeviceID 0x%x EventID 0x%x vPEID 0x%x Dbell_pINTID 0x%x"
172
+gicv3_its_cmd_vmapti(uint32_t devid, uint32_t eventid, uint32_t vpeid, uint32_t vintid, uint32_t doorbell) "GICv3 ITS: command VMAPI DeviceID 0x%x EventID 0x%x vPEID 0x%x vINTID 0x%x Dbell_pINTID 0x%x"
173
gicv3_its_cmd_unknown(unsigned cmd) "GICv3 ITS: unknown command 0x%x"
174
gicv3_its_cte_read(uint32_t icid, int valid, uint32_t rdbase) "GICv3 ITS: Collection Table read for ICID 0x%x: valid %d RDBase 0x%x"
175
gicv3_its_cte_write(uint32_t icid, int valid, uint32_t rdbase) "GICv3 ITS: Collection Table write for ICID 0x%x: valid %d RDBase 0x%x"
176
--
249
--
177
2.25.1
250
2.34.1
diff view generated by jsdifflib
1
The function gicv3_cpuif_virt_update() currently sets all of vIRQ,
1
Convert the insns in the atomic memory operations group to
2
vFIQ and the maintenance interrupt. This implies that it has to be
2
decodetree.
3
used quite carefully -- as the comment notes, setting the maintenance
4
interrupt will typically cause the GIC code to be re-entered
5
recursively. For handling vLPIs, we need the redistributor to be
6
able to tell the cpuif to update the vIRQ and vFIQ lines when the
7
highest priority pending vLPI changes. Since that change can't cause
8
the maintenance interrupt state to change, we can pull the "update
9
vIRQ/vFIQ" parts of gicv3_cpuif_virt_update() out into a separate
10
function, which the redistributor can then call without having to
11
worry about the reentrancy issue.
12
3
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
Message-id: 20220408141550.1271295-25-peter.maydell@linaro.org
6
Message-id: 20230602155223.2040685-16-peter.maydell@linaro.org
16
---
7
---
17
hw/intc/gicv3_internal.h | 11 +++++++
8
target/arm/tcg/a64.decode | 15 ++++
18
hw/intc/arm_gicv3_cpuif.c | 64 ++++++++++++++++++++++++---------------
9
target/arm/tcg/translate-a64.c | 153 ++++++++++++---------------------
19
hw/intc/trace-events | 3 +-
10
2 files changed, 70 insertions(+), 98 deletions(-)
20
3 files changed, 53 insertions(+), 25 deletions(-)
21
11
22
diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h
12
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
23
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
24
--- a/hw/intc/gicv3_internal.h
14
--- a/target/arm/tcg/a64.decode
25
+++ b/hw/intc/gicv3_internal.h
15
+++ b/target/arm/tcg/a64.decode
26
@@ -XXX,XX +XXX,XX @@ void gicv3_init_cpuif(GICv3State *s);
16
@@ -XXX,XX +XXX,XX @@ STR_v sz:2 111 1 00 00 1 ..... ... . 10 ..... ..... @ldst sign=0 ext=0
27
*/
17
STR_v 00 111 1 00 10 1 ..... ... . 10 ..... ..... @ldst sign=0 ext=0 sz=4
28
void gicv3_cpuif_update(GICv3CPUState *cs);
18
LDR_v sz:2 111 1 00 01 1 ..... ... . 10 ..... ..... @ldst sign=0 ext=0
29
19
LDR_v 00 111 1 00 11 1 ..... ... . 10 ..... ..... @ldst sign=0 ext=0 sz=4
30
+/*
20
+
31
+ * gicv3_cpuif_virt_irq_fiq_update:
21
+# Atomic memory operations
32
+ * @cs: GICv3CPUState for the CPU to update
22
+&atomic rs rn rt a r sz
33
+ *
23
+@atomic sz:2 ... . .. a:1 r:1 . rs:5 . ... .. rn:5 rt:5 &atomic
34
+ * Recalculate whether to assert the virtual IRQ or FIQ lines after
24
+LDADD .. 111 0 00 . . 1 ..... 0000 00 ..... ..... @atomic
35
+ * a change to the current highest priority pending virtual interrupt.
25
+LDCLR .. 111 0 00 . . 1 ..... 0001 00 ..... ..... @atomic
36
+ * Note that this does not recalculate and change the maintenance
26
+LDEOR .. 111 0 00 . . 1 ..... 0010 00 ..... ..... @atomic
37
+ * interrupt status (for that, see gicv3_cpuif_virt_update()).
27
+LDSET .. 111 0 00 . . 1 ..... 0011 00 ..... ..... @atomic
38
+ */
28
+LDSMAX .. 111 0 00 . . 1 ..... 0100 00 ..... ..... @atomic
39
+void gicv3_cpuif_virt_irq_fiq_update(GICv3CPUState *cs);
29
+LDSMIN .. 111 0 00 . . 1 ..... 0101 00 ..... ..... @atomic
40
+
30
+LDUMAX .. 111 0 00 . . 1 ..... 0110 00 ..... ..... @atomic
41
static inline uint32_t gicv3_iidr(void)
31
+LDUMIN .. 111 0 00 . . 1 ..... 0111 00 ..... ..... @atomic
32
+SWP .. 111 0 00 . . 1 ..... 1000 00 ..... ..... @atomic
33
+
34
+LDAPR sz:2 111 0 00 1 0 1 11111 1100 00 rn:5 rt:5
35
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
36
index XXXXXXX..XXXXXXX 100644
37
--- a/target/arm/tcg/translate-a64.c
38
+++ b/target/arm/tcg/translate-a64.c
39
@@ -XXX,XX +XXX,XX @@ static bool trans_STR_v(DisasContext *s, arg_ldst *a)
40
return true;
41
}
42
43
-/* Atomic memory operations
44
- *
45
- * 31 30 27 26 24 22 21 16 15 12 10 5 0
46
- * +------+-------+---+-----+-----+---+----+----+-----+-----+----+-----+
47
- * | size | 1 1 1 | V | 0 0 | A R | 1 | Rs | o3 | opc | 0 0 | Rn | Rt |
48
- * +------+-------+---+-----+-----+--------+----+-----+-----+----+-----+
49
- *
50
- * Rt: the result register
51
- * Rn: base address or SP
52
- * Rs: the source register for the operation
53
- * V: vector flag (always 0 as of v8.3)
54
- * A: acquire flag
55
- * R: release flag
56
- */
57
-static void disas_ldst_atomic(DisasContext *s, uint32_t insn,
58
- int size, int rt, bool is_vector)
59
+
60
+static bool do_atomic_ld(DisasContext *s, arg_atomic *a, AtomicThreeOpFn *fn,
61
+ int sign, bool invert)
42
{
62
{
43
/* Return the Implementer Identification Register value
63
- int rs = extract32(insn, 16, 5);
44
diff --git a/hw/intc/arm_gicv3_cpuif.c b/hw/intc/arm_gicv3_cpuif.c
64
- int rn = extract32(insn, 5, 5);
45
index XXXXXXX..XXXXXXX 100644
65
- int o3_opc = extract32(insn, 12, 4);
46
--- a/hw/intc/arm_gicv3_cpuif.c
66
- bool r = extract32(insn, 22, 1);
47
+++ b/hw/intc/arm_gicv3_cpuif.c
67
- bool a = extract32(insn, 23, 1);
48
@@ -XXX,XX +XXX,XX @@ static uint32_t maintenance_interrupt_state(GICv3CPUState *cs)
68
- TCGv_i64 tcg_rs, tcg_rt, clean_addr;
49
return value;
69
- AtomicThreeOpFn *fn = NULL;
50
}
70
- MemOp mop = size;
51
71
+ MemOp mop = a->sz | sign;
52
-static void gicv3_cpuif_virt_update(GICv3CPUState *cs)
72
+ TCGv_i64 clean_addr, tcg_rs, tcg_rt;
53
+void gicv3_cpuif_virt_irq_fiq_update(GICv3CPUState *cs)
73
54
{
74
- if (is_vector || !dc_isar_feature(aa64_atomics, s)) {
55
- /* Tell the CPU about any pending virtual interrupts or
75
- unallocated_encoding(s);
56
- * maintenance interrupts, following a change to the state
76
- return;
57
- * of the CPU interface relevant to virtual interrupts.
77
- }
58
- *
78
- switch (o3_opc) {
59
- * CAUTION: this function will call qemu_set_irq() on the
79
- case 000: /* LDADD */
60
- * CPU maintenance IRQ line, which is typically wired up
80
- fn = tcg_gen_atomic_fetch_add_i64;
61
- * to the GIC as a per-CPU interrupt. This means that it
81
- break;
62
- * will recursively call back into the GIC code via
82
- case 001: /* LDCLR */
63
- * gicv3_redist_set_irq() and thus into the CPU interface code's
83
- fn = tcg_gen_atomic_fetch_and_i64;
64
- * gicv3_cpuif_update(). It is therefore important that this
84
- break;
65
- * function is only called as the final action of a CPU interface
85
- case 002: /* LDEOR */
66
- * register write implementation, after all the GIC state
86
- fn = tcg_gen_atomic_fetch_xor_i64;
67
- * fields have been updated. gicv3_cpuif_update() also must
87
- break;
68
- * not cause this function to be called, but that happens
88
- case 003: /* LDSET */
69
- * naturally as a result of there being no architectural
89
- fn = tcg_gen_atomic_fetch_or_i64;
70
- * linkage between the physical and virtual GIC logic.
90
- break;
91
- case 004: /* LDSMAX */
92
- fn = tcg_gen_atomic_fetch_smax_i64;
93
- mop |= MO_SIGN;
94
- break;
95
- case 005: /* LDSMIN */
96
- fn = tcg_gen_atomic_fetch_smin_i64;
97
- mop |= MO_SIGN;
98
- break;
99
- case 006: /* LDUMAX */
100
- fn = tcg_gen_atomic_fetch_umax_i64;
101
- break;
102
- case 007: /* LDUMIN */
103
- fn = tcg_gen_atomic_fetch_umin_i64;
104
- break;
105
- case 010: /* SWP */
106
- fn = tcg_gen_atomic_xchg_i64;
107
- break;
108
- case 014: /* LDAPR, LDAPRH, LDAPRB */
109
- if (!dc_isar_feature(aa64_rcpc_8_3, s) ||
110
- rs != 31 || a != 1 || r != 0) {
111
- unallocated_encoding(s);
112
- return;
113
- }
114
- break;
115
- default:
116
- unallocated_encoding(s);
117
- return;
118
- }
119
-
120
- if (rn == 31) {
121
+ if (a->rn == 31) {
122
gen_check_sp_alignment(s);
123
}
124
-
125
- mop = check_atomic_align(s, rn, mop);
126
- clean_addr = gen_mte_check1(s, cpu_reg_sp(s, rn), false, rn != 31, mop);
127
-
128
- if (o3_opc == 014) {
129
- /*
130
- * LDAPR* are a special case because they are a simple load, not a
131
- * fetch-and-do-something op.
132
- * The architectural consistency requirements here are weaker than
133
- * full load-acquire (we only need "load-acquire processor consistent"),
134
- * but we choose to implement them as full LDAQ.
135
- */
136
- do_gpr_ld(s, cpu_reg(s, rt), clean_addr, mop, false,
137
- true, rt, disas_ldst_compute_iss_sf(size, false, 0), true);
138
- tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ);
139
- return;
140
- }
141
-
142
- tcg_rs = read_cpu_reg(s, rs, true);
143
- tcg_rt = cpu_reg(s, rt);
144
-
145
- if (o3_opc == 1) { /* LDCLR */
146
+ mop = check_atomic_align(s, a->rn, mop);
147
+ clean_addr = gen_mte_check1(s, cpu_reg_sp(s, a->rn), false,
148
+ a->rn != 31, mop);
149
+ tcg_rs = read_cpu_reg(s, a->rs, true);
150
+ tcg_rt = cpu_reg(s, a->rt);
151
+ if (invert) {
152
tcg_gen_not_i64(tcg_rs, tcg_rs);
153
}
154
-
155
- /* The tcg atomic primitives are all full barriers. Therefore we
71
+ /*
156
+ /*
72
+ * Tell the CPU about any pending virtual interrupts.
157
+ * The tcg atomic primitives are all full barriers. Therefore we
73
+ * This should only be called for changes that affect the
158
* can ignore the Acquire and Release bits of this instruction.
74
+ * vIRQ and vFIQ status and do not change the maintenance
75
+ * interrupt status. This means that unlike gicv3_cpuif_virt_update()
76
+ * this function won't recursively call back into the GIC code.
77
+ * The main use of this is when the redistributor has changed the
78
+ * highest priority pending virtual LPI.
79
*/
159
*/
80
int idx;
160
fn(tcg_rt, clean_addr, tcg_rs, get_mem_index(s), mop);
81
int irqlevel = 0;
161
82
int fiqlevel = 0;
162
if (mop & MO_SIGN) {
83
- int maintlevel = 0;
163
- switch (size) {
84
- ARMCPU *cpu = ARM_CPU(cs->cpu);
164
+ switch (a->sz) {
85
165
case MO_8:
86
idx = hppvi_index(cs);
166
tcg_gen_ext8u_i64(tcg_rt, tcg_rt);
87
trace_gicv3_cpuif_virt_update(gicv3_redist_affid(cs), idx);
167
break;
88
@@ -XXX,XX +XXX,XX @@ static void gicv3_cpuif_virt_update(GICv3CPUState *cs)
168
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_atomic(DisasContext *s, uint32_t insn,
169
g_assert_not_reached();
89
}
170
}
90
}
171
}
91
172
+ return true;
92
+ trace_gicv3_cpuif_virt_set_irqs(gicv3_redist_affid(cs), fiqlevel, irqlevel);
93
+ qemu_set_irq(cs->parent_vfiq, fiqlevel);
94
+ qemu_set_irq(cs->parent_virq, irqlevel);
95
+}
173
+}
96
+
174
+
97
+static void gicv3_cpuif_virt_update(GICv3CPUState *cs)
175
+TRANS_FEAT(LDADD, aa64_atomics, do_atomic_ld, a, tcg_gen_atomic_fetch_add_i64, 0, false)
176
+TRANS_FEAT(LDCLR, aa64_atomics, do_atomic_ld, a, tcg_gen_atomic_fetch_and_i64, 0, true)
177
+TRANS_FEAT(LDEOR, aa64_atomics, do_atomic_ld, a, tcg_gen_atomic_fetch_xor_i64, 0, false)
178
+TRANS_FEAT(LDSET, aa64_atomics, do_atomic_ld, a, tcg_gen_atomic_fetch_or_i64, 0, false)
179
+TRANS_FEAT(LDSMAX, aa64_atomics, do_atomic_ld, a, tcg_gen_atomic_fetch_smax_i64, MO_SIGN, false)
180
+TRANS_FEAT(LDSMIN, aa64_atomics, do_atomic_ld, a, tcg_gen_atomic_fetch_smin_i64, MO_SIGN, false)
181
+TRANS_FEAT(LDUMAX, aa64_atomics, do_atomic_ld, a, tcg_gen_atomic_fetch_umax_i64, 0, false)
182
+TRANS_FEAT(LDUMIN, aa64_atomics, do_atomic_ld, a, tcg_gen_atomic_fetch_umin_i64, 0, false)
183
+TRANS_FEAT(SWP, aa64_atomics, do_atomic_ld, a, tcg_gen_atomic_xchg_i64, 0, false)
184
+
185
+static bool trans_LDAPR(DisasContext *s, arg_LDAPR *a)
98
+{
186
+{
187
+ bool iss_sf = ldst_iss_sf(a->sz, false, false);
188
+ TCGv_i64 clean_addr;
189
+ MemOp mop;
190
+
191
+ if (!dc_isar_feature(aa64_atomics, s) ||
192
+ !dc_isar_feature(aa64_rcpc_8_3, s)) {
193
+ return false;
194
+ }
195
+ if (a->rn == 31) {
196
+ gen_check_sp_alignment(s);
197
+ }
198
+ mop = check_atomic_align(s, a->rn, a->sz);
199
+ clean_addr = gen_mte_check1(s, cpu_reg_sp(s, a->rn), false,
200
+ a->rn != 31, mop);
99
+ /*
201
+ /*
100
+ * Tell the CPU about any pending virtual interrupts or
202
+ * LDAPR* are a special case because they are a simple load, not a
101
+ * maintenance interrupts, following a change to the state
203
+ * fetch-and-do-something op.
102
+ * of the CPU interface relevant to virtual interrupts.
204
+ * The architectural consistency requirements here are weaker than
103
+ *
205
+ * full load-acquire (we only need "load-acquire processor consistent"),
104
+ * CAUTION: this function will call qemu_set_irq() on the
206
+ * but we choose to implement them as full LDAQ.
105
+ * CPU maintenance IRQ line, which is typically wired up
106
+ * to the GIC as a per-CPU interrupt. This means that it
107
+ * will recursively call back into the GIC code via
108
+ * gicv3_redist_set_irq() and thus into the CPU interface code's
109
+ * gicv3_cpuif_update(). It is therefore important that this
110
+ * function is only called as the final action of a CPU interface
111
+ * register write implementation, after all the GIC state
112
+ * fields have been updated. gicv3_cpuif_update() also must
113
+ * not cause this function to be called, but that happens
114
+ * naturally as a result of there being no architectural
115
+ * linkage between the physical and virtual GIC logic.
116
+ */
207
+ */
117
+ ARMCPU *cpu = ARM_CPU(cs->cpu);
208
+ do_gpr_ld(s, cpu_reg(s, a->rt), clean_addr, mop, false,
118
+ int maintlevel = 0;
209
+ true, a->rt, iss_sf, true);
119
+
210
+ tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ);
120
+ gicv3_cpuif_virt_irq_fiq_update(cs);
211
+ return true;
121
+
122
if ((cs->ich_hcr_el2 & ICH_HCR_EL2_EN) &&
123
maintenance_interrupt_state(cs) != 0) {
124
maintlevel = 1;
125
}
126
127
- trace_gicv3_cpuif_virt_set_irqs(gicv3_redist_affid(cs), fiqlevel,
128
- irqlevel, maintlevel);
129
-
130
- qemu_set_irq(cs->parent_vfiq, fiqlevel);
131
- qemu_set_irq(cs->parent_virq, irqlevel);
132
+ trace_gicv3_cpuif_virt_set_maint_irq(gicv3_redist_affid(cs), maintlevel);
133
qemu_set_irq(cpu->gicv3_maintenance_interrupt, maintlevel);
134
}
212
}
135
213
136
diff --git a/hw/intc/trace-events b/hw/intc/trace-events
214
/*
137
index XXXXXXX..XXXXXXX 100644
215
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_reg(DisasContext *s, uint32_t insn)
138
--- a/hw/intc/trace-events
216
}
139
+++ b/hw/intc/trace-events
217
switch (extract32(insn, 10, 2)) {
140
@@ -XXX,XX +XXX,XX @@ gicv3_icv_dir_write(uint32_t cpu, uint64_t val) "GICv3 ICV_DIR write cpu 0x%x va
218
case 0:
141
gicv3_icv_iar_read(int grp, uint32_t cpu, uint64_t val) "GICv3 ICV_IAR%d read cpu 0x%x value 0x%" PRIx64
219
- disas_ldst_atomic(s, insn, size, rt, is_vector);
142
gicv3_icv_eoir_write(int grp, uint32_t cpu, uint64_t val) "GICv3 ICV_EOIR%d write cpu 0x%x value 0x%" PRIx64
220
- return;
143
gicv3_cpuif_virt_update(uint32_t cpuid, int idx) "GICv3 CPU i/f 0x%x virt HPPI update LR index %d"
221
case 2:
144
-gicv3_cpuif_virt_set_irqs(uint32_t cpuid, int fiqlevel, int irqlevel, int maintlevel) "GICv3 CPU i/f 0x%x virt HPPI update: setting FIQ %d IRQ %d maintenance-irq %d"
222
break;
145
+gicv3_cpuif_virt_set_irqs(uint32_t cpuid, int fiqlevel, int irqlevel) "GICv3 CPU i/f 0x%x virt HPPI update: setting FIQ %d IRQ %d"
223
default:
146
+gicv3_cpuif_virt_set_maint_irq(uint32_t cpuid, int maintlevel) "GICv3 CPU i/f 0x%x virt HPPI update: setting maintenance-irq %d"
147
148
# arm_gicv3_dist.c
149
gicv3_dist_read(uint64_t offset, uint64_t data, unsigned size, bool secure) "GICv3 distributor read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u secure %d"
150
--
224
--
151
2.25.1
225
2.34.1
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
Convert the instructions in the load/store register (pointer
2
authentication) group ot decodetree: LDRAA, LDRAB.
2
3
3
Use tcg_constant_{i32,i64} as appropriate throughout.
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20230602155223.2040685-17-peter.maydell@linaro.org
8
---
9
target/arm/tcg/a64.decode | 7 +++
10
target/arm/tcg/translate-a64.c | 83 +++++++---------------------------
11
2 files changed, 23 insertions(+), 67 deletions(-)
4
12
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
13
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
---
9
target/arm/translate-vfp.c | 76 ++++++++++++--------------------------
10
1 file changed, 23 insertions(+), 53 deletions(-)
11
12
diff --git a/target/arm/translate-vfp.c b/target/arm/translate-vfp.c
13
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/translate-vfp.c
15
--- a/target/arm/tcg/a64.decode
15
+++ b/target/arm/translate-vfp.c
16
+++ b/target/arm/tcg/a64.decode
16
@@ -XXX,XX +XXX,XX @@ static void gen_update_fp_context(DisasContext *s)
17
@@ -XXX,XX +XXX,XX @@ LDUMIN .. 111 0 00 . . 1 ..... 0111 00 ..... ..... @atomic
17
gen_helper_vfp_set_fpscr(cpu_env, fpscr);
18
SWP .. 111 0 00 . . 1 ..... 1000 00 ..... ..... @atomic
18
tcg_temp_free_i32(fpscr);
19
19
if (dc_isar_feature(aa32_mve, s)) {
20
LDAPR sz:2 111 0 00 1 0 1 11111 1100 00 rn:5 rt:5
20
- TCGv_i32 z32 = tcg_const_i32(0);
21
+
21
- store_cpu_field(z32, v7m.vpr);
22
+# Load/store register (pointer authentication)
22
+ store_cpu_field(tcg_constant_i32(0), v7m.vpr);
23
+
23
}
24
+# LDRA immediate is 10 bits signed and scaled, but the bits aren't all contiguous
24
/*
25
+%ldra_imm 22:s1 12:9 !function=times_2
25
* We just updated the FPSCR and VPR. Some of this state is cached
26
+
26
@@ -XXX,XX +XXX,XX @@ static bool trans_VSEL(DisasContext *s, arg_VSEL *a)
27
+LDRA 11 111 0 00 m:1 . 1 ......... w:1 1 rn:5 rt:5 imm=%ldra_imm
27
TCGv_i64 frn, frm, dest;
28
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
28
TCGv_i64 tmp, zero, zf, nf, vf;
29
index XXXXXXX..XXXXXXX 100644
29
30
--- a/target/arm/tcg/translate-a64.c
30
- zero = tcg_const_i64(0);
31
+++ b/target/arm/tcg/translate-a64.c
31
+ zero = tcg_constant_i64(0);
32
@@ -XXX,XX +XXX,XX @@ static bool trans_LDAPR(DisasContext *s, arg_LDAPR *a)
32
33
frn = tcg_temp_new_i64();
34
frm = tcg_temp_new_i64();
35
@@ -XXX,XX +XXX,XX @@ static bool trans_VSEL(DisasContext *s, arg_VSEL *a)
36
vfp_load_reg64(frm, rm);
37
switch (a->cc) {
38
case 0: /* eq: Z */
39
- tcg_gen_movcond_i64(TCG_COND_EQ, dest, zf, zero,
40
- frn, frm);
41
+ tcg_gen_movcond_i64(TCG_COND_EQ, dest, zf, zero, frn, frm);
42
break;
43
case 1: /* vs: V */
44
- tcg_gen_movcond_i64(TCG_COND_LT, dest, vf, zero,
45
- frn, frm);
46
+ tcg_gen_movcond_i64(TCG_COND_LT, dest, vf, zero, frn, frm);
47
break;
48
case 2: /* ge: N == V -> N ^ V == 0 */
49
tmp = tcg_temp_new_i64();
50
tcg_gen_xor_i64(tmp, vf, nf);
51
- tcg_gen_movcond_i64(TCG_COND_GE, dest, tmp, zero,
52
- frn, frm);
53
+ tcg_gen_movcond_i64(TCG_COND_GE, dest, tmp, zero, frn, frm);
54
tcg_temp_free_i64(tmp);
55
break;
56
case 3: /* gt: !Z && N == V */
57
- tcg_gen_movcond_i64(TCG_COND_NE, dest, zf, zero,
58
- frn, frm);
59
+ tcg_gen_movcond_i64(TCG_COND_NE, dest, zf, zero, frn, frm);
60
tmp = tcg_temp_new_i64();
61
tcg_gen_xor_i64(tmp, vf, nf);
62
- tcg_gen_movcond_i64(TCG_COND_GE, dest, tmp, zero,
63
- dest, frm);
64
+ tcg_gen_movcond_i64(TCG_COND_GE, dest, tmp, zero, dest, frm);
65
tcg_temp_free_i64(tmp);
66
break;
67
}
68
@@ -XXX,XX +XXX,XX @@ static bool trans_VSEL(DisasContext *s, arg_VSEL *a)
69
tcg_temp_free_i64(zf);
70
tcg_temp_free_i64(nf);
71
tcg_temp_free_i64(vf);
72
-
73
- tcg_temp_free_i64(zero);
74
} else {
75
TCGv_i32 frn, frm, dest;
76
TCGv_i32 tmp, zero;
77
78
- zero = tcg_const_i32(0);
79
+ zero = tcg_constant_i32(0);
80
81
frn = tcg_temp_new_i32();
82
frm = tcg_temp_new_i32();
83
@@ -XXX,XX +XXX,XX @@ static bool trans_VSEL(DisasContext *s, arg_VSEL *a)
84
vfp_load_reg32(frm, rm);
85
switch (a->cc) {
86
case 0: /* eq: Z */
87
- tcg_gen_movcond_i32(TCG_COND_EQ, dest, cpu_ZF, zero,
88
- frn, frm);
89
+ tcg_gen_movcond_i32(TCG_COND_EQ, dest, cpu_ZF, zero, frn, frm);
90
break;
91
case 1: /* vs: V */
92
- tcg_gen_movcond_i32(TCG_COND_LT, dest, cpu_VF, zero,
93
- frn, frm);
94
+ tcg_gen_movcond_i32(TCG_COND_LT, dest, cpu_VF, zero, frn, frm);
95
break;
96
case 2: /* ge: N == V -> N ^ V == 0 */
97
tmp = tcg_temp_new_i32();
98
tcg_gen_xor_i32(tmp, cpu_VF, cpu_NF);
99
- tcg_gen_movcond_i32(TCG_COND_GE, dest, tmp, zero,
100
- frn, frm);
101
+ tcg_gen_movcond_i32(TCG_COND_GE, dest, tmp, zero, frn, frm);
102
tcg_temp_free_i32(tmp);
103
break;
104
case 3: /* gt: !Z && N == V */
105
- tcg_gen_movcond_i32(TCG_COND_NE, dest, cpu_ZF, zero,
106
- frn, frm);
107
+ tcg_gen_movcond_i32(TCG_COND_NE, dest, cpu_ZF, zero, frn, frm);
108
tmp = tcg_temp_new_i32();
109
tcg_gen_xor_i32(tmp, cpu_VF, cpu_NF);
110
- tcg_gen_movcond_i32(TCG_COND_GE, dest, tmp, zero,
111
- dest, frm);
112
+ tcg_gen_movcond_i32(TCG_COND_GE, dest, tmp, zero, dest, frm);
113
tcg_temp_free_i32(tmp);
114
break;
115
}
116
@@ -XXX,XX +XXX,XX @@ static bool trans_VSEL(DisasContext *s, arg_VSEL *a)
117
tcg_temp_free_i32(frn);
118
tcg_temp_free_i32(frm);
119
tcg_temp_free_i32(dest);
120
-
121
- tcg_temp_free_i32(zero);
122
}
123
124
return true;
125
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT(DisasContext *s, arg_VCVT *a)
126
fpst = fpstatus_ptr(FPST_FPCR);
127
}
128
129
- tcg_shift = tcg_const_i32(0);
130
+ tcg_shift = tcg_constant_i32(0);
131
132
tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rounding));
133
gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
134
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT(DisasContext *s, arg_VCVT *a)
135
gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
136
tcg_temp_free_i32(tcg_rmode);
137
138
- tcg_temp_free_i32(tcg_shift);
139
-
140
tcg_temp_free_ptr(fpst);
141
142
return true;
143
@@ -XXX,XX +XXX,XX @@ static bool trans_VMSR_VMRS(DisasContext *s, arg_VMSR_VMRS *a)
144
case ARM_VFP_MVFR2:
145
case ARM_VFP_FPSID:
146
if (s->current_el == 1) {
147
- TCGv_i32 tcg_reg, tcg_rt;
148
-
149
gen_set_condexec(s);
150
gen_set_pc_im(s, s->pc_curr);
151
- tcg_reg = tcg_const_i32(a->reg);
152
- tcg_rt = tcg_const_i32(a->rt);
153
- gen_helper_check_hcr_el2_trap(cpu_env, tcg_rt, tcg_reg);
154
- tcg_temp_free_i32(tcg_reg);
155
- tcg_temp_free_i32(tcg_rt);
156
+ gen_helper_check_hcr_el2_trap(cpu_env,
157
+ tcg_constant_i32(a->rt),
158
+ tcg_constant_i32(a->reg));
159
}
160
/* fall through */
161
case ARM_VFP_FPEXC:
162
@@ -XXX,XX +XXX,XX @@ MAKE_VFM_TRANS_FNS(dp)
163
164
static bool trans_VMOV_imm_hp(DisasContext *s, arg_VMOV_imm_sp *a)
165
{
166
- TCGv_i32 fd;
167
-
168
if (!dc_isar_feature(aa32_fp16_arith, s)) {
169
return false;
170
}
171
@@ -XXX,XX +XXX,XX @@ static bool trans_VMOV_imm_hp(DisasContext *s, arg_VMOV_imm_sp *a)
172
return true;
173
}
174
175
- fd = tcg_const_i32(vfp_expand_imm(MO_16, a->imm));
176
- vfp_store_reg32(fd, a->vd);
177
- tcg_temp_free_i32(fd);
178
+ vfp_store_reg32(tcg_constant_i32(vfp_expand_imm(MO_16, a->imm)), a->vd);
179
return true;
33
return true;
180
}
34
}
181
35
182
@@ -XXX,XX +XXX,XX @@ static bool trans_VMOV_imm_sp(DisasContext *s, arg_VMOV_imm_sp *a)
36
-/*
37
- * PAC memory operations
38
- *
39
- * 31 30 27 26 24 22 21 12 11 10 5 0
40
- * +------+-------+---+-----+-----+---+--------+---+---+----+-----+
41
- * | size | 1 1 1 | V | 0 0 | M S | 1 | imm9 | W | 1 | Rn | Rt |
42
- * +------+-------+---+-----+-----+---+--------+---+---+----+-----+
43
- *
44
- * Rt: the result register
45
- * Rn: base address or SP
46
- * V: vector flag (always 0 as of v8.3)
47
- * M: clear for key DA, set for key DB
48
- * W: pre-indexing flag
49
- * S: sign for imm9.
50
- */
51
-static void disas_ldst_pac(DisasContext *s, uint32_t insn,
52
- int size, int rt, bool is_vector)
53
+static bool trans_LDRA(DisasContext *s, arg_LDRA *a)
54
{
55
- int rn = extract32(insn, 5, 5);
56
- bool is_wback = extract32(insn, 11, 1);
57
- bool use_key_a = !extract32(insn, 23, 1);
58
- int offset;
59
TCGv_i64 clean_addr, dirty_addr, tcg_rt;
60
MemOp memop;
61
62
- if (size != 3 || is_vector || !dc_isar_feature(aa64_pauth, s)) {
63
- unallocated_encoding(s);
64
- return;
65
+ /* Load with pointer authentication */
66
+ if (!dc_isar_feature(aa64_pauth, s)) {
67
+ return false;
68
}
69
70
- if (rn == 31) {
71
+ if (a->rn == 31) {
72
gen_check_sp_alignment(s);
73
}
74
- dirty_addr = read_cpu_reg_sp(s, rn, 1);
75
+ dirty_addr = read_cpu_reg_sp(s, a->rn, 1);
76
77
if (s->pauth_active) {
78
- if (use_key_a) {
79
+ if (!a->m) {
80
gen_helper_autda(dirty_addr, cpu_env, dirty_addr,
81
tcg_constant_i64(0));
82
} else {
83
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_pac(DisasContext *s, uint32_t insn,
183
}
84
}
184
}
85
}
185
86
186
- fd = tcg_const_i32(vfp_expand_imm(MO_32, a->imm));
87
- /* Form the 10-bit signed, scaled offset. */
187
+ fd = tcg_constant_i32(vfp_expand_imm(MO_32, a->imm));
88
- offset = (extract32(insn, 22, 1) << 9) | extract32(insn, 12, 9);
188
89
- offset = sextract32(offset << size, 0, 10 + size);
189
for (;;) {
90
- tcg_gen_addi_i64(dirty_addr, dirty_addr, offset);
190
vfp_store_reg32(fd, vd);
91
+ tcg_gen_addi_i64(dirty_addr, dirty_addr, a->imm);
191
@@ -XXX,XX +XXX,XX @@ static bool trans_VMOV_imm_sp(DisasContext *s, arg_VMOV_imm_sp *a)
92
192
vd = vfp_advance_sreg(vd, delta_d);
93
- memop = finalize_memop(s, size);
94
+ memop = finalize_memop(s, MO_64);
95
96
/* Note that "clean" and "dirty" here refer to TBI not PAC. */
97
clean_addr = gen_mte_check1(s, dirty_addr, false,
98
- is_wback || rn != 31, memop);
99
+ a->w || a->rn != 31, memop);
100
101
- tcg_rt = cpu_reg(s, rt);
102
+ tcg_rt = cpu_reg(s, a->rt);
103
do_gpr_ld(s, tcg_rt, clean_addr, memop,
104
- /* extend */ false, /* iss_valid */ !is_wback,
105
- /* iss_srt */ rt, /* iss_sf */ true, /* iss_ar */ false);
106
+ /* extend */ false, /* iss_valid */ !a->w,
107
+ /* iss_srt */ a->rt, /* iss_sf */ true, /* iss_ar */ false);
108
109
- if (is_wback) {
110
- tcg_gen_mov_i64(cpu_reg_sp(s, rn), dirty_addr);
111
+ if (a->w) {
112
+ tcg_gen_mov_i64(cpu_reg_sp(s, a->rn), dirty_addr);
193
}
113
}
194
114
+ return true;
195
- tcg_temp_free_i32(fd);
196
return true;
197
}
115
}
198
116
199
@@ -XXX,XX +XXX,XX @@ static bool trans_VMOV_imm_dp(DisasContext *s, arg_VMOV_imm_dp *a)
117
/*
200
}
118
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_ldapr_stlr(DisasContext *s, uint32_t insn)
201
}
119
}
202
203
- fd = tcg_const_i64(vfp_expand_imm(MO_64, a->imm));
204
+ fd = tcg_constant_i64(vfp_expand_imm(MO_64, a->imm));
205
206
for (;;) {
207
vfp_store_reg64(fd, vd);
208
@@ -XXX,XX +XXX,XX @@ static bool trans_VMOV_imm_dp(DisasContext *s, arg_VMOV_imm_dp *a)
209
vd = vfp_advance_dreg(vd, delta_d);
210
}
211
212
- tcg_temp_free_i64(fd);
213
return true;
214
}
120
}
215
121
216
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_fix_hp(DisasContext *s, arg_VCVT_fix_sp *a)
122
-/* Load/store register (all forms) */
217
vfp_load_reg32(vd, a->vd);
123
-static void disas_ldst_reg(DisasContext *s, uint32_t insn)
218
124
-{
219
fpst = fpstatus_ptr(FPST_FPCR_F16);
125
- int rt = extract32(insn, 0, 5);
220
- shift = tcg_const_i32(frac_bits);
126
- bool is_vector = extract32(insn, 26, 1);
221
+ shift = tcg_constant_i32(frac_bits);
127
- int size = extract32(insn, 30, 2);
222
128
-
223
/* Switch on op:U:sx bits */
129
- switch (extract32(insn, 24, 2)) {
224
switch (a->opc) {
130
- case 0:
225
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_fix_hp(DisasContext *s, arg_VCVT_fix_sp *a)
131
- if (extract32(insn, 21, 1) == 0) {
226
132
- break;
227
vfp_store_reg32(vd, a->vd);
133
- }
228
tcg_temp_free_i32(vd);
134
- switch (extract32(insn, 10, 2)) {
229
- tcg_temp_free_i32(shift);
135
- case 0:
230
tcg_temp_free_ptr(fpst);
136
- case 2:
231
return true;
137
- break;
232
}
138
- default:
233
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_fix_sp(DisasContext *s, arg_VCVT_fix_sp *a)
139
- disas_ldst_pac(s, insn, size, rt, is_vector);
234
vfp_load_reg32(vd, a->vd);
140
- return;
235
141
- }
236
fpst = fpstatus_ptr(FPST_FPCR);
142
- break;
237
- shift = tcg_const_i32(frac_bits);
143
- }
238
+ shift = tcg_constant_i32(frac_bits);
144
- unallocated_encoding(s);
239
145
-}
240
/* Switch on op:U:sx bits */
146
-
241
switch (a->opc) {
147
/* AdvSIMD load/store multiple structures
242
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_fix_sp(DisasContext *s, arg_VCVT_fix_sp *a)
148
*
243
149
* 31 30 29 23 22 21 16 15 12 11 10 9 5 4 0
244
vfp_store_reg32(vd, a->vd);
150
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_tag(DisasContext *s, uint32_t insn)
245
tcg_temp_free_i32(vd);
151
static void disas_ldst(DisasContext *s, uint32_t insn)
246
- tcg_temp_free_i32(shift);
152
{
247
tcg_temp_free_ptr(fpst);
153
switch (extract32(insn, 24, 6)) {
248
return true;
154
- case 0x38: case 0x39:
249
}
155
- case 0x3c: case 0x3d: /* Load/store register (all forms) */
250
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_fix_dp(DisasContext *s, arg_VCVT_fix_dp *a)
156
- disas_ldst_reg(s, insn);
251
vfp_load_reg64(vd, a->vd);
157
- break;
252
158
case 0x0c: /* AdvSIMD load/store multiple structures */
253
fpst = fpstatus_ptr(FPST_FPCR);
159
disas_ldst_multiple_struct(s, insn);
254
- shift = tcg_const_i32(frac_bits);
160
break;
255
+ shift = tcg_constant_i32(frac_bits);
256
257
/* Switch on op:U:sx bits */
258
switch (a->opc) {
259
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_fix_dp(DisasContext *s, arg_VCVT_fix_dp *a)
260
261
vfp_store_reg64(vd, a->vd);
262
tcg_temp_free_i64(vd);
263
- tcg_temp_free_i32(shift);
264
tcg_temp_free_ptr(fpst);
265
return true;
266
}
267
--
161
--
268
2.25.1
162
2.34.1
163
164
diff view generated by jsdifflib
1
Factor out the code which sets a single bit in an LPI pending table.
1
Convert the instructions in the LDAPR/STLR (unscaled immediate)
2
We're going to need this for handling vLPI tables, not just the
2
group to decodetree.
3
physical LPI table.
4
3
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20220408141550.1271295-31-peter.maydell@linaro.org
6
Message-id: 20230602155223.2040685-18-peter.maydell@linaro.org
8
---
7
---
9
hw/intc/arm_gicv3_redist.c | 49 +++++++++++++++++++++++---------------
8
target/arm/tcg/a64.decode | 10 +++
10
1 file changed, 30 insertions(+), 19 deletions(-)
9
target/arm/tcg/translate-a64.c | 132 ++++++++++++---------------------
10
2 files changed, 56 insertions(+), 86 deletions(-)
11
11
12
diff --git a/hw/intc/arm_gicv3_redist.c b/hw/intc/arm_gicv3_redist.c
12
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
13
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/intc/arm_gicv3_redist.c
14
--- a/target/arm/tcg/a64.decode
15
+++ b/hw/intc/arm_gicv3_redist.c
15
+++ b/target/arm/tcg/a64.decode
16
@@ -XXX,XX +XXX,XX @@ static void update_for_all_lpis(GICv3CPUState *cs, uint64_t ptbase,
16
@@ -XXX,XX +XXX,XX @@ LDAPR sz:2 111 0 00 1 0 1 11111 1100 00 rn:5 rt:5
17
%ldra_imm 22:s1 12:9 !function=times_2
18
19
LDRA 11 111 0 00 m:1 . 1 ......... w:1 1 rn:5 rt:5 imm=%ldra_imm
20
+
21
+&ldapr_stlr_i rn rt imm sz sign ext
22
+@ldapr_stlr_i .. ...... .. . imm:9 .. rn:5 rt:5 &ldapr_stlr_i
23
+STLR_i sz:2 011001 00 0 ......... 00 ..... ..... @ldapr_stlr_i sign=0 ext=0
24
+LDAPR_i sz:2 011001 01 0 ......... 00 ..... ..... @ldapr_stlr_i sign=0 ext=0
25
+LDAPR_i 00 011001 10 0 ......... 00 ..... ..... @ldapr_stlr_i sign=1 ext=0 sz=0
26
+LDAPR_i 01 011001 10 0 ......... 00 ..... ..... @ldapr_stlr_i sign=1 ext=0 sz=1
27
+LDAPR_i 10 011001 10 0 ......... 00 ..... ..... @ldapr_stlr_i sign=1 ext=0 sz=2
28
+LDAPR_i 00 011001 11 0 ......... 00 ..... ..... @ldapr_stlr_i sign=1 ext=1 sz=0
29
+LDAPR_i 01 011001 11 0 ......... 00 ..... ..... @ldapr_stlr_i sign=1 ext=1 sz=1
30
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
31
index XXXXXXX..XXXXXXX 100644
32
--- a/target/arm/tcg/translate-a64.c
33
+++ b/target/arm/tcg/translate-a64.c
34
@@ -XXX,XX +XXX,XX @@ static void gen_compare_and_swap_pair(DisasContext *s, int rs, int rt,
17
}
35
}
18
}
36
}
19
37
20
+/**
38
-/* Update the Sixty-Four bit (SF) registersize. This logic is derived
21
+ * set_lpi_pending_bit: Set or clear pending bit for an LPI
39
+/*
22
+ *
40
+ * Compute the ISS.SF bit for syndrome information if an exception
23
+ * @cs: GICv3CPUState
41
+ * is taken on a load or store. This indicates whether the instruction
24
+ * @ptbase: physical address of LPI Pending table
42
+ * is accessing a 32-bit or 64-bit register. This logic is derived
25
+ * @irq: LPI to change pending state for
43
* from the ARMv8 specs for LDR (Shared decode for all encodings).
26
+ * @level: false to clear pending state, true to set
44
*/
27
+ *
45
-static bool disas_ldst_compute_iss_sf(int size, bool is_signed, int opc)
28
+ * Returns true if we needed to do something, false if the pending bit
46
-{
29
+ * was already at @level.
47
- int opc0 = extract32(opc, 0, 1);
30
+ */
48
- int regsize;
31
+static bool set_pending_table_bit(GICv3CPUState *cs, uint64_t ptbase,
49
-
32
+ int irq, bool level)
50
- if (is_signed) {
33
+{
51
- regsize = opc0 ? 32 : 64;
34
+ AddressSpace *as = &cs->gic->dma_as;
52
- } else {
35
+ uint64_t addr = ptbase + irq / 8;
53
- regsize = size == 3 ? 64 : 32;
36
+ uint8_t pend;
54
- }
37
+
55
- return regsize == 64;
38
+ address_space_read(as, addr, MEMTXATTRS_UNSPECIFIED, &pend, 1);
56
-}
39
+ if (extract32(pend, irq % 8, 1) == level) {
57
-
40
+ /* Bit already at requested state, no action required */
58
static bool ldst_iss_sf(int size, bool sign, bool ext)
59
{
60
61
@@ -XXX,XX +XXX,XX @@ static bool trans_LDRA(DisasContext *s, arg_LDRA *a)
62
return true;
63
}
64
65
-/*
66
- * LDAPR/STLR (unscaled immediate)
67
- *
68
- * 31 30 24 22 21 12 10 5 0
69
- * +------+-------------+-----+---+--------+-----+----+-----+
70
- * | size | 0 1 1 0 0 1 | opc | 0 | imm9 | 0 0 | Rn | Rt |
71
- * +------+-------------+-----+---+--------+-----+----+-----+
72
- *
73
- * Rt: source or destination register
74
- * Rn: base register
75
- * imm9: unscaled immediate offset
76
- * opc: 00: STLUR*, 01/10/11: various LDAPUR*
77
- * size: size of load/store
78
- */
79
-static void disas_ldst_ldapr_stlr(DisasContext *s, uint32_t insn)
80
+static bool trans_LDAPR_i(DisasContext *s, arg_ldapr_stlr_i *a)
81
{
82
- int rt = extract32(insn, 0, 5);
83
- int rn = extract32(insn, 5, 5);
84
- int offset = sextract32(insn, 12, 9);
85
- int opc = extract32(insn, 22, 2);
86
- int size = extract32(insn, 30, 2);
87
TCGv_i64 clean_addr, dirty_addr;
88
- bool is_store = false;
89
- bool extend = false;
90
- bool iss_sf;
91
- MemOp mop = size;
92
+ MemOp mop = a->sz | (a->sign ? MO_SIGN : 0);
93
+ bool iss_sf = ldst_iss_sf(a->sz, a->sign, a->ext);
94
95
if (!dc_isar_feature(aa64_rcpc_8_4, s)) {
96
- unallocated_encoding(s);
97
- return;
41
+ return false;
98
+ return false;
42
+ }
99
}
43
+ pend = deposit32(pend, irq % 8, 1, level ? 1 : 0);
100
44
+ address_space_write(as, addr, MEMTXATTRS_UNSPECIFIED, &pend, 1);
101
- switch (opc) {
102
- case 0: /* STLURB */
103
- is_store = true;
104
- break;
105
- case 1: /* LDAPUR* */
106
- break;
107
- case 2: /* LDAPURS* 64-bit variant */
108
- if (size == 3) {
109
- unallocated_encoding(s);
110
- return;
111
- }
112
- mop |= MO_SIGN;
113
- break;
114
- case 3: /* LDAPURS* 32-bit variant */
115
- if (size > 1) {
116
- unallocated_encoding(s);
117
- return;
118
- }
119
- mop |= MO_SIGN;
120
- extend = true; /* zero-extend 32->64 after signed load */
121
- break;
122
- default:
123
- g_assert_not_reached();
124
- }
125
-
126
- iss_sf = disas_ldst_compute_iss_sf(size, (mop & MO_SIGN) != 0, opc);
127
-
128
- if (rn == 31) {
129
+ if (a->rn == 31) {
130
gen_check_sp_alignment(s);
131
}
132
133
- mop = check_ordered_align(s, rn, offset, is_store, mop);
134
-
135
- dirty_addr = read_cpu_reg_sp(s, rn, 1);
136
- tcg_gen_addi_i64(dirty_addr, dirty_addr, offset);
137
+ mop = check_ordered_align(s, a->rn, a->imm, false, mop);
138
+ dirty_addr = read_cpu_reg_sp(s, a->rn, 1);
139
+ tcg_gen_addi_i64(dirty_addr, dirty_addr, a->imm);
140
clean_addr = clean_data_tbi(s, dirty_addr);
141
142
- if (is_store) {
143
- /* Store-Release semantics */
144
- tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
145
- do_gpr_st(s, cpu_reg(s, rt), clean_addr, mop, true, rt, iss_sf, true);
146
- } else {
147
- /*
148
- * Load-AcquirePC semantics; we implement as the slightly more
149
- * restrictive Load-Acquire.
150
- */
151
- do_gpr_ld(s, cpu_reg(s, rt), clean_addr, mop,
152
- extend, true, rt, iss_sf, true);
153
- tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ);
154
+ /*
155
+ * Load-AcquirePC semantics; we implement as the slightly more
156
+ * restrictive Load-Acquire.
157
+ */
158
+ do_gpr_ld(s, cpu_reg(s, a->rt), clean_addr, mop, a->ext, true,
159
+ a->rt, iss_sf, true);
160
+ tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ);
45
+ return true;
161
+ return true;
46
+}
162
+}
47
+
163
+
48
static uint8_t gicr_read_ipriorityr(GICv3CPUState *cs, MemTxAttrs attrs,
164
+static bool trans_STLR_i(DisasContext *s, arg_ldapr_stlr_i *a)
49
int irq)
165
+{
50
{
166
+ TCGv_i64 clean_addr, dirty_addr;
51
@@ -XXX,XX +XXX,XX @@ void gicv3_redist_lpi_pending(GICv3CPUState *cs, int irq, int level)
167
+ MemOp mop = a->sz;
52
* This function updates the pending bit in lpi pending table for
168
+ bool iss_sf = ldst_iss_sf(a->sz, a->sign, a->ext);
53
* the irq being activated or deactivated.
169
+
54
*/
170
+ if (!dc_isar_feature(aa64_rcpc_8_4, s)) {
55
- AddressSpace *as = &cs->gic->dma_as;
171
+ return false;
56
uint64_t lpipt_baddr;
172
}
57
- bool ispend = false;
173
+
58
- uint8_t pend;
174
+ /* TODO: ARMv8.4-LSE SCTLR.nAA */
59
175
+
60
- /*
176
+ if (a->rn == 31) {
61
- * get the bit value corresponding to this irq in the
177
+ gen_check_sp_alignment(s);
62
- * lpi pending table
178
+ }
63
- */
179
+
64
lpipt_baddr = cs->gicr_pendbaser & R_GICR_PENDBASER_PHYADDR_MASK;
180
+ mop = check_ordered_align(s, a->rn, a->imm, true, mop);
65
-
181
+ dirty_addr = read_cpu_reg_sp(s, a->rn, 1);
66
- address_space_read(as, lpipt_baddr + ((irq / 8) * sizeof(pend)),
182
+ tcg_gen_addi_i64(dirty_addr, dirty_addr, a->imm);
67
- MEMTXATTRS_UNSPECIFIED, &pend, sizeof(pend));
183
+ clean_addr = clean_data_tbi(s, dirty_addr);
68
-
184
+
69
- ispend = extract32(pend, irq % 8, 1);
185
+ /* Store-Release semantics */
70
-
186
+ tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
71
- /* no change in the value of pending bit, return */
187
+ do_gpr_st(s, cpu_reg(s, a->rt), clean_addr, mop, true, a->rt, iss_sf, true);
72
- if (ispend == level) {
188
+ return true;
73
+ if (!set_pending_table_bit(cs, lpipt_baddr, irq, level)) {
189
}
74
+ /* no change in the value of pending bit, return */
190
75
return;
191
/* AdvSIMD load/store multiple structures
76
}
192
@@ -XXX,XX +XXX,XX @@ static void disas_ldst(DisasContext *s, uint32_t insn)
77
- pend = deposit32(pend, irq % 8, 1, level ? 1 : 0);
193
case 0x19:
78
-
194
if (extract32(insn, 21, 1) != 0) {
79
- address_space_write(as, lpipt_baddr + ((irq / 8) * sizeof(pend)),
195
disas_ldst_tag(s, insn);
80
- MEMTXATTRS_UNSPECIFIED, &pend, sizeof(pend));
196
- } else if (extract32(insn, 10, 2) == 0) {
81
197
- disas_ldst_ldapr_stlr(s, insn);
82
/*
198
} else {
83
* check if this LPI is better than the current hpplpi, if yes
199
unallocated_encoding(s);
200
}
84
--
201
--
85
2.25.1
202
2.34.1
diff view generated by jsdifflib
1
Implement the GICv4 VMAPP command, which writes an entry to the vPE
1
Convert the instructions in the ASIMD load/store multiple structures
2
table.
2
instruction classes to decodetree.
3
4
For GICv4.1 this command has extra fields in the command packet
5
and additional behaviour. We define the 4.1-only fields with the
6
FIELD macro, but only implement the GICv4.0 version of the command.
7
3
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20220408141550.1271295-10-peter.maydell@linaro.org
6
Message-id: 20230602155223.2040685-19-peter.maydell@linaro.org
11
---
7
---
12
hw/intc/gicv3_internal.h | 12 ++++++
8
target/arm/tcg/a64.decode | 20 +++
13
hw/intc/arm_gicv3_its.c | 88 ++++++++++++++++++++++++++++++++++++++++
9
target/arm/tcg/translate-a64.c | 222 ++++++++++++++++-----------------
14
hw/intc/trace-events | 2 +
10
2 files changed, 131 insertions(+), 111 deletions(-)
15
3 files changed, 102 insertions(+)
16
11
17
diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h
12
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
18
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/intc/gicv3_internal.h
14
--- a/target/arm/tcg/a64.decode
20
+++ b/hw/intc/gicv3_internal.h
15
+++ b/target/arm/tcg/a64.decode
21
@@ -XXX,XX +XXX,XX @@ FIELD(GITS_TYPER, CIL, 36, 1)
16
@@ -XXX,XX +XXX,XX @@ LDAPR_i 01 011001 10 0 ......... 00 ..... ..... @ldapr_stlr_i sign=1 ext
22
#define GITS_CMD_INVALL 0x0D
17
LDAPR_i 10 011001 10 0 ......... 00 ..... ..... @ldapr_stlr_i sign=1 ext=0 sz=2
23
#define GITS_CMD_MOVALL 0x0E
18
LDAPR_i 00 011001 11 0 ......... 00 ..... ..... @ldapr_stlr_i sign=1 ext=1 sz=0
24
#define GITS_CMD_DISCARD 0x0F
19
LDAPR_i 01 011001 11 0 ......... 00 ..... ..... @ldapr_stlr_i sign=1 ext=1 sz=1
25
+#define GITS_CMD_VMAPP 0x29
20
+
26
#define GITS_CMD_VMAPTI 0x2A
21
+# Load/store multiple structures
27
#define GITS_CMD_VMAPI 0x2B
22
+# The 4-bit opcode in [15:12] encodes repeat count and structure elements
28
23
+&ldst_mult rm rn rt sz q p rpt selem
29
@@ -XXX,XX +XXX,XX @@ FIELD(VMAPTI_1, VPEID, 32, 16)
24
+@ldst_mult . q:1 ...... p:1 . . rm:5 .... sz:2 rn:5 rt:5 &ldst_mult
30
FIELD(VMAPTI_2, VINTID, 0, 32) /* VMAPTI only */
25
+ST_mult 0 . 001100 . 0 0 ..... 0000 .. ..... ..... @ldst_mult rpt=1 selem=4
31
FIELD(VMAPTI_2, DOORBELL, 32, 32)
26
+ST_mult 0 . 001100 . 0 0 ..... 0010 .. ..... ..... @ldst_mult rpt=4 selem=1
32
27
+ST_mult 0 . 001100 . 0 0 ..... 0100 .. ..... ..... @ldst_mult rpt=1 selem=3
33
+/* VMAPP command fields */
28
+ST_mult 0 . 001100 . 0 0 ..... 0110 .. ..... ..... @ldst_mult rpt=3 selem=1
34
+FIELD(VMAPP_0, ALLOC, 8, 1) /* GICv4.1 only */
29
+ST_mult 0 . 001100 . 0 0 ..... 0111 .. ..... ..... @ldst_mult rpt=1 selem=1
35
+FIELD(VMAPP_0, PTZ, 9, 1) /* GICv4.1 only */
30
+ST_mult 0 . 001100 . 0 0 ..... 1000 .. ..... ..... @ldst_mult rpt=1 selem=2
36
+FIELD(VMAPP_0, VCONFADDR, 16, 36) /* GICv4.1 only */
31
+ST_mult 0 . 001100 . 0 0 ..... 1010 .. ..... ..... @ldst_mult rpt=2 selem=1
37
+FIELD(VMAPP_1, DEFAULT_DOORBELL, 0, 32) /* GICv4.1 only */
32
+
38
+FIELD(VMAPP_1, VPEID, 32, 16)
33
+LD_mult 0 . 001100 . 1 0 ..... 0000 .. ..... ..... @ldst_mult rpt=1 selem=4
39
+FIELD(VMAPP_2, RDBASE, 16, 36)
34
+LD_mult 0 . 001100 . 1 0 ..... 0010 .. ..... ..... @ldst_mult rpt=4 selem=1
40
+FIELD(VMAPP_2, V, 63, 1)
35
+LD_mult 0 . 001100 . 1 0 ..... 0100 .. ..... ..... @ldst_mult rpt=1 selem=3
41
+FIELD(VMAPP_3, VPTSIZE, 0, 8) /* For GICv4.0, bits [7:6] are RES0 */
36
+LD_mult 0 . 001100 . 1 0 ..... 0110 .. ..... ..... @ldst_mult rpt=3 selem=1
42
+FIELD(VMAPP_3, VPTADDR, 16, 36)
37
+LD_mult 0 . 001100 . 1 0 ..... 0111 .. ..... ..... @ldst_mult rpt=1 selem=1
43
+
38
+LD_mult 0 . 001100 . 1 0 ..... 1000 .. ..... ..... @ldst_mult rpt=1 selem=2
44
/*
39
+LD_mult 0 . 001100 . 1 0 ..... 1010 .. ..... ..... @ldst_mult rpt=2 selem=1
45
* 12 bytes Interrupt translation Table Entry size
40
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
46
* as per Table 5.3 in GICv3 spec
47
diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
48
index XXXXXXX..XXXXXXX 100644
41
index XXXXXXX..XXXXXXX 100644
49
--- a/hw/intc/arm_gicv3_its.c
42
--- a/target/arm/tcg/translate-a64.c
50
+++ b/hw/intc/arm_gicv3_its.c
43
+++ b/target/arm/tcg/translate-a64.c
51
@@ -XXX,XX +XXX,XX @@ typedef struct ITEntry {
44
@@ -XXX,XX +XXX,XX @@ static bool trans_STLR_i(DisasContext *s, arg_ldapr_stlr_i *a)
52
uint32_t vpeid;
45
return true;
53
} ITEntry;
54
55
+typedef struct VTEntry {
56
+ bool valid;
57
+ unsigned vptsize;
58
+ uint32_t rdbase;
59
+ uint64_t vptaddr;
60
+} VTEntry;
61
62
/*
63
* The ITS spec permits a range of CONSTRAINED UNPREDICTABLE options
64
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_movi(GICv3ITSState *s, const uint64_t *cmdpkt)
65
return update_ite(s, eventid, &dte, &old_ite) ? CMD_CONTINUE : CMD_STALL;
66
}
46
}
67
47
68
+/*
48
-/* AdvSIMD load/store multiple structures
69
+ * Update the vPE Table entry at index @vpeid with the entry @vte.
49
- *
70
+ * Returns true on success, false if there was a memory access error.
50
- * 31 30 29 23 22 21 16 15 12 11 10 9 5 4 0
71
+ */
51
- * +---+---+---------------+---+-------------+--------+------+------+------+
72
+static bool update_vte(GICv3ITSState *s, uint32_t vpeid, const VTEntry *vte)
52
- * | 0 | Q | 0 0 1 1 0 0 0 | L | 0 0 0 0 0 0 | opcode | size | Rn | Rt |
53
- * +---+---+---------------+---+-------------+--------+------+------+------+
54
- *
55
- * AdvSIMD load/store multiple structures (post-indexed)
56
- *
57
- * 31 30 29 23 22 21 20 16 15 12 11 10 9 5 4 0
58
- * +---+---+---------------+---+---+---------+--------+------+------+------+
59
- * | 0 | Q | 0 0 1 1 0 0 1 | L | 0 | Rm | opcode | size | Rn | Rt |
60
- * +---+---+---------------+---+---+---------+--------+------+------+------+
61
- *
62
- * Rt: first (or only) SIMD&FP register to be transferred
63
- * Rn: base address or SP
64
- * Rm (post-index only): post-index register (when !31) or size dependent #imm
65
- */
66
-static void disas_ldst_multiple_struct(DisasContext *s, uint32_t insn)
67
+static bool trans_LD_mult(DisasContext *s, arg_ldst_mult *a)
68
{
69
- int rt = extract32(insn, 0, 5);
70
- int rn = extract32(insn, 5, 5);
71
- int rm = extract32(insn, 16, 5);
72
- int size = extract32(insn, 10, 2);
73
- int opcode = extract32(insn, 12, 4);
74
- bool is_store = !extract32(insn, 22, 1);
75
- bool is_postidx = extract32(insn, 23, 1);
76
- bool is_q = extract32(insn, 30, 1);
77
TCGv_i64 clean_addr, tcg_rn, tcg_ebytes;
78
MemOp endian, align, mop;
79
80
int total; /* total bytes */
81
int elements; /* elements per vector */
82
- int rpt; /* num iterations */
83
- int selem; /* structure elements */
84
int r;
85
+ int size = a->sz;
86
87
- if (extract32(insn, 31, 1) || extract32(insn, 21, 1)) {
88
- unallocated_encoding(s);
89
- return;
90
+ if (!a->p && a->rm != 0) {
91
+ /* For non-postindexed accesses the Rm field must be 0 */
92
+ return false;
93
}
94
-
95
- if (!is_postidx && rm != 0) {
96
- unallocated_encoding(s);
97
- return;
98
+ if (size == 3 && !a->q && a->selem != 1) {
99
+ return false;
100
}
101
-
102
- /* From the shared decode logic */
103
- switch (opcode) {
104
- case 0x0:
105
- rpt = 1;
106
- selem = 4;
107
- break;
108
- case 0x2:
109
- rpt = 4;
110
- selem = 1;
111
- break;
112
- case 0x4:
113
- rpt = 1;
114
- selem = 3;
115
- break;
116
- case 0x6:
117
- rpt = 3;
118
- selem = 1;
119
- break;
120
- case 0x7:
121
- rpt = 1;
122
- selem = 1;
123
- break;
124
- case 0x8:
125
- rpt = 1;
126
- selem = 2;
127
- break;
128
- case 0xa:
129
- rpt = 2;
130
- selem = 1;
131
- break;
132
- default:
133
- unallocated_encoding(s);
134
- return;
135
- }
136
-
137
- if (size == 3 && !is_q && selem != 1) {
138
- /* reserved */
139
- unallocated_encoding(s);
140
- return;
141
- }
142
-
143
if (!fp_access_check(s)) {
144
- return;
145
+ return true;
146
}
147
148
- if (rn == 31) {
149
+ if (a->rn == 31) {
150
gen_check_sp_alignment(s);
151
}
152
153
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_multiple_struct(DisasContext *s, uint32_t insn)
154
endian = MO_LE;
155
}
156
157
- total = rpt * selem * (is_q ? 16 : 8);
158
- tcg_rn = cpu_reg_sp(s, rn);
159
+ total = a->rpt * a->selem * (a->q ? 16 : 8);
160
+ tcg_rn = cpu_reg_sp(s, a->rn);
161
162
/*
163
* Issue the MTE check vs the logical repeat count, before we
164
* promote consecutive little-endian elements below.
165
*/
166
- clean_addr = gen_mte_checkN(s, tcg_rn, is_store, is_postidx || rn != 31,
167
- total, finalize_memop_asimd(s, size));
168
+ clean_addr = gen_mte_checkN(s, tcg_rn, false, a->p || a->rn != 31, total,
169
+ finalize_memop_asimd(s, size));
170
171
/*
172
* Consecutive little-endian elements from a single register
173
* can be promoted to a larger little-endian operation.
174
*/
175
align = MO_ALIGN;
176
- if (selem == 1 && endian == MO_LE) {
177
+ if (a->selem == 1 && endian == MO_LE) {
178
align = pow2_align(size);
179
size = 3;
180
}
181
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_multiple_struct(DisasContext *s, uint32_t insn)
182
}
183
mop = endian | size | align;
184
185
- elements = (is_q ? 16 : 8) >> size;
186
+ elements = (a->q ? 16 : 8) >> size;
187
tcg_ebytes = tcg_constant_i64(1 << size);
188
- for (r = 0; r < rpt; r++) {
189
+ for (r = 0; r < a->rpt; r++) {
190
int e;
191
for (e = 0; e < elements; e++) {
192
int xs;
193
- for (xs = 0; xs < selem; xs++) {
194
- int tt = (rt + r + xs) % 32;
195
- if (is_store) {
196
- do_vec_st(s, tt, e, clean_addr, mop);
197
- } else {
198
- do_vec_ld(s, tt, e, clean_addr, mop);
199
- }
200
+ for (xs = 0; xs < a->selem; xs++) {
201
+ int tt = (a->rt + r + xs) % 32;
202
+ do_vec_ld(s, tt, e, clean_addr, mop);
203
tcg_gen_add_i64(clean_addr, clean_addr, tcg_ebytes);
204
}
205
}
206
}
207
208
- if (!is_store) {
209
- /* For non-quad operations, setting a slice of the low
210
- * 64 bits of the register clears the high 64 bits (in
211
- * the ARM ARM pseudocode this is implicit in the fact
212
- * that 'rval' is a 64 bit wide variable).
213
- * For quad operations, we might still need to zero the
214
- * high bits of SVE.
215
- */
216
- for (r = 0; r < rpt * selem; r++) {
217
- int tt = (rt + r) % 32;
218
- clear_vec_high(s, is_q, tt);
219
+ /*
220
+ * For non-quad operations, setting a slice of the low 64 bits of
221
+ * the register clears the high 64 bits (in the ARM ARM pseudocode
222
+ * this is implicit in the fact that 'rval' is a 64 bit wide
223
+ * variable). For quad operations, we might still need to zero
224
+ * the high bits of SVE.
225
+ */
226
+ for (r = 0; r < a->rpt * a->selem; r++) {
227
+ int tt = (a->rt + r) % 32;
228
+ clear_vec_high(s, a->q, tt);
229
+ }
230
+
231
+ if (a->p) {
232
+ if (a->rm == 31) {
233
+ tcg_gen_addi_i64(tcg_rn, tcg_rn, total);
234
+ } else {
235
+ tcg_gen_add_i64(tcg_rn, tcg_rn, cpu_reg(s, a->rm));
236
+ }
237
+ }
238
+ return true;
239
+}
240
+
241
+static bool trans_ST_mult(DisasContext *s, arg_ldst_mult *a)
73
+{
242
+{
74
+ AddressSpace *as = &s->gicv3->dma_as;
243
+ TCGv_i64 clean_addr, tcg_rn, tcg_ebytes;
75
+ uint64_t entry_addr;
244
+ MemOp endian, align, mop;
76
+ uint64_t vteval = 0;
245
+
77
+ MemTxResult res = MEMTX_OK;
246
+ int total; /* total bytes */
78
+
247
+ int elements; /* elements per vector */
79
+ trace_gicv3_its_vte_write(vpeid, vte->valid, vte->vptsize, vte->vptaddr,
248
+ int r;
80
+ vte->rdbase);
249
+ int size = a->sz;
81
+
250
+
82
+ if (vte->valid) {
251
+ if (!a->p && a->rm != 0) {
83
+ vteval = FIELD_DP64(vteval, VTE, VALID, 1);
252
+ /* For non-postindexed accesses the Rm field must be 0 */
84
+ vteval = FIELD_DP64(vteval, VTE, VPTSIZE, vte->vptsize);
85
+ vteval = FIELD_DP64(vteval, VTE, VPTADDR, vte->vptaddr);
86
+ vteval = FIELD_DP64(vteval, VTE, RDBASE, vte->rdbase);
87
+ }
88
+
89
+ entry_addr = table_entry_addr(s, &s->vpet, vpeid, &res);
90
+ if (res != MEMTX_OK) {
91
+ return false;
253
+ return false;
92
+ }
254
+ }
93
+ if (entry_addr == -1) {
255
+ if (size == 3 && !a->q && a->selem != 1) {
94
+ /* No L2 table for this index: discard write and continue */
256
+ return false;
257
+ }
258
+ if (!fp_access_check(s)) {
95
+ return true;
259
+ return true;
96
+ }
260
+ }
97
+ address_space_stq_le(as, entry_addr, vteval, MEMTXATTRS_UNSPECIFIED, &res);
261
+
98
+ return res == MEMTX_OK;
262
+ if (a->rn == 31) {
99
+}
263
+ gen_check_sp_alignment(s);
100
+
264
+ }
101
+static ItsCmdResult process_vmapp(GICv3ITSState *s, const uint64_t *cmdpkt)
265
+
102
+{
266
+ /* For our purposes, bytes are always little-endian. */
103
+ VTEntry vte;
267
+ endian = s->be_data;
104
+ uint32_t vpeid;
268
+ if (size == 0) {
105
+
269
+ endian = MO_LE;
106
+ if (!its_feature_virtual(s)) {
270
+ }
107
+ return CMD_CONTINUE;
271
+
108
+ }
272
+ total = a->rpt * a->selem * (a->q ? 16 : 8);
109
+
273
+ tcg_rn = cpu_reg_sp(s, a->rn);
110
+ vpeid = FIELD_EX64(cmdpkt[1], VMAPP_1, VPEID);
111
+ vte.rdbase = FIELD_EX64(cmdpkt[2], VMAPP_2, RDBASE);
112
+ vte.valid = FIELD_EX64(cmdpkt[2], VMAPP_2, V);
113
+ vte.vptsize = FIELD_EX64(cmdpkt[3], VMAPP_3, VPTSIZE);
114
+ vte.vptaddr = FIELD_EX64(cmdpkt[3], VMAPP_3, VPTADDR);
115
+
116
+ trace_gicv3_its_cmd_vmapp(vpeid, vte.rdbase, vte.valid,
117
+ vte.vptaddr, vte.vptsize);
118
+
274
+
119
+ /*
275
+ /*
120
+ * For GICv4.0 the VPT_size field is only 5 bits, whereas we
276
+ * Issue the MTE check vs the logical repeat count, before we
121
+ * define our field macros to include the full GICv4.1 8 bits.
277
+ * promote consecutive little-endian elements below.
122
+ * The range check on VPT_size will catch the cases where
123
+ * the guest set the RES0-in-GICv4.0 bits [7:6].
124
+ */
278
+ */
125
+ if (vte.vptsize > FIELD_EX64(s->typer, GITS_TYPER, IDBITS)) {
279
+ clean_addr = gen_mte_checkN(s, tcg_rn, true, a->p || a->rn != 31, total,
126
+ qemu_log_mask(LOG_GUEST_ERROR,
280
+ finalize_memop_asimd(s, size));
127
+ "%s: invalid VPT_size 0x%x\n", __func__, vte.vptsize);
281
+
128
+ return CMD_CONTINUE;
282
+ /*
129
+ }
283
+ * Consecutive little-endian elements from a single register
130
+
284
+ * can be promoted to a larger little-endian operation.
131
+ if (vte.valid && vte.rdbase >= s->gicv3->num_cpu) {
285
+ */
132
+ qemu_log_mask(LOG_GUEST_ERROR,
286
+ align = MO_ALIGN;
133
+ "%s: invalid rdbase 0x%x\n", __func__, vte.rdbase);
287
+ if (a->selem == 1 && endian == MO_LE) {
134
+ return CMD_CONTINUE;
288
+ align = pow2_align(size);
135
+ }
289
+ size = 3;
136
+
290
+ }
137
+ if (vpeid >= s->vpet.num_entries) {
291
+ if (!s->align_mem) {
138
+ qemu_log_mask(LOG_GUEST_ERROR,
292
+ align = 0;
139
+ "%s: VPEID 0x%x out of range (must be less than 0x%x)\n",
293
+ }
140
+ __func__, vpeid, s->vpet.num_entries);
294
+ mop = endian | size | align;
141
+ return CMD_CONTINUE;
295
+
142
+ }
296
+ elements = (a->q ? 16 : 8) >> size;
143
+
297
+ tcg_ebytes = tcg_constant_i64(1 << size);
144
+ return update_vte(s, vpeid, &vte) ? CMD_CONTINUE : CMD_STALL;
298
+ for (r = 0; r < a->rpt; r++) {
145
+}
299
+ int e;
146
+
300
+ for (e = 0; e < elements; e++) {
147
/*
301
+ int xs;
148
* Current implementation blocks until all
302
+ for (xs = 0; xs < a->selem; xs++) {
149
* commands are processed
303
+ int tt = (a->rt + r + xs) % 32;
150
@@ -XXX,XX +XXX,XX @@ static void process_cmdq(GICv3ITSState *s)
304
+ do_vec_st(s, tt, e, clean_addr, mop);
151
case GITS_CMD_VMAPI:
305
+ tcg_gen_add_i64(clean_addr, clean_addr, tcg_ebytes);
152
result = process_vmapti(s, cmdpkt, true);
306
+ }
153
break;
307
}
154
+ case GITS_CMD_VMAPP:
308
}
155
+ result = process_vmapp(s, cmdpkt);
309
156
+ break;
310
- if (is_postidx) {
157
default:
311
- if (rm == 31) {
158
trace_gicv3_its_cmd_unknown(cmd);
312
+ if (a->p) {
159
break;
313
+ if (a->rm == 31) {
160
diff --git a/hw/intc/trace-events b/hw/intc/trace-events
314
tcg_gen_addi_i64(tcg_rn, tcg_rn, total);
161
index XXXXXXX..XXXXXXX 100644
315
} else {
162
--- a/hw/intc/trace-events
316
- tcg_gen_add_i64(tcg_rn, tcg_rn, cpu_reg(s, rm));
163
+++ b/hw/intc/trace-events
317
+ tcg_gen_add_i64(tcg_rn, tcg_rn, cpu_reg(s, a->rm));
164
@@ -XXX,XX +XXX,XX @@ gicv3_its_cmd_movall(uint64_t rd1, uint64_t rd2) "GICv3 ITS: command MOVALL RDba
318
}
165
gicv3_its_cmd_movi(uint32_t devid, uint32_t eventid, uint32_t icid) "GICv3 ITS: command MOVI DeviceID 0x%x EventID 0x%x ICID 0x%x"
319
}
166
gicv3_its_cmd_vmapi(uint32_t devid, uint32_t eventid, uint32_t vpeid, uint32_t doorbell) "GICv3 ITS: command VMAPI DeviceID 0x%x EventID 0x%x vPEID 0x%x Dbell_pINTID 0x%x"
320
+ return true;
167
gicv3_its_cmd_vmapti(uint32_t devid, uint32_t eventid, uint32_t vpeid, uint32_t vintid, uint32_t doorbell) "GICv3 ITS: command VMAPI DeviceID 0x%x EventID 0x%x vPEID 0x%x vINTID 0x%x Dbell_pINTID 0x%x"
321
}
168
+gicv3_its_cmd_vmapp(uint32_t vpeid, uint64_t rdbase, int valid, uint64_t vptaddr, uint32_t vptsize) "GICv3 ITS: command VMAPP vPEID 0x%x RDbase 0x%" PRIx64 " V %d VPT_addr 0x%" PRIx64 " VPT_size 0x%x"
322
169
gicv3_its_cmd_unknown(unsigned cmd) "GICv3 ITS: unknown command 0x%x"
323
/* AdvSIMD load/store single structure
170
gicv3_its_cte_read(uint32_t icid, int valid, uint32_t rdbase) "GICv3 ITS: Collection Table read for ICID 0x%x: valid %d RDBase 0x%x"
324
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_tag(DisasContext *s, uint32_t insn)
171
gicv3_its_cte_write(uint32_t icid, int valid, uint32_t rdbase) "GICv3 ITS: Collection Table write for ICID 0x%x: valid %d RDBase 0x%x"
325
static void disas_ldst(DisasContext *s, uint32_t insn)
172
@@ -XXX,XX +XXX,XX @@ gicv3_its_ite_write(uint64_t ittaddr, uint32_t eventid, int valid, int inttype,
326
{
173
gicv3_its_dte_read(uint32_t devid, int valid, uint32_t size, uint64_t ittaddr) "GICv3 ITS: Device Table read for DeviceID 0x%x: valid %d size 0x%x ITTaddr 0x%" PRIx64
327
switch (extract32(insn, 24, 6)) {
174
gicv3_its_dte_write(uint32_t devid, int valid, uint32_t size, uint64_t ittaddr) "GICv3 ITS: Device Table write for DeviceID 0x%x: valid %d size 0x%x ITTaddr 0x%" PRIx64
328
- case 0x0c: /* AdvSIMD load/store multiple structures */
175
gicv3_its_dte_read_fault(uint32_t devid) "GICv3 ITS: Device Table read for DeviceID 0x%x: faulted"
329
- disas_ldst_multiple_struct(s, insn);
176
+gicv3_its_vte_write(uint32_t vpeid, int valid, uint32_t vptsize, uint64_t vptaddr, uint32_t rdbase) "GICv3 ITS: vPE Table write for vPEID 0x%x: valid %d VPTsize 0x%x VPTaddr 0x%" PRIx64 " RDbase 0x%x"
330
- break;
177
331
case 0x0d: /* AdvSIMD load/store single structure */
178
# armv7m_nvic.c
332
disas_ldst_single_struct(s, insn);
179
nvic_recompute_state(int vectpending, int vectpending_prio, int exception_prio) "NVIC state recomputed: vectpending %d vectpending_prio %d exception_prio %d"
333
break;
180
--
334
--
181
2.25.1
335
2.34.1
diff view generated by jsdifflib
Deleted patch
1
In the ItsCmdResult enum, we currently distinguish only CMD_STALL
2
(failure, stall processing of the command queue) and CMD_CONTINUE
3
(keep processing the queue), and we use the latter both for "there
4
was a parameter error, go on to the next command" and "the command
5
succeeded, go on to the next command". Sometimes we would like to
6
distinguish those two cases, so add CMD_CONTINUE_OK to the enum to
7
represent the success situation, and use it in the relevant places.
8
1
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20220408141550.1271295-11-peter.maydell@linaro.org
12
---
13
hw/intc/arm_gicv3_its.c | 29 ++++++++++++++++-------------
14
1 file changed, 16 insertions(+), 13 deletions(-)
15
16
diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/intc/arm_gicv3_its.c
19
+++ b/hw/intc/arm_gicv3_its.c
20
@@ -XXX,XX +XXX,XX @@ typedef struct VTEntry {
21
* and continue processing.
22
* The process_* functions which handle individual ITS commands all
23
* return an ItsCmdResult which tells process_cmdq() whether it should
24
- * stall or keep going.
25
+ * stall, keep going because of an error, or keep going because the
26
+ * command was a success.
27
*/
28
typedef enum ItsCmdResult {
29
CMD_STALL = 0,
30
CMD_CONTINUE = 1,
31
+ CMD_CONTINUE_OK = 2,
32
} ItsCmdResult;
33
34
/* True if the ITS supports the GICv4 virtual LPI feature */
35
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult do_process_its_cmd(GICv3ITSState *s, uint32_t devid,
36
ITEntry ite = {};
37
/* remove mapping from interrupt translation table */
38
ite.valid = false;
39
- return update_ite(s, eventid, &dte, &ite) ? CMD_CONTINUE : CMD_STALL;
40
+ return update_ite(s, eventid, &dte, &ite) ? CMD_CONTINUE_OK : CMD_STALL;
41
}
42
- return CMD_CONTINUE;
43
+ return CMD_CONTINUE_OK;
44
}
45
46
static ItsCmdResult process_its_cmd(GICv3ITSState *s, const uint64_t *cmdpkt,
47
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_mapti(GICv3ITSState *s, const uint64_t *cmdpkt,
48
ite.icid = icid;
49
ite.doorbell = INTID_SPURIOUS;
50
ite.vpeid = 0;
51
- return update_ite(s, eventid, &dte, &ite) ? CMD_CONTINUE : CMD_STALL;
52
+ return update_ite(s, eventid, &dte, &ite) ? CMD_CONTINUE_OK : CMD_STALL;
53
}
54
55
static ItsCmdResult process_vmapti(GICv3ITSState *s, const uint64_t *cmdpkt,
56
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_vmapti(GICv3ITSState *s, const uint64_t *cmdpkt,
57
ite.icid = 0;
58
ite.doorbell = doorbell;
59
ite.vpeid = vpeid;
60
- return update_ite(s, eventid, &dte, &ite) ? CMD_CONTINUE : CMD_STALL;
61
+ return update_ite(s, eventid, &dte, &ite) ? CMD_CONTINUE_OK : CMD_STALL;
62
}
63
64
/*
65
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_mapc(GICv3ITSState *s, const uint64_t *cmdpkt)
66
return CMD_CONTINUE;
67
}
68
69
- return update_cte(s, icid, &cte) ? CMD_CONTINUE : CMD_STALL;
70
+ return update_cte(s, icid, &cte) ? CMD_CONTINUE_OK : CMD_STALL;
71
}
72
73
/*
74
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_mapd(GICv3ITSState *s, const uint64_t *cmdpkt)
75
return CMD_CONTINUE;
76
}
77
78
- return update_dte(s, devid, &dte) ? CMD_CONTINUE : CMD_STALL;
79
+ return update_dte(s, devid, &dte) ? CMD_CONTINUE_OK : CMD_STALL;
80
}
81
82
static ItsCmdResult process_movall(GICv3ITSState *s, const uint64_t *cmdpkt)
83
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_movall(GICv3ITSState *s, const uint64_t *cmdpkt)
84
85
if (rd1 == rd2) {
86
/* Move to same target must succeed as a no-op */
87
- return CMD_CONTINUE;
88
+ return CMD_CONTINUE_OK;
89
}
90
91
/* Move all pending LPIs from redistributor 1 to redistributor 2 */
92
gicv3_redist_movall_lpis(&s->gicv3->cpu[rd1], &s->gicv3->cpu[rd2]);
93
94
- return CMD_CONTINUE;
95
+ return CMD_CONTINUE_OK;
96
}
97
98
static ItsCmdResult process_movi(GICv3ITSState *s, const uint64_t *cmdpkt)
99
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_movi(GICv3ITSState *s, const uint64_t *cmdpkt)
100
101
/* Update the ICID field in the interrupt translation table entry */
102
old_ite.icid = new_icid;
103
- return update_ite(s, eventid, &dte, &old_ite) ? CMD_CONTINUE : CMD_STALL;
104
+ return update_ite(s, eventid, &dte, &old_ite) ? CMD_CONTINUE_OK : CMD_STALL;
105
}
106
107
/*
108
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_vmapp(GICv3ITSState *s, const uint64_t *cmdpkt)
109
return CMD_CONTINUE;
110
}
111
112
- return update_vte(s, vpeid, &vte) ? CMD_CONTINUE : CMD_STALL;
113
+ return update_vte(s, vpeid, &vte) ? CMD_CONTINUE_OK : CMD_STALL;
114
}
115
116
/*
117
@@ -XXX,XX +XXX,XX @@ static void process_cmdq(GICv3ITSState *s)
118
}
119
120
while (wr_offset != rd_offset) {
121
- ItsCmdResult result = CMD_CONTINUE;
122
+ ItsCmdResult result = CMD_CONTINUE_OK;
123
void *hostmem;
124
hwaddr buflen;
125
uint64_t cmdpkt[GITS_CMDQ_ENTRY_WORDS];
126
@@ -XXX,XX +XXX,XX @@ static void process_cmdq(GICv3ITSState *s)
127
trace_gicv3_its_cmd_unknown(cmd);
128
break;
129
}
130
- if (result == CMD_CONTINUE) {
131
+ if (result != CMD_STALL) {
132
+ /* CMD_CONTINUE or CMD_CONTINUE_OK */
133
rd_offset++;
134
rd_offset %= s->cq.num_entries;
135
s->creadr = FIELD_DP64(s->creadr, GITS_CREADR, OFFSET, rd_offset);
136
--
137
2.25.1
diff view generated by jsdifflib
Deleted patch
1
The GICv4 ITS VMOVP command's semantics require it to perform the
2
operation on every ITS connected to the same GIC that the ITS that
3
received the command is attached to. This means that the GIC object
4
needs to keep a pointer to every ITS that is connected to it
5
(previously it was sufficient for the ITS to have a pointer to its
6
GIC).
7
1
8
Add a glib ptrarray to the GICv3 object which holds pointers to every
9
connected ITS, and make the ITS add itself to the array for the GIC
10
it is connected to when it is realized.
11
12
Note that currently all QEMU machine types with an ITS have exactly
13
one ITS in the system, so typically the length of this ptrarray will
14
be 1. Multiple ITSes are typically used to improve performance on
15
real hardware, so we wouldn't need to have more than one unless we
16
were modelling a real machine type that had multile ITSes.
17
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
20
Message-id: 20220408141550.1271295-16-peter.maydell@linaro.org
21
---
22
hw/intc/gicv3_internal.h | 9 +++++++++
23
include/hw/intc/arm_gicv3_common.h | 2 ++
24
hw/intc/arm_gicv3_common.c | 2 ++
25
hw/intc/arm_gicv3_its.c | 2 ++
26
hw/intc/arm_gicv3_its_kvm.c | 2 ++
27
5 files changed, 17 insertions(+)
28
29
diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h
30
index XXXXXXX..XXXXXXX 100644
31
--- a/hw/intc/gicv3_internal.h
32
+++ b/hw/intc/gicv3_internal.h
33
@@ -XXX,XX +XXX,XX @@ static inline void gicv3_cache_all_target_cpustates(GICv3State *s)
34
35
void gicv3_set_gicv3state(CPUState *cpu, GICv3CPUState *s);
36
37
+/*
38
+ * The ITS should call this when it is realized to add itself
39
+ * to its GIC's list of connected ITSes.
40
+ */
41
+static inline void gicv3_add_its(GICv3State *s, DeviceState *its)
42
+{
43
+ g_ptr_array_add(s->itslist, its);
44
+}
45
+
46
#endif /* QEMU_ARM_GICV3_INTERNAL_H */
47
diff --git a/include/hw/intc/arm_gicv3_common.h b/include/hw/intc/arm_gicv3_common.h
48
index XXXXXXX..XXXXXXX 100644
49
--- a/include/hw/intc/arm_gicv3_common.h
50
+++ b/include/hw/intc/arm_gicv3_common.h
51
@@ -XXX,XX +XXX,XX @@ struct GICv3State {
52
uint32_t gicd_nsacr[DIV_ROUND_UP(GICV3_MAXIRQ, 16)];
53
54
GICv3CPUState *cpu;
55
+ /* List of all ITSes connected to this GIC */
56
+ GPtrArray *itslist;
57
};
58
59
#define GICV3_BITMAP_ACCESSORS(BMP) \
60
diff --git a/hw/intc/arm_gicv3_common.c b/hw/intc/arm_gicv3_common.c
61
index XXXXXXX..XXXXXXX 100644
62
--- a/hw/intc/arm_gicv3_common.c
63
+++ b/hw/intc/arm_gicv3_common.c
64
@@ -XXX,XX +XXX,XX @@ static void arm_gicv3_common_realize(DeviceState *dev, Error **errp)
65
cpuidx += s->redist_region_count[i];
66
s->cpu[cpuidx - 1].gicr_typer |= GICR_TYPER_LAST;
67
}
68
+
69
+ s->itslist = g_ptr_array_new();
70
}
71
72
static void arm_gicv3_finalize(Object *obj)
73
diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
74
index XXXXXXX..XXXXXXX 100644
75
--- a/hw/intc/arm_gicv3_its.c
76
+++ b/hw/intc/arm_gicv3_its.c
77
@@ -XXX,XX +XXX,XX @@ static void gicv3_arm_its_realize(DeviceState *dev, Error **errp)
78
}
79
}
80
81
+ gicv3_add_its(s->gicv3, dev);
82
+
83
gicv3_its_init_mmio(s, &gicv3_its_control_ops, &gicv3_its_translation_ops);
84
85
/* set the ITS default features supported */
86
diff --git a/hw/intc/arm_gicv3_its_kvm.c b/hw/intc/arm_gicv3_its_kvm.c
87
index XXXXXXX..XXXXXXX 100644
88
--- a/hw/intc/arm_gicv3_its_kvm.c
89
+++ b/hw/intc/arm_gicv3_its_kvm.c
90
@@ -XXX,XX +XXX,XX @@ static void kvm_arm_its_realize(DeviceState *dev, Error **errp)
91
kvm_arm_register_device(&s->iomem_its_cntrl, -1, KVM_DEV_ARM_VGIC_GRP_ADDR,
92
KVM_VGIC_ITS_ADDR_TYPE, s->dev_fd, 0);
93
94
+ gicv3_add_its(s->gicv3, dev);
95
+
96
gicv3_its_init_mmio(s, NULL, NULL);
97
98
if (!kvm_device_check_attr(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_ITS_REGS,
99
--
100
2.25.1
diff view generated by jsdifflib
Deleted patch
1
The VSYNC command forces the ITS to synchronize all outstanding ITS
2
operations for the specified vPEID, so that subsequent writes to
3
GITS_TRANSLATER honour them. The QEMU implementation is always in
4
sync, so for us this is a nop, like the existing SYNC command.
5
1
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20220408141550.1271295-18-peter.maydell@linaro.org
9
---
10
hw/intc/gicv3_internal.h | 1 +
11
hw/intc/arm_gicv3_its.c | 11 +++++++++++
12
hw/intc/trace-events | 1 +
13
3 files changed, 13 insertions(+)
14
15
diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h
16
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/intc/gicv3_internal.h
18
+++ b/hw/intc/gicv3_internal.h
19
@@ -XXX,XX +XXX,XX @@ FIELD(GITS_TYPER, CIL, 36, 1)
20
#define GITS_CMD_MOVALL 0x0E
21
#define GITS_CMD_DISCARD 0x0F
22
#define GITS_CMD_VMOVP 0x22
23
+#define GITS_CMD_VSYNC 0x25
24
#define GITS_CMD_VMAPP 0x29
25
#define GITS_CMD_VMAPTI 0x2A
26
#define GITS_CMD_VMAPI 0x2B
27
diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
28
index XXXXXXX..XXXXXXX 100644
29
--- a/hw/intc/arm_gicv3_its.c
30
+++ b/hw/intc/arm_gicv3_its.c
31
@@ -XXX,XX +XXX,XX @@ static void process_cmdq(GICv3ITSState *s)
32
*/
33
trace_gicv3_its_cmd_sync();
34
break;
35
+ case GITS_CMD_VSYNC:
36
+ /*
37
+ * VSYNC also is a nop, because our implementation is always
38
+ * in sync.
39
+ */
40
+ if (!its_feature_virtual(s)) {
41
+ result = CMD_CONTINUE;
42
+ break;
43
+ }
44
+ trace_gicv3_its_cmd_vsync();
45
+ break;
46
case GITS_CMD_MAPD:
47
result = process_mapd(s, cmdpkt);
48
break;
49
diff --git a/hw/intc/trace-events b/hw/intc/trace-events
50
index XXXXXXX..XXXXXXX 100644
51
--- a/hw/intc/trace-events
52
+++ b/hw/intc/trace-events
53
@@ -XXX,XX +XXX,XX @@ gicv3_its_cmd_vmapi(uint32_t devid, uint32_t eventid, uint32_t vpeid, uint32_t d
54
gicv3_its_cmd_vmapti(uint32_t devid, uint32_t eventid, uint32_t vpeid, uint32_t vintid, uint32_t doorbell) "GICv3 ITS: command VMAPI DeviceID 0x%x EventID 0x%x vPEID 0x%x vINTID 0x%x Dbell_pINTID 0x%x"
55
gicv3_its_cmd_vmapp(uint32_t vpeid, uint64_t rdbase, int valid, uint64_t vptaddr, uint32_t vptsize) "GICv3 ITS: command VMAPP vPEID 0x%x RDbase 0x%" PRIx64 " V %d VPT_addr 0x%" PRIx64 " VPT_size 0x%x"
56
gicv3_its_cmd_vmovp(uint32_t vpeid, uint64_t rdbase) "GICv3 ITS: command VMOVP vPEID 0x%x RDbase 0x%" PRIx64
57
+gicv3_its_cmd_vsync(void) "GICv3 ITS: command VSYNC"
58
gicv3_its_cmd_unknown(unsigned cmd) "GICv3 ITS: unknown command 0x%x"
59
gicv3_its_cte_read(uint32_t icid, int valid, uint32_t rdbase) "GICv3 ITS: Collection Table read for ICID 0x%x: valid %d RDBase 0x%x"
60
gicv3_its_cte_write(uint32_t icid, int valid, uint32_t rdbase) "GICv3 ITS: Collection Table write for ICID 0x%x: valid %d RDBase 0x%x"
61
--
62
2.25.1
diff view generated by jsdifflib
Deleted patch
1
Implement the ITS side of the handling of the INV command for
2
virtual interrupts; as usual this calls into a redistributor
3
function which we leave as a stub to fill in later.
4
1
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20220408141550.1271295-20-peter.maydell@linaro.org
8
---
9
hw/intc/gicv3_internal.h | 9 +++++++++
10
hw/intc/arm_gicv3_its.c | 16 ++++++++++++++--
11
hw/intc/arm_gicv3_redist.c | 8 ++++++++
12
3 files changed, 31 insertions(+), 2 deletions(-)
13
14
diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h
15
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/intc/gicv3_internal.h
17
+++ b/hw/intc/gicv3_internal.h
18
@@ -XXX,XX +XXX,XX @@ void gicv3_redist_update_lpi_only(GICv3CPUState *cs);
19
* Forget or update any cached information associated with this LPI.
20
*/
21
void gicv3_redist_inv_lpi(GICv3CPUState *cs, int irq);
22
+/**
23
+ * gicv3_redist_inv_vlpi:
24
+ * @cs: GICv3CPUState
25
+ * @irq: vLPI to invalidate cached information for
26
+ * @vptaddr: (guest) address of vLPI table
27
+ *
28
+ * Forget or update any cached information associated with this vLPI.
29
+ */
30
+void gicv3_redist_inv_vlpi(GICv3CPUState *cs, int irq, uint64_t vptaddr);
31
/**
32
* gicv3_redist_mov_lpi:
33
* @src: source redistributor
34
diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
35
index XXXXXXX..XXXXXXX 100644
36
--- a/hw/intc/arm_gicv3_its.c
37
+++ b/hw/intc/arm_gicv3_its.c
38
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_inv(GICv3ITSState *s, const uint64_t *cmdpkt)
39
ITEntry ite;
40
DTEntry dte;
41
CTEntry cte;
42
+ VTEntry vte;
43
ItsCmdResult cmdres;
44
45
devid = FIELD_EX64(cmdpkt[0], INV_0, DEVICEID);
46
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_inv(GICv3ITSState *s, const uint64_t *cmdpkt)
47
__func__, ite.inttype);
48
return CMD_CONTINUE;
49
}
50
- /* We will implement the vLPI invalidation in a later commit */
51
- g_assert_not_reached();
52
+
53
+ cmdres = lookup_vte(s, __func__, ite.vpeid, &vte);
54
+ if (cmdres != CMD_CONTINUE_OK) {
55
+ return cmdres;
56
+ }
57
+ if (!intid_in_lpi_range(ite.intid) ||
58
+ ite.intid >= (1ULL << (vte.vptsize + 1))) {
59
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: intid 0x%x out of range\n",
60
+ __func__, ite.intid);
61
+ return CMD_CONTINUE;
62
+ }
63
+ gicv3_redist_inv_vlpi(&s->gicv3->cpu[vte.rdbase], ite.intid,
64
+ vte.vptaddr << 16);
65
break;
66
default:
67
g_assert_not_reached();
68
diff --git a/hw/intc/arm_gicv3_redist.c b/hw/intc/arm_gicv3_redist.c
69
index XXXXXXX..XXXXXXX 100644
70
--- a/hw/intc/arm_gicv3_redist.c
71
+++ b/hw/intc/arm_gicv3_redist.c
72
@@ -XXX,XX +XXX,XX @@ void gicv3_redist_process_vlpi(GICv3CPUState *cs, int irq, uint64_t vptaddr,
73
*/
74
}
75
76
+void gicv3_redist_inv_vlpi(GICv3CPUState *cs, int irq, uint64_t vptaddr)
77
+{
78
+ /*
79
+ * The redistributor handling for invalidating cached information
80
+ * about a VLPI will be added in a subsequent commit.
81
+ */
82
+}
83
+
84
void gicv3_redist_set_irq(GICv3CPUState *cs, int irq, int level)
85
{
86
/* Update redistributor state for a change in an external PPI input line */
87
--
88
2.25.1
diff view generated by jsdifflib
Deleted patch
1
The VINVALL command should cause any cached information in the
2
ITS or redistributor for the specified vCPU to be dropped or
3
otherwise made consistent with the in-memory LPI configuration
4
tables.
5
1
6
Here we implement the command and table parsing, leaving the
7
redistributor part as a stub for the moment, as usual.
8
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20220408141550.1271295-22-peter.maydell@linaro.org
12
---
13
hw/intc/gicv3_internal.h | 13 +++++++++++++
14
hw/intc/arm_gicv3_its.c | 26 ++++++++++++++++++++++++++
15
hw/intc/arm_gicv3_redist.c | 5 +++++
16
hw/intc/trace-events | 1 +
17
4 files changed, 45 insertions(+)
18
19
diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h
20
index XXXXXXX..XXXXXXX 100644
21
--- a/hw/intc/gicv3_internal.h
22
+++ b/hw/intc/gicv3_internal.h
23
@@ -XXX,XX +XXX,XX @@ FIELD(GITS_TYPER, CIL, 36, 1)
24
#define GITS_CMD_VMAPP 0x29
25
#define GITS_CMD_VMAPTI 0x2A
26
#define GITS_CMD_VMAPI 0x2B
27
+#define GITS_CMD_VINVALL 0x2D
28
29
/* MAPC command fields */
30
#define ICID_LENGTH 16
31
@@ -XXX,XX +XXX,XX @@ FIELD(VMOVI_1, VPEID, 32, 16)
32
FIELD(VMOVI_2, D, 0, 1)
33
FIELD(VMOVI_2, DOORBELL, 32, 32)
34
35
+/* VINVALL command fields */
36
+FIELD(VINVALL_1, VPEID, 32, 16)
37
+
38
/*
39
* 12 bytes Interrupt translation Table Entry size
40
* as per Table 5.3 in GICv3 spec
41
@@ -XXX,XX +XXX,XX @@ void gicv3_redist_movall_lpis(GICv3CPUState *src, GICv3CPUState *dest);
42
void gicv3_redist_mov_vlpi(GICv3CPUState *src, uint64_t src_vptaddr,
43
GICv3CPUState *dest, uint64_t dest_vptaddr,
44
int irq, int doorbell);
45
+/**
46
+ * gicv3_redist_vinvall:
47
+ * @cs: GICv3CPUState
48
+ * @vptaddr: address of VLPI pending table
49
+ *
50
+ * On redistributor @cs, invalidate all cached information associated
51
+ * with the vCPU defined by @vptaddr.
52
+ */
53
+void gicv3_redist_vinvall(GICv3CPUState *cs, uint64_t vptaddr);
54
55
void gicv3_redist_send_sgi(GICv3CPUState *cs, int grp, int irq, bool ns);
56
void gicv3_init_cpuif(GICv3State *s);
57
diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
58
index XXXXXXX..XXXXXXX 100644
59
--- a/hw/intc/arm_gicv3_its.c
60
+++ b/hw/intc/arm_gicv3_its.c
61
@@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_vmovi(GICv3ITSState *s, const uint64_t *cmdpkt)
62
return update_ite(s, eventid, &dte, &ite) ? CMD_CONTINUE_OK : CMD_STALL;
63
}
64
65
+static ItsCmdResult process_vinvall(GICv3ITSState *s, const uint64_t *cmdpkt)
66
+{
67
+ VTEntry vte;
68
+ uint32_t vpeid;
69
+ ItsCmdResult cmdres;
70
+
71
+ if (!its_feature_virtual(s)) {
72
+ return CMD_CONTINUE;
73
+ }
74
+
75
+ vpeid = FIELD_EX64(cmdpkt[1], VINVALL_1, VPEID);
76
+
77
+ trace_gicv3_its_cmd_vinvall(vpeid);
78
+
79
+ cmdres = lookup_vte(s, __func__, vpeid, &vte);
80
+ if (cmdres != CMD_CONTINUE_OK) {
81
+ return cmdres;
82
+ }
83
+
84
+ gicv3_redist_vinvall(&s->gicv3->cpu[vte.rdbase], vte.vptaddr << 16);
85
+ return CMD_CONTINUE_OK;
86
+}
87
+
88
static ItsCmdResult process_inv(GICv3ITSState *s, const uint64_t *cmdpkt)
89
{
90
uint32_t devid, eventid;
91
@@ -XXX,XX +XXX,XX @@ static void process_cmdq(GICv3ITSState *s)
92
case GITS_CMD_VMOVI:
93
result = process_vmovi(s, cmdpkt);
94
break;
95
+ case GITS_CMD_VINVALL:
96
+ result = process_vinvall(s, cmdpkt);
97
+ break;
98
default:
99
trace_gicv3_its_cmd_unknown(cmd);
100
break;
101
diff --git a/hw/intc/arm_gicv3_redist.c b/hw/intc/arm_gicv3_redist.c
102
index XXXXXXX..XXXXXXX 100644
103
--- a/hw/intc/arm_gicv3_redist.c
104
+++ b/hw/intc/arm_gicv3_redist.c
105
@@ -XXX,XX +XXX,XX @@ void gicv3_redist_mov_vlpi(GICv3CPUState *src, uint64_t src_vptaddr,
106
*/
107
}
108
109
+void gicv3_redist_vinvall(GICv3CPUState *cs, uint64_t vptaddr)
110
+{
111
+ /* The redistributor handling will be added in a subsequent commit */
112
+}
113
+
114
void gicv3_redist_inv_vlpi(GICv3CPUState *cs, int irq, uint64_t vptaddr)
115
{
116
/*
117
diff --git a/hw/intc/trace-events b/hw/intc/trace-events
118
index XXXXXXX..XXXXXXX 100644
119
--- a/hw/intc/trace-events
120
+++ b/hw/intc/trace-events
121
@@ -XXX,XX +XXX,XX @@ gicv3_its_cmd_vmapp(uint32_t vpeid, uint64_t rdbase, int valid, uint64_t vptaddr
122
gicv3_its_cmd_vmovp(uint32_t vpeid, uint64_t rdbase) "GICv3 ITS: command VMOVP vPEID 0x%x RDbase 0x%" PRIx64
123
gicv3_its_cmd_vsync(void) "GICv3 ITS: command VSYNC"
124
gicv3_its_cmd_vmovi(uint32_t devid, uint32_t eventid, uint32_t vpeid, int dbvalid, uint32_t doorbell) "GICv3 ITS: command VMOVI DeviceID 0x%x EventID 0x%x vPEID 0x%x D %d Dbell_pINTID 0x%x"
125
+gicv3_its_cmd_vinvall(uint32_t vpeid) "GICv3 ITS: command VINVALL vPEID 0x%x"
126
gicv3_its_cmd_unknown(unsigned cmd) "GICv3 ITS: unknown command 0x%x"
127
gicv3_its_cte_read(uint32_t icid, int valid, uint32_t rdbase) "GICv3 ITS: Collection Table read for ICID 0x%x: valid %d RDBase 0x%x"
128
gicv3_its_cte_write(uint32_t icid, int valid, uint32_t rdbase) "GICv3 ITS: Collection Table write for ICID 0x%x: valid %d RDBase 0x%x"
129
--
130
2.25.1
diff view generated by jsdifflib
Deleted patch
1
The GICv4 extends the redistributor register map -- where GICv3
2
had two 64KB frames per CPU, GICv4 has four frames. Add support
3
for the extra frame by using a new gicv3_redist_size() function
4
in the places in the GIC implementation which currently use
5
a fixed constant size for the redistributor register block.
6
(Until we implement the extra registers they will RAZ/WI.)
7
1
8
Any board that wants to use a GICv4 will need to also adjust
9
to handle the different sized redistributor register block;
10
that will be done separately.
11
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
14
Message-id: 20220408141550.1271295-23-peter.maydell@linaro.org
15
---
16
hw/intc/gicv3_internal.h | 21 +++++++++++++++++++++
17
include/hw/intc/arm_gicv3_common.h | 5 +++++
18
hw/intc/arm_gicv3_common.c | 2 +-
19
hw/intc/arm_gicv3_redist.c | 8 ++++----
20
4 files changed, 31 insertions(+), 5 deletions(-)
21
22
diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h
23
index XXXXXXX..XXXXXXX 100644
24
--- a/hw/intc/gicv3_internal.h
25
+++ b/hw/intc/gicv3_internal.h
26
@@ -XXX,XX +XXX,XX @@ FIELD(VTE, RDBASE, 42, RDBASE_PROCNUM_LENGTH)
27
28
/* Functions internal to the emulated GICv3 */
29
30
+/**
31
+ * gicv3_redist_size:
32
+ * @s: GICv3State
33
+ *
34
+ * Return the size of the redistributor register frame in bytes
35
+ * (which depends on what GIC version this is)
36
+ */
37
+static inline int gicv3_redist_size(GICv3State *s)
38
+{
39
+ /*
40
+ * Redistributor size is controlled by the redistributor GICR_TYPER.VLPIS.
41
+ * It's the same for every redistributor in the GIC, so arbitrarily
42
+ * use the register field in the first one.
43
+ */
44
+ if (s->cpu[0].gicr_typer & GICR_TYPER_VLPIS) {
45
+ return GICV4_REDIST_SIZE;
46
+ } else {
47
+ return GICV3_REDIST_SIZE;
48
+ }
49
+}
50
+
51
/**
52
* gicv3_intid_is_special:
53
* @intid: interrupt ID
54
diff --git a/include/hw/intc/arm_gicv3_common.h b/include/hw/intc/arm_gicv3_common.h
55
index XXXXXXX..XXXXXXX 100644
56
--- a/include/hw/intc/arm_gicv3_common.h
57
+++ b/include/hw/intc/arm_gicv3_common.h
58
@@ -XXX,XX +XXX,XX @@
59
60
#define GICV3_LPI_INTID_START 8192
61
62
+/*
63
+ * The redistributor in GICv3 has two 64KB frames per CPU; in
64
+ * GICv4 it has four 64KB frames per CPU.
65
+ */
66
#define GICV3_REDIST_SIZE 0x20000
67
+#define GICV4_REDIST_SIZE 0x40000
68
69
/* Number of SGI target-list bits */
70
#define GICV3_TARGETLIST_BITS 16
71
diff --git a/hw/intc/arm_gicv3_common.c b/hw/intc/arm_gicv3_common.c
72
index XXXXXXX..XXXXXXX 100644
73
--- a/hw/intc/arm_gicv3_common.c
74
+++ b/hw/intc/arm_gicv3_common.c
75
@@ -XXX,XX +XXX,XX @@ void gicv3_init_irqs_and_mmio(GICv3State *s, qemu_irq_handler handler,
76
77
memory_region_init_io(&region->iomem, OBJECT(s),
78
ops ? &ops[1] : NULL, region, name,
79
- s->redist_region_count[i] * GICV3_REDIST_SIZE);
80
+ s->redist_region_count[i] * gicv3_redist_size(s));
81
sysbus_init_mmio(sbd, &region->iomem);
82
g_free(name);
83
}
84
diff --git a/hw/intc/arm_gicv3_redist.c b/hw/intc/arm_gicv3_redist.c
85
index XXXXXXX..XXXXXXX 100644
86
--- a/hw/intc/arm_gicv3_redist.c
87
+++ b/hw/intc/arm_gicv3_redist.c
88
@@ -XXX,XX +XXX,XX @@ MemTxResult gicv3_redist_read(void *opaque, hwaddr offset, uint64_t *data,
89
* in the memory map); if so then the GIC has multiple MemoryRegions
90
* for the redistributors.
91
*/
92
- cpuidx = region->cpuidx + offset / GICV3_REDIST_SIZE;
93
- offset %= GICV3_REDIST_SIZE;
94
+ cpuidx = region->cpuidx + offset / gicv3_redist_size(s);
95
+ offset %= gicv3_redist_size(s);
96
97
cs = &s->cpu[cpuidx];
98
99
@@ -XXX,XX +XXX,XX @@ MemTxResult gicv3_redist_write(void *opaque, hwaddr offset, uint64_t data,
100
* in the memory map); if so then the GIC has multiple MemoryRegions
101
* for the redistributors.
102
*/
103
- cpuidx = region->cpuidx + offset / GICV3_REDIST_SIZE;
104
- offset %= GICV3_REDIST_SIZE;
105
+ cpuidx = region->cpuidx + offset / gicv3_redist_size(s);
106
+ offset %= gicv3_redist_size(s);
107
108
cs = &s->cpu[cpuidx];
109
110
--
111
2.25.1
diff view generated by jsdifflib
Deleted patch
1
Implement the new GICv4 redistributor registers: GICR_VPROPBASER
2
and GICR_VPENDBASER; for the moment we implement these as simple
3
reads-as-written stubs, together with the necessary migration
4
and reset handling.
5
1
6
We don't put ID-register checks on the handling of these registers,
7
because they are all in the only-in-v4 extra register frames, so
8
they're not accessible in a GICv3.
9
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20220408141550.1271295-24-peter.maydell@linaro.org
13
---
14
hw/intc/gicv3_internal.h | 21 +++++++++++
15
include/hw/intc/arm_gicv3_common.h | 3 ++
16
hw/intc/arm_gicv3_common.c | 22 ++++++++++++
17
hw/intc/arm_gicv3_redist.c | 56 ++++++++++++++++++++++++++++++
18
4 files changed, 102 insertions(+)
19
20
diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h
21
index XXXXXXX..XXXXXXX 100644
22
--- a/hw/intc/gicv3_internal.h
23
+++ b/hw/intc/gicv3_internal.h
24
@@ -XXX,XX +XXX,XX @@
25
* Redistributor frame offsets from RD_base
26
*/
27
#define GICR_SGI_OFFSET 0x10000
28
+#define GICR_VLPI_OFFSET 0x20000
29
30
/*
31
* Redistributor registers, offsets from RD_base
32
@@ -XXX,XX +XXX,XX @@
33
#define GICR_IGRPMODR0 (GICR_SGI_OFFSET + 0x0D00)
34
#define GICR_NSACR (GICR_SGI_OFFSET + 0x0E00)
35
36
+/* VLPI redistributor registers, offsets from VLPI_base */
37
+#define GICR_VPROPBASER (GICR_VLPI_OFFSET + 0x70)
38
+#define GICR_VPENDBASER (GICR_VLPI_OFFSET + 0x78)
39
+
40
#define GICR_CTLR_ENABLE_LPIS (1U << 0)
41
#define GICR_CTLR_CES (1U << 1)
42
#define GICR_CTLR_RWP (1U << 3)
43
@@ -XXX,XX +XXX,XX @@ FIELD(GICR_PENDBASER, PTZ, 62, 1)
44
45
#define GICR_PROPBASER_IDBITS_THRESHOLD 0xd
46
47
+/* These are the GICv4 VPROPBASER and VPENDBASER layouts; v4.1 is different */
48
+FIELD(GICR_VPROPBASER, IDBITS, 0, 5)
49
+FIELD(GICR_VPROPBASER, INNERCACHE, 7, 3)
50
+FIELD(GICR_VPROPBASER, SHAREABILITY, 10, 2)
51
+FIELD(GICR_VPROPBASER, PHYADDR, 12, 40)
52
+FIELD(GICR_VPROPBASER, OUTERCACHE, 56, 3)
53
+
54
+FIELD(GICR_VPENDBASER, INNERCACHE, 7, 3)
55
+FIELD(GICR_VPENDBASER, SHAREABILITY, 10, 2)
56
+FIELD(GICR_VPENDBASER, PHYADDR, 16, 36)
57
+FIELD(GICR_VPENDBASER, OUTERCACHE, 56, 3)
58
+FIELD(GICR_VPENDBASER, DIRTY, 60, 1)
59
+FIELD(GICR_VPENDBASER, PENDINGLAST, 61, 1)
60
+FIELD(GICR_VPENDBASER, IDAI, 62, 1)
61
+FIELD(GICR_VPENDBASER, VALID, 63, 1)
62
+
63
#define ICC_CTLR_EL1_CBPR (1U << 0)
64
#define ICC_CTLR_EL1_EOIMODE (1U << 1)
65
#define ICC_CTLR_EL1_PMHE (1U << 6)
66
diff --git a/include/hw/intc/arm_gicv3_common.h b/include/hw/intc/arm_gicv3_common.h
67
index XXXXXXX..XXXXXXX 100644
68
--- a/include/hw/intc/arm_gicv3_common.h
69
+++ b/include/hw/intc/arm_gicv3_common.h
70
@@ -XXX,XX +XXX,XX @@ struct GICv3CPUState {
71
uint32_t gicr_igrpmodr0;
72
uint32_t gicr_nsacr;
73
uint8_t gicr_ipriorityr[GIC_INTERNAL];
74
+ /* VLPI_base page registers */
75
+ uint64_t gicr_vpropbaser;
76
+ uint64_t gicr_vpendbaser;
77
78
/* CPU interface */
79
uint64_t icc_sre_el1;
80
diff --git a/hw/intc/arm_gicv3_common.c b/hw/intc/arm_gicv3_common.c
81
index XXXXXXX..XXXXXXX 100644
82
--- a/hw/intc/arm_gicv3_common.c
83
+++ b/hw/intc/arm_gicv3_common.c
84
@@ -XXX,XX +XXX,XX @@ const VMStateDescription vmstate_gicv3_cpu_sre_el1 = {
85
}
86
};
87
88
+static bool gicv4_needed(void *opaque)
89
+{
90
+ GICv3CPUState *cs = opaque;
91
+
92
+ return cs->gic->revision > 3;
93
+}
94
+
95
+const VMStateDescription vmstate_gicv3_gicv4 = {
96
+ .name = "arm_gicv3_cpu/gicv4",
97
+ .version_id = 1,
98
+ .minimum_version_id = 1,
99
+ .needed = gicv4_needed,
100
+ .fields = (VMStateField[]) {
101
+ VMSTATE_UINT64(gicr_vpropbaser, GICv3CPUState),
102
+ VMSTATE_UINT64(gicr_vpendbaser, GICv3CPUState),
103
+ VMSTATE_END_OF_LIST()
104
+ }
105
+};
106
+
107
static const VMStateDescription vmstate_gicv3_cpu = {
108
.name = "arm_gicv3_cpu",
109
.version_id = 1,
110
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_gicv3_cpu = {
111
.subsections = (const VMStateDescription * []) {
112
&vmstate_gicv3_cpu_virt,
113
&vmstate_gicv3_cpu_sre_el1,
114
+ &vmstate_gicv3_gicv4,
115
NULL
116
}
117
};
118
@@ -XXX,XX +XXX,XX @@ static void arm_gicv3_common_reset(DeviceState *dev)
119
cs->gicr_waker = GICR_WAKER_ProcessorSleep | GICR_WAKER_ChildrenAsleep;
120
cs->gicr_propbaser = 0;
121
cs->gicr_pendbaser = 0;
122
+ cs->gicr_vpropbaser = 0;
123
+ cs->gicr_vpendbaser = 0;
124
/* If we're resetting a TZ-aware GIC as if secure firmware
125
* had set it up ready to start a kernel in non-secure, we
126
* need to set interrupts to group 1 so the kernel can use them.
127
diff --git a/hw/intc/arm_gicv3_redist.c b/hw/intc/arm_gicv3_redist.c
128
index XXXXXXX..XXXXXXX 100644
129
--- a/hw/intc/arm_gicv3_redist.c
130
+++ b/hw/intc/arm_gicv3_redist.c
131
@@ -XXX,XX +XXX,XX @@ static MemTxResult gicr_readl(GICv3CPUState *cs, hwaddr offset,
132
case GICR_IDREGS ... GICR_IDREGS + 0x2f:
133
*data = gicv3_idreg(offset - GICR_IDREGS, GICV3_PIDR0_REDIST);
134
return MEMTX_OK;
135
+ /*
136
+ * VLPI frame registers. We don't need a version check for
137
+ * VPROPBASER and VPENDBASER because gicv3_redist_size() will
138
+ * prevent pre-v4 GIC from passing us offsets this high.
139
+ */
140
+ case GICR_VPROPBASER:
141
+ *data = extract64(cs->gicr_vpropbaser, 0, 32);
142
+ return MEMTX_OK;
143
+ case GICR_VPROPBASER + 4:
144
+ *data = extract64(cs->gicr_vpropbaser, 32, 32);
145
+ return MEMTX_OK;
146
+ case GICR_VPENDBASER:
147
+ *data = extract64(cs->gicr_vpendbaser, 0, 32);
148
+ return MEMTX_OK;
149
+ case GICR_VPENDBASER + 4:
150
+ *data = extract64(cs->gicr_vpendbaser, 32, 32);
151
+ return MEMTX_OK;
152
default:
153
return MEMTX_ERROR;
154
}
155
@@ -XXX,XX +XXX,XX @@ static MemTxResult gicr_writel(GICv3CPUState *cs, hwaddr offset,
156
"%s: invalid guest write to RO register at offset "
157
TARGET_FMT_plx "\n", __func__, offset);
158
return MEMTX_OK;
159
+ /*
160
+ * VLPI frame registers. We don't need a version check for
161
+ * VPROPBASER and VPENDBASER because gicv3_redist_size() will
162
+ * prevent pre-v4 GIC from passing us offsets this high.
163
+ */
164
+ case GICR_VPROPBASER:
165
+ cs->gicr_vpropbaser = deposit64(cs->gicr_vpropbaser, 0, 32, value);
166
+ return MEMTX_OK;
167
+ case GICR_VPROPBASER + 4:
168
+ cs->gicr_vpropbaser = deposit64(cs->gicr_vpropbaser, 32, 32, value);
169
+ return MEMTX_OK;
170
+ case GICR_VPENDBASER:
171
+ cs->gicr_vpendbaser = deposit64(cs->gicr_vpendbaser, 0, 32, value);
172
+ return MEMTX_OK;
173
+ case GICR_VPENDBASER + 4:
174
+ cs->gicr_vpendbaser = deposit64(cs->gicr_vpendbaser, 32, 32, value);
175
+ return MEMTX_OK;
176
default:
177
return MEMTX_ERROR;
178
}
179
@@ -XXX,XX +XXX,XX @@ static MemTxResult gicr_readll(GICv3CPUState *cs, hwaddr offset,
180
case GICR_PENDBASER:
181
*data = cs->gicr_pendbaser;
182
return MEMTX_OK;
183
+ /*
184
+ * VLPI frame registers. We don't need a version check for
185
+ * VPROPBASER and VPENDBASER because gicv3_redist_size() will
186
+ * prevent pre-v4 GIC from passing us offsets this high.
187
+ */
188
+ case GICR_VPROPBASER:
189
+ *data = cs->gicr_vpropbaser;
190
+ return MEMTX_OK;
191
+ case GICR_VPENDBASER:
192
+ *data = cs->gicr_vpendbaser;
193
+ return MEMTX_OK;
194
default:
195
return MEMTX_ERROR;
196
}
197
@@ -XXX,XX +XXX,XX @@ static MemTxResult gicr_writell(GICv3CPUState *cs, hwaddr offset,
198
"%s: invalid guest write to RO register at offset "
199
TARGET_FMT_plx "\n", __func__, offset);
200
return MEMTX_OK;
201
+ /*
202
+ * VLPI frame registers. We don't need a version check for
203
+ * VPROPBASER and VPENDBASER because gicv3_redist_size() will
204
+ * prevent pre-v4 GIC from passing us offsets this high.
205
+ */
206
+ case GICR_VPROPBASER:
207
+ cs->gicr_vpropbaser = value;
208
+ return MEMTX_OK;
209
+ case GICR_VPENDBASER:
210
+ cs->gicr_vpendbaser = value;
211
+ return MEMTX_OK;
212
default:
213
return MEMTX_ERROR;
214
}
215
--
216
2.25.1
diff view generated by jsdifflib
1
Currently the functions which update the highest priority pending LPI
1
Convert the ASIMD load/store single structure insns to decodetree.
2
information by looking at the LPI Pending and Configuration tables
3
are hard-coded to use the physical LPI tables addressed by
4
GICR_PENDBASER and GICR_PROPBASER. To support virtual LPIs we will
5
need to do essentially the same job, but looking at the current
6
virtual LPI Pending and Configuration tables and updating cs->hppvlpi
7
instead of cs->hpplpi.
8
9
Factor out the common part of the gicv3_redist_check_lpi_priority()
10
function into a new update_for_one_lpi() function, which updates
11
a PendingIrq struct if the specified LPI is higher priority than
12
what is currently recorded there.
13
2
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Message-id: 20230602155223.2040685-20-peter.maydell@linaro.org
15
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
16
Message-id: 20220408141550.1271295-28-peter.maydell@linaro.org
17
---
6
---
18
hw/intc/arm_gicv3_redist.c | 74 ++++++++++++++++++++++++--------------
7
target/arm/tcg/a64.decode | 34 +++++
19
1 file changed, 47 insertions(+), 27 deletions(-)
8
target/arm/tcg/translate-a64.c | 219 +++++++++++++++------------------
9
2 files changed, 136 insertions(+), 117 deletions(-)
20
10
21
diff --git a/hw/intc/arm_gicv3_redist.c b/hw/intc/arm_gicv3_redist.c
11
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
22
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
23
--- a/hw/intc/arm_gicv3_redist.c
13
--- a/target/arm/tcg/a64.decode
24
+++ b/hw/intc/arm_gicv3_redist.c
14
+++ b/target/arm/tcg/a64.decode
25
@@ -XXX,XX +XXX,XX @@ static uint32_t gicr_read_bitmap_reg(GICv3CPUState *cs, MemTxAttrs attrs,
15
@@ -XXX,XX +XXX,XX @@ LD_mult 0 . 001100 . 1 0 ..... 0110 .. ..... ..... @ldst_mult rpt=3 sele
26
return reg;
16
LD_mult 0 . 001100 . 1 0 ..... 0111 .. ..... ..... @ldst_mult rpt=1 selem=1
17
LD_mult 0 . 001100 . 1 0 ..... 1000 .. ..... ..... @ldst_mult rpt=1 selem=2
18
LD_mult 0 . 001100 . 1 0 ..... 1010 .. ..... ..... @ldst_mult rpt=2 selem=1
19
+
20
+# Load/store single structure
21
+&ldst_single rm rn rt p selem index scale
22
+
23
+%ldst_single_selem 13:1 21:1 !function=plus_1
24
+
25
+%ldst_single_index_b 30:1 10:3
26
+%ldst_single_index_h 30:1 11:2
27
+%ldst_single_index_s 30:1 12:1
28
+
29
+@ldst_single_b .. ...... p:1 .. rm:5 ...... rn:5 rt:5 \
30
+ &ldst_single scale=0 selem=%ldst_single_selem \
31
+ index=%ldst_single_index_b
32
+@ldst_single_h .. ...... p:1 .. rm:5 ...... rn:5 rt:5 \
33
+ &ldst_single scale=1 selem=%ldst_single_selem \
34
+ index=%ldst_single_index_h
35
+@ldst_single_s .. ...... p:1 .. rm:5 ...... rn:5 rt:5 \
36
+ &ldst_single scale=2 selem=%ldst_single_selem \
37
+ index=%ldst_single_index_s
38
+@ldst_single_d . index:1 ...... p:1 .. rm:5 ...... rn:5 rt:5 \
39
+ &ldst_single scale=3 selem=%ldst_single_selem
40
+
41
+ST_single 0 . 001101 . 0 . ..... 00 . ... ..... ..... @ldst_single_b
42
+ST_single 0 . 001101 . 0 . ..... 01 . ..0 ..... ..... @ldst_single_h
43
+ST_single 0 . 001101 . 0 . ..... 10 . .00 ..... ..... @ldst_single_s
44
+ST_single 0 . 001101 . 0 . ..... 10 . 001 ..... ..... @ldst_single_d
45
+
46
+LD_single 0 . 001101 . 1 . ..... 00 . ... ..... ..... @ldst_single_b
47
+LD_single 0 . 001101 . 1 . ..... 01 . ..0 ..... ..... @ldst_single_h
48
+LD_single 0 . 001101 . 1 . ..... 10 . .00 ..... ..... @ldst_single_s
49
+LD_single 0 . 001101 . 1 . ..... 10 . 001 ..... ..... @ldst_single_d
50
+
51
+# Replicating load case
52
+LD_single_repl 0 q:1 001101 p:1 1 . rm:5 11 . 0 scale:2 rn:5 rt:5 selem=%ldst_single_selem
53
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
54
index XXXXXXX..XXXXXXX 100644
55
--- a/target/arm/tcg/translate-a64.c
56
+++ b/target/arm/tcg/translate-a64.c
57
@@ -XXX,XX +XXX,XX @@ static bool trans_ST_mult(DisasContext *s, arg_ldst_mult *a)
58
return true;
27
}
59
}
28
60
29
+/**
61
-/* AdvSIMD load/store single structure
30
+ * update_for_one_lpi: Update pending information if this LPI is better
62
- *
31
+ *
63
- * 31 30 29 23 22 21 20 16 15 13 12 11 10 9 5 4 0
32
+ * @cs: GICv3CPUState
64
- * +---+---+---------------+-----+-----------+-----+---+------+------+------+
33
+ * @irq: interrupt to look up in the LPI Configuration table
65
- * | 0 | Q | 0 0 1 1 0 1 0 | L R | 0 0 0 0 0 | opc | S | size | Rn | Rt |
34
+ * @ctbase: physical address of the LPI Configuration table to use
66
- * +---+---+---------------+-----+-----------+-----+---+------+------+------+
35
+ * @ds: true if priority value should not be shifted
67
- *
36
+ * @hpp: points to pending information to update
68
- * AdvSIMD load/store single structure (post-indexed)
37
+ *
69
- *
38
+ * Look up @irq in the Configuration table specified by @ctbase
70
- * 31 30 29 23 22 21 20 16 15 13 12 11 10 9 5 4 0
39
+ * to see if it is enabled and what its priority is. If it is an
71
- * +---+---+---------------+-----+-----------+-----+---+------+------+------+
40
+ * enabled interrupt with a higher priority than that currently
72
- * | 0 | Q | 0 0 1 1 0 1 1 | L R | Rm | opc | S | size | Rn | Rt |
41
+ * recorded in @hpp, update @hpp.
73
- * +---+---+---------------+-----+-----------+-----+---+------+------+------+
42
+ */
74
- *
43
+static void update_for_one_lpi(GICv3CPUState *cs, int irq,
75
- * Rt: first (or only) SIMD&FP register to be transferred
44
+ uint64_t ctbase, bool ds, PendingIrq *hpp)
76
- * Rn: base address or SP
45
+{
77
- * Rm (post-index only): post-index register (when !31) or size dependent #imm
46
+ uint8_t lpite;
78
- * index = encoded in Q:S:size dependent on size
47
+ uint8_t prio;
79
- *
48
+
80
- * lane_size = encoded in R, opc
49
+ address_space_read(&cs->gic->dma_as,
81
- * transfer width = encoded in opc, S, size
50
+ ctbase + ((irq - GICV3_LPI_INTID_START) * sizeof(lpite)),
82
- */
51
+ MEMTXATTRS_UNSPECIFIED, &lpite, sizeof(lpite));
83
-static void disas_ldst_single_struct(DisasContext *s, uint32_t insn)
52
+
84
+static bool trans_ST_single(DisasContext *s, arg_ldst_single *a)
53
+ if (!(lpite & LPI_CTE_ENABLED)) {
54
+ return;
55
+ }
56
+
57
+ if (ds) {
58
+ prio = lpite & LPI_PRIORITY_MASK;
59
+ } else {
60
+ prio = ((lpite & LPI_PRIORITY_MASK) >> 1) | 0x80;
61
+ }
62
+
63
+ if ((prio < hpp->prio) ||
64
+ ((prio == hpp->prio) && (irq <= hpp->irq))) {
65
+ hpp->irq = irq;
66
+ hpp->prio = prio;
67
+ /* LPIs and vLPIs are always non-secure Grp1 interrupts */
68
+ hpp->grp = GICV3_G1NS;
69
+ }
70
+}
71
+
72
static uint8_t gicr_read_ipriorityr(GICv3CPUState *cs, MemTxAttrs attrs,
73
int irq)
74
{
85
{
75
@@ -XXX,XX +XXX,XX @@ MemTxResult gicv3_redist_write(void *opaque, hwaddr offset, uint64_t data,
86
- int rt = extract32(insn, 0, 5);
76
87
- int rn = extract32(insn, 5, 5);
77
static void gicv3_redist_check_lpi_priority(GICv3CPUState *cs, int irq)
88
- int rm = extract32(insn, 16, 5);
78
{
89
- int size = extract32(insn, 10, 2);
79
- AddressSpace *as = &cs->gic->dma_as;
90
- int S = extract32(insn, 12, 1);
80
- uint64_t lpict_baddr;
91
- int opc = extract32(insn, 13, 3);
81
- uint8_t lpite;
92
- int R = extract32(insn, 21, 1);
82
- uint8_t prio;
93
- int is_load = extract32(insn, 22, 1);
83
+ uint64_t lpict_baddr = cs->gicr_propbaser & R_GICR_PROPBASER_PHYADDR_MASK;
94
- int is_postidx = extract32(insn, 23, 1);
84
95
- int is_q = extract32(insn, 30, 1);
85
- lpict_baddr = cs->gicr_propbaser & R_GICR_PROPBASER_PHYADDR_MASK;
96
-
86
-
97
- int scale = extract32(opc, 1, 2);
87
- address_space_read(as, lpict_baddr + ((irq - GICV3_LPI_INTID_START) *
98
- int selem = (extract32(opc, 0, 1) << 1 | R) + 1;
88
- sizeof(lpite)), MEMTXATTRS_UNSPECIFIED, &lpite,
99
- bool replicate = false;
89
- sizeof(lpite));
100
- int index = is_q << 3 | S << 2 | size;
90
-
101
- int xs, total;
91
- if (!(lpite & LPI_CTE_ENABLED)) {
102
+ int xs, total, rt;
103
TCGv_i64 clean_addr, tcg_rn, tcg_ebytes;
104
MemOp mop;
105
106
- if (extract32(insn, 31, 1)) {
107
- unallocated_encoding(s);
108
- return;
109
+ if (!a->p && a->rm != 0) {
110
+ return false;
111
}
112
- if (!is_postidx && rm != 0) {
113
- unallocated_encoding(s);
92
- return;
114
- return;
93
- }
115
- }
94
-
116
-
95
- if (cs->gic->gicd_ctlr & GICD_CTLR_DS) {
117
- switch (scale) {
96
- prio = lpite & LPI_PRIORITY_MASK;
118
- case 3:
97
- } else {
119
- if (!is_load || S) {
98
- prio = ((lpite & LPI_PRIORITY_MASK) >> 1) | 0x80;
120
- unallocated_encoding(s);
121
- return;
122
- }
123
- scale = size;
124
- replicate = true;
125
- break;
126
- case 0:
127
- break;
128
- case 1:
129
- if (extract32(size, 0, 1)) {
130
- unallocated_encoding(s);
131
- return;
132
- }
133
- index >>= 1;
134
- break;
135
- case 2:
136
- if (extract32(size, 1, 1)) {
137
- unallocated_encoding(s);
138
- return;
139
- }
140
- if (!extract32(size, 0, 1)) {
141
- index >>= 2;
142
- } else {
143
- if (S) {
144
- unallocated_encoding(s);
145
- return;
146
- }
147
- index >>= 3;
148
- scale = 3;
149
- }
150
- break;
151
- default:
152
- g_assert_not_reached();
99
- }
153
- }
100
-
154
-
101
- if ((prio < cs->hpplpi.prio) ||
155
if (!fp_access_check(s)) {
102
- ((prio == cs->hpplpi.prio) && (irq <= cs->hpplpi.irq))) {
156
- return;
103
- cs->hpplpi.irq = irq;
157
+ return true;
104
- cs->hpplpi.prio = prio;
158
}
105
- /* LPIs are always non-secure Grp1 interrupts */
159
106
- cs->hpplpi.grp = GICV3_G1NS;
160
- if (rn == 31) {
107
- }
161
+ if (a->rn == 31) {
108
+ update_for_one_lpi(cs, irq, lpict_baddr,
162
gen_check_sp_alignment(s);
109
+ cs->gic->gicd_ctlr & GICD_CTLR_DS,
163
}
110
+ &cs->hpplpi);
164
165
- total = selem << scale;
166
- tcg_rn = cpu_reg_sp(s, rn);
167
+ total = a->selem << a->scale;
168
+ tcg_rn = cpu_reg_sp(s, a->rn);
169
170
- mop = finalize_memop_asimd(s, scale);
171
-
172
- clean_addr = gen_mte_checkN(s, tcg_rn, !is_load, is_postidx || rn != 31,
173
+ mop = finalize_memop_asimd(s, a->scale);
174
+ clean_addr = gen_mte_checkN(s, tcg_rn, true, a->p || a->rn != 31,
175
total, mop);
176
177
- tcg_ebytes = tcg_constant_i64(1 << scale);
178
- for (xs = 0; xs < selem; xs++) {
179
- if (replicate) {
180
- /* Load and replicate to all elements */
181
- TCGv_i64 tcg_tmp = tcg_temp_new_i64();
182
-
183
- tcg_gen_qemu_ld_i64(tcg_tmp, clean_addr, get_mem_index(s), mop);
184
- tcg_gen_gvec_dup_i64(scale, vec_full_reg_offset(s, rt),
185
- (is_q + 1) * 8, vec_full_reg_size(s),
186
- tcg_tmp);
187
- } else {
188
- /* Load/store one element per register */
189
- if (is_load) {
190
- do_vec_ld(s, rt, index, clean_addr, mop);
191
- } else {
192
- do_vec_st(s, rt, index, clean_addr, mop);
193
- }
194
- }
195
+ tcg_ebytes = tcg_constant_i64(1 << a->scale);
196
+ for (xs = 0, rt = a->rt; xs < a->selem; xs++, rt = (rt + 1) % 32) {
197
+ do_vec_st(s, rt, a->index, clean_addr, mop);
198
tcg_gen_add_i64(clean_addr, clean_addr, tcg_ebytes);
199
- rt = (rt + 1) % 32;
200
}
201
202
- if (is_postidx) {
203
- if (rm == 31) {
204
+ if (a->p) {
205
+ if (a->rm == 31) {
206
tcg_gen_addi_i64(tcg_rn, tcg_rn, total);
207
} else {
208
- tcg_gen_add_i64(tcg_rn, tcg_rn, cpu_reg(s, rm));
209
+ tcg_gen_add_i64(tcg_rn, tcg_rn, cpu_reg(s, a->rm));
210
}
211
}
212
+ return true;
213
+}
214
+
215
+static bool trans_LD_single(DisasContext *s, arg_ldst_single *a)
216
+{
217
+ int xs, total, rt;
218
+ TCGv_i64 clean_addr, tcg_rn, tcg_ebytes;
219
+ MemOp mop;
220
+
221
+ if (!a->p && a->rm != 0) {
222
+ return false;
223
+ }
224
+ if (!fp_access_check(s)) {
225
+ return true;
226
+ }
227
+
228
+ if (a->rn == 31) {
229
+ gen_check_sp_alignment(s);
230
+ }
231
+
232
+ total = a->selem << a->scale;
233
+ tcg_rn = cpu_reg_sp(s, a->rn);
234
+
235
+ mop = finalize_memop_asimd(s, a->scale);
236
+ clean_addr = gen_mte_checkN(s, tcg_rn, false, a->p || a->rn != 31,
237
+ total, mop);
238
+
239
+ tcg_ebytes = tcg_constant_i64(1 << a->scale);
240
+ for (xs = 0, rt = a->rt; xs < a->selem; xs++, rt = (rt + 1) % 32) {
241
+ do_vec_ld(s, rt, a->index, clean_addr, mop);
242
+ tcg_gen_add_i64(clean_addr, clean_addr, tcg_ebytes);
243
+ }
244
+
245
+ if (a->p) {
246
+ if (a->rm == 31) {
247
+ tcg_gen_addi_i64(tcg_rn, tcg_rn, total);
248
+ } else {
249
+ tcg_gen_add_i64(tcg_rn, tcg_rn, cpu_reg(s, a->rm));
250
+ }
251
+ }
252
+ return true;
253
+}
254
+
255
+static bool trans_LD_single_repl(DisasContext *s, arg_LD_single_repl *a)
256
+{
257
+ int xs, total, rt;
258
+ TCGv_i64 clean_addr, tcg_rn, tcg_ebytes;
259
+ MemOp mop;
260
+
261
+ if (!a->p && a->rm != 0) {
262
+ return false;
263
+ }
264
+ if (!fp_access_check(s)) {
265
+ return true;
266
+ }
267
+
268
+ if (a->rn == 31) {
269
+ gen_check_sp_alignment(s);
270
+ }
271
+
272
+ total = a->selem << a->scale;
273
+ tcg_rn = cpu_reg_sp(s, a->rn);
274
+
275
+ mop = finalize_memop_asimd(s, a->scale);
276
+ clean_addr = gen_mte_checkN(s, tcg_rn, false, a->p || a->rn != 31,
277
+ total, mop);
278
+
279
+ tcg_ebytes = tcg_constant_i64(1 << a->scale);
280
+ for (xs = 0, rt = a->rt; xs < a->selem; xs++, rt = (rt + 1) % 32) {
281
+ /* Load and replicate to all elements */
282
+ TCGv_i64 tcg_tmp = tcg_temp_new_i64();
283
+
284
+ tcg_gen_qemu_ld_i64(tcg_tmp, clean_addr, get_mem_index(s), mop);
285
+ tcg_gen_gvec_dup_i64(a->scale, vec_full_reg_offset(s, rt),
286
+ (a->q + 1) * 8, vec_full_reg_size(s), tcg_tmp);
287
+ tcg_gen_add_i64(clean_addr, clean_addr, tcg_ebytes);
288
+ }
289
+
290
+ if (a->p) {
291
+ if (a->rm == 31) {
292
+ tcg_gen_addi_i64(tcg_rn, tcg_rn, total);
293
+ } else {
294
+ tcg_gen_add_i64(tcg_rn, tcg_rn, cpu_reg(s, a->rm));
295
+ }
296
+ }
297
+ return true;
111
}
298
}
112
299
113
void gicv3_redist_update_lpi_only(GICv3CPUState *cs)
300
/*
301
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_tag(DisasContext *s, uint32_t insn)
302
static void disas_ldst(DisasContext *s, uint32_t insn)
303
{
304
switch (extract32(insn, 24, 6)) {
305
- case 0x0d: /* AdvSIMD load/store single structure */
306
- disas_ldst_single_struct(s, insn);
307
- break;
308
case 0x19:
309
if (extract32(insn, 21, 1) != 0) {
310
disas_ldst_tag(s, insn);
114
--
311
--
115
2.25.1
312
2.34.1
diff view generated by jsdifflib
1
The guest uses GICR_VPENDBASER to tell the redistributor when it is
1
Convert the instructions in the load/store memory tags instruction
2
scheduling or descheduling a vCPU. When it writes and changes the
2
group to decodetree.
3
VALID bit from 0 to 1, it is scheduling a vCPU, and we must update
4
our view of the current highest priority pending vLPI from the new
5
Pending and Configuration tables. When it writes and changes the
6
VALID bit from 1 to 0, it is descheduling, which means that there is
7
no longer a highest priority pending vLPI.
8
9
The specification allows the implementation to use part of the vLPI
10
Pending table as an IMPDEF area where it can cache information when a
11
vCPU is descheduled, so that it can avoid having to do a full rescan
12
of the tables when the vCPU is scheduled again. For now, we don't
13
take advantage of this, and simply do a complete rescan.
14
3
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
17
Message-id: 20220408141550.1271295-30-peter.maydell@linaro.org
6
Message-id: 20230602155223.2040685-21-peter.maydell@linaro.org
18
---
7
---
19
hw/intc/arm_gicv3_redist.c | 87 ++++++++++++++++++++++++++++++++++++--
8
target/arm/tcg/a64.decode | 25 +++
20
1 file changed, 84 insertions(+), 3 deletions(-)
9
target/arm/tcg/translate-a64.c | 360 ++++++++++++++++-----------------
10
2 files changed, 199 insertions(+), 186 deletions(-)
21
11
22
diff --git a/hw/intc/arm_gicv3_redist.c b/hw/intc/arm_gicv3_redist.c
12
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
23
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
24
--- a/hw/intc/arm_gicv3_redist.c
14
--- a/target/arm/tcg/a64.decode
25
+++ b/hw/intc/arm_gicv3_redist.c
15
+++ b/target/arm/tcg/a64.decode
26
@@ -XXX,XX +XXX,XX @@ static void gicr_write_ipriorityr(GICv3CPUState *cs, MemTxAttrs attrs, int irq,
16
@@ -XXX,XX +XXX,XX @@ LD_single 0 . 001101 . 1 . ..... 10 . 001 ..... ..... @ldst_single_d
27
cs->gicr_ipriorityr[irq] = value;
17
18
# Replicating load case
19
LD_single_repl 0 q:1 001101 p:1 1 . rm:5 11 . 0 scale:2 rn:5 rt:5 selem=%ldst_single_selem
20
+
21
+%tag_offset 12:s9 !function=scale_by_log2_tag_granule
22
+&ldst_tag rn rt imm p w
23
+@ldst_tag ........ .. . ......... .. rn:5 rt:5 &ldst_tag imm=%tag_offset
24
+@ldst_tag_mult ........ .. . 000000000 .. rn:5 rt:5 &ldst_tag imm=0
25
+
26
+STZGM 11011001 00 1 ......... 00 ..... ..... @ldst_tag_mult p=0 w=0
27
+STG 11011001 00 1 ......... 01 ..... ..... @ldst_tag p=1 w=1
28
+STG 11011001 00 1 ......... 10 ..... ..... @ldst_tag p=0 w=0
29
+STG 11011001 00 1 ......... 11 ..... ..... @ldst_tag p=0 w=1
30
+
31
+LDG 11011001 01 1 ......... 00 ..... ..... @ldst_tag p=0 w=0
32
+STZG 11011001 01 1 ......... 01 ..... ..... @ldst_tag p=1 w=1
33
+STZG 11011001 01 1 ......... 10 ..... ..... @ldst_tag p=0 w=0
34
+STZG 11011001 01 1 ......... 11 ..... ..... @ldst_tag p=0 w=1
35
+
36
+STGM 11011001 10 1 ......... 00 ..... ..... @ldst_tag_mult p=0 w=0
37
+ST2G 11011001 10 1 ......... 01 ..... ..... @ldst_tag p=1 w=1
38
+ST2G 11011001 10 1 ......... 10 ..... ..... @ldst_tag p=0 w=0
39
+ST2G 11011001 10 1 ......... 11 ..... ..... @ldst_tag p=0 w=1
40
+
41
+LDGM 11011001 11 1 ......... 00 ..... ..... @ldst_tag_mult p=0 w=0
42
+STZ2G 11011001 11 1 ......... 01 ..... ..... @ldst_tag p=1 w=1
43
+STZ2G 11011001 11 1 ......... 10 ..... ..... @ldst_tag p=0 w=0
44
+STZ2G 11011001 11 1 ......... 11 ..... ..... @ldst_tag p=0 w=1
45
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
46
index XXXXXXX..XXXXXXX 100644
47
--- a/target/arm/tcg/translate-a64.c
48
+++ b/target/arm/tcg/translate-a64.c
49
@@ -XXX,XX +XXX,XX @@ static int uimm_scaled(DisasContext *s, int x)
50
return imm << scale;
28
}
51
}
29
52
30
+static void gicv3_redist_update_vlpi_only(GICv3CPUState *cs)
53
+/* For load/store memory tags: scale offset by LOG2_TAG_GRANULE */
54
+static int scale_by_log2_tag_granule(DisasContext *s, int x)
31
+{
55
+{
32
+ uint64_t ptbase, ctbase, idbits;
56
+ return x << LOG2_TAG_GRANULE;
33
+
34
+ if (!FIELD_EX64(cs->gicr_vpendbaser, GICR_VPENDBASER, VALID)) {
35
+ cs->hppvlpi.prio = 0xff;
36
+ return;
37
+ }
38
+
39
+ ptbase = cs->gicr_vpendbaser & R_GICR_VPENDBASER_PHYADDR_MASK;
40
+ ctbase = cs->gicr_vpropbaser & R_GICR_VPROPBASER_PHYADDR_MASK;
41
+ idbits = FIELD_EX64(cs->gicr_vpropbaser, GICR_VPROPBASER, IDBITS);
42
+
43
+ update_for_all_lpis(cs, ptbase, ctbase, idbits, true, &cs->hppvlpi);
44
+}
57
+}
45
+
58
+
46
+static void gicv3_redist_update_vlpi(GICv3CPUState *cs)
59
/*
60
* Include the generated decoders.
61
*/
62
@@ -XXX,XX +XXX,XX @@ static bool trans_LD_single_repl(DisasContext *s, arg_LD_single_repl *a)
63
return true;
64
}
65
66
-/*
67
- * Load/Store memory tags
68
- *
69
- * 31 30 29 24 22 21 12 10 5 0
70
- * +-----+-------------+-----+---+------+-----+------+------+
71
- * | 1 1 | 0 1 1 0 0 1 | op1 | 1 | imm9 | op2 | Rn | Rt |
72
- * +-----+-------------+-----+---+------+-----+------+------+
73
- */
74
-static void disas_ldst_tag(DisasContext *s, uint32_t insn)
75
+static bool trans_STZGM(DisasContext *s, arg_ldst_tag *a)
76
{
77
- int rt = extract32(insn, 0, 5);
78
- int rn = extract32(insn, 5, 5);
79
- uint64_t offset = sextract64(insn, 12, 9) << LOG2_TAG_GRANULE;
80
- int op2 = extract32(insn, 10, 2);
81
- int op1 = extract32(insn, 22, 2);
82
- bool is_load = false, is_pair = false, is_zero = false, is_mult = false;
83
- int index = 0;
84
TCGv_i64 addr, clean_addr, tcg_rt;
85
+ int size = 4 << s->dcz_blocksize;
86
87
- /* We checked insn bits [29:24,21] in the caller. */
88
- if (extract32(insn, 30, 2) != 3) {
89
- goto do_unallocated;
90
+ if (!dc_isar_feature(aa64_mte, s)) {
91
+ return false;
92
+ }
93
+ if (s->current_el == 0) {
94
+ return false;
95
}
96
97
- /*
98
- * @index is a tri-state variable which has 3 states:
99
- * < 0 : post-index, writeback
100
- * = 0 : signed offset
101
- * > 0 : pre-index, writeback
102
- */
103
- switch (op1) {
104
- case 0:
105
- if (op2 != 0) {
106
- /* STG */
107
- index = op2 - 2;
108
- } else {
109
- /* STZGM */
110
- if (s->current_el == 0 || offset != 0) {
111
- goto do_unallocated;
112
- }
113
- is_mult = is_zero = true;
114
- }
115
- break;
116
- case 1:
117
- if (op2 != 0) {
118
- /* STZG */
119
- is_zero = true;
120
- index = op2 - 2;
121
- } else {
122
- /* LDG */
123
- is_load = true;
124
- }
125
- break;
126
- case 2:
127
- if (op2 != 0) {
128
- /* ST2G */
129
- is_pair = true;
130
- index = op2 - 2;
131
- } else {
132
- /* STGM */
133
- if (s->current_el == 0 || offset != 0) {
134
- goto do_unallocated;
135
- }
136
- is_mult = true;
137
- }
138
- break;
139
- case 3:
140
- if (op2 != 0) {
141
- /* STZ2G */
142
- is_pair = is_zero = true;
143
- index = op2 - 2;
144
- } else {
145
- /* LDGM */
146
- if (s->current_el == 0 || offset != 0) {
147
- goto do_unallocated;
148
- }
149
- is_mult = is_load = true;
150
- }
151
- break;
152
-
153
- default:
154
- do_unallocated:
155
- unallocated_encoding(s);
156
- return;
157
- }
158
-
159
- if (is_mult
160
- ? !dc_isar_feature(aa64_mte, s)
161
- : !dc_isar_feature(aa64_mte_insn_reg, s)) {
162
- goto do_unallocated;
163
- }
164
-
165
- if (rn == 31) {
166
+ if (a->rn == 31) {
167
gen_check_sp_alignment(s);
168
}
169
170
- addr = read_cpu_reg_sp(s, rn, true);
171
- if (index >= 0) {
172
+ addr = read_cpu_reg_sp(s, a->rn, true);
173
+ tcg_gen_addi_i64(addr, addr, a->imm);
174
+ tcg_rt = cpu_reg(s, a->rt);
175
+
176
+ if (s->ata) {
177
+ gen_helper_stzgm_tags(cpu_env, addr, tcg_rt);
178
+ }
179
+ /*
180
+ * The non-tags portion of STZGM is mostly like DC_ZVA,
181
+ * except the alignment happens before the access.
182
+ */
183
+ clean_addr = clean_data_tbi(s, addr);
184
+ tcg_gen_andi_i64(clean_addr, clean_addr, -size);
185
+ gen_helper_dc_zva(cpu_env, clean_addr);
186
+ return true;
187
+}
188
+
189
+static bool trans_STGM(DisasContext *s, arg_ldst_tag *a)
47
+{
190
+{
48
+ gicv3_redist_update_vlpi_only(cs);
191
+ TCGv_i64 addr, clean_addr, tcg_rt;
49
+ gicv3_cpuif_virt_irq_fiq_update(cs);
192
+
193
+ if (!dc_isar_feature(aa64_mte, s)) {
194
+ return false;
195
+ }
196
+ if (s->current_el == 0) {
197
+ return false;
198
+ }
199
+
200
+ if (a->rn == 31) {
201
+ gen_check_sp_alignment(s);
202
+ }
203
+
204
+ addr = read_cpu_reg_sp(s, a->rn, true);
205
+ tcg_gen_addi_i64(addr, addr, a->imm);
206
+ tcg_rt = cpu_reg(s, a->rt);
207
+
208
+ if (s->ata) {
209
+ gen_helper_stgm(cpu_env, addr, tcg_rt);
210
+ } else {
211
+ MMUAccessType acc = MMU_DATA_STORE;
212
+ int size = 4 << GMID_EL1_BS;
213
+
214
+ clean_addr = clean_data_tbi(s, addr);
215
+ tcg_gen_andi_i64(clean_addr, clean_addr, -size);
216
+ gen_probe_access(s, clean_addr, acc, size);
217
+ }
218
+ return true;
50
+}
219
+}
51
+
220
+
52
+static void gicr_write_vpendbaser(GICv3CPUState *cs, uint64_t newval)
221
+static bool trans_LDGM(DisasContext *s, arg_ldst_tag *a)
53
+{
222
+{
54
+ /* Write @newval to GICR_VPENDBASER, handling its effects */
223
+ TCGv_i64 addr, clean_addr, tcg_rt;
55
+ bool oldvalid = FIELD_EX64(cs->gicr_vpendbaser, GICR_VPENDBASER, VALID);
224
+
56
+ bool newvalid = FIELD_EX64(newval, GICR_VPENDBASER, VALID);
225
+ if (!dc_isar_feature(aa64_mte, s)) {
57
+ bool pendinglast;
226
+ return false;
58
+
227
+ }
59
+ /*
228
+ if (s->current_el == 0) {
60
+ * The DIRTY bit is read-only and for us is always zero;
229
+ return false;
61
+ * other fields are writeable.
230
+ }
62
+ */
231
+
63
+ newval &= R_GICR_VPENDBASER_INNERCACHE_MASK |
232
+ if (a->rn == 31) {
64
+ R_GICR_VPENDBASER_SHAREABILITY_MASK |
233
+ gen_check_sp_alignment(s);
65
+ R_GICR_VPENDBASER_PHYADDR_MASK |
234
+ }
66
+ R_GICR_VPENDBASER_OUTERCACHE_MASK |
235
+
67
+ R_GICR_VPENDBASER_PENDINGLAST_MASK |
236
+ addr = read_cpu_reg_sp(s, a->rn, true);
68
+ R_GICR_VPENDBASER_IDAI_MASK |
237
+ tcg_gen_addi_i64(addr, addr, a->imm);
69
+ R_GICR_VPENDBASER_VALID_MASK;
238
+ tcg_rt = cpu_reg(s, a->rt);
70
+
239
+
71
+ if (oldvalid && newvalid) {
240
+ if (s->ata) {
72
+ /*
241
+ gen_helper_ldgm(tcg_rt, cpu_env, addr);
73
+ * Changing other fields while VALID is 1 is UNPREDICTABLE;
242
+ } else {
74
+ * we choose to log and ignore the write.
243
+ MMUAccessType acc = MMU_DATA_LOAD;
75
+ */
244
+ int size = 4 << GMID_EL1_BS;
76
+ if (cs->gicr_vpendbaser ^ newval) {
245
+
77
+ qemu_log_mask(LOG_GUEST_ERROR,
246
+ clean_addr = clean_data_tbi(s, addr);
78
+ "%s: Changing GICR_VPENDBASER when VALID=1 "
247
+ tcg_gen_andi_i64(clean_addr, clean_addr, -size);
79
+ "is UNPREDICTABLE\n", __func__);
248
+ gen_probe_access(s, clean_addr, acc, size);
80
+ }
249
+ /* The result tags are zeros. */
81
+ return;
250
+ tcg_gen_movi_i64(tcg_rt, 0);
82
+ }
251
+ }
83
+ if (!oldvalid && !newvalid) {
252
+ return true;
84
+ cs->gicr_vpendbaser = newval;
253
+}
85
+ return;
254
+
86
+ }
255
+static bool trans_LDG(DisasContext *s, arg_ldst_tag *a)
87
+
256
+{
88
+ if (newvalid) {
257
+ TCGv_i64 addr, clean_addr, tcg_rt;
89
+ /*
258
+
90
+ * Valid going from 0 to 1: update hppvlpi from tables.
259
+ if (!dc_isar_feature(aa64_mte_insn_reg, s)) {
91
+ * If IDAI is 0 we are allowed to use the info we cached in
260
+ return false;
92
+ * the IMPDEF area of the table.
261
+ }
93
+ * PendingLast is RES1 when we make this transition.
262
+
94
+ */
263
+ if (a->rn == 31) {
95
+ pendinglast = true;
264
+ gen_check_sp_alignment(s);
265
+ }
266
+
267
+ addr = read_cpu_reg_sp(s, a->rn, true);
268
+ if (!a->p) {
269
/* pre-index or signed offset */
270
- tcg_gen_addi_i64(addr, addr, offset);
271
+ tcg_gen_addi_i64(addr, addr, a->imm);
272
}
273
274
- if (is_mult) {
275
- tcg_rt = cpu_reg(s, rt);
276
+ tcg_gen_andi_i64(addr, addr, -TAG_GRANULE);
277
+ tcg_rt = cpu_reg(s, a->rt);
278
+ if (s->ata) {
279
+ gen_helper_ldg(tcg_rt, cpu_env, addr, tcg_rt);
96
+ } else {
280
+ } else {
97
+ /*
281
+ /*
98
+ * Valid going from 1 to 0:
282
+ * Tag access disabled: we must check for aborts on the load
99
+ * Set PendingLast if there was a pending enabled interrupt
283
+ * load from [rn+offset], and then insert a 0 tag into rt.
100
+ * for the vPE that was just descheduled.
101
+ * If we cache info in the IMPDEF area, write it out here.
102
+ */
284
+ */
103
+ pendinglast = cs->hppvlpi.prio != 0xff;
285
+ clean_addr = clean_data_tbi(s, addr);
104
+ }
286
+ gen_probe_access(s, clean_addr, MMU_DATA_LOAD, MO_8);
105
+
287
+ gen_address_with_allocation_tag0(tcg_rt, tcg_rt);
106
+ newval = FIELD_DP64(newval, GICR_VPENDBASER, PENDINGLAST, pendinglast);
288
+ }
107
+ cs->gicr_vpendbaser = newval;
289
108
+ gicv3_redist_update_vlpi(cs);
290
- if (is_zero) {
291
- int size = 4 << s->dcz_blocksize;
292
-
293
- if (s->ata) {
294
- gen_helper_stzgm_tags(cpu_env, addr, tcg_rt);
295
- }
296
- /*
297
- * The non-tags portion of STZGM is mostly like DC_ZVA,
298
- * except the alignment happens before the access.
299
- */
300
- clean_addr = clean_data_tbi(s, addr);
301
- tcg_gen_andi_i64(clean_addr, clean_addr, -size);
302
- gen_helper_dc_zva(cpu_env, clean_addr);
303
- } else if (s->ata) {
304
- if (is_load) {
305
- gen_helper_ldgm(tcg_rt, cpu_env, addr);
306
- } else {
307
- gen_helper_stgm(cpu_env, addr, tcg_rt);
308
- }
309
- } else {
310
- MMUAccessType acc = is_load ? MMU_DATA_LOAD : MMU_DATA_STORE;
311
- int size = 4 << GMID_EL1_BS;
312
-
313
- clean_addr = clean_data_tbi(s, addr);
314
- tcg_gen_andi_i64(clean_addr, clean_addr, -size);
315
- gen_probe_access(s, clean_addr, acc, size);
316
-
317
- if (is_load) {
318
- /* The result tags are zeros. */
319
- tcg_gen_movi_i64(tcg_rt, 0);
320
- }
321
+ if (a->w) {
322
+ /* pre-index or post-index */
323
+ if (a->p) {
324
+ /* post-index */
325
+ tcg_gen_addi_i64(addr, addr, a->imm);
326
}
327
- return;
328
+ tcg_gen_mov_i64(cpu_reg_sp(s, a->rn), addr);
329
+ }
330
+ return true;
109
+}
331
+}
110
+
332
+
111
static MemTxResult gicr_readb(GICv3CPUState *cs, hwaddr offset,
333
+static bool do_STG(DisasContext *s, arg_ldst_tag *a, bool is_zero, bool is_pair)
112
uint64_t *data, MemTxAttrs attrs)
334
+{
335
+ TCGv_i64 addr, tcg_rt;
336
+
337
+ if (a->rn == 31) {
338
+ gen_check_sp_alignment(s);
339
}
340
341
- if (is_load) {
342
- tcg_gen_andi_i64(addr, addr, -TAG_GRANULE);
343
- tcg_rt = cpu_reg(s, rt);
344
- if (s->ata) {
345
- gen_helper_ldg(tcg_rt, cpu_env, addr, tcg_rt);
346
+ addr = read_cpu_reg_sp(s, a->rn, true);
347
+ if (!a->p) {
348
+ /* pre-index or signed offset */
349
+ tcg_gen_addi_i64(addr, addr, a->imm);
350
+ }
351
+ tcg_rt = cpu_reg_sp(s, a->rt);
352
+ if (!s->ata) {
353
+ /*
354
+ * For STG and ST2G, we need to check alignment and probe memory.
355
+ * TODO: For STZG and STZ2G, we could rely on the stores below,
356
+ * at least for system mode; user-only won't enforce alignment.
357
+ */
358
+ if (is_pair) {
359
+ gen_helper_st2g_stub(cpu_env, addr);
360
} else {
361
- /*
362
- * Tag access disabled: we must check for aborts on the load
363
- * load from [rn+offset], and then insert a 0 tag into rt.
364
- */
365
- clean_addr = clean_data_tbi(s, addr);
366
- gen_probe_access(s, clean_addr, MMU_DATA_LOAD, MO_8);
367
- gen_address_with_allocation_tag0(tcg_rt, tcg_rt);
368
+ gen_helper_stg_stub(cpu_env, addr);
369
+ }
370
+ } else if (tb_cflags(s->base.tb) & CF_PARALLEL) {
371
+ if (is_pair) {
372
+ gen_helper_st2g_parallel(cpu_env, addr, tcg_rt);
373
+ } else {
374
+ gen_helper_stg_parallel(cpu_env, addr, tcg_rt);
375
}
376
} else {
377
- tcg_rt = cpu_reg_sp(s, rt);
378
- if (!s->ata) {
379
- /*
380
- * For STG and ST2G, we need to check alignment and probe memory.
381
- * TODO: For STZG and STZ2G, we could rely on the stores below,
382
- * at least for system mode; user-only won't enforce alignment.
383
- */
384
- if (is_pair) {
385
- gen_helper_st2g_stub(cpu_env, addr);
386
- } else {
387
- gen_helper_stg_stub(cpu_env, addr);
388
- }
389
- } else if (tb_cflags(s->base.tb) & CF_PARALLEL) {
390
- if (is_pair) {
391
- gen_helper_st2g_parallel(cpu_env, addr, tcg_rt);
392
- } else {
393
- gen_helper_stg_parallel(cpu_env, addr, tcg_rt);
394
- }
395
+ if (is_pair) {
396
+ gen_helper_st2g(cpu_env, addr, tcg_rt);
397
} else {
398
- if (is_pair) {
399
- gen_helper_st2g(cpu_env, addr, tcg_rt);
400
- } else {
401
- gen_helper_stg(cpu_env, addr, tcg_rt);
402
- }
403
+ gen_helper_stg(cpu_env, addr, tcg_rt);
404
}
405
}
406
407
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_tag(DisasContext *s, uint32_t insn)
408
}
409
}
410
411
- if (index != 0) {
412
+ if (a->w) {
413
/* pre-index or post-index */
414
- if (index < 0) {
415
+ if (a->p) {
416
/* post-index */
417
- tcg_gen_addi_i64(addr, addr, offset);
418
+ tcg_gen_addi_i64(addr, addr, a->imm);
419
}
420
- tcg_gen_mov_i64(cpu_reg_sp(s, rn), addr);
421
+ tcg_gen_mov_i64(cpu_reg_sp(s, a->rn), addr);
422
}
423
+ return true;
424
}
425
426
-/* Loads and stores */
427
-static void disas_ldst(DisasContext *s, uint32_t insn)
428
-{
429
- switch (extract32(insn, 24, 6)) {
430
- case 0x19:
431
- if (extract32(insn, 21, 1) != 0) {
432
- disas_ldst_tag(s, insn);
433
- } else {
434
- unallocated_encoding(s);
435
- }
436
- break;
437
- default:
438
- unallocated_encoding(s);
439
- break;
440
- }
441
-}
442
+TRANS_FEAT(STG, aa64_mte_insn_reg, do_STG, a, false, false)
443
+TRANS_FEAT(STZG, aa64_mte_insn_reg, do_STG, a, true, false)
444
+TRANS_FEAT(ST2G, aa64_mte_insn_reg, do_STG, a, false, true)
445
+TRANS_FEAT(STZ2G, aa64_mte_insn_reg, do_STG, a, true, true)
446
447
typedef void ArithTwoOp(TCGv_i64, TCGv_i64, TCGv_i64);
448
449
@@ -XXX,XX +XXX,XX @@ static bool btype_destination_ok(uint32_t insn, bool bt, int btype)
450
static void disas_a64_legacy(DisasContext *s, uint32_t insn)
113
{
451
{
114
@@ -XXX,XX +XXX,XX @@ static MemTxResult gicr_writel(GICv3CPUState *cs, hwaddr offset,
452
switch (extract32(insn, 25, 4)) {
115
cs->gicr_vpropbaser = deposit64(cs->gicr_vpropbaser, 32, 32, value);
453
- case 0x4:
116
return MEMTX_OK;
454
- case 0x6:
117
case GICR_VPENDBASER:
455
- case 0xc:
118
- cs->gicr_vpendbaser = deposit64(cs->gicr_vpendbaser, 0, 32, value);
456
- case 0xe: /* Loads and stores */
119
+ gicr_write_vpendbaser(cs, deposit64(cs->gicr_vpendbaser, 0, 32, value));
457
- disas_ldst(s, insn);
120
return MEMTX_OK;
458
- break;
121
case GICR_VPENDBASER + 4:
459
case 0x5:
122
- cs->gicr_vpendbaser = deposit64(cs->gicr_vpendbaser, 32, 32, value);
460
case 0xd: /* Data processing - register */
123
+ gicr_write_vpendbaser(cs, deposit64(cs->gicr_vpendbaser, 32, 32, value));
461
disas_data_proc_reg(s, insn);
124
return MEMTX_OK;
125
default:
126
return MEMTX_ERROR;
127
@@ -XXX,XX +XXX,XX @@ static MemTxResult gicr_writell(GICv3CPUState *cs, hwaddr offset,
128
cs->gicr_vpropbaser = value;
129
return MEMTX_OK;
130
case GICR_VPENDBASER:
131
- cs->gicr_vpendbaser = value;
132
+ gicr_write_vpendbaser(cs, value);
133
return MEMTX_OK;
134
default:
135
return MEMTX_ERROR;
136
--
462
--
137
2.25.1
463
2.34.1
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
In commit 2c5fa0778c3b430 we fixed an endianness bug in the Allwinner
2
A10 PIC model; however in the process we introduced a regression.
3
This is because the old code was robust against the incoming 'level'
4
argument being something other than 0 or 1, whereas the new code was
5
not.
2
6
3
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
In particular, the allwinner-sdhost code treats its IRQ line
4
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
as 0-vs-non-0 rather than 0-vs-1, so when the SD controller
9
set its IRQ line for any reason other than transmit the
10
interrupt controller would ignore it. The observed effect
11
was a guest timeout when rebooting the guest kernel.
12
13
Handle level values other than 0 or 1, to restore the old
14
behaviour.
15
16
Fixes: 2c5fa0778c3b430 ("hw/intc/allwinner-a10-pic: Don't use set_bit()/clear_bit()")
17
Cc: qemu-stable@nongnu.org
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
20
Tested-by: Guenter Roeck <linux@roeck-us.net>
21
Message-id: 20230606104609.3692557-2-peter.maydell@linaro.org
6
---
22
---
7
target/arm/translate.h | 13 +++----------
23
hw/intc/allwinner-a10-pic.c | 2 +-
8
1 file changed, 3 insertions(+), 10 deletions(-)
24
1 file changed, 1 insertion(+), 1 deletion(-)
9
25
10
diff --git a/target/arm/translate.h b/target/arm/translate.h
26
diff --git a/hw/intc/allwinner-a10-pic.c b/hw/intc/allwinner-a10-pic.c
11
index XXXXXXX..XXXXXXX 100644
27
index XXXXXXX..XXXXXXX 100644
12
--- a/target/arm/translate.h
28
--- a/hw/intc/allwinner-a10-pic.c
13
+++ b/target/arm/translate.h
29
+++ b/hw/intc/allwinner-a10-pic.c
14
@@ -XXX,XX +XXX,XX @@ static inline void gen_ss_advance(DisasContext *s)
30
@@ -XXX,XX +XXX,XX @@ static void aw_a10_pic_set_irq(void *opaque, int irq, int level)
15
static inline void gen_exception(int excp, uint32_t syndrome,
31
AwA10PICState *s = opaque;
16
uint32_t target_el)
32
uint32_t *pending_reg = &s->irq_pending[irq / 32];
17
{
33
18
- TCGv_i32 tcg_excp = tcg_const_i32(excp);
34
- *pending_reg = deposit32(*pending_reg, irq % 32, 1, level);
19
- TCGv_i32 tcg_syn = tcg_const_i32(syndrome);
35
+ *pending_reg = deposit32(*pending_reg, irq % 32, 1, !!level);
20
- TCGv_i32 tcg_el = tcg_const_i32(target_el);
36
aw_a10_pic_update(s);
21
-
22
- gen_helper_exception_with_syndrome(cpu_env, tcg_excp,
23
- tcg_syn, tcg_el);
24
-
25
- tcg_temp_free_i32(tcg_el);
26
- tcg_temp_free_i32(tcg_syn);
27
- tcg_temp_free_i32(tcg_excp);
28
+ gen_helper_exception_with_syndrome(cpu_env, tcg_constant_i32(excp),
29
+ tcg_constant_i32(syndrome),
30
+ tcg_constant_i32(target_el));
31
}
37
}
32
38
33
/* Generate an architectural singlestep exception */
34
--
39
--
35
2.25.1
40
2.34.1
41
42
diff view generated by jsdifflib
1
The CPU interface changes to support vLPIs are fairly minor:
1
QEMU allows qemu_irq lines to transfer arbitrary integers. However
2
in the parts of the code that currently look at the list registers
2
the convention is that for a simple IRQ line the values transferred
3
to determine the highest priority pending virtual interrupt, we
3
are always 0 and 1. The A10 SD controller device instead assumes a
4
must also look at the highest priority pending vLPI. To do this
4
0-vs-non-0 convention, which happens to work with the interrupt
5
we change hppvi_index() to check the vLPI and return a special-case
5
controller it is wired up to.
6
value if that is the right virtual interrupt to take. The callsites
7
(which handle HPPIR and IAR registers and the "raise vIRQ and vFIQ
8
lines" code) then have to handle this special-case value.
9
6
10
This commit includes two interfaces with the as-yet-unwritten
7
Coerce the value to boolean to follow our usual convention.
11
redistributor code:
12
* the new GICv3CPUState::hppvlpi will be set by the redistributor
13
(in the same way as the existing hpplpi does for physical LPIs)
14
* when the CPU interface acknowledges a vLPI it needs to set it
15
to non-pending; the new gicv3_redist_vlpi_pending() function
16
(which matches the existing gicv3_redist_lpi_pending() used
17
for physical LPIs) is a stub that will be filled in later
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: Philippe Mathieu-Daudé <philmd@linaro.org>
21
Message-id: 20220408141550.1271295-26-peter.maydell@linaro.org
11
Tested-by: Guenter Roeck <linux@roeck-us.net>
12
Message-id: 20230606104609.3692557-3-peter.maydell@linaro.org
22
---
13
---
23
hw/intc/gicv3_internal.h | 13 ++++
14
hw/sd/allwinner-sdhost.c | 2 +-
24
include/hw/intc/arm_gicv3_common.h | 3 +
15
1 file changed, 1 insertion(+), 1 deletion(-)
25
hw/intc/arm_gicv3_common.c | 1 +
26
hw/intc/arm_gicv3_cpuif.c | 119 +++++++++++++++++++++++++++--
27
hw/intc/arm_gicv3_redist.c | 8 ++
28
hw/intc/trace-events | 2 +-
29
6 files changed, 140 insertions(+), 6 deletions(-)
30
16
31
diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h
17
diff --git a/hw/sd/allwinner-sdhost.c b/hw/sd/allwinner-sdhost.c
32
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
33
--- a/hw/intc/gicv3_internal.h
19
--- a/hw/sd/allwinner-sdhost.c
34
+++ b/hw/intc/gicv3_internal.h
20
+++ b/hw/sd/allwinner-sdhost.c
35
@@ -XXX,XX +XXX,XX @@ void gicv3_redist_process_lpi(GICv3CPUState *cs, int irq, int level);
21
@@ -XXX,XX +XXX,XX @@ static void allwinner_sdhost_update_irq(AwSdHostState *s)
36
*/
37
void gicv3_redist_process_vlpi(GICv3CPUState *cs, int irq, uint64_t vptaddr,
38
int doorbell, int level);
39
+/**
40
+ * gicv3_redist_vlpi_pending:
41
+ * @cs: GICv3CPUState
42
+ * @irq: (virtual) interrupt number
43
+ * @level: level to set @irq to
44
+ *
45
+ * Set/clear the pending status of a virtual LPI in the vLPI table
46
+ * that this redistributor is currently using. (The difference between
47
+ * this and gicv3_redist_process_vlpi() is that this is called from
48
+ * the cpuif and does not need to do the not-running-on-this-vcpu checks.)
49
+ */
50
+void gicv3_redist_vlpi_pending(GICv3CPUState *cs, int irq, int level);
51
+
52
void gicv3_redist_lpi_pending(GICv3CPUState *cs, int irq, int level);
53
/**
54
* gicv3_redist_update_lpi:
55
diff --git a/include/hw/intc/arm_gicv3_common.h b/include/hw/intc/arm_gicv3_common.h
56
index XXXXXXX..XXXXXXX 100644
57
--- a/include/hw/intc/arm_gicv3_common.h
58
+++ b/include/hw/intc/arm_gicv3_common.h
59
@@ -XXX,XX +XXX,XX @@ struct GICv3CPUState {
60
*/
61
PendingIrq hpplpi;
62
63
+ /* Cached information recalculated from vLPI tables in guest memory */
64
+ PendingIrq hppvlpi;
65
+
66
/* This is temporary working state, to avoid a malloc in gicv3_update() */
67
bool seenbetter;
68
};
69
diff --git a/hw/intc/arm_gicv3_common.c b/hw/intc/arm_gicv3_common.c
70
index XXXXXXX..XXXXXXX 100644
71
--- a/hw/intc/arm_gicv3_common.c
72
+++ b/hw/intc/arm_gicv3_common.c
73
@@ -XXX,XX +XXX,XX @@ static void arm_gicv3_common_reset(DeviceState *dev)
74
75
cs->hppi.prio = 0xff;
76
cs->hpplpi.prio = 0xff;
77
+ cs->hppvlpi.prio = 0xff;
78
79
/* State in the CPU interface must *not* be reset here, because it
80
* is part of the CPU's reset domain, not the GIC device's.
81
diff --git a/hw/intc/arm_gicv3_cpuif.c b/hw/intc/arm_gicv3_cpuif.c
82
index XXXXXXX..XXXXXXX 100644
83
--- a/hw/intc/arm_gicv3_cpuif.c
84
+++ b/hw/intc/arm_gicv3_cpuif.c
85
@@ -XXX,XX +XXX,XX @@
86
#include "hw/irq.h"
87
#include "cpu.h"
88
89
+/*
90
+ * Special case return value from hppvi_index(); must be larger than
91
+ * the architecturally maximum possible list register index (which is 15)
92
+ */
93
+#define HPPVI_INDEX_VLPI 16
94
+
95
static GICv3CPUState *icc_cs_from_env(CPUARMState *env)
96
{
97
return env->gicv3state;
98
@@ -XXX,XX +XXX,XX @@ static int ich_highest_active_virt_prio(GICv3CPUState *cs)
99
100
static int hppvi_index(GICv3CPUState *cs)
101
{
102
- /* Return the list register index of the highest priority pending
103
+ /*
104
+ * Return the list register index of the highest priority pending
105
* virtual interrupt, as per the HighestPriorityVirtualInterrupt
106
* pseudocode. If no pending virtual interrupts, return -1.
107
+ * If the highest priority pending virtual interrupt is a vLPI,
108
+ * return HPPVI_INDEX_VLPI.
109
+ * (The pseudocode handles checking whether the vLPI is higher
110
+ * priority than the highest priority list register at every
111
+ * callsite of HighestPriorityVirtualInterrupt; we check it here.)
112
*/
113
+ ARMCPU *cpu = ARM_CPU(cs->cpu);
114
+ CPUARMState *env = &cpu->env;
115
int idx = -1;
116
int i;
117
/* Note that a list register entry with a priority of 0xff will
118
@@ -XXX,XX +XXX,XX @@ static int hppvi_index(GICv3CPUState *cs)
119
}
120
}
22
}
121
23
122
+ /*
24
trace_allwinner_sdhost_update_irq(irq);
123
+ * "no pending vLPI" is indicated with prio = 0xff, which always
25
- qemu_set_irq(s->irq, irq);
124
+ * fails the priority check here. vLPIs are only considered
26
+ qemu_set_irq(s->irq, !!irq);
125
+ * when we are in Non-Secure state.
126
+ */
127
+ if (cs->hppvlpi.prio < prio && !arm_is_secure(env)) {
128
+ if (cs->hppvlpi.grp == GICV3_G0) {
129
+ if (cs->ich_vmcr_el2 & ICH_VMCR_EL2_VENG0) {
130
+ return HPPVI_INDEX_VLPI;
131
+ }
132
+ } else {
133
+ if (cs->ich_vmcr_el2 & ICH_VMCR_EL2_VENG1) {
134
+ return HPPVI_INDEX_VLPI;
135
+ }
136
+ }
137
+ }
138
+
139
return idx;
140
}
27
}
141
28
142
@@ -XXX,XX +XXX,XX @@ static bool icv_hppi_can_preempt(GICv3CPUState *cs, uint64_t lr)
29
static void allwinner_sdhost_update_transfer_cnt(AwSdHostState *s,
143
return false;
144
}
145
146
+static bool icv_hppvlpi_can_preempt(GICv3CPUState *cs)
147
+{
148
+ /*
149
+ * Return true if we can signal the highest priority pending vLPI.
150
+ * We can assume we're Non-secure because hppvi_index() already
151
+ * tested for that.
152
+ */
153
+ uint32_t mask, rprio, vpmr;
154
+
155
+ if (!(cs->ich_hcr_el2 & ICH_HCR_EL2_EN)) {
156
+ /* Virtual interface disabled */
157
+ return false;
158
+ }
159
+
160
+ vpmr = extract64(cs->ich_vmcr_el2, ICH_VMCR_EL2_VPMR_SHIFT,
161
+ ICH_VMCR_EL2_VPMR_LENGTH);
162
+
163
+ if (cs->hppvlpi.prio >= vpmr) {
164
+ /* Priority mask masks this interrupt */
165
+ return false;
166
+ }
167
+
168
+ rprio = ich_highest_active_virt_prio(cs);
169
+ if (rprio == 0xff) {
170
+ /* No running interrupt so we can preempt */
171
+ return true;
172
+ }
173
+
174
+ mask = icv_gprio_mask(cs, cs->hppvlpi.grp);
175
+
176
+ /*
177
+ * We only preempt a running interrupt if the pending interrupt's
178
+ * group priority is sufficient (the subpriorities are not considered).
179
+ */
180
+ if ((cs->hppvlpi.prio & mask) < (rprio & mask)) {
181
+ return true;
182
+ }
183
+
184
+ return false;
185
+}
186
+
187
static uint32_t eoi_maintenance_interrupt_state(GICv3CPUState *cs,
188
uint32_t *misr)
189
{
190
@@ -XXX,XX +XXX,XX @@ void gicv3_cpuif_virt_irq_fiq_update(GICv3CPUState *cs)
191
int fiqlevel = 0;
192
193
idx = hppvi_index(cs);
194
- trace_gicv3_cpuif_virt_update(gicv3_redist_affid(cs), idx);
195
- if (idx >= 0) {
196
+ trace_gicv3_cpuif_virt_update(gicv3_redist_affid(cs), idx,
197
+ cs->hppvlpi.irq, cs->hppvlpi.grp,
198
+ cs->hppvlpi.prio);
199
+ if (idx == HPPVI_INDEX_VLPI) {
200
+ if (icv_hppvlpi_can_preempt(cs)) {
201
+ if (cs->hppvlpi.grp == GICV3_G0) {
202
+ fiqlevel = 1;
203
+ } else {
204
+ irqlevel = 1;
205
+ }
206
+ }
207
+ } else if (idx >= 0) {
208
uint64_t lr = cs->ich_lr_el2[idx];
209
210
if (icv_hppi_can_preempt(cs, lr)) {
211
@@ -XXX,XX +XXX,XX @@ static uint64_t icv_hppir_read(CPUARMState *env, const ARMCPRegInfo *ri)
212
int idx = hppvi_index(cs);
213
uint64_t value = INTID_SPURIOUS;
214
215
- if (idx >= 0) {
216
+ if (idx == HPPVI_INDEX_VLPI) {
217
+ if (cs->hppvlpi.grp == grp) {
218
+ value = cs->hppvlpi.irq;
219
+ }
220
+ } else if (idx >= 0) {
221
uint64_t lr = cs->ich_lr_el2[idx];
222
int thisgrp = (lr & ICH_LR_EL2_GROUP) ? GICV3_G1NS : GICV3_G0;
223
224
@@ -XXX,XX +XXX,XX @@ static void icv_activate_irq(GICv3CPUState *cs, int idx, int grp)
225
cs->ich_apr[grp][regno] |= (1 << regbit);
226
}
227
228
+static void icv_activate_vlpi(GICv3CPUState *cs)
229
+{
230
+ uint32_t mask = icv_gprio_mask(cs, cs->hppvlpi.grp);
231
+ int prio = cs->hppvlpi.prio & mask;
232
+ int aprbit = prio >> (8 - cs->vprebits);
233
+ int regno = aprbit / 32;
234
+ int regbit = aprbit % 32;
235
+
236
+ cs->ich_apr[cs->hppvlpi.grp][regno] |= (1 << regbit);
237
+ gicv3_redist_vlpi_pending(cs, cs->hppvlpi.irq, 0);
238
+}
239
+
240
static uint64_t icv_iar_read(CPUARMState *env, const ARMCPRegInfo *ri)
241
{
242
GICv3CPUState *cs = icc_cs_from_env(env);
243
@@ -XXX,XX +XXX,XX @@ static uint64_t icv_iar_read(CPUARMState *env, const ARMCPRegInfo *ri)
244
int idx = hppvi_index(cs);
245
uint64_t intid = INTID_SPURIOUS;
246
247
- if (idx >= 0) {
248
+ if (idx == HPPVI_INDEX_VLPI) {
249
+ if (cs->hppvlpi.grp == grp && icv_hppvlpi_can_preempt(cs)) {
250
+ intid = cs->hppvlpi.irq;
251
+ icv_activate_vlpi(cs);
252
+ }
253
+ } else if (idx >= 0) {
254
uint64_t lr = cs->ich_lr_el2[idx];
255
int thisgrp = (lr & ICH_LR_EL2_GROUP) ? GICV3_G1NS : GICV3_G0;
256
257
@@ -XXX,XX +XXX,XX @@ static void gicv3_cpuif_el_change_hook(ARMCPU *cpu, void *opaque)
258
GICv3CPUState *cs = opaque;
259
260
gicv3_cpuif_update(cs);
261
+ /*
262
+ * Because vLPIs are only pending in NonSecure state,
263
+ * an EL change can change the VIRQ/VFIQ status (but
264
+ * cannot affect the maintenance interrupt state)
265
+ */
266
+ gicv3_cpuif_virt_irq_fiq_update(cs);
267
}
268
269
void gicv3_init_cpuif(GICv3State *s)
270
diff --git a/hw/intc/arm_gicv3_redist.c b/hw/intc/arm_gicv3_redist.c
271
index XXXXXXX..XXXXXXX 100644
272
--- a/hw/intc/arm_gicv3_redist.c
273
+++ b/hw/intc/arm_gicv3_redist.c
274
@@ -XXX,XX +XXX,XX @@ void gicv3_redist_movall_lpis(GICv3CPUState *src, GICv3CPUState *dest)
275
gicv3_redist_update_lpi(dest);
276
}
277
278
+void gicv3_redist_vlpi_pending(GICv3CPUState *cs, int irq, int level)
279
+{
280
+ /*
281
+ * The redistributor handling for changing the pending state
282
+ * of a vLPI will be added in a subsequent commit.
283
+ */
284
+}
285
+
286
void gicv3_redist_process_vlpi(GICv3CPUState *cs, int irq, uint64_t vptaddr,
287
int doorbell, int level)
288
{
289
diff --git a/hw/intc/trace-events b/hw/intc/trace-events
290
index XXXXXXX..XXXXXXX 100644
291
--- a/hw/intc/trace-events
292
+++ b/hw/intc/trace-events
293
@@ -XXX,XX +XXX,XX @@ gicv3_icv_hppir_read(int grp, uint32_t cpu, uint64_t val) "GICv3 ICV_HPPIR%d rea
294
gicv3_icv_dir_write(uint32_t cpu, uint64_t val) "GICv3 ICV_DIR write cpu 0x%x value 0x%" PRIx64
295
gicv3_icv_iar_read(int grp, uint32_t cpu, uint64_t val) "GICv3 ICV_IAR%d read cpu 0x%x value 0x%" PRIx64
296
gicv3_icv_eoir_write(int grp, uint32_t cpu, uint64_t val) "GICv3 ICV_EOIR%d write cpu 0x%x value 0x%" PRIx64
297
-gicv3_cpuif_virt_update(uint32_t cpuid, int idx) "GICv3 CPU i/f 0x%x virt HPPI update LR index %d"
298
+gicv3_cpuif_virt_update(uint32_t cpuid, int idx, int hppvlpi, int grp, int prio) "GICv3 CPU i/f 0x%x virt HPPI update LR index %d HPPVLPI %d grp %d prio %d"
299
gicv3_cpuif_virt_set_irqs(uint32_t cpuid, int fiqlevel, int irqlevel) "GICv3 CPU i/f 0x%x virt HPPI update: setting FIQ %d IRQ %d"
300
gicv3_cpuif_virt_set_maint_irq(uint32_t cpuid, int maintlevel) "GICv3 CPU i/f 0x%x virt HPPI update: setting maintenance-irq %d"
301
302
--
30
--
303
2.25.1
31
2.34.1
32
33
diff view generated by jsdifflib
Deleted patch
1
Implement the function gicv3_redist_vlpi_pending(), which was
2
previously left as a stub. This is the function that is called by
3
the CPU interface when it changes the state of a vLPI. It's similar
4
to gicv3_redist_process_vlpi(), but we know that the vCPU is
5
definitely resident on the redistributor and the irq is in range, so
6
it is a bit simpler.
7
1
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20220408141550.1271295-33-peter.maydell@linaro.org
11
---
12
hw/intc/arm_gicv3_redist.c | 23 +++++++++++++++++++++--
13
1 file changed, 21 insertions(+), 2 deletions(-)
14
15
diff --git a/hw/intc/arm_gicv3_redist.c b/hw/intc/arm_gicv3_redist.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/intc/arm_gicv3_redist.c
18
+++ b/hw/intc/arm_gicv3_redist.c
19
@@ -XXX,XX +XXX,XX @@ void gicv3_redist_movall_lpis(GICv3CPUState *src, GICv3CPUState *dest)
20
void gicv3_redist_vlpi_pending(GICv3CPUState *cs, int irq, int level)
21
{
22
/*
23
- * The redistributor handling for changing the pending state
24
- * of a vLPI will be added in a subsequent commit.
25
+ * Change the pending state of the specified vLPI.
26
+ * Unlike gicv3_redist_process_vlpi(), we know here that the
27
+ * vCPU is definitely resident on this redistributor, and that
28
+ * the irq is in range.
29
*/
30
+ uint64_t vptbase, ctbase;
31
+
32
+ vptbase = FIELD_EX64(cs->gicr_vpendbaser, GICR_VPENDBASER, PHYADDR) << 16;
33
+
34
+ if (set_pending_table_bit(cs, vptbase, irq, level)) {
35
+ if (level) {
36
+ /* Check whether this vLPI is now the best */
37
+ ctbase = cs->gicr_vpropbaser & R_GICR_VPROPBASER_PHYADDR_MASK;
38
+ update_for_one_lpi(cs, irq, ctbase, true, &cs->hppvlpi);
39
+ gicv3_cpuif_virt_irq_fiq_update(cs);
40
+ } else {
41
+ /* Only need to recalculate if this was previously the best vLPI */
42
+ if (irq == cs->hppvlpi.irq) {
43
+ gicv3_redist_update_vlpi(cs);
44
+ }
45
+ }
46
+ }
47
}
48
49
void gicv3_redist_process_vlpi(GICv3CPUState *cs, int irq, uint64_t vptaddr,
50
--
51
2.25.1
diff view generated by jsdifflib
Deleted patch
1
We can use our new set_pending_table_bit() utility function
2
in gicv3_redist_mov_lpi() to clear the bit in the source
3
pending table, rather than doing the "load, clear bit, store"
4
ourselves.
5
1
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20220408141550.1271295-34-peter.maydell@linaro.org
9
---
10
hw/intc/arm_gicv3_redist.c | 9 +--------
11
1 file changed, 1 insertion(+), 8 deletions(-)
12
13
diff --git a/hw/intc/arm_gicv3_redist.c b/hw/intc/arm_gicv3_redist.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/intc/arm_gicv3_redist.c
16
+++ b/hw/intc/arm_gicv3_redist.c
17
@@ -XXX,XX +XXX,XX @@ void gicv3_redist_mov_lpi(GICv3CPUState *src, GICv3CPUState *dest, int irq)
18
* we choose to NOP. If LPIs are disabled on source there's nothing
19
* to be transferred anyway.
20
*/
21
- AddressSpace *as = &src->gic->dma_as;
22
uint64_t idbits;
23
uint32_t pendt_size;
24
uint64_t src_baddr;
25
- uint8_t src_pend;
26
27
if (!(src->gicr_ctlr & GICR_CTLR_ENABLE_LPIS) ||
28
!(dest->gicr_ctlr & GICR_CTLR_ENABLE_LPIS)) {
29
@@ -XXX,XX +XXX,XX @@ void gicv3_redist_mov_lpi(GICv3CPUState *src, GICv3CPUState *dest, int irq)
30
31
src_baddr = src->gicr_pendbaser & R_GICR_PENDBASER_PHYADDR_MASK;
32
33
- address_space_read(as, src_baddr + (irq / 8),
34
- MEMTXATTRS_UNSPECIFIED, &src_pend, sizeof(src_pend));
35
- if (!extract32(src_pend, irq % 8, 1)) {
36
+ if (!set_pending_table_bit(src, src_baddr, irq, 0)) {
37
/* Not pending on source, nothing to do */
38
return;
39
}
40
- src_pend &= ~(1 << (irq % 8));
41
- address_space_write(as, src_baddr + (irq / 8),
42
- MEMTXATTRS_UNSPECIFIED, &src_pend, sizeof(src_pend));
43
if (irq == src->hpplpi.irq) {
44
/*
45
* We just made this LPI not-pending so only need to update
46
--
47
2.25.1
diff view generated by jsdifflib
Deleted patch
1
Implement the gicv3_redist_mov_vlpi() function (previously left as a
2
stub). This function handles the work of a VMOVI command: it marks
3
the vLPI not-pending on the source and pending on the destination.
4
1
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20220408141550.1271295-35-peter.maydell@linaro.org
8
---
9
hw/intc/arm_gicv3_redist.c | 20 ++++++++++++++++++--
10
1 file changed, 18 insertions(+), 2 deletions(-)
11
12
diff --git a/hw/intc/arm_gicv3_redist.c b/hw/intc/arm_gicv3_redist.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/intc/arm_gicv3_redist.c
15
+++ b/hw/intc/arm_gicv3_redist.c
16
@@ -XXX,XX +XXX,XX @@ void gicv3_redist_mov_vlpi(GICv3CPUState *src, uint64_t src_vptaddr,
17
int irq, int doorbell)
18
{
19
/*
20
- * The redistributor handling for moving a VLPI will be added
21
- * in a subsequent commit.
22
+ * Move the specified vLPI's pending state from the source redistributor
23
+ * to the destination.
24
*/
25
+ if (!set_pending_table_bit(src, src_vptaddr, irq, 0)) {
26
+ /* Not pending on source, nothing to do */
27
+ return;
28
+ }
29
+ if (vcpu_resident(src, src_vptaddr) && irq == src->hppvlpi.irq) {
30
+ /*
31
+ * Update src's cached highest-priority pending vLPI if we just made
32
+ * it not-pending
33
+ */
34
+ gicv3_redist_update_vlpi(src);
35
+ }
36
+ /*
37
+ * Mark the vLPI pending on the destination (ringing the doorbell
38
+ * if the vCPU isn't resident)
39
+ */
40
+ gicv3_redist_process_vlpi(dest, irq, dest_vptaddr, doorbell, irq);
41
}
42
43
void gicv3_redist_vinvall(GICv3CPUState *cs, uint64_t vptaddr)
44
--
45
2.25.1
diff view generated by jsdifflib
Deleted patch
1
Implement the gicv3_redist_vinvall() function (previously left as a
2
stub). This function handles the work of a VINVALL command: it must
3
invalidate any cached information associated with a specific vCPU.
4
1
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20220408141550.1271295-36-peter.maydell@linaro.org
8
---
9
hw/intc/arm_gicv3_redist.c | 8 +++++++-
10
1 file changed, 7 insertions(+), 1 deletion(-)
11
12
diff --git a/hw/intc/arm_gicv3_redist.c b/hw/intc/arm_gicv3_redist.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/intc/arm_gicv3_redist.c
15
+++ b/hw/intc/arm_gicv3_redist.c
16
@@ -XXX,XX +XXX,XX @@ void gicv3_redist_mov_vlpi(GICv3CPUState *src, uint64_t src_vptaddr,
17
18
void gicv3_redist_vinvall(GICv3CPUState *cs, uint64_t vptaddr)
19
{
20
- /* The redistributor handling will be added in a subsequent commit */
21
+ if (!vcpu_resident(cs, vptaddr)) {
22
+ /* We don't have anything cached if the vCPU isn't resident */
23
+ return;
24
+ }
25
+
26
+ /* Otherwise, our only cached information is the HPPVLPI info */
27
+ gicv3_redist_update_vlpi(cs);
28
}
29
30
void gicv3_redist_inv_vlpi(GICv3CPUState *cs, int irq, uint64_t vptaddr)
31
--
32
2.25.1
diff view generated by jsdifflib
Deleted patch
1
Implement the function gicv3_redist_inv_vlpi(), which was previously
2
left as a stub. This is the function that does the work of the INV
3
command for a virtual interrupt.
4
1
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20220408141550.1271295-37-peter.maydell@linaro.org
8
---
9
hw/intc/arm_gicv3_redist.c | 7 +++++--
10
1 file changed, 5 insertions(+), 2 deletions(-)
11
12
diff --git a/hw/intc/arm_gicv3_redist.c b/hw/intc/arm_gicv3_redist.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/intc/arm_gicv3_redist.c
15
+++ b/hw/intc/arm_gicv3_redist.c
16
@@ -XXX,XX +XXX,XX @@ void gicv3_redist_vinvall(GICv3CPUState *cs, uint64_t vptaddr)
17
void gicv3_redist_inv_vlpi(GICv3CPUState *cs, int irq, uint64_t vptaddr)
18
{
19
/*
20
- * The redistributor handling for invalidating cached information
21
- * about a VLPI will be added in a subsequent commit.
22
+ * The only cached information for LPIs we have is the HPPLPI.
23
+ * We could be cleverer about identifying when we don't need
24
+ * to do a full rescan of the pending table, but until we find
25
+ * this is a performance issue, just always recalculate.
26
*/
27
+ gicv3_redist_vinvall(cs, vptaddr);
28
}
29
30
void gicv3_redist_set_irq(GICv3CPUState *cs, int irq, int level)
31
--
32
2.25.1
diff view generated by jsdifflib
Deleted patch
1
Update the various GIC ID and feature registers for GICv4:
2
* PIDR2 [7:4] is the GIC architecture revision
3
* GICD_TYPER.DVIS is 1 to indicate direct vLPI injection support
4
* GICR_TYPER.VLPIS is 1 to indicate redistributor support for vLPIs
5
* GITS_TYPER.VIRTUAL is 1 to indicate vLPI support
6
* GITS_TYPER.VMOVP is 1 to indicate that our VMOVP implementation
7
handles cross-ITS synchronization for the guest
8
* ICH_VTR_EL2.nV4 is 0 to indicate direct vLPI injection support
9
1
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20220408141550.1271295-38-peter.maydell@linaro.org
13
---
14
hw/intc/gicv3_internal.h | 15 +++++++++++----
15
hw/intc/arm_gicv3_common.c | 7 +++++--
16
hw/intc/arm_gicv3_cpuif.c | 6 +++++-
17
hw/intc/arm_gicv3_dist.c | 7 ++++---
18
hw/intc/arm_gicv3_its.c | 7 ++++++-
19
hw/intc/arm_gicv3_redist.c | 2 +-
20
6 files changed, 32 insertions(+), 12 deletions(-)
21
22
diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h
23
index XXXXXXX..XXXXXXX 100644
24
--- a/hw/intc/gicv3_internal.h
25
+++ b/hw/intc/gicv3_internal.h
26
@@ -XXX,XX +XXX,XX @@ FIELD(GITS_TYPER, SEIS, 18, 1)
27
FIELD(GITS_TYPER, PTA, 19, 1)
28
FIELD(GITS_TYPER, CIDBITS, 32, 4)
29
FIELD(GITS_TYPER, CIL, 36, 1)
30
+FIELD(GITS_TYPER, VMOVP, 37, 1)
31
32
#define GITS_IDREGS 0xFFD0
33
34
@@ -XXX,XX +XXX,XX @@ static inline uint32_t gicv3_iidr(void)
35
#define GICV3_PIDR0_REDIST 0x93
36
#define GICV3_PIDR0_ITS 0x94
37
38
-static inline uint32_t gicv3_idreg(int regoffset, uint8_t pidr0)
39
+static inline uint32_t gicv3_idreg(GICv3State *s, int regoffset, uint8_t pidr0)
40
{
41
/* Return the value of the CoreSight ID register at the specified
42
* offset from the first ID register (as found in the distributor
43
* and redistributor register banks).
44
- * These values indicate an ARM implementation of a GICv3.
45
+ * These values indicate an ARM implementation of a GICv3 or v4.
46
*/
47
static const uint8_t gicd_ids[] = {
48
- 0x44, 0x00, 0x00, 0x00, 0x92, 0xB4, 0x3B, 0x00, 0x0D, 0xF0, 0x05, 0xB1
49
+ 0x44, 0x00, 0x00, 0x00, 0x92, 0xB4, 0x0B, 0x00, 0x0D, 0xF0, 0x05, 0xB1
50
};
51
+ uint32_t id;
52
53
regoffset /= 4;
54
55
if (regoffset == 4) {
56
return pidr0;
57
}
58
- return gicd_ids[regoffset];
59
+ id = gicd_ids[regoffset];
60
+ if (regoffset == 6) {
61
+ /* PIDR2 bits [7:4] are the GIC architecture revision */
62
+ id |= s->revision << 4;
63
+ }
64
+ return id;
65
}
66
67
/**
68
diff --git a/hw/intc/arm_gicv3_common.c b/hw/intc/arm_gicv3_common.c
69
index XXXXXXX..XXXXXXX 100644
70
--- a/hw/intc/arm_gicv3_common.c
71
+++ b/hw/intc/arm_gicv3_common.c
72
@@ -XXX,XX +XXX,XX @@ static void arm_gicv3_common_realize(DeviceState *dev, Error **errp)
73
* Last == 1 if this is the last redistributor in a series of
74
* contiguous redistributor pages
75
* DirectLPI == 0 (direct injection of LPIs not supported)
76
- * VLPIS == 0 (virtual LPIs not supported)
77
- * PLPIS == 0 (physical LPIs not supported)
78
+ * VLPIS == 1 if vLPIs supported (GICv4 and up)
79
+ * PLPIS == 1 if LPIs supported
80
*/
81
cpu_affid = object_property_get_uint(OBJECT(cpu), "mp-affinity", NULL);
82
83
@@ -XXX,XX +XXX,XX @@ static void arm_gicv3_common_realize(DeviceState *dev, Error **errp)
84
85
if (s->lpi_enable) {
86
s->cpu[i].gicr_typer |= GICR_TYPER_PLPIS;
87
+ if (s->revision > 3) {
88
+ s->cpu[i].gicr_typer |= GICR_TYPER_VLPIS;
89
+ }
90
}
91
}
92
93
diff --git a/hw/intc/arm_gicv3_cpuif.c b/hw/intc/arm_gicv3_cpuif.c
94
index XXXXXXX..XXXXXXX 100644
95
--- a/hw/intc/arm_gicv3_cpuif.c
96
+++ b/hw/intc/arm_gicv3_cpuif.c
97
@@ -XXX,XX +XXX,XX @@ static uint64_t ich_vtr_read(CPUARMState *env, const ARMCPRegInfo *ri)
98
uint64_t value;
99
100
value = ((cs->num_list_regs - 1) << ICH_VTR_EL2_LISTREGS_SHIFT)
101
- | ICH_VTR_EL2_TDS | ICH_VTR_EL2_NV4 | ICH_VTR_EL2_A3V
102
+ | ICH_VTR_EL2_TDS | ICH_VTR_EL2_A3V
103
| (1 << ICH_VTR_EL2_IDBITS_SHIFT)
104
| ((cs->vprebits - 1) << ICH_VTR_EL2_PREBITS_SHIFT)
105
| ((cs->vpribits - 1) << ICH_VTR_EL2_PRIBITS_SHIFT);
106
107
+ if (cs->gic->revision < 4) {
108
+ value |= ICH_VTR_EL2_NV4;
109
+ }
110
+
111
trace_gicv3_ich_vtr_read(gicv3_redist_affid(cs), value);
112
return value;
113
}
114
diff --git a/hw/intc/arm_gicv3_dist.c b/hw/intc/arm_gicv3_dist.c
115
index XXXXXXX..XXXXXXX 100644
116
--- a/hw/intc/arm_gicv3_dist.c
117
+++ b/hw/intc/arm_gicv3_dist.c
118
@@ -XXX,XX +XXX,XX @@ static bool gicd_readl(GICv3State *s, hwaddr offset,
119
* No1N == 1 (1-of-N SPI interrupts not supported)
120
* A3V == 1 (non-zero values of Affinity level 3 supported)
121
* IDbits == 0xf (we support 16-bit interrupt identifiers)
122
- * DVIS == 0 (Direct virtual LPI injection not supported)
123
+ * DVIS == 1 (Direct virtual LPI injection supported) if GICv4
124
* LPIS == 1 (LPIs are supported if affinity routing is enabled)
125
* num_LPIs == 0b00000 (bits [15:11],Number of LPIs as indicated
126
* by GICD_TYPER.IDbits)
127
@@ -XXX,XX +XXX,XX @@ static bool gicd_readl(GICv3State *s, hwaddr offset,
128
* so we only need to check the DS bit.
129
*/
130
bool sec_extn = !(s->gicd_ctlr & GICD_CTLR_DS);
131
+ bool dvis = s->revision >= 4;
132
133
- *data = (1 << 25) | (1 << 24) | (sec_extn << 10) |
134
+ *data = (1 << 25) | (1 << 24) | (dvis << 18) | (sec_extn << 10) |
135
(s->lpi_enable << GICD_TYPER_LPIS_SHIFT) |
136
(0xf << 19) | itlinesnumber;
137
return true;
138
@@ -XXX,XX +XXX,XX @@ static bool gicd_readl(GICv3State *s, hwaddr offset,
139
}
140
case GICD_IDREGS ... GICD_IDREGS + 0x2f:
141
/* ID registers */
142
- *data = gicv3_idreg(offset - GICD_IDREGS, GICV3_PIDR0_DIST);
143
+ *data = gicv3_idreg(s, offset - GICD_IDREGS, GICV3_PIDR0_DIST);
144
return true;
145
case GICD_SGIR:
146
/* WO registers, return unknown value */
147
diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
148
index XXXXXXX..XXXXXXX 100644
149
--- a/hw/intc/arm_gicv3_its.c
150
+++ b/hw/intc/arm_gicv3_its.c
151
@@ -XXX,XX +XXX,XX @@ static bool its_readl(GICv3ITSState *s, hwaddr offset,
152
break;
153
case GITS_IDREGS ... GITS_IDREGS + 0x2f:
154
/* ID registers */
155
- *data = gicv3_idreg(offset - GITS_IDREGS, GICV3_PIDR0_ITS);
156
+ *data = gicv3_idreg(s->gicv3, offset - GITS_IDREGS, GICV3_PIDR0_ITS);
157
break;
158
case GITS_TYPER:
159
*data = extract64(s->typer, 0, 32);
160
@@ -XXX,XX +XXX,XX @@ static void gicv3_arm_its_realize(DeviceState *dev, Error **errp)
161
s->typer = FIELD_DP64(s->typer, GITS_TYPER, DEVBITS, ITS_DEVBITS);
162
s->typer = FIELD_DP64(s->typer, GITS_TYPER, CIL, 1);
163
s->typer = FIELD_DP64(s->typer, GITS_TYPER, CIDBITS, ITS_CIDBITS);
164
+ if (s->gicv3->revision >= 4) {
165
+ /* Our VMOVP handles cross-ITS synchronization itself */
166
+ s->typer = FIELD_DP64(s->typer, GITS_TYPER, VMOVP, 1);
167
+ s->typer = FIELD_DP64(s->typer, GITS_TYPER, VIRTUAL, 1);
168
+ }
169
}
170
171
static void gicv3_its_reset(DeviceState *dev)
172
diff --git a/hw/intc/arm_gicv3_redist.c b/hw/intc/arm_gicv3_redist.c
173
index XXXXXXX..XXXXXXX 100644
174
--- a/hw/intc/arm_gicv3_redist.c
175
+++ b/hw/intc/arm_gicv3_redist.c
176
@@ -XXX,XX +XXX,XX @@ static MemTxResult gicr_readl(GICv3CPUState *cs, hwaddr offset,
177
*data = cs->gicr_nsacr;
178
return MEMTX_OK;
179
case GICR_IDREGS ... GICR_IDREGS + 0x2f:
180
- *data = gicv3_idreg(offset - GICR_IDREGS, GICV3_PIDR0_REDIST);
181
+ *data = gicv3_idreg(cs->gic, offset - GICR_IDREGS, GICV3_PIDR0_REDIST);
182
return MEMTX_OK;
183
/*
184
* VLPI frame registers. We don't need a version check for
185
--
186
2.25.1
diff view generated by jsdifflib
Deleted patch
1
Now that we have implemented all the GICv4 requirements, relax the
2
error-checking on the GIC object's 'revision' property to allow a TCG
3
GIC to be a GICv4, whilst still constraining the KVM GIC to GICv3.
4
1
5
Our 'revision' property doesn't consider the possibility of wanting
6
to specify the minor version of the GIC -- for instance there is a
7
GICv3.1 which adds support for extended SPI and PPI ranges, among
8
other things, and also GICv4.1. But since the QOM property is
9
internal to QEMU, not user-facing, we can cross that bridge when we
10
come to it. Within the GIC implementation itself code generally
11
checks against the appropriate ID register feature bits, and the
12
only use of s->revision is for setting those ID register bits.
13
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
16
Message-id: 20220408141550.1271295-39-peter.maydell@linaro.org
17
---
18
hw/intc/arm_gicv3_common.c | 12 +++++++-----
19
hw/intc/arm_gicv3_kvm.c | 5 +++++
20
2 files changed, 12 insertions(+), 5 deletions(-)
21
22
diff --git a/hw/intc/arm_gicv3_common.c b/hw/intc/arm_gicv3_common.c
23
index XXXXXXX..XXXXXXX 100644
24
--- a/hw/intc/arm_gicv3_common.c
25
+++ b/hw/intc/arm_gicv3_common.c
26
@@ -XXX,XX +XXX,XX @@ static void arm_gicv3_common_realize(DeviceState *dev, Error **errp)
27
GICv3State *s = ARM_GICV3_COMMON(dev);
28
int i, rdist_capacity, cpuidx;
29
30
- /* revision property is actually reserved and currently used only in order
31
- * to keep the interface compatible with GICv2 code, avoiding extra
32
- * conditions. However, in future it could be used, for example, if we
33
- * implement GICv4.
34
+ /*
35
+ * This GIC device supports only revisions 3 and 4. The GICv1/v2
36
+ * is a separate device.
37
+ * Note that subclasses of this device may impose further restrictions
38
+ * on the GIC revision: notably, the in-kernel KVM GIC doesn't
39
+ * support GICv4.
40
*/
41
- if (s->revision != 3) {
42
+ if (s->revision != 3 && s->revision != 4) {
43
error_setg(errp, "unsupported GIC revision %d", s->revision);
44
return;
45
}
46
diff --git a/hw/intc/arm_gicv3_kvm.c b/hw/intc/arm_gicv3_kvm.c
47
index XXXXXXX..XXXXXXX 100644
48
--- a/hw/intc/arm_gicv3_kvm.c
49
+++ b/hw/intc/arm_gicv3_kvm.c
50
@@ -XXX,XX +XXX,XX @@ static void kvm_arm_gicv3_realize(DeviceState *dev, Error **errp)
51
return;
52
}
53
54
+ if (s->revision != 3) {
55
+ error_setg(errp, "unsupported GIC revision %d for in-kernel GIC",
56
+ s->revision);
57
+ }
58
+
59
if (s->security_extn) {
60
error_setg(errp, "the in-kernel VGICv3 does not implement the "
61
"security extensions");
62
--
63
2.25.1
diff view generated by jsdifflib
Deleted patch
1
Everywhere we need to check which GIC version we're using, we look at
2
vms->gic_version and use the VIRT_GIC_VERSION_* enum values, except
3
in create_gic(), which copies vms->gic_version into a local 'int'
4
variable and makes direct comparisons against values 2 and 3.
5
1
6
For consistency, change this function to check the GIC version
7
the same way we do elsewhere. This includes not implicitly relying
8
on the enumeration type values happening to match the integer
9
'revision' values the GIC device object wants.
10
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
13
Message-id: 20220408141550.1271295-40-peter.maydell@linaro.org
14
---
15
hw/arm/virt.c | 31 +++++++++++++++++++++++--------
16
1 file changed, 23 insertions(+), 8 deletions(-)
17
18
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
19
index XXXXXXX..XXXXXXX 100644
20
--- a/hw/arm/virt.c
21
+++ b/hw/arm/virt.c
22
@@ -XXX,XX +XXX,XX @@ static void create_gic(VirtMachineState *vms, MemoryRegion *mem)
23
/* We create a standalone GIC */
24
SysBusDevice *gicbusdev;
25
const char *gictype;
26
- int type = vms->gic_version, i;
27
+ int i;
28
unsigned int smp_cpus = ms->smp.cpus;
29
uint32_t nb_redist_regions = 0;
30
+ int revision;
31
32
- gictype = (type == 3) ? gicv3_class_name() : gic_class_name();
33
+ if (vms->gic_version == VIRT_GIC_VERSION_2) {
34
+ gictype = gic_class_name();
35
+ } else {
36
+ gictype = gicv3_class_name();
37
+ }
38
39
+ switch (vms->gic_version) {
40
+ case VIRT_GIC_VERSION_2:
41
+ revision = 2;
42
+ break;
43
+ case VIRT_GIC_VERSION_3:
44
+ revision = 3;
45
+ break;
46
+ default:
47
+ g_assert_not_reached();
48
+ }
49
vms->gic = qdev_new(gictype);
50
- qdev_prop_set_uint32(vms->gic, "revision", type);
51
+ qdev_prop_set_uint32(vms->gic, "revision", revision);
52
qdev_prop_set_uint32(vms->gic, "num-cpu", smp_cpus);
53
/* Note that the num-irq property counts both internal and external
54
* interrupts; there are always 32 of the former (mandated by GIC spec).
55
@@ -XXX,XX +XXX,XX @@ static void create_gic(VirtMachineState *vms, MemoryRegion *mem)
56
qdev_prop_set_bit(vms->gic, "has-security-extensions", vms->secure);
57
}
58
59
- if (type == 3) {
60
+ if (vms->gic_version == VIRT_GIC_VERSION_3) {
61
uint32_t redist0_capacity =
62
vms->memmap[VIRT_GIC_REDIST].size / GICV3_REDIST_SIZE;
63
uint32_t redist0_count = MIN(smp_cpus, redist0_capacity);
64
@@ -XXX,XX +XXX,XX @@ static void create_gic(VirtMachineState *vms, MemoryRegion *mem)
65
gicbusdev = SYS_BUS_DEVICE(vms->gic);
66
sysbus_realize_and_unref(gicbusdev, &error_fatal);
67
sysbus_mmio_map(gicbusdev, 0, vms->memmap[VIRT_GIC_DIST].base);
68
- if (type == 3) {
69
+ if (vms->gic_version == VIRT_GIC_VERSION_3) {
70
sysbus_mmio_map(gicbusdev, 1, vms->memmap[VIRT_GIC_REDIST].base);
71
if (nb_redist_regions == 2) {
72
sysbus_mmio_map(gicbusdev, 2,
73
@@ -XXX,XX +XXX,XX @@ static void create_gic(VirtMachineState *vms, MemoryRegion *mem)
74
ppibase + timer_irq[irq]));
75
}
76
77
- if (type == 3) {
78
+ if (vms->gic_version == VIRT_GIC_VERSION_3) {
79
qemu_irq irq = qdev_get_gpio_in(vms->gic,
80
ppibase + ARCH_GIC_MAINT_IRQ);
81
qdev_connect_gpio_out_named(cpudev, "gicv3-maintenance-interrupt",
82
@@ -XXX,XX +XXX,XX @@ static void create_gic(VirtMachineState *vms, MemoryRegion *mem)
83
84
fdt_add_gic_node(vms);
85
86
- if (type == 3 && vms->its) {
87
+ if (vms->gic_version == VIRT_GIC_VERSION_3 && vms->its) {
88
create_its(vms);
89
- } else if (type == 2) {
90
+ } else if (vms->gic_version == VIRT_GIC_VERSION_2) {
91
create_v2m(vms);
92
}
93
}
94
--
95
2.25.1
diff view generated by jsdifflib
Deleted patch
1
In several places in virt.c we calculate the number of redistributors that
2
fit in a region of our memory map, which is the size of the region
3
divided by the size of a single redistributor frame. For GICv4, the
4
redistributor frame is a different size from that for GICv3. Abstract
5
out the calculation of redistributor region capacity so that we have
6
one place we need to change to handle GICv4 rather than several.
7
1
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20220408141550.1271295-41-peter.maydell@linaro.org
11
---
12
include/hw/arm/virt.h | 9 +++++++--
13
hw/arm/virt.c | 11 ++++-------
14
2 files changed, 11 insertions(+), 9 deletions(-)
15
16
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
17
index XXXXXXX..XXXXXXX 100644
18
--- a/include/hw/arm/virt.h
19
+++ b/include/hw/arm/virt.h
20
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_TYPE(VirtMachineState, VirtMachineClass, VIRT_MACHINE)
21
void virt_acpi_setup(VirtMachineState *vms);
22
bool virt_is_acpi_enabled(VirtMachineState *vms);
23
24
+/* Return number of redistributors that fit in the specified region */
25
+static uint32_t virt_redist_capacity(VirtMachineState *vms, int region)
26
+{
27
+ return vms->memmap[region].size / GICV3_REDIST_SIZE;
28
+}
29
+
30
/* Return the number of used redistributor regions */
31
static inline int virt_gicv3_redist_region_count(VirtMachineState *vms)
32
{
33
- uint32_t redist0_capacity =
34
- vms->memmap[VIRT_GIC_REDIST].size / GICV3_REDIST_SIZE;
35
+ uint32_t redist0_capacity = virt_redist_capacity(vms, VIRT_GIC_REDIST);
36
37
assert(vms->gic_version == VIRT_GIC_VERSION_3);
38
39
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
40
index XXXXXXX..XXXXXXX 100644
41
--- a/hw/arm/virt.c
42
+++ b/hw/arm/virt.c
43
@@ -XXX,XX +XXX,XX @@ static void create_gic(VirtMachineState *vms, MemoryRegion *mem)
44
}
45
46
if (vms->gic_version == VIRT_GIC_VERSION_3) {
47
- uint32_t redist0_capacity =
48
- vms->memmap[VIRT_GIC_REDIST].size / GICV3_REDIST_SIZE;
49
+ uint32_t redist0_capacity = virt_redist_capacity(vms, VIRT_GIC_REDIST);
50
uint32_t redist0_count = MIN(smp_cpus, redist0_capacity);
51
52
nb_redist_regions = virt_gicv3_redist_region_count(vms);
53
@@ -XXX,XX +XXX,XX @@ static void create_gic(VirtMachineState *vms, MemoryRegion *mem)
54
55
if (nb_redist_regions == 2) {
56
uint32_t redist1_capacity =
57
- vms->memmap[VIRT_HIGH_GIC_REDIST2].size / GICV3_REDIST_SIZE;
58
+ virt_redist_capacity(vms, VIRT_HIGH_GIC_REDIST2);
59
60
qdev_prop_set_uint32(vms->gic, "redist-region-count[1]",
61
MIN(smp_cpus - redist0_count, redist1_capacity));
62
@@ -XXX,XX +XXX,XX @@ static void machvirt_init(MachineState *machine)
63
* many redistributors we can fit into the memory map.
64
*/
65
if (vms->gic_version == VIRT_GIC_VERSION_3) {
66
- virt_max_cpus =
67
- vms->memmap[VIRT_GIC_REDIST].size / GICV3_REDIST_SIZE;
68
- virt_max_cpus +=
69
- vms->memmap[VIRT_HIGH_GIC_REDIST2].size / GICV3_REDIST_SIZE;
70
+ virt_max_cpus = virt_redist_capacity(vms, VIRT_GIC_REDIST) +
71
+ virt_redist_capacity(vms, VIRT_HIGH_GIC_REDIST2);
72
} else {
73
virt_max_cpus = GIC_NCPU;
74
}
75
--
76
2.25.1
diff view generated by jsdifflib
Deleted patch
1
Add support for the TCG GICv4 to the virt board. For the board,
2
the GICv4 is very similar to the GICv3, with the only difference
3
being the size of the redistributor frame. The changes here are thus:
4
* calculating virt_redist_capacity correctly for GICv4
5
* changing various places which were "if GICv3" to be "if not GICv2"
6
* the commandline option handling
7
1
8
Note that using GICv4 reduces the maximum possible number of CPUs on
9
the virt board from 512 to 317, because we can now only fit half as
10
many redistributors into the redistributor regions we have defined.
11
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
14
Message-id: 20220408141550.1271295-42-peter.maydell@linaro.org
15
---
16
docs/system/arm/virt.rst | 5 ++-
17
include/hw/arm/virt.h | 12 +++++--
18
hw/arm/virt.c | 70 ++++++++++++++++++++++++++++++----------
19
3 files changed, 67 insertions(+), 20 deletions(-)
20
21
diff --git a/docs/system/arm/virt.rst b/docs/system/arm/virt.rst
22
index XXXXXXX..XXXXXXX 100644
23
--- a/docs/system/arm/virt.rst
24
+++ b/docs/system/arm/virt.rst
25
@@ -XXX,XX +XXX,XX @@ gic-version
26
GICv2. Note that this limits the number of CPUs to 8.
27
``3``
28
GICv3. This allows up to 512 CPUs.
29
+ ``4``
30
+ GICv4. Requires ``virtualization`` to be ``on``; allows up to 317 CPUs.
31
``host``
32
Use the same GIC version the host provides, when using KVM
33
``max``
34
Use the best GIC version possible (same as host when using KVM;
35
- currently same as ``3``` for TCG, but this may change in future)
36
+ with TCG this is currently ``3`` if ``virtualization`` is ``off`` and
37
+ ``4`` if ``virtualization`` is ``on``, but this may change in future)
38
39
its
40
Set ``on``/``off`` to enable/disable ITS instantiation. The default is ``on``
41
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
42
index XXXXXXX..XXXXXXX 100644
43
--- a/include/hw/arm/virt.h
44
+++ b/include/hw/arm/virt.h
45
@@ -XXX,XX +XXX,XX @@ typedef enum VirtGICType {
46
VIRT_GIC_VERSION_HOST,
47
VIRT_GIC_VERSION_2,
48
VIRT_GIC_VERSION_3,
49
+ VIRT_GIC_VERSION_4,
50
VIRT_GIC_VERSION_NOSEL,
51
} VirtGICType;
52
53
@@ -XXX,XX +XXX,XX @@ bool virt_is_acpi_enabled(VirtMachineState *vms);
54
/* Return number of redistributors that fit in the specified region */
55
static uint32_t virt_redist_capacity(VirtMachineState *vms, int region)
56
{
57
- return vms->memmap[region].size / GICV3_REDIST_SIZE;
58
+ uint32_t redist_size;
59
+
60
+ if (vms->gic_version == VIRT_GIC_VERSION_3) {
61
+ redist_size = GICV3_REDIST_SIZE;
62
+ } else {
63
+ redist_size = GICV4_REDIST_SIZE;
64
+ }
65
+ return vms->memmap[region].size / redist_size;
66
}
67
68
/* Return the number of used redistributor regions */
69
@@ -XXX,XX +XXX,XX @@ static inline int virt_gicv3_redist_region_count(VirtMachineState *vms)
70
{
71
uint32_t redist0_capacity = virt_redist_capacity(vms, VIRT_GIC_REDIST);
72
73
- assert(vms->gic_version == VIRT_GIC_VERSION_3);
74
+ assert(vms->gic_version != VIRT_GIC_VERSION_2);
75
76
return (MACHINE(vms)->smp.cpus > redist0_capacity &&
77
vms->highmem_redists) ? 2 : 1;
78
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
79
index XXXXXXX..XXXXXXX 100644
80
--- a/hw/arm/virt.c
81
+++ b/hw/arm/virt.c
82
@@ -XXX,XX +XXX,XX @@ static void fdt_add_gic_node(VirtMachineState *vms)
83
qemu_fdt_setprop_cell(ms->fdt, nodename, "#address-cells", 0x2);
84
qemu_fdt_setprop_cell(ms->fdt, nodename, "#size-cells", 0x2);
85
qemu_fdt_setprop(ms->fdt, nodename, "ranges", NULL, 0);
86
- if (vms->gic_version == VIRT_GIC_VERSION_3) {
87
+ if (vms->gic_version != VIRT_GIC_VERSION_2) {
88
int nb_redist_regions = virt_gicv3_redist_region_count(vms);
89
90
qemu_fdt_setprop_string(ms->fdt, nodename, "compatible",
91
@@ -XXX,XX +XXX,XX @@ static void create_gic(VirtMachineState *vms, MemoryRegion *mem)
92
case VIRT_GIC_VERSION_3:
93
revision = 3;
94
break;
95
+ case VIRT_GIC_VERSION_4:
96
+ revision = 4;
97
+ break;
98
default:
99
g_assert_not_reached();
100
}
101
@@ -XXX,XX +XXX,XX @@ static void create_gic(VirtMachineState *vms, MemoryRegion *mem)
102
qdev_prop_set_bit(vms->gic, "has-security-extensions", vms->secure);
103
}
104
105
- if (vms->gic_version == VIRT_GIC_VERSION_3) {
106
+ if (vms->gic_version != VIRT_GIC_VERSION_2) {
107
uint32_t redist0_capacity = virt_redist_capacity(vms, VIRT_GIC_REDIST);
108
uint32_t redist0_count = MIN(smp_cpus, redist0_capacity);
109
110
@@ -XXX,XX +XXX,XX @@ static void create_gic(VirtMachineState *vms, MemoryRegion *mem)
111
gicbusdev = SYS_BUS_DEVICE(vms->gic);
112
sysbus_realize_and_unref(gicbusdev, &error_fatal);
113
sysbus_mmio_map(gicbusdev, 0, vms->memmap[VIRT_GIC_DIST].base);
114
- if (vms->gic_version == VIRT_GIC_VERSION_3) {
115
+ if (vms->gic_version != VIRT_GIC_VERSION_2) {
116
sysbus_mmio_map(gicbusdev, 1, vms->memmap[VIRT_GIC_REDIST].base);
117
if (nb_redist_regions == 2) {
118
sysbus_mmio_map(gicbusdev, 2,
119
@@ -XXX,XX +XXX,XX @@ static void create_gic(VirtMachineState *vms, MemoryRegion *mem)
120
ppibase + timer_irq[irq]));
121
}
122
123
- if (vms->gic_version == VIRT_GIC_VERSION_3) {
124
+ if (vms->gic_version != VIRT_GIC_VERSION_2) {
125
qemu_irq irq = qdev_get_gpio_in(vms->gic,
126
ppibase + ARCH_GIC_MAINT_IRQ);
127
qdev_connect_gpio_out_named(cpudev, "gicv3-maintenance-interrupt",
128
@@ -XXX,XX +XXX,XX @@ static void create_gic(VirtMachineState *vms, MemoryRegion *mem)
129
130
fdt_add_gic_node(vms);
131
132
- if (vms->gic_version == VIRT_GIC_VERSION_3 && vms->its) {
133
+ if (vms->gic_version != VIRT_GIC_VERSION_2 && vms->its) {
134
create_its(vms);
135
} else if (vms->gic_version == VIRT_GIC_VERSION_2) {
136
create_v2m(vms);
137
@@ -XXX,XX +XXX,XX @@ static uint64_t virt_cpu_mp_affinity(VirtMachineState *vms, int idx)
138
* purposes are to make TCG consistent (with 64-bit KVM hosts)
139
* and to improve SGI efficiency.
140
*/
141
- if (vms->gic_version == VIRT_GIC_VERSION_3) {
142
- clustersz = GICV3_TARGETLIST_BITS;
143
- } else {
144
+ if (vms->gic_version == VIRT_GIC_VERSION_2) {
145
clustersz = GIC_TARGETLIST_BITS;
146
+ } else {
147
+ clustersz = GICV3_TARGETLIST_BITS;
148
}
149
}
150
return arm_cpu_mp_affinity(idx, clustersz);
151
@@ -XXX,XX +XXX,XX @@ static void finalize_gic_version(VirtMachineState *vms)
152
error_report(
153
"gic-version=3 is not supported with kernel-irqchip=off");
154
exit(1);
155
+ case VIRT_GIC_VERSION_4:
156
+ error_report(
157
+ "gic-version=4 is not supported with kernel-irqchip=off");
158
+ exit(1);
159
}
160
}
161
162
@@ -XXX,XX +XXX,XX @@ static void finalize_gic_version(VirtMachineState *vms)
163
case VIRT_GIC_VERSION_2:
164
case VIRT_GIC_VERSION_3:
165
break;
166
+ case VIRT_GIC_VERSION_4:
167
+ error_report("gic-version=4 is not supported with KVM");
168
+ exit(1);
169
}
170
171
/* Check chosen version is effectively supported by the host */
172
@@ -XXX,XX +XXX,XX @@ static void finalize_gic_version(VirtMachineState *vms)
173
case VIRT_GIC_VERSION_MAX:
174
if (module_object_class_by_name("arm-gicv3")) {
175
/* CONFIG_ARM_GICV3_TCG was set */
176
- vms->gic_version = VIRT_GIC_VERSION_3;
177
+ if (vms->virt) {
178
+ /* GICv4 only makes sense if CPU has EL2 */
179
+ vms->gic_version = VIRT_GIC_VERSION_4;
180
+ } else {
181
+ vms->gic_version = VIRT_GIC_VERSION_3;
182
+ }
183
} else {
184
vms->gic_version = VIRT_GIC_VERSION_2;
185
}
186
@@ -XXX,XX +XXX,XX @@ static void finalize_gic_version(VirtMachineState *vms)
187
case VIRT_GIC_VERSION_HOST:
188
error_report("gic-version=host requires KVM");
189
exit(1);
190
+ case VIRT_GIC_VERSION_4:
191
+ if (!vms->virt) {
192
+ error_report("gic-version=4 requires virtualization enabled");
193
+ exit(1);
194
+ }
195
+ break;
196
case VIRT_GIC_VERSION_2:
197
case VIRT_GIC_VERSION_3:
198
break;
199
@@ -XXX,XX +XXX,XX @@ static void machvirt_init(MachineState *machine)
200
vms->psci_conduit = QEMU_PSCI_CONDUIT_HVC;
201
}
202
203
- /* The maximum number of CPUs depends on the GIC version, or on how
204
- * many redistributors we can fit into the memory map.
205
+ /*
206
+ * The maximum number of CPUs depends on the GIC version, or on how
207
+ * many redistributors we can fit into the memory map (which in turn
208
+ * depends on whether this is a GICv3 or v4).
209
*/
210
- if (vms->gic_version == VIRT_GIC_VERSION_3) {
211
+ if (vms->gic_version == VIRT_GIC_VERSION_2) {
212
+ virt_max_cpus = GIC_NCPU;
213
+ } else {
214
virt_max_cpus = virt_redist_capacity(vms, VIRT_GIC_REDIST) +
215
virt_redist_capacity(vms, VIRT_HIGH_GIC_REDIST2);
216
- } else {
217
- virt_max_cpus = GIC_NCPU;
218
}
219
220
if (max_cpus > virt_max_cpus) {
221
@@ -XXX,XX +XXX,XX @@ static void virt_set_mte(Object *obj, bool value, Error **errp)
222
static char *virt_get_gic_version(Object *obj, Error **errp)
223
{
224
VirtMachineState *vms = VIRT_MACHINE(obj);
225
- const char *val = vms->gic_version == VIRT_GIC_VERSION_3 ? "3" : "2";
226
+ const char *val;
227
228
+ switch (vms->gic_version) {
229
+ case VIRT_GIC_VERSION_4:
230
+ val = "4";
231
+ break;
232
+ case VIRT_GIC_VERSION_3:
233
+ val = "3";
234
+ break;
235
+ default:
236
+ val = "2";
237
+ break;
238
+ }
239
return g_strdup(val);
240
}
241
242
@@ -XXX,XX +XXX,XX @@ static void virt_set_gic_version(Object *obj, const char *value, Error **errp)
243
{
244
VirtMachineState *vms = VIRT_MACHINE(obj);
245
246
- if (!strcmp(value, "3")) {
247
+ if (!strcmp(value, "4")) {
248
+ vms->gic_version = VIRT_GIC_VERSION_4;
249
+ } else if (!strcmp(value, "3")) {
250
vms->gic_version = VIRT_GIC_VERSION_3;
251
} else if (!strcmp(value, "2")) {
252
vms->gic_version = VIRT_GIC_VERSION_2;
253
@@ -XXX,XX +XXX,XX @@ static void virt_machine_class_init(ObjectClass *oc, void *data)
254
virt_set_gic_version);
255
object_class_property_set_description(oc, "gic-version",
256
"Set GIC version. "
257
- "Valid values are 2, 3, host and max");
258
+ "Valid values are 2, 3, 4, host and max");
259
260
object_class_property_add_str(oc, "iommu", virt_get_iommu, virt_set_iommu);
261
object_class_property_set_description(oc, "iommu",
262
--
263
2.25.1
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
The nrf51_timer has a free-running counter which we implement using
2
the pattern of using two fields (update_counter_ns, counter) to track
3
the last point at which we calculated the counter value, and the
4
counter value at that time. Then we can find the current counter
5
value by converting the difference in wall-clock time between then
6
and now to a tick count that we need to add to the counter value.
2
7
3
The operation we're performing with the movcond
8
Unfortunately the nrf51_timer's implementation of this has a bug
4
is either min/max depending on cond -- simplify.
9
which means it loses time every time update_counter() is called.
5
Use tcg_constant_i64 while we're at it.
10
After updating s->counter it always sets s->update_counter_ns to
11
'now', even though the actual point when s->counter hit the new value
12
will be some point in the past (half a tick, say). In the worst case
13
(guest code in a tight loop reading the counter, icount mode) the
14
counter is continually queried less than a tick after it was last
15
read, so s->counter never advances but s->update_counter_ns does, and
16
the guest never makes forward progress.
6
17
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
18
The fix for this is to only advance update_counter_ns to the
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
19
timestamp of the last tick, not all the way to 'now'. (This is the
20
pattern used in hw/misc/mps2-fpgaio.c's counter.)
21
22
Cc: qemu-stable@nongnu.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
23
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
24
Reviewed-by: Joel Stanley <joel@jms.id.au>
25
Message-id: 20230606134917.3782215-1-peter.maydell@linaro.org
10
---
26
---
11
target/arm/translate-sve.c | 9 ++-------
27
hw/timer/nrf51_timer.c | 7 ++++++-
12
1 file changed, 2 insertions(+), 7 deletions(-)
28
1 file changed, 6 insertions(+), 1 deletion(-)
13
29
14
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
30
diff --git a/hw/timer/nrf51_timer.c b/hw/timer/nrf51_timer.c
15
index XXXXXXX..XXXXXXX 100644
31
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/translate-sve.c
32
--- a/hw/timer/nrf51_timer.c
17
+++ b/target/arm/translate-sve.c
33
+++ b/hw/timer/nrf51_timer.c
18
@@ -XXX,XX +XXX,XX @@ static bool trans_PNEXT(DisasContext *s, arg_rr_esz *a)
34
@@ -XXX,XX +XXX,XX @@ static uint32_t update_counter(NRF51TimerState *s, int64_t now)
19
static void do_sat_addsub_32(TCGv_i64 reg, TCGv_i64 val, bool u, bool d)
35
uint32_t ticks = ns_to_ticks(s, now - s->update_counter_ns);
20
{
36
21
int64_t ibound;
37
s->counter = (s->counter + ticks) % BIT(bitwidths[s->bitmode]);
22
- TCGv_i64 bound;
38
- s->update_counter_ns = now;
23
- TCGCond cond;
39
+ /*
24
40
+ * Only advance the sync time to the timestamp of the last tick,
25
/* Use normal 64-bit arithmetic to detect 32-bit overflow. */
41
+ * not all the way to 'now', so we don't lose time if we do
26
if (u) {
42
+ * multiple resyncs in a single tick.
27
@@ -XXX,XX +XXX,XX @@ static void do_sat_addsub_32(TCGv_i64 reg, TCGv_i64 val, bool u, bool d)
43
+ */
28
if (d) {
44
+ s->update_counter_ns += ticks_to_ns(s, ticks);
29
tcg_gen_sub_i64(reg, reg, val);
45
return ticks;
30
ibound = (u ? 0 : INT32_MIN);
31
- cond = TCG_COND_LT;
32
+ tcg_gen_smax_i64(reg, reg, tcg_constant_i64(ibound));
33
} else {
34
tcg_gen_add_i64(reg, reg, val);
35
ibound = (u ? UINT32_MAX : INT32_MAX);
36
- cond = TCG_COND_GT;
37
+ tcg_gen_smin_i64(reg, reg, tcg_constant_i64(ibound));
38
}
39
- bound = tcg_const_i64(ibound);
40
- tcg_gen_movcond_i64(cond, reg, reg, bound, bound, reg);
41
- tcg_temp_free_i64(bound);
42
}
46
}
43
47
44
/* Similarly with 64-bit values. */
45
--
48
--
46
2.25.1
49
2.34.1
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Marcin Juszkiewicz <marcin.juszkiewicz@linaro.org>
2
2
3
Use tcg_constant_{i32,i64} as appropriate throughout.
3
Signed-off-by: Marcin Juszkiewicz <marcin.juszkiewicz@linaro.org>
4
This fixes a bug in trans_VSCCLRM() where we were leaking a TCGv.
4
Reviewed-by: Thomas Huth <thuth@redhat.com>
5
5
Message-id: 20230607092112.655098-1-marcin.juszkiewicz@linaro.org
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@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
target/arm/translate-m-nocp.c | 12 +++++-------
8
hw/arm/Kconfig | 1 +
11
1 file changed, 5 insertions(+), 7 deletions(-)
9
1 file changed, 1 insertion(+)
12
10
13
diff --git a/target/arm/translate-m-nocp.c b/target/arm/translate-m-nocp.c
11
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
14
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/translate-m-nocp.c
13
--- a/hw/arm/Kconfig
16
+++ b/target/arm/translate-m-nocp.c
14
+++ b/hw/arm/Kconfig
17
@@ -XXX,XX +XXX,XX @@ static bool trans_VSCCLRM(DisasContext *s, arg_VSCCLRM *a)
15
@@ -XXX,XX +XXX,XX @@ config SBSA_REF
18
}
16
select PL061 # GPIO
19
17
select USB_EHCI_SYSBUS
20
/* Zero the Sregs from btmreg to topreg inclusive. */
18
select WDT_SBSA
21
- zero = tcg_const_i64(0);
19
+ select BOCHS_DISPLAY
22
+ zero = tcg_constant_i64(0);
20
23
if (btmreg & 1) {
21
config SABRELITE
24
write_neon_element64(zero, btmreg >> 1, 1, MO_32);
22
bool
25
btmreg++;
26
@@ -XXX,XX +XXX,XX @@ static bool trans_VSCCLRM(DisasContext *s, arg_VSCCLRM *a)
27
}
28
assert(btmreg == topreg + 1);
29
if (dc_isar_feature(aa32_mve, s)) {
30
- TCGv_i32 z32 = tcg_const_i32(0);
31
- store_cpu_field(z32, v7m.vpr);
32
+ store_cpu_field(tcg_constant_i32(0), v7m.vpr);
33
}
34
35
clear_eci_state(s);
36
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_read(DisasContext *s, int regno,
37
}
38
case ARM_VFP_FPCXT_NS:
39
{
40
- TCGv_i32 control, sfpa, fpscr, fpdscr, zero;
41
+ TCGv_i32 control, sfpa, fpscr, fpdscr;
42
TCGLabel *lab_active = gen_new_label();
43
44
lookup_tb = true;
45
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_read(DisasContext *s, int regno,
46
storefn(s, opaque, tmp, true);
47
/* If SFPA is zero then set FPSCR from FPDSCR_NS */
48
fpdscr = load_cpu_field(v7m.fpdscr[M_REG_NS]);
49
- zero = tcg_const_i32(0);
50
- tcg_gen_movcond_i32(TCG_COND_EQ, fpscr, sfpa, zero, fpdscr, fpscr);
51
+ tcg_gen_movcond_i32(TCG_COND_EQ, fpscr, sfpa, tcg_constant_i32(0),
52
+ fpdscr, fpscr);
53
gen_helper_vfp_set_fpscr(cpu_env, fpscr);
54
- tcg_temp_free_i32(zero);
55
tcg_temp_free_i32(sfpa);
56
tcg_temp_free_i32(fpdscr);
57
tcg_temp_free_i32(fpscr);
58
--
23
--
59
2.25.1
24
2.34.1
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Martin Kaiser <martin@kaiser.cx>
2
2
3
Bool is a more appropriate type for this value.
3
The Linux kernel added a flood check for RX data recently in commit
4
Move the member down in the struct to keep the
4
496a4471b7c3 ("serial: imx: work-around for hardware RX flood"). This
5
bool type members together and remove a hole.
5
check uses the wake bit in the UART status register 2. The wake bit
6
indicates that the receiver detected a start bit on the RX line. If the
7
kernel sees a number of RX interrupts without the wake bit being set, it
8
treats this as spurious data and resets the UART port. imx_serial does
9
never set the wake bit and triggers the kernel's flood check.
6
10
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
This patch adds support for the wake bit. wake is set when we receive a
8
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
12
new character (it's not set for break events). It seems that wake is
13
cleared by the kernel driver, the hardware does not have to clear it
14
automatically after data was read.
15
16
The wake bit can be configured as an interrupt source. Support this
17
mechanism as well.
18
19
Co-developed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
20
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
21
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
22
Signed-off-by: Martin Kaiser <martin@kaiser.cx>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
23
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
24
---
11
target/arm/translate.h | 2 +-
25
include/hw/char/imx_serial.h | 1 +
12
target/arm/translate-a64.c | 2 +-
26
hw/char/imx_serial.c | 5 ++++-
13
target/arm/translate.c | 2 +-
27
2 files changed, 5 insertions(+), 1 deletion(-)
14
3 files changed, 3 insertions(+), 3 deletions(-)
15
28
16
diff --git a/target/arm/translate.h b/target/arm/translate.h
29
diff --git a/include/hw/char/imx_serial.h b/include/hw/char/imx_serial.h
17
index XXXXXXX..XXXXXXX 100644
30
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/translate.h
31
--- a/include/hw/char/imx_serial.h
19
+++ b/target/arm/translate.h
32
+++ b/include/hw/char/imx_serial.h
20
@@ -XXX,XX +XXX,XX @@ typedef struct DisasContext {
33
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_SIMPLE_TYPE(IMXSerialState, IMX_SERIAL)
21
* so that top level loop can generate correct syndrome information.
34
35
#define UCR4_DREN BIT(0) /* Receive Data Ready interrupt enable */
36
#define UCR4_TCEN BIT(3) /* TX complete interrupt enable */
37
+#define UCR4_WKEN BIT(7) /* WAKE interrupt enable */
38
39
#define UTS1_TXEMPTY (1<<6)
40
#define UTS1_RXEMPTY (1<<5)
41
diff --git a/hw/char/imx_serial.c b/hw/char/imx_serial.c
42
index XXXXXXX..XXXXXXX 100644
43
--- a/hw/char/imx_serial.c
44
+++ b/hw/char/imx_serial.c
45
@@ -XXX,XX +XXX,XX @@ static void imx_update(IMXSerialState *s)
46
* TCEN and TXDC are both bit 3
47
* RDR and DREN are both bit 0
22
*/
48
*/
23
uint32_t svc_imm;
49
- mask |= s->ucr4 & (UCR4_TCEN | UCR4_DREN);
24
- int aarch64;
50
+ mask |= s->ucr4 & (UCR4_WKEN | UCR4_TCEN | UCR4_DREN);
25
int current_el;
51
26
/* Debug target exception level for single-step exceptions */
52
usr2 = s->usr2 & mask;
27
int debug_target_el;
53
28
GHashTable *cp_regs;
54
@@ -XXX,XX +XXX,XX @@ static void imx_put_data(void *opaque, uint32_t value)
29
uint64_t features; /* CPU features bits */
55
30
+ bool aarch64;
56
static void imx_receive(void *opaque, const uint8_t *buf, int size)
31
/* Because unallocated encodings generate different exception syndrome
57
{
32
* information from traps due to FP being disabled, we can't do a single
58
+ IMXSerialState *s = (IMXSerialState *)opaque;
33
* "is fp access disabled" check at a high level in the decode tree.
59
+
34
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
60
+ s->usr2 |= USR2_WAKE;
35
index XXXXXXX..XXXXXXX 100644
61
imx_put_data(opaque, *buf);
36
--- a/target/arm/translate-a64.c
62
}
37
+++ b/target/arm/translate-a64.c
63
38
@@ -XXX,XX +XXX,XX @@ static void aarch64_tr_init_disas_context(DisasContextBase *dcbase,
39
dc->isar = &arm_cpu->isar;
40
dc->condjmp = 0;
41
42
- dc->aarch64 = 1;
43
+ dc->aarch64 = true;
44
/* If we are coming from secure EL0 in a system with a 32-bit EL3, then
45
* there is no secure EL1, so we route exceptions to EL3.
46
*/
47
diff --git a/target/arm/translate.c b/target/arm/translate.c
48
index XXXXXXX..XXXXXXX 100644
49
--- a/target/arm/translate.c
50
+++ b/target/arm/translate.c
51
@@ -XXX,XX +XXX,XX @@ static void arm_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
52
dc->isar = &cpu->isar;
53
dc->condjmp = 0;
54
55
- dc->aarch64 = 0;
56
+ dc->aarch64 = false;
57
/* If we are coming from secure EL0 in a system with a 32-bit EL3, then
58
* there is no secure EL1, so we route exceptions to EL3.
59
*/
60
--
64
--
61
2.25.1
65
2.34.1
62
66
63
67
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Marcin Juszkiewicz <marcin.juszkiewicz@linaro.org>
2
2
3
The length of the previous insn may be computed from
3
We plan to add more hardware information into DeviceTree to limit amount
4
the difference of start and end addresses.
4
of hardcoded values in firmware.
5
Use tcg_constant_i32 while we're at it.
6
5
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Marcin Juszkiewicz <marcin.juszkiewicz@linaro.org>
7
Message-id: 20230531171834.236569-1-marcin.juszkiewicz@linaro.org
8
[PMM: fix format nits, add text about platform version fields from
9
a comment in the C source file]
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
12
---
11
target/arm/translate.c | 12 ++++--------
13
docs/system/arm/sbsa.rst | 38 +++++++++++++++++++++++++++++++-------
12
1 file changed, 4 insertions(+), 8 deletions(-)
14
1 file changed, 31 insertions(+), 7 deletions(-)
13
15
14
diff --git a/target/arm/translate.c b/target/arm/translate.c
16
diff --git a/docs/system/arm/sbsa.rst b/docs/system/arm/sbsa.rst
15
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/translate.c
18
--- a/docs/system/arm/sbsa.rst
17
+++ b/target/arm/translate.c
19
+++ b/docs/system/arm/sbsa.rst
18
@@ -XXX,XX +XXX,XX @@ static void arm_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
20
@@ -XXX,XX +XXX,XX @@ any real hardware the ``sbsa-ref`` board intends to look like real
19
/* nothing more to generate */
21
hardware. The `Server Base System Architecture
20
break;
22
<https://developer.arm.com/documentation/den0029/latest>`_ defines a
21
case DISAS_WFI:
23
minimum base line of hardware support and importantly how the firmware
22
- {
24
-reports that to any operating system. It is a static system that
23
- TCGv_i32 tmp = tcg_const_i32((dc->thumb &&
25
-reports a very minimal DT to the firmware for non-discoverable
24
- !(dc->insn & (1U << 31))) ? 2 : 4);
26
-information about components affected by the qemu command line (i.e.
25
-
27
-cpus and memory). As a result it must have a firmware specifically
26
- gen_helper_wfi(cpu_env, tmp);
28
-built to expect a certain hardware layout (as you would in a real
27
- tcg_temp_free_i32(tmp);
29
-machine).
28
- /* The helper doesn't necessarily throw an exception, but we
30
+reports that to any operating system.
29
+ gen_helper_wfi(cpu_env,
31
30
+ tcg_constant_i32(dc->base.pc_next - dc->pc_curr));
32
It is intended to be a machine for developing firmware and testing
31
+ /*
33
standards compliance with operating systems.
32
+ * The helper doesn't necessarily throw an exception, but we
34
@@ -XXX,XX +XXX,XX @@ standards compliance with operating systems.
33
* must go back to the main loop to check for interrupts anyway.
35
Supported devices
34
*/
36
"""""""""""""""""
35
tcg_gen_exit_tb(NULL, 0);
37
36
break;
38
-The sbsa-ref board supports:
37
- }
39
+The ``sbsa-ref`` board supports:
38
case DISAS_WFE:
40
39
gen_helper_wfe(cpu_env);
41
- A configurable number of AArch64 CPUs
40
break;
42
- GIC version 3
43
@@ -XXX,XX +XXX,XX @@ The sbsa-ref board supports:
44
- Bochs display adapter on PCIe bus
45
- A generic SBSA watchdog device
46
47
+
48
+Board to firmware interface
49
+"""""""""""""""""""""""""""
50
+
51
+``sbsa-ref`` is a static system that reports a very minimal devicetree to the
52
+firmware for non-discoverable information about system components. This
53
+includes both internal hardware and parts affected by the qemu command line
54
+(i.e. CPUs and memory). As a result it must have a firmware specifically built
55
+to expect a certain hardware layout (as you would in a real machine).
56
+
57
+DeviceTree information
58
+''''''''''''''''''''''
59
+
60
+The devicetree provided by the board model to the firmware is not intended
61
+to be a complete compliant DT. It currently reports:
62
+
63
+ - CPUs
64
+ - memory
65
+ - platform version
66
+ - GIC addresses
67
+
68
+The platform version is only for informing platform firmware about
69
+what kind of ``sbsa-ref`` board it is running on. It is neither
70
+a QEMU versioned machine type nor a reflection of the level of the
71
+SBSA/SystemReady SR support provided.
72
+
73
+The ``machine-version-major`` value is updated when changes breaking
74
+fw compatibility are introduced. The ``machine-version-minor`` value
75
+is updated when features are added that don't break fw compatibility.
41
--
76
--
42
2.25.1
77
2.34.1
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Sergey Kambalin <sergey.kambalin@auriga.com>
2
2
3
Update SCTLR_ELx fields per ARM DDI0487 H.a.
3
Signed-off-by: Sergey Kambalin <sergey.kambalin@auriga.com>
4
4
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Acked-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
6
Message-id: 20230612223456.33824-2-philmd@linaro.org
7
Message-Id: <20230531155258.8361-1-sergey.kambalin@auriga.com>
8
[PMD: Split from bigger patch: 1/4]
9
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
---
11
---
9
target/arm/cpu.h | 14 ++++++++++++++
12
include/hw/misc/raspberrypi-fw-defs.h | 163 ++++++++++++++++++++++++++
10
1 file changed, 14 insertions(+)
13
1 file changed, 163 insertions(+)
14
create mode 100644 include/hw/misc/raspberrypi-fw-defs.h
11
15
12
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
16
diff --git a/include/hw/misc/raspberrypi-fw-defs.h b/include/hw/misc/raspberrypi-fw-defs.h
13
index XXXXXXX..XXXXXXX 100644
17
new file mode 100644
14
--- a/target/arm/cpu.h
18
index XXXXXXX..XXXXXXX
15
+++ b/target/arm/cpu.h
19
--- /dev/null
16
@@ -XXX,XX +XXX,XX @@ void pmu_init(ARMCPU *cpu);
20
+++ b/include/hw/misc/raspberrypi-fw-defs.h
17
#define SCTLR_ATA0 (1ULL << 42) /* v8.5-MemTag */
21
@@ -XXX,XX +XXX,XX @@
18
#define SCTLR_ATA (1ULL << 43) /* v8.5-MemTag */
22
+/*
19
#define SCTLR_DSSBS_64 (1ULL << 44) /* v8.5, AArch64 only */
23
+ * Raspberry Pi firmware definitions
20
+#define SCTLR_TWEDEn (1ULL << 45) /* FEAT_TWED */
24
+ *
21
+#define SCTLR_TWEDEL MAKE_64_MASK(46, 4) /* FEAT_TWED */
25
+ * Copyright (C) 2022 Auriga LLC, based on Linux kernel
22
+#define SCTLR_TMT0 (1ULL << 50) /* FEAT_TME */
26
+ * `include/soc/bcm2835/raspberrypi-firmware.h` (Copyright © 2015 Broadcom)
23
+#define SCTLR_TMT (1ULL << 51) /* FEAT_TME */
27
+ *
24
+#define SCTLR_TME0 (1ULL << 52) /* FEAT_TME */
28
+ * SPDX-License-Identifier: GPL-2.0-or-later
25
+#define SCTLR_TME (1ULL << 53) /* FEAT_TME */
29
+ */
26
+#define SCTLR_EnASR (1ULL << 54) /* FEAT_LS64_V */
30
+
27
+#define SCTLR_EnAS0 (1ULL << 55) /* FEAT_LS64_ACCDATA */
31
+#ifndef INCLUDE_HW_MISC_RASPBERRYPI_FW_DEFS_H_
28
+#define SCTLR_EnALS (1ULL << 56) /* FEAT_LS64 */
32
+#define INCLUDE_HW_MISC_RASPBERRYPI_FW_DEFS_H_
29
+#define SCTLR_EPAN (1ULL << 57) /* FEAT_PAN3 */
33
+
30
+#define SCTLR_EnTP2 (1ULL << 60) /* FEAT_SME */
34
+#include "qemu/osdep.h"
31
+#define SCTLR_NMI (1ULL << 61) /* FEAT_NMI */
35
+
32
+#define SCTLR_SPINTMASK (1ULL << 62) /* FEAT_NMI */
36
+enum rpi_firmware_property_tag {
33
+#define SCTLR_TIDCP (1ULL << 63) /* FEAT_TIDCP1 */
37
+ RPI_FWREQ_PROPERTY_END = 0,
34
38
+ RPI_FWREQ_GET_FIRMWARE_REVISION = 0x00000001,
35
#define CPTR_TCPAC (1U << 31)
39
+ RPI_FWREQ_GET_FIRMWARE_VARIANT = 0x00000002,
36
#define CPTR_TTA (1U << 20)
40
+ RPI_FWREQ_GET_FIRMWARE_HASH = 0x00000003,
41
+
42
+ RPI_FWREQ_SET_CURSOR_INFO = 0x00008010,
43
+ RPI_FWREQ_SET_CURSOR_STATE = 0x00008011,
44
+
45
+ RPI_FWREQ_GET_BOARD_MODEL = 0x00010001,
46
+ RPI_FWREQ_GET_BOARD_REVISION = 0x00010002,
47
+ RPI_FWREQ_GET_BOARD_MAC_ADDRESS = 0x00010003,
48
+ RPI_FWREQ_GET_BOARD_SERIAL = 0x00010004,
49
+ RPI_FWREQ_GET_ARM_MEMORY = 0x00010005,
50
+ RPI_FWREQ_GET_VC_MEMORY = 0x00010006,
51
+ RPI_FWREQ_GET_CLOCKS = 0x00010007,
52
+ RPI_FWREQ_GET_POWER_STATE = 0x00020001,
53
+ RPI_FWREQ_GET_TIMING = 0x00020002,
54
+ RPI_FWREQ_SET_POWER_STATE = 0x00028001,
55
+ RPI_FWREQ_GET_CLOCK_STATE = 0x00030001,
56
+ RPI_FWREQ_GET_CLOCK_RATE = 0x00030002,
57
+ RPI_FWREQ_GET_VOLTAGE = 0x00030003,
58
+ RPI_FWREQ_GET_MAX_CLOCK_RATE = 0x00030004,
59
+ RPI_FWREQ_GET_MAX_VOLTAGE = 0x00030005,
60
+ RPI_FWREQ_GET_TEMPERATURE = 0x00030006,
61
+ RPI_FWREQ_GET_MIN_CLOCK_RATE = 0x00030007,
62
+ RPI_FWREQ_GET_MIN_VOLTAGE = 0x00030008,
63
+ RPI_FWREQ_GET_TURBO = 0x00030009,
64
+ RPI_FWREQ_GET_MAX_TEMPERATURE = 0x0003000a,
65
+ RPI_FWREQ_GET_STC = 0x0003000b,
66
+ RPI_FWREQ_ALLOCATE_MEMORY = 0x0003000c,
67
+ RPI_FWREQ_LOCK_MEMORY = 0x0003000d,
68
+ RPI_FWREQ_UNLOCK_MEMORY = 0x0003000e,
69
+ RPI_FWREQ_RELEASE_MEMORY = 0x0003000f,
70
+ RPI_FWREQ_EXECUTE_CODE = 0x00030010,
71
+ RPI_FWREQ_EXECUTE_QPU = 0x00030011,
72
+ RPI_FWREQ_SET_ENABLE_QPU = 0x00030012,
73
+ RPI_FWREQ_GET_DISPMANX_RESOURCE_MEM_HANDLE = 0x00030014,
74
+ RPI_FWREQ_GET_EDID_BLOCK = 0x00030020,
75
+ RPI_FWREQ_GET_CUSTOMER_OTP = 0x00030021,
76
+ RPI_FWREQ_GET_EDID_BLOCK_DISPLAY = 0x00030023,
77
+ RPI_FWREQ_GET_DOMAIN_STATE = 0x00030030,
78
+ RPI_FWREQ_GET_THROTTLED = 0x00030046,
79
+ RPI_FWREQ_GET_CLOCK_MEASURED = 0x00030047,
80
+ RPI_FWREQ_NOTIFY_REBOOT = 0x00030048,
81
+ RPI_FWREQ_SET_CLOCK_STATE = 0x00038001,
82
+ RPI_FWREQ_SET_CLOCK_RATE = 0x00038002,
83
+ RPI_FWREQ_SET_VOLTAGE = 0x00038003,
84
+ RPI_FWREQ_SET_MAX_CLOCK_RATE = 0x00038004,
85
+ RPI_FWREQ_SET_MIN_CLOCK_RATE = 0x00038007,
86
+ RPI_FWREQ_SET_TURBO = 0x00038009,
87
+ RPI_FWREQ_SET_CUSTOMER_OTP = 0x00038021,
88
+ RPI_FWREQ_SET_DOMAIN_STATE = 0x00038030,
89
+ RPI_FWREQ_GET_GPIO_STATE = 0x00030041,
90
+ RPI_FWREQ_SET_GPIO_STATE = 0x00038041,
91
+ RPI_FWREQ_SET_SDHOST_CLOCK = 0x00038042,
92
+ RPI_FWREQ_GET_GPIO_CONFIG = 0x00030043,
93
+ RPI_FWREQ_SET_GPIO_CONFIG = 0x00038043,
94
+ RPI_FWREQ_GET_PERIPH_REG = 0x00030045,
95
+ RPI_FWREQ_SET_PERIPH_REG = 0x00038045,
96
+ RPI_FWREQ_GET_POE_HAT_VAL = 0x00030049,
97
+ RPI_FWREQ_SET_POE_HAT_VAL = 0x00038049,
98
+ RPI_FWREQ_SET_POE_HAT_VAL_OLD = 0x00030050,
99
+ RPI_FWREQ_NOTIFY_XHCI_RESET = 0x00030058,
100
+ RPI_FWREQ_GET_REBOOT_FLAGS = 0x00030064,
101
+ RPI_FWREQ_SET_REBOOT_FLAGS = 0x00038064,
102
+ RPI_FWREQ_NOTIFY_DISPLAY_DONE = 0x00030066,
103
+
104
+ /* Dispmanx TAGS */
105
+ RPI_FWREQ_FRAMEBUFFER_ALLOCATE = 0x00040001,
106
+ RPI_FWREQ_FRAMEBUFFER_BLANK = 0x00040002,
107
+ RPI_FWREQ_FRAMEBUFFER_GET_PHYSICAL_WIDTH_HEIGHT = 0x00040003,
108
+ RPI_FWREQ_FRAMEBUFFER_GET_VIRTUAL_WIDTH_HEIGHT = 0x00040004,
109
+ RPI_FWREQ_FRAMEBUFFER_GET_DEPTH = 0x00040005,
110
+ RPI_FWREQ_FRAMEBUFFER_GET_PIXEL_ORDER = 0x00040006,
111
+ RPI_FWREQ_FRAMEBUFFER_GET_ALPHA_MODE = 0x00040007,
112
+ RPI_FWREQ_FRAMEBUFFER_GET_PITCH = 0x00040008,
113
+ RPI_FWREQ_FRAMEBUFFER_GET_VIRTUAL_OFFSET = 0x00040009,
114
+ RPI_FWREQ_FRAMEBUFFER_GET_OVERSCAN = 0x0004000a,
115
+ RPI_FWREQ_FRAMEBUFFER_GET_PALETTE = 0x0004000b,
116
+ RPI_FWREQ_FRAMEBUFFER_GET_LAYER = 0x0004000c,
117
+ RPI_FWREQ_FRAMEBUFFER_GET_TRANSFORM = 0x0004000d,
118
+ RPI_FWREQ_FRAMEBUFFER_GET_VSYNC = 0x0004000e,
119
+ RPI_FWREQ_FRAMEBUFFER_GET_TOUCHBUF = 0x0004000f,
120
+ RPI_FWREQ_FRAMEBUFFER_GET_GPIOVIRTBUF = 0x00040010,
121
+ RPI_FWREQ_FRAMEBUFFER_RELEASE = 0x00048001,
122
+ RPI_FWREQ_FRAMEBUFFER_GET_DISPLAY_ID = 0x00040016,
123
+ RPI_FWREQ_FRAMEBUFFER_SET_DISPLAY_NUM = 0x00048013,
124
+ RPI_FWREQ_FRAMEBUFFER_GET_NUM_DISPLAYS = 0x00040013,
125
+ RPI_FWREQ_FRAMEBUFFER_GET_DISPLAY_SETTINGS = 0x00040014,
126
+ RPI_FWREQ_FRAMEBUFFER_TEST_PHYSICAL_WIDTH_HEIGHT = 0x00044003,
127
+ RPI_FWREQ_FRAMEBUFFER_TEST_VIRTUAL_WIDTH_HEIGHT = 0x00044004,
128
+ RPI_FWREQ_FRAMEBUFFER_TEST_DEPTH = 0x00044005,
129
+ RPI_FWREQ_FRAMEBUFFER_TEST_PIXEL_ORDER = 0x00044006,
130
+ RPI_FWREQ_FRAMEBUFFER_TEST_ALPHA_MODE = 0x00044007,
131
+ RPI_FWREQ_FRAMEBUFFER_TEST_VIRTUAL_OFFSET = 0x00044009,
132
+ RPI_FWREQ_FRAMEBUFFER_TEST_OVERSCAN = 0x0004400a,
133
+ RPI_FWREQ_FRAMEBUFFER_TEST_PALETTE = 0x0004400b,
134
+ RPI_FWREQ_FRAMEBUFFER_TEST_LAYER = 0x0004400c,
135
+ RPI_FWREQ_FRAMEBUFFER_TEST_TRANSFORM = 0x0004400d,
136
+ RPI_FWREQ_FRAMEBUFFER_TEST_VSYNC = 0x0004400e,
137
+ RPI_FWREQ_FRAMEBUFFER_SET_PHYSICAL_WIDTH_HEIGHT = 0x00048003,
138
+ RPI_FWREQ_FRAMEBUFFER_SET_VIRTUAL_WIDTH_HEIGHT = 0x00048004,
139
+ RPI_FWREQ_FRAMEBUFFER_SET_DEPTH = 0x00048005,
140
+ RPI_FWREQ_FRAMEBUFFER_SET_PIXEL_ORDER = 0x00048006,
141
+ RPI_FWREQ_FRAMEBUFFER_SET_ALPHA_MODE = 0x00048007,
142
+ RPI_FWREQ_FRAMEBUFFER_SET_PITCH = 0x00048008,
143
+ RPI_FWREQ_FRAMEBUFFER_SET_VIRTUAL_OFFSET = 0x00048009,
144
+ RPI_FWREQ_FRAMEBUFFER_SET_OVERSCAN = 0x0004800a,
145
+ RPI_FWREQ_FRAMEBUFFER_SET_PALETTE = 0x0004800b,
146
+
147
+ RPI_FWREQ_FRAMEBUFFER_SET_TOUCHBUF = 0x0004801f,
148
+ RPI_FWREQ_FRAMEBUFFER_SET_GPIOVIRTBUF = 0x00048020,
149
+ RPI_FWREQ_FRAMEBUFFER_SET_VSYNC = 0x0004800e,
150
+ RPI_FWREQ_FRAMEBUFFER_SET_LAYER = 0x0004800c,
151
+ RPI_FWREQ_FRAMEBUFFER_SET_TRANSFORM = 0x0004800d,
152
+ RPI_FWREQ_FRAMEBUFFER_SET_BACKLIGHT = 0x0004800f,
153
+
154
+ RPI_FWREQ_VCHIQ_INIT = 0x00048010,
155
+
156
+ RPI_FWREQ_SET_PLANE = 0x00048015,
157
+ RPI_FWREQ_GET_DISPLAY_TIMING = 0x00040017,
158
+ RPI_FWREQ_SET_TIMING = 0x00048017,
159
+ RPI_FWREQ_GET_DISPLAY_CFG = 0x00040018,
160
+ RPI_FWREQ_SET_DISPLAY_POWER = 0x00048019,
161
+ RPI_FWREQ_GET_COMMAND_LINE = 0x00050001,
162
+ RPI_FWREQ_GET_DMA_CHANNELS = 0x00060001,
163
+};
164
+
165
+enum rpi_firmware_clk_id {
166
+ RPI_FIRMWARE_EMMC_CLK_ID = 1,
167
+ RPI_FIRMWARE_UART_CLK_ID,
168
+ RPI_FIRMWARE_ARM_CLK_ID,
169
+ RPI_FIRMWARE_CORE_CLK_ID,
170
+ RPI_FIRMWARE_V3D_CLK_ID,
171
+ RPI_FIRMWARE_H264_CLK_ID,
172
+ RPI_FIRMWARE_ISP_CLK_ID,
173
+ RPI_FIRMWARE_SDRAM_CLK_ID,
174
+ RPI_FIRMWARE_PIXEL_CLK_ID,
175
+ RPI_FIRMWARE_PWM_CLK_ID,
176
+ RPI_FIRMWARE_HEVC_CLK_ID,
177
+ RPI_FIRMWARE_EMMC2_CLK_ID,
178
+ RPI_FIRMWARE_M2MC_CLK_ID,
179
+ RPI_FIRMWARE_PIXEL_BVB_CLK_ID,
180
+ RPI_FIRMWARE_VEC_CLK_ID,
181
+ RPI_FIRMWARE_NUM_CLK_ID,
182
+};
183
+
184
+#endif /* INCLUDE_HW_MISC_RASPBERRYPI_FW_DEFS_H_ */
37
--
185
--
38
2.25.1
186
2.34.1
39
187
40
188
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Sergey Kambalin <sergey.kambalin@auriga.com>
2
2
3
Use tcg_gen_umin_i32 instead of tcg_gen_movcond_i32.
3
Replace magic property values by a proper definition,
4
Use tcg_constant_i32 while we're at it.
4
removing redundant comments.
5
5
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Sergey Kambalin <sergey.kambalin@auriga.com>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20230612223456.33824-3-philmd@linaro.org
10
Message-Id: <20230531155258.8361-1-sergey.kambalin@auriga.com>
11
[PMD: Split from bigger patch: 2/4]
12
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
14
---
10
target/arm/translate.c | 8 +++-----
15
hw/misc/bcm2835_property.c | 101 +++++++++++++++++++------------------
11
1 file changed, 3 insertions(+), 5 deletions(-)
16
1 file changed, 51 insertions(+), 50 deletions(-)
12
17
13
diff --git a/target/arm/translate.c b/target/arm/translate.c
18
diff --git a/hw/misc/bcm2835_property.c b/hw/misc/bcm2835_property.c
14
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/translate.c
20
--- a/hw/misc/bcm2835_property.c
16
+++ b/target/arm/translate.c
21
+++ b/hw/misc/bcm2835_property.c
17
@@ -XXX,XX +XXX,XX @@ GEN_SHIFT(shr)
22
@@ -XXX,XX +XXX,XX @@
18
23
#include "migration/vmstate.h"
19
static void gen_sar(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
24
#include "hw/irq.h"
20
{
25
#include "hw/misc/bcm2835_mbox_defs.h"
21
- TCGv_i32 tmp1, tmp2;
26
+#include "hw/misc/raspberrypi-fw-defs.h"
22
- tmp1 = tcg_temp_new_i32();
27
#include "sysemu/dma.h"
23
+ TCGv_i32 tmp1 = tcg_temp_new_i32();
28
#include "qemu/log.h"
24
+
29
#include "qemu/module.h"
25
tcg_gen_andi_i32(tmp1, t1, 0xff);
30
@@ -XXX,XX +XXX,XX @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
26
- tmp2 = tcg_const_i32(0x1f);
31
/* @(value + 8) : Request/response indicator */
27
- tcg_gen_movcond_i32(TCG_COND_GTU, tmp1, tmp1, tmp2, tmp2, tmp1);
32
resplen = 0;
28
- tcg_temp_free_i32(tmp2);
33
switch (tag) {
29
+ tcg_gen_umin_i32(tmp1, tmp1, tcg_constant_i32(31));
34
- case 0x00000000: /* End tag */
30
tcg_gen_sar_i32(dest, t0, tmp1);
35
+ case RPI_FWREQ_PROPERTY_END:
31
tcg_temp_free_i32(tmp1);
36
break;
32
}
37
- case 0x00000001: /* Get firmware revision */
38
+ case RPI_FWREQ_GET_FIRMWARE_REVISION:
39
stl_le_phys(&s->dma_as, value + 12, 346337);
40
resplen = 4;
41
break;
42
- case 0x00010001: /* Get board model */
43
+ case RPI_FWREQ_GET_BOARD_MODEL:
44
qemu_log_mask(LOG_UNIMP,
45
"bcm2835_property: 0x%08x get board model NYI\n",
46
tag);
47
resplen = 4;
48
break;
49
- case 0x00010002: /* Get board revision */
50
+ case RPI_FWREQ_GET_BOARD_REVISION:
51
stl_le_phys(&s->dma_as, value + 12, s->board_rev);
52
resplen = 4;
53
break;
54
- case 0x00010003: /* Get board MAC address */
55
+ case RPI_FWREQ_GET_BOARD_MAC_ADDRESS:
56
resplen = sizeof(s->macaddr.a);
57
dma_memory_write(&s->dma_as, value + 12, s->macaddr.a, resplen,
58
MEMTXATTRS_UNSPECIFIED);
59
break;
60
- case 0x00010004: /* Get board serial */
61
+ case RPI_FWREQ_GET_BOARD_SERIAL:
62
qemu_log_mask(LOG_UNIMP,
63
"bcm2835_property: 0x%08x get board serial NYI\n",
64
tag);
65
resplen = 8;
66
break;
67
- case 0x00010005: /* Get ARM memory */
68
+ case RPI_FWREQ_GET_ARM_MEMORY:
69
/* base */
70
stl_le_phys(&s->dma_as, value + 12, 0);
71
/* size */
72
stl_le_phys(&s->dma_as, value + 16, s->fbdev->vcram_base);
73
resplen = 8;
74
break;
75
- case 0x00010006: /* Get VC memory */
76
+ case RPI_FWREQ_GET_VC_MEMORY:
77
/* base */
78
stl_le_phys(&s->dma_as, value + 12, s->fbdev->vcram_base);
79
/* size */
80
stl_le_phys(&s->dma_as, value + 16, s->fbdev->vcram_size);
81
resplen = 8;
82
break;
83
- case 0x00028001: /* Set power state */
84
+ case RPI_FWREQ_SET_POWER_STATE:
85
/* Assume that whatever device they asked for exists,
86
* and we'll just claim we set it to the desired state
87
*/
88
@@ -XXX,XX +XXX,XX @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
89
90
/* Clocks */
91
92
- case 0x00030001: /* Get clock state */
93
+ case RPI_FWREQ_GET_CLOCK_STATE:
94
stl_le_phys(&s->dma_as, value + 16, 0x1);
95
resplen = 8;
96
break;
97
98
- case 0x00038001: /* Set clock state */
99
+ case RPI_FWREQ_SET_CLOCK_STATE:
100
qemu_log_mask(LOG_UNIMP,
101
"bcm2835_property: 0x%08x set clock state NYI\n",
102
tag);
103
resplen = 8;
104
break;
105
106
- case 0x00030002: /* Get clock rate */
107
- case 0x00030004: /* Get max clock rate */
108
- case 0x00030007: /* Get min clock rate */
109
+ case RPI_FWREQ_GET_CLOCK_RATE:
110
+ case RPI_FWREQ_GET_MAX_CLOCK_RATE:
111
+ case RPI_FWREQ_GET_MIN_CLOCK_RATE:
112
switch (ldl_le_phys(&s->dma_as, value + 12)) {
113
- case 1: /* EMMC */
114
+ case RPI_FIRMWARE_EMMC_CLK_ID:
115
stl_le_phys(&s->dma_as, value + 16, 50000000);
116
break;
117
- case 2: /* UART */
118
+ case RPI_FIRMWARE_UART_CLK_ID:
119
stl_le_phys(&s->dma_as, value + 16, 3000000);
120
break;
121
default:
122
@@ -XXX,XX +XXX,XX @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
123
resplen = 8;
124
break;
125
126
- case 0x00038002: /* Set clock rate */
127
- case 0x00038004: /* Set max clock rate */
128
- case 0x00038007: /* Set min clock rate */
129
+ case RPI_FWREQ_SET_CLOCK_RATE:
130
+ case RPI_FWREQ_SET_MAX_CLOCK_RATE:
131
+ case RPI_FWREQ_SET_MIN_CLOCK_RATE:
132
qemu_log_mask(LOG_UNIMP,
133
"bcm2835_property: 0x%08x set clock rate NYI\n",
134
tag);
135
@@ -XXX,XX +XXX,XX @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
136
137
/* Temperature */
138
139
- case 0x00030006: /* Get temperature */
140
+ case RPI_FWREQ_GET_TEMPERATURE:
141
stl_le_phys(&s->dma_as, value + 16, 25000);
142
resplen = 8;
143
break;
144
145
- case 0x0003000A: /* Get max temperature */
146
+ case RPI_FWREQ_GET_MAX_TEMPERATURE:
147
stl_le_phys(&s->dma_as, value + 16, 99000);
148
resplen = 8;
149
break;
150
151
/* Frame buffer */
152
153
- case 0x00040001: /* Allocate buffer */
154
+ case RPI_FWREQ_FRAMEBUFFER_ALLOCATE:
155
stl_le_phys(&s->dma_as, value + 12, fbconfig.base);
156
stl_le_phys(&s->dma_as, value + 16,
157
bcm2835_fb_get_size(&fbconfig));
158
resplen = 8;
159
break;
160
- case 0x00048001: /* Release buffer */
161
+ case RPI_FWREQ_FRAMEBUFFER_RELEASE:
162
resplen = 0;
163
break;
164
- case 0x00040002: /* Blank screen */
165
+ case RPI_FWREQ_FRAMEBUFFER_BLANK:
166
resplen = 4;
167
break;
168
- case 0x00044003: /* Test physical display width/height */
169
- case 0x00044004: /* Test virtual display width/height */
170
+ case RPI_FWREQ_FRAMEBUFFER_TEST_PHYSICAL_WIDTH_HEIGHT:
171
+ case RPI_FWREQ_FRAMEBUFFER_TEST_VIRTUAL_WIDTH_HEIGHT:
172
resplen = 8;
173
break;
174
- case 0x00048003: /* Set physical display width/height */
175
+ case RPI_FWREQ_FRAMEBUFFER_SET_PHYSICAL_WIDTH_HEIGHT:
176
fbconfig.xres = ldl_le_phys(&s->dma_as, value + 12);
177
fbconfig.yres = ldl_le_phys(&s->dma_as, value + 16);
178
bcm2835_fb_validate_config(&fbconfig);
179
fbconfig_updated = true;
180
/* fall through */
181
- case 0x00040003: /* Get physical display width/height */
182
+ case RPI_FWREQ_FRAMEBUFFER_GET_PHYSICAL_WIDTH_HEIGHT:
183
stl_le_phys(&s->dma_as, value + 12, fbconfig.xres);
184
stl_le_phys(&s->dma_as, value + 16, fbconfig.yres);
185
resplen = 8;
186
break;
187
- case 0x00048004: /* Set virtual display width/height */
188
+ case RPI_FWREQ_FRAMEBUFFER_SET_VIRTUAL_WIDTH_HEIGHT:
189
fbconfig.xres_virtual = ldl_le_phys(&s->dma_as, value + 12);
190
fbconfig.yres_virtual = ldl_le_phys(&s->dma_as, value + 16);
191
bcm2835_fb_validate_config(&fbconfig);
192
fbconfig_updated = true;
193
/* fall through */
194
- case 0x00040004: /* Get virtual display width/height */
195
+ case RPI_FWREQ_FRAMEBUFFER_GET_VIRTUAL_WIDTH_HEIGHT:
196
stl_le_phys(&s->dma_as, value + 12, fbconfig.xres_virtual);
197
stl_le_phys(&s->dma_as, value + 16, fbconfig.yres_virtual);
198
resplen = 8;
199
break;
200
- case 0x00044005: /* Test depth */
201
+ case RPI_FWREQ_FRAMEBUFFER_TEST_DEPTH:
202
resplen = 4;
203
break;
204
- case 0x00048005: /* Set depth */
205
+ case RPI_FWREQ_FRAMEBUFFER_SET_DEPTH:
206
fbconfig.bpp = ldl_le_phys(&s->dma_as, value + 12);
207
bcm2835_fb_validate_config(&fbconfig);
208
fbconfig_updated = true;
209
/* fall through */
210
- case 0x00040005: /* Get depth */
211
+ case RPI_FWREQ_FRAMEBUFFER_GET_DEPTH:
212
stl_le_phys(&s->dma_as, value + 12, fbconfig.bpp);
213
resplen = 4;
214
break;
215
- case 0x00044006: /* Test pixel order */
216
+ case RPI_FWREQ_FRAMEBUFFER_TEST_PIXEL_ORDER:
217
resplen = 4;
218
break;
219
- case 0x00048006: /* Set pixel order */
220
+ case RPI_FWREQ_FRAMEBUFFER_SET_PIXEL_ORDER:
221
fbconfig.pixo = ldl_le_phys(&s->dma_as, value + 12);
222
bcm2835_fb_validate_config(&fbconfig);
223
fbconfig_updated = true;
224
/* fall through */
225
- case 0x00040006: /* Get pixel order */
226
+ case RPI_FWREQ_FRAMEBUFFER_GET_PIXEL_ORDER:
227
stl_le_phys(&s->dma_as, value + 12, fbconfig.pixo);
228
resplen = 4;
229
break;
230
- case 0x00044007: /* Test pixel alpha */
231
+ case RPI_FWREQ_FRAMEBUFFER_TEST_ALPHA_MODE:
232
resplen = 4;
233
break;
234
- case 0x00048007: /* Set alpha */
235
+ case RPI_FWREQ_FRAMEBUFFER_SET_ALPHA_MODE:
236
fbconfig.alpha = ldl_le_phys(&s->dma_as, value + 12);
237
bcm2835_fb_validate_config(&fbconfig);
238
fbconfig_updated = true;
239
/* fall through */
240
- case 0x00040007: /* Get alpha */
241
+ case RPI_FWREQ_FRAMEBUFFER_GET_ALPHA_MODE:
242
stl_le_phys(&s->dma_as, value + 12, fbconfig.alpha);
243
resplen = 4;
244
break;
245
- case 0x00040008: /* Get pitch */
246
+ case RPI_FWREQ_FRAMEBUFFER_GET_PITCH:
247
stl_le_phys(&s->dma_as, value + 12,
248
bcm2835_fb_get_pitch(&fbconfig));
249
resplen = 4;
250
break;
251
- case 0x00044009: /* Test virtual offset */
252
+ case RPI_FWREQ_FRAMEBUFFER_TEST_VIRTUAL_OFFSET:
253
resplen = 8;
254
break;
255
- case 0x00048009: /* Set virtual offset */
256
+ case RPI_FWREQ_FRAMEBUFFER_SET_VIRTUAL_OFFSET:
257
fbconfig.xoffset = ldl_le_phys(&s->dma_as, value + 12);
258
fbconfig.yoffset = ldl_le_phys(&s->dma_as, value + 16);
259
bcm2835_fb_validate_config(&fbconfig);
260
fbconfig_updated = true;
261
/* fall through */
262
- case 0x00040009: /* Get virtual offset */
263
+ case RPI_FWREQ_FRAMEBUFFER_GET_VIRTUAL_OFFSET:
264
stl_le_phys(&s->dma_as, value + 12, fbconfig.xoffset);
265
stl_le_phys(&s->dma_as, value + 16, fbconfig.yoffset);
266
resplen = 8;
267
break;
268
- case 0x0004000a: /* Get/Test/Set overscan */
269
- case 0x0004400a:
270
- case 0x0004800a:
271
+ case RPI_FWREQ_FRAMEBUFFER_GET_OVERSCAN:
272
+ case RPI_FWREQ_FRAMEBUFFER_TEST_OVERSCAN:
273
+ case RPI_FWREQ_FRAMEBUFFER_SET_OVERSCAN:
274
stl_le_phys(&s->dma_as, value + 12, 0);
275
stl_le_phys(&s->dma_as, value + 16, 0);
276
stl_le_phys(&s->dma_as, value + 20, 0);
277
stl_le_phys(&s->dma_as, value + 24, 0);
278
resplen = 16;
279
break;
280
- case 0x0004800b: /* Set palette */
281
+ case RPI_FWREQ_FRAMEBUFFER_SET_PALETTE:
282
offset = ldl_le_phys(&s->dma_as, value + 12);
283
length = ldl_le_phys(&s->dma_as, value + 16);
284
n = 0;
285
@@ -XXX,XX +XXX,XX @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
286
stl_le_phys(&s->dma_as, value + 12, 0);
287
resplen = 4;
288
break;
289
- case 0x00040013: /* Get number of displays */
290
+ case RPI_FWREQ_FRAMEBUFFER_GET_NUM_DISPLAYS:
291
stl_le_phys(&s->dma_as, value + 12, 1);
292
resplen = 4;
293
break;
294
295
- case 0x00060001: /* Get DMA channels */
296
+ case RPI_FWREQ_GET_DMA_CHANNELS:
297
/* channels 2-5 */
298
stl_le_phys(&s->dma_as, value + 12, 0x003C);
299
resplen = 4;
300
break;
301
302
- case 0x00050001: /* Get command line */
303
+ case RPI_FWREQ_GET_COMMAND_LINE:
304
/*
305
* We follow the firmware behaviour: no NUL terminator is
306
* written to the buffer, and if the buffer is too short
33
--
307
--
34
2.25.1
308
2.34.1
309
310
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Sergey Kambalin <sergey.kambalin@auriga.com>
2
2
3
Update SCR_EL3 fields per ARM DDI0487 H.a.
3
Signed-off-by: Sergey Kambalin <sergey.kambalin@auriga.com>
4
4
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
6
Message-id: 20230612223456.33824-4-philmd@linaro.org
7
Message-Id: <20230531155258.8361-1-sergey.kambalin@auriga.com>
8
[PMD: Split from bigger patch: 4/4]
9
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
---
11
---
9
target/arm/cpu.h | 12 ++++++++++++
12
include/hw/arm/raspi_platform.h | 5 +++++
10
1 file changed, 12 insertions(+)
13
hw/misc/bcm2835_property.c | 8 +++++---
14
2 files changed, 10 insertions(+), 3 deletions(-)
11
15
12
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
16
diff --git a/include/hw/arm/raspi_platform.h b/include/hw/arm/raspi_platform.h
13
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/cpu.h
18
--- a/include/hw/arm/raspi_platform.h
15
+++ b/target/arm/cpu.h
19
+++ b/include/hw/arm/raspi_platform.h
16
@@ -XXX,XX +XXX,XX @@ static inline void xpsr_write(CPUARMState *env, uint32_t val, uint32_t mask)
20
@@ -XXX,XX +XXX,XX @@
17
#define SCR_FIEN (1U << 21)
21
#define INTERRUPT_ILLEGAL_TYPE0 6
18
#define SCR_ENSCXT (1U << 25)
22
#define INTERRUPT_ILLEGAL_TYPE1 7
19
#define SCR_ATA (1U << 26)
23
20
+#define SCR_FGTEN (1U << 27)
24
+/* Clock rates */
21
+#define SCR_ECVEN (1U << 28)
25
+#define RPI_FIRMWARE_EMMC_CLK_RATE 50000000
22
+#define SCR_TWEDEN (1U << 29)
26
+#define RPI_FIRMWARE_UART_CLK_RATE 3000000
23
+#define SCR_TWEDEL MAKE_64BIT_MASK(30, 4)
27
+#define RPI_FIRMWARE_DEFAULT_CLK_RATE 700000000
24
+#define SCR_TME (1ULL << 34)
28
+
25
+#define SCR_AMVOFFEN (1ULL << 35)
29
#endif
26
+#define SCR_ENAS0 (1ULL << 36)
30
diff --git a/hw/misc/bcm2835_property.c b/hw/misc/bcm2835_property.c
27
+#define SCR_ADEN (1ULL << 37)
31
index XXXXXXX..XXXXXXX 100644
28
+#define SCR_HXEN (1ULL << 38)
32
--- a/hw/misc/bcm2835_property.c
29
+#define SCR_TRNDR (1ULL << 40)
33
+++ b/hw/misc/bcm2835_property.c
30
+#define SCR_ENTP2 (1ULL << 41)
34
@@ -XXX,XX +XXX,XX @@
31
+#define SCR_GPF (1ULL << 48)
35
#include "qemu/log.h"
32
36
#include "qemu/module.h"
33
#define HSTR_TTEE (1 << 16)
37
#include "trace.h"
34
#define HSTR_TJDBX (1 << 17)
38
+#include "hw/arm/raspi_platform.h"
39
40
/* https://github.com/raspberrypi/firmware/wiki/Mailbox-property-interface */
41
42
@@ -XXX,XX +XXX,XX @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
43
case RPI_FWREQ_GET_MIN_CLOCK_RATE:
44
switch (ldl_le_phys(&s->dma_as, value + 12)) {
45
case RPI_FIRMWARE_EMMC_CLK_ID:
46
- stl_le_phys(&s->dma_as, value + 16, 50000000);
47
+ stl_le_phys(&s->dma_as, value + 16, RPI_FIRMWARE_EMMC_CLK_RATE);
48
break;
49
case RPI_FIRMWARE_UART_CLK_ID:
50
- stl_le_phys(&s->dma_as, value + 16, 3000000);
51
+ stl_le_phys(&s->dma_as, value + 16, RPI_FIRMWARE_UART_CLK_RATE);
52
break;
53
default:
54
- stl_le_phys(&s->dma_as, value + 16, 700000000);
55
+ stl_le_phys(&s->dma_as, value + 16,
56
+ RPI_FIRMWARE_DEFAULT_CLK_RATE);
57
break;
58
}
59
resplen = 8;
35
--
60
--
36
2.25.1
61
2.34.1
37
62
38
63
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Sergey Kambalin <sergey.kambalin@auriga.com>
2
2
3
Update isar fields per ARM DDI0487 H.a.
3
Signed-off-by: Sergey Kambalin <sergey.kambalin@auriga.com>
4
4
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
5
Message-id: 20230612223456.33824-5-philmd@linaro.org
6
Message-Id: <20230531155258.8361-1-sergey.kambalin@auriga.com>
7
[PMD: Split from bigger patch: 3/4]
8
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
9
[PMM: added a comment about RPI_FIRMWARE_CORE_CLK_RATE
10
really being SoC-specific]
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
13
---
10
target/arm/cpu.h | 24 ++++++++++++++++++++++++
14
include/hw/arm/raspi_platform.h | 5 +++++
11
1 file changed, 24 insertions(+)
15
hw/misc/bcm2835_property.c | 3 +++
16
2 files changed, 8 insertions(+)
12
17
13
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
18
diff --git a/include/hw/arm/raspi_platform.h b/include/hw/arm/raspi_platform.h
14
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/cpu.h
20
--- a/include/hw/arm/raspi_platform.h
16
+++ b/target/arm/cpu.h
21
+++ b/include/hw/arm/raspi_platform.h
17
@@ -XXX,XX +XXX,XX @@ FIELD(ID_MMFR4, CCIDX, 24, 4)
22
@@ -XXX,XX +XXX,XX @@
18
FIELD(ID_MMFR4, EVT, 28, 4)
23
/* Clock rates */
19
24
#define RPI_FIRMWARE_EMMC_CLK_RATE 50000000
20
FIELD(ID_MMFR5, ETS, 0, 4)
25
#define RPI_FIRMWARE_UART_CLK_RATE 3000000
21
+FIELD(ID_MMFR5, NTLBPA, 4, 4)
26
+/*
22
27
+ * TODO: this is really SoC-specific; we might want to
23
FIELD(ID_PFR0, STATE0, 0, 4)
28
+ * set it per-SoC if it turns out any guests care.
24
FIELD(ID_PFR0, STATE1, 4, 4)
29
+ */
25
@@ -XXX,XX +XXX,XX @@ FIELD(ID_AA64ISAR1, SPECRES, 40, 4)
30
+#define RPI_FIRMWARE_CORE_CLK_RATE 350000000
26
FIELD(ID_AA64ISAR1, BF16, 44, 4)
31
#define RPI_FIRMWARE_DEFAULT_CLK_RATE 700000000
27
FIELD(ID_AA64ISAR1, DGH, 48, 4)
32
28
FIELD(ID_AA64ISAR1, I8MM, 52, 4)
33
#endif
29
+FIELD(ID_AA64ISAR1, XS, 56, 4)
34
diff --git a/hw/misc/bcm2835_property.c b/hw/misc/bcm2835_property.c
30
+FIELD(ID_AA64ISAR1, LS64, 60, 4)
35
index XXXXXXX..XXXXXXX 100644
31
+
36
--- a/hw/misc/bcm2835_property.c
32
+FIELD(ID_AA64ISAR2, WFXT, 0, 4)
37
+++ b/hw/misc/bcm2835_property.c
33
+FIELD(ID_AA64ISAR2, RPRES, 4, 4)
38
@@ -XXX,XX +XXX,XX @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
34
+FIELD(ID_AA64ISAR2, GPA3, 8, 4)
39
case RPI_FIRMWARE_UART_CLK_ID:
35
+FIELD(ID_AA64ISAR2, APA3, 12, 4)
40
stl_le_phys(&s->dma_as, value + 16, RPI_FIRMWARE_UART_CLK_RATE);
36
+FIELD(ID_AA64ISAR2, MOPS, 16, 4)
41
break;
37
+FIELD(ID_AA64ISAR2, BC, 20, 4)
42
+ case RPI_FIRMWARE_CORE_CLK_ID:
38
+FIELD(ID_AA64ISAR2, PAC_FRAC, 24, 4)
43
+ stl_le_phys(&s->dma_as, value + 16, RPI_FIRMWARE_CORE_CLK_RATE);
39
44
+ break;
40
FIELD(ID_AA64PFR0, EL0, 0, 4)
45
default:
41
FIELD(ID_AA64PFR0, EL1, 4, 4)
46
stl_le_phys(&s->dma_as, value + 16,
42
@@ -XXX,XX +XXX,XX @@ FIELD(ID_AA64PFR1, SSBS, 4, 4)
47
RPI_FIRMWARE_DEFAULT_CLK_RATE);
43
FIELD(ID_AA64PFR1, MTE, 8, 4)
44
FIELD(ID_AA64PFR1, RAS_FRAC, 12, 4)
45
FIELD(ID_AA64PFR1, MPAM_FRAC, 16, 4)
46
+FIELD(ID_AA64PFR1, SME, 24, 4)
47
+FIELD(ID_AA64PFR1, RNDR_TRAP, 28, 4)
48
+FIELD(ID_AA64PFR1, CSV2_FRAC, 32, 4)
49
+FIELD(ID_AA64PFR1, NMI, 36, 4)
50
51
FIELD(ID_AA64MMFR0, PARANGE, 0, 4)
52
FIELD(ID_AA64MMFR0, ASIDBITS, 4, 4)
53
@@ -XXX,XX +XXX,XX @@ FIELD(ID_AA64MMFR1, SPECSEI, 24, 4)
54
FIELD(ID_AA64MMFR1, XNX, 28, 4)
55
FIELD(ID_AA64MMFR1, TWED, 32, 4)
56
FIELD(ID_AA64MMFR1, ETS, 36, 4)
57
+FIELD(ID_AA64MMFR1, HCX, 40, 4)
58
+FIELD(ID_AA64MMFR1, AFP, 44, 4)
59
+FIELD(ID_AA64MMFR1, NTLBPA, 48, 4)
60
+FIELD(ID_AA64MMFR1, TIDCP1, 52, 4)
61
+FIELD(ID_AA64MMFR1, CMOW, 56, 4)
62
63
FIELD(ID_AA64MMFR2, CNP, 0, 4)
64
FIELD(ID_AA64MMFR2, UAO, 4, 4)
65
@@ -XXX,XX +XXX,XX @@ FIELD(ID_AA64DFR0, CTX_CMPS, 28, 4)
66
FIELD(ID_AA64DFR0, PMSVER, 32, 4)
67
FIELD(ID_AA64DFR0, DOUBLELOCK, 36, 4)
68
FIELD(ID_AA64DFR0, TRACEFILT, 40, 4)
69
+FIELD(ID_AA64DFR0, TRACEBUFFER, 44, 4)
70
FIELD(ID_AA64DFR0, MTPMU, 48, 4)
71
+FIELD(ID_AA64DFR0, BRBE, 52, 4)
72
+FIELD(ID_AA64DFR0, HPMN0, 60, 4)
73
74
FIELD(ID_AA64ZFR0, SVEVER, 0, 4)
75
FIELD(ID_AA64ZFR0, AES, 4, 4)
76
@@ -XXX,XX +XXX,XX @@ FIELD(ID_DFR0, PERFMON, 24, 4)
77
FIELD(ID_DFR0, TRACEFILT, 28, 4)
78
79
FIELD(ID_DFR1, MTPMU, 0, 4)
80
+FIELD(ID_DFR1, HPMN0, 4, 4)
81
82
FIELD(DBGDIDR, SE_IMP, 12, 1)
83
FIELD(DBGDIDR, NSUHD_IMP, 14, 1)
84
--
48
--
85
2.25.1
49
2.34.1
86
50
87
51
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
Currently we assume all fields are 32-bit.
4
Prepare for fields of a single byte, using sizeof_field().
5
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
[PMM: use sizeof_field() instead of raw sizeof()]
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
target/arm/translate-a32.h | 13 +++++--------
12
target/arm/translate.c | 21 ++++++++++++++++++++-
13
2 files changed, 25 insertions(+), 9 deletions(-)
14
15
diff --git a/target/arm/translate-a32.h b/target/arm/translate-a32.h
16
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/translate-a32.h
18
+++ b/target/arm/translate-a32.h
19
@@ -XXX,XX +XXX,XX @@ static inline TCGv_i32 load_cpu_offset(int offset)
20
21
#define load_cpu_field(name) load_cpu_offset(offsetof(CPUARMState, name))
22
23
-static inline void store_cpu_offset(TCGv_i32 var, int offset)
24
-{
25
- tcg_gen_st_i32(var, cpu_env, offset);
26
- tcg_temp_free_i32(var);
27
-}
28
+void store_cpu_offset(TCGv_i32 var, int offset, int size);
29
30
-#define store_cpu_field(var, name) \
31
- store_cpu_offset(var, offsetof(CPUARMState, name))
32
+#define store_cpu_field(var, name) \
33
+ store_cpu_offset(var, offsetof(CPUARMState, name), \
34
+ sizeof_field(CPUARMState, name))
35
36
#define store_cpu_field_constant(val, name) \
37
- tcg_gen_st_i32(tcg_constant_i32(val), cpu_env, offsetof(CPUARMState, name))
38
+ store_cpu_field(tcg_constant_i32(val), name)
39
40
/* Create a new temporary and set it to the value of a CPU register. */
41
static inline TCGv_i32 load_reg(DisasContext *s, int reg)
42
diff --git a/target/arm/translate.c b/target/arm/translate.c
43
index XXXXXXX..XXXXXXX 100644
44
--- a/target/arm/translate.c
45
+++ b/target/arm/translate.c
46
@@ -XXX,XX +XXX,XX @@ typedef enum ISSInfo {
47
ISSIs16Bit = (1 << 8),
48
} ISSInfo;
49
50
+/*
51
+ * Store var into env + offset to a member with size bytes.
52
+ * Free var after use.
53
+ */
54
+void store_cpu_offset(TCGv_i32 var, int offset, int size)
55
+{
56
+ switch (size) {
57
+ case 1:
58
+ tcg_gen_st8_i32(var, cpu_env, offset);
59
+ break;
60
+ case 4:
61
+ tcg_gen_st_i32(var, cpu_env, offset);
62
+ break;
63
+ default:
64
+ g_assert_not_reached();
65
+ }
66
+ tcg_temp_free_i32(var);
67
+}
68
+
69
/* Save the syndrome information for a Data Abort */
70
static void disas_set_da_iss(DisasContext *s, MemOp memop, ISSInfo issinfo)
71
{
72
@@ -XXX,XX +XXX,XX @@ static void do_coproc_insn(DisasContext *s, int cpnum, int is64,
73
tcg_temp_free_i32(tmp);
74
} else {
75
TCGv_i32 tmp = load_reg(s, rt);
76
- store_cpu_offset(tmp, ri->fieldoffset);
77
+ store_cpu_offset(tmp, ri->fieldoffset, 4);
78
}
79
}
80
}
81
--
82
2.25.1
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
Bool is a more appropriate type for this value.
4
Move the member down in the struct to keep the
5
bool type members together and remove a hole.
6
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
target/arm/translate.h | 2 +-
12
target/arm/translate-a64.c | 2 +-
13
2 files changed, 2 insertions(+), 2 deletions(-)
14
15
diff --git a/target/arm/translate.h b/target/arm/translate.h
16
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/translate.h
18
+++ b/target/arm/translate.h
19
@@ -XXX,XX +XXX,XX @@ typedef struct DisasContext {
20
bool eci_handled;
21
/* TCG op to rewind to if this turns out to be an invalid ECI state */
22
TCGOp *insn_eci_rewind;
23
- int thumb;
24
int sctlr_b;
25
MemOp be_data;
26
#if !defined(CONFIG_USER_ONLY)
27
@@ -XXX,XX +XXX,XX @@ typedef struct DisasContext {
28
GHashTable *cp_regs;
29
uint64_t features; /* CPU features bits */
30
bool aarch64;
31
+ bool thumb;
32
/* Because unallocated encodings generate different exception syndrome
33
* information from traps due to FP being disabled, we can't do a single
34
* "is fp access disabled" check at a high level in the decode tree.
35
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
36
index XXXXXXX..XXXXXXX 100644
37
--- a/target/arm/translate-a64.c
38
+++ b/target/arm/translate-a64.c
39
@@ -XXX,XX +XXX,XX @@ static void aarch64_tr_init_disas_context(DisasContextBase *dcbase,
40
*/
41
dc->secure_routed_to_el3 = arm_feature(env, ARM_FEATURE_EL3) &&
42
!arm_el_is_aa64(env, 3);
43
- dc->thumb = 0;
44
+ dc->thumb = false;
45
dc->sctlr_b = 0;
46
dc->be_data = EX_TBFLAG_ANY(tb_flags, BE_DATA) ? MO_BE : MO_LE;
47
dc->condexec_mask = 0;
48
--
49
2.25.1
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
Bool is a more appropriate type for this value.
4
Adjust the assignments to use true/false.
5
6
Signed-off-by: Richard Henderson <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
target/arm/cpu.h | 2 +-
11
linux-user/arm/cpu_loop.c | 2 +-
12
target/arm/cpu.c | 2 +-
13
target/arm/m_helper.c | 6 +++---
14
4 files changed, 6 insertions(+), 6 deletions(-)
15
16
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
17
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/cpu.h
19
+++ b/target/arm/cpu.h
20
@@ -XXX,XX +XXX,XX @@ typedef struct CPUArchState {
21
*/
22
uint32_t pstate;
23
bool aarch64; /* True if CPU is in aarch64 state; inverse of PSTATE.nRW */
24
+ bool thumb; /* True if CPU is in thumb mode; cpsr[5] */
25
26
/* Cached TBFLAGS state. See below for which bits are included. */
27
CPUARMTBFlags hflags;
28
@@ -XXX,XX +XXX,XX @@ typedef struct CPUArchState {
29
uint32_t ZF; /* Z set if zero. */
30
uint32_t QF; /* 0 or 1 */
31
uint32_t GE; /* cpsr[19:16] */
32
- uint32_t thumb; /* cpsr[5]. 0 = arm mode, 1 = thumb mode. */
33
uint32_t condexec_bits; /* IT bits. cpsr[15:10,26:25]. */
34
uint32_t btype; /* BTI branch type. spsr[11:10]. */
35
uint64_t daif; /* exception masks, in the bits they are in PSTATE */
36
diff --git a/linux-user/arm/cpu_loop.c b/linux-user/arm/cpu_loop.c
37
index XXXXXXX..XXXXXXX 100644
38
--- a/linux-user/arm/cpu_loop.c
39
+++ b/linux-user/arm/cpu_loop.c
40
@@ -XXX,XX +XXX,XX @@ do_kernel_trap(CPUARMState *env)
41
/* Jump back to the caller. */
42
addr = env->regs[14];
43
if (addr & 1) {
44
- env->thumb = 1;
45
+ env->thumb = true;
46
addr &= ~1;
47
}
48
env->regs[15] = addr;
49
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
50
index XXXXXXX..XXXXXXX 100644
51
--- a/target/arm/cpu.c
52
+++ b/target/arm/cpu.c
53
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_set_pc(CPUState *cs, vaddr value)
54
55
if (is_a64(env)) {
56
env->pc = value;
57
- env->thumb = 0;
58
+ env->thumb = false;
59
} else {
60
env->regs[15] = value & ~1;
61
env->thumb = value & 1;
62
diff --git a/target/arm/m_helper.c b/target/arm/m_helper.c
63
index XXXXXXX..XXXXXXX 100644
64
--- a/target/arm/m_helper.c
65
+++ b/target/arm/m_helper.c
66
@@ -XXX,XX +XXX,XX @@ void HELPER(v7m_bxns)(CPUARMState *env, uint32_t dest)
67
env->v7m.control[M_REG_S] &= ~R_V7M_CONTROL_SFPA_MASK;
68
}
69
switch_v7m_security_state(env, dest & 1);
70
- env->thumb = 1;
71
+ env->thumb = true;
72
env->regs[15] = dest & ~1;
73
arm_rebuild_hflags(env);
74
}
75
@@ -XXX,XX +XXX,XX @@ void HELPER(v7m_blxns)(CPUARMState *env, uint32_t dest)
76
* except that the low bit doesn't indicate Thumb/not.
77
*/
78
env->regs[14] = nextinst;
79
- env->thumb = 1;
80
+ env->thumb = true;
81
env->regs[15] = dest & ~1;
82
return;
83
}
84
@@ -XXX,XX +XXX,XX @@ void HELPER(v7m_blxns)(CPUARMState *env, uint32_t dest)
85
}
86
env->v7m.control[M_REG_S] &= ~R_V7M_CONTROL_SFPA_MASK;
87
switch_v7m_security_state(env, 0);
88
- env->thumb = 1;
89
+ env->thumb = true;
90
env->regs[15] = dest;
91
arm_rebuild_hflags(env);
92
}
93
--
94
2.25.1
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
Common code for reset_btype and set_btype.
4
Use tcg_constant_i32.
5
6
Signed-off-by: Richard Henderson <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
target/arm/translate-a64.c | 25 ++++++++++++-------------
11
1 file changed, 12 insertions(+), 13 deletions(-)
12
13
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/translate-a64.c
16
+++ b/target/arm/translate-a64.c
17
@@ -XXX,XX +XXX,XX @@ static int get_a64_user_mem_index(DisasContext *s)
18
return arm_to_core_mmu_idx(useridx);
19
}
20
21
-static void reset_btype(DisasContext *s)
22
+static void set_btype_raw(int val)
23
{
24
- if (s->btype != 0) {
25
- TCGv_i32 zero = tcg_const_i32(0);
26
- tcg_gen_st_i32(zero, cpu_env, offsetof(CPUARMState, btype));
27
- tcg_temp_free_i32(zero);
28
- s->btype = 0;
29
- }
30
+ tcg_gen_st_i32(tcg_constant_i32(val), cpu_env,
31
+ offsetof(CPUARMState, btype));
32
}
33
34
static void set_btype(DisasContext *s, int val)
35
{
36
- TCGv_i32 tcg_val;
37
-
38
/* BTYPE is a 2-bit field, and 0 should be done with reset_btype. */
39
tcg_debug_assert(val >= 1 && val <= 3);
40
-
41
- tcg_val = tcg_const_i32(val);
42
- tcg_gen_st_i32(tcg_val, cpu_env, offsetof(CPUARMState, btype));
43
- tcg_temp_free_i32(tcg_val);
44
+ set_btype_raw(val);
45
s->btype = -1;
46
}
47
48
+static void reset_btype(DisasContext *s)
49
+{
50
+ if (s->btype != 0) {
51
+ set_btype_raw(0);
52
+ s->btype = 0;
53
+ }
54
+}
55
+
56
void gen_a64_set_pc_im(uint64_t val)
57
{
58
tcg_gen_movi_i64(cpu_pc, val);
59
--
60
2.25.1
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
Instead of computing
4
5
tmp1 = shift & 0xff;
6
dest = (tmp1 > 0x1f ? 0 : value) << (tmp1 & 0x1f)
7
8
use
9
10
tmpd = value << (shift & 0x1f);
11
dest = shift & 0xe0 ? 0 : tmpd;
12
13
which has a flatter dependency tree.
14
Use tcg_constant_i32 while we're at it.
15
16
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
17
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
---
20
target/arm/translate.c | 18 ++++++++----------
21
1 file changed, 8 insertions(+), 10 deletions(-)
22
23
diff --git a/target/arm/translate.c b/target/arm/translate.c
24
index XXXXXXX..XXXXXXX 100644
25
--- a/target/arm/translate.c
26
+++ b/target/arm/translate.c
27
@@ -XXX,XX +XXX,XX @@ static void gen_sbc_CC(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
28
#define GEN_SHIFT(name) \
29
static void gen_##name(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1) \
30
{ \
31
- TCGv_i32 tmp1, tmp2, tmp3; \
32
- tmp1 = tcg_temp_new_i32(); \
33
- tcg_gen_andi_i32(tmp1, t1, 0xff); \
34
- tmp2 = tcg_const_i32(0); \
35
- tmp3 = tcg_const_i32(0x1f); \
36
- tcg_gen_movcond_i32(TCG_COND_GTU, tmp2, tmp1, tmp3, tmp2, t0); \
37
- tcg_temp_free_i32(tmp3); \
38
- tcg_gen_andi_i32(tmp1, tmp1, 0x1f); \
39
- tcg_gen_##name##_i32(dest, tmp2, tmp1); \
40
- tcg_temp_free_i32(tmp2); \
41
+ TCGv_i32 tmpd = tcg_temp_new_i32(); \
42
+ TCGv_i32 tmp1 = tcg_temp_new_i32(); \
43
+ TCGv_i32 zero = tcg_constant_i32(0); \
44
+ tcg_gen_andi_i32(tmp1, t1, 0x1f); \
45
+ tcg_gen_##name##_i32(tmpd, t0, tmp1); \
46
+ tcg_gen_andi_i32(tmp1, t1, 0xe0); \
47
+ tcg_gen_movcond_i32(TCG_COND_NE, dest, tmp1, zero, zero, tmpd); \
48
+ tcg_temp_free_i32(tmpd); \
49
tcg_temp_free_i32(tmp1); \
50
}
51
GEN_SHIFT(shl)
52
--
53
2.25.1
diff view generated by jsdifflib